hb-blob.cc revision 47e71d9661946a4ffb96026bf1d697d788414ab5
1f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod/* 22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2009 Red Hat, Inc. 3f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 4c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod * This is part of HarfBuzz, a text shaping library. 5f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 6f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * Permission is hereby granted, without written agreement and without 7f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 8f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * software and its documentation for any purpose, provided that the 9f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * above copyright notice and the following two paragraphs appear in 10f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * all copies of this software. 11f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 12f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * DAMAGE. 17f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 18f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 24f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod 25f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod */ 26f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 27c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh" 28f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 29c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-blob-private.hh" 30f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 31ec90ee23b29aab187c3fa209970aa97434c84b1bBehdad Esfahbod#ifdef HAVE_SYS_MMAN_H 32c486ea9c3582710474c1085c21c1dc5e2700adc3Behdad Esfahbod#ifdef HAVE_UNISTD_H 33a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod#include <unistd.h> 34c486ea9c3582710474c1085c21c1dc5e2700adc3Behdad Esfahbod#endif /* HAVE_UNISTD_H */ 35a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod#include <sys/mman.h> 36ec90ee23b29aab187c3fa209970aa97434c84b1bBehdad Esfahbod#endif /* HAVE_SYS_MMAN_H */ 37a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 38acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod#include <stdio.h> 39acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod#include <errno.h> 40acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 41acdba3f90b232fc12fcb200dca2584481b339118Behdad EsfahbodHB_BEGIN_DECLS 42acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 43acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 4495e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_BLOB 4511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_BLOB (HB_DEBUG+0) 4695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 4795e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 481cebfbb0636b13dc5dc6a4b8b7acbb7da28129d2Behdad Esfahbodhb_blob_t _hb_blob_nil = { 49fca368c4682624346a0aaee690e1ad6ed4c0b337Behdad Esfahbod HB_OBJECT_HEADER_STATIC, 50e97a95f2ea2770689bbf076d3c3ac404f273271eBehdad Esfahbod 51a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 0, /* length */ 527f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 537f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod HB_MUTEX_INIT, /* lock */ 547f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 557f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 0, /* lock_count */ 56388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod HB_MEMORY_MODE_READONLY, /* mode */ 57f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 587f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod NULL, /* data */ 597f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 60e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod NULL, /* user_data */ 61e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod NULL /* destroy */ 62f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod}; 63f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 64f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodstatic void 65f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod_hb_blob_destroy_user_data (hb_blob_t *blob) 66f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 67f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (blob->destroy) { 68f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->destroy (blob->user_data); 69f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->user_data = NULL; 70e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = NULL; 71f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 72f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 73f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 74a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodstatic void 75fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod_hb_blob_unlock_and_destroy (hb_blob_t *blob) 76a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod{ 77fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod hb_blob_unlock (blob); 78fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod hb_blob_destroy (blob); 79a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod} 80a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 81f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_t * 82f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_create (const char *data, 83a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int length, 84f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod hb_memory_mode_t mode, 85e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod void *user_data, 86e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod hb_destroy_func_t destroy) 87f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 88f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod hb_blob_t *blob; 89f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 9047e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (!length || !(blob = hb_object_create<hb_blob_t> ())) { 91f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (destroy) 92f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod destroy (user_data); 93f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod return &_hb_blob_nil; 94f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 95f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 967f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_init (blob->lock); 977f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod blob->lock_count = 0; 98fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 99f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->data = data; 100a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod blob->length = length; 101f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->mode = mode; 102f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 103f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->user_data = user_data; 104e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = destroy; 105f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 106f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { 107f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->mode = HB_MEMORY_MODE_READONLY; 108977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod if (!hb_blob_try_writable (blob)) { 109fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod hb_blob_destroy (blob); 110fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod return &_hb_blob_nil; 111fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod } 112f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 113f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 114f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod return blob; 115f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 116f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 117f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_t * 118a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_create_sub_blob (hb_blob_t *parent, 119a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int offset, 120a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int length) 121a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod{ 122a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod hb_blob_t *blob; 123fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod const char *pdata; 124a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 12547e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (!length || offset >= parent->length || !(blob = hb_object_create<hb_blob_t> ())) 126a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return &_hb_blob_nil; 127a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 128fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod pdata = hb_blob_lock (parent); 129a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 130fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod blob->data = pdata + offset; 131fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod blob->length = MIN (length, parent->length - offset); 1327f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 1337f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_lock (parent->lock); 134a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod blob->mode = parent->mode; 1357f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_unlock (parent->lock); 136a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 137a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod blob->user_data = hb_blob_reference (parent); 138e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = (hb_destroy_func_t) _hb_blob_unlock_and_destroy; 139a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 140a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return blob; 141a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod} 142a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 143a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_t * 144a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_create_empty (void) 145a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod{ 146a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return &_hb_blob_nil; 147a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod} 148a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 149a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_t * 150f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_reference (hb_blob_t *blob) 151f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 15247e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod return hb_object_reference (blob); 153f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 154f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 155f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodvoid 156f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_destroy (hb_blob_t *blob) 157f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 15847e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (!hb_object_destroy (blob)) return; 159f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 160f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod _hb_blob_destroy_user_data (blob); 161f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 162f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod free (blob); 163f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 164f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 165fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbodunsigned int 166fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbodhb_blob_get_length (hb_blob_t *blob) 167fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod{ 168fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod return blob->length; 169fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod} 170fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 171f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodconst char * 172fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbodhb_blob_lock (hb_blob_t *blob) 173f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 17447e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (hb_object_is_inert (blob)) 1757f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod return NULL; 1767f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 1777f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_lock (blob->lock); 178a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 179a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 1808be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s (%d) -> %p\n", blob, HB_FUNC, 181a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod blob->lock_count, blob->data)); 1827acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod 1835a11c875d8c95d480e6f32b57e969ee34ca1940dBehdad Esfahbod blob->lock_count++; 1845a11c875d8c95d480e6f32b57e969ee34ca1940dBehdad Esfahbod 1857f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_unlock (blob->lock); 1867f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 187fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod return blob->data; 188fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod} 189f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 190fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbodvoid 191fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbodhb_blob_unlock (hb_blob_t *blob) 192fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod{ 19347e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (hb_object_is_inert (blob)) 1947f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod return; 1957f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 1967f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_lock (blob->lock); 1977acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod 198a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 1998be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s (%d) -> %p\n", blob, HB_FUNC, 200a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod blob->lock_count, blob->data)); 2017f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2025a11c875d8c95d480e6f32b57e969ee34ca1940dBehdad Esfahbod assert (blob->lock_count > 0); 2035a11c875d8c95d480e6f32b57e969ee34ca1940dBehdad Esfahbod blob->lock_count--; 2045a11c875d8c95d480e6f32b57e969ee34ca1940dBehdad Esfahbod 2057f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_unlock (blob->lock); 206f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 207f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 208f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_bool_t 209977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbodhb_blob_is_writable (hb_blob_t *blob) 210f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 2117f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_memory_mode_t mode; 2127f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 21347e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (hb_object_is_inert (blob)) 2147f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod return FALSE; 2157f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2167f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_lock (blob->lock); 2177f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2187f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod mode = blob->mode; 2197f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2207f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_unlock (blob->lock); 2217f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 222977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod return mode == HB_MEMORY_MODE_WRITABLE; 223f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 224f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 2254ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2264ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbodstatic hb_bool_t 227977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod_try_make_writable_inplace_unix_locked (hb_blob_t *blob) 2284ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod{ 2294ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT) 230917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod uintptr_t pagesize = -1, mask, length; 2314ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod const char *addr; 2324ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2334ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) 234917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE); 2354ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) 236917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod pagesize = (uintptr_t) sysconf (_SC_PAGESIZE); 2374ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#elif defined(HAVE_GETPAGESIZE) 238917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod pagesize = (uintptr_t) getpagesize (); 2394ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#endif 2404ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 241917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod if ((uintptr_t) -1L == pagesize) { 242a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2438be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: failed to get pagesize: %s\n", blob, HB_FUNC, strerror (errno))); 2444ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return FALSE; 2454ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod } 246a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2478be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: pagesize is %lu\n", blob, HB_FUNC, (unsigned long) pagesize)); 2484ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2494ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod mask = ~(pagesize-1); 250917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod addr = (const char *) (((uintptr_t) blob->data) & mask); 251917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr; 252a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 25317e9ff938b638fd1cb80c990ba13bd47562116b8Behdad Esfahbod fprintf (stderr, "%p %s: calling mprotect on [%p..%p] (%lu bytes)\n", 2548be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod blob, HB_FUNC, 255a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod addr, addr+length, (unsigned long) length)); 2564ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) { 257a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2588be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: %s\n", blob, HB_FUNC, strerror (errno))); 2594ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return FALSE; 2604ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod } 2614ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 262a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 26317e9ff938b638fd1cb80c990ba13bd47562116b8Behdad Esfahbod fprintf (stderr, "%p %s: successfully made [%p..%p] (%lu bytes) writable\n", 2648be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod blob, HB_FUNC, 265a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod addr, addr+length, (unsigned long) length)); 2664ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return TRUE; 2674ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#else 2684ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return FALSE; 2694ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#endif 2704ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod} 2714ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 272388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbodstatic void 273acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbodtry_writable_inplace_locked (hb_blob_t *blob) 274388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod{ 275a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2768be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: making writable\n", blob, HB_FUNC)); 277388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod 278388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod if (_try_make_writable_inplace_unix_locked (blob)) { 279a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2808be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: making writable -> succeeded\n", blob, HB_FUNC)); 281388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod blob->mode = HB_MEMORY_MODE_WRITABLE; 282388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod } else { 283a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2848be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: making writable -> FAILED\n", blob, HB_FUNC)); 285388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod /* Failed to make writable inplace, mark that */ 286388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod blob->mode = HB_MEMORY_MODE_READONLY; 287388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod } 288388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod} 2894ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 290f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_bool_t 291977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbodhb_blob_try_writable_inplace (hb_blob_t *blob) 292f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 2937f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_memory_mode_t mode; 2947f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 29547e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (hb_object_is_inert (blob)) 2967f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod return FALSE; 2977f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2987f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_lock (blob->lock); 2997f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 300388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE) 301acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod try_writable_inplace_locked (blob); 302f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 3037f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod mode = blob->mode; 3047f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 3057f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_unlock (blob->lock); 3067f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 307977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod return mode == HB_MEMORY_MODE_WRITABLE; 308f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 309f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 310fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbodhb_bool_t 311977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbodhb_blob_try_writable (hb_blob_t *blob) 312f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 3137f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_memory_mode_t mode; 3147f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 31547e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (hb_object_is_inert (blob)) 316fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod return FALSE; 317fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 3187f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_lock (blob->lock); 3197f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 32071e735e915c85536ee4d3035576f7426e8cd19ddBehdad Esfahbod if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE) 321acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod try_writable_inplace_locked (blob); 32271e735e915c85536ee4d3035576f7426e8cd19ddBehdad Esfahbod 323fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_READONLY) 324f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod { 325f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod char *new_data; 326f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 327a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 3288be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s (%d) -> %p\n", blob, HB_FUNC, 329a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod blob->lock_count, blob->data)); 3307f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 3317f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod if (blob->lock_count) 3327f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod goto done; 333f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 334f19f4f9b0965ad7473a0f3a1ffcdbf16930e35d4Behdad Esfahbod new_data = (char *) malloc (blob->length); 335fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod if (new_data) { 336a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 3378be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: dupped successfully -> %p\n", blob, HB_FUNC, blob->data)); 338fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod memcpy (new_data, blob->data, blob->length); 339a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod _hb_blob_destroy_user_data (blob); 34012b27ed91de0192deee4e9feffcaf4aca4c78113Behdad Esfahbod blob->mode = HB_MEMORY_MODE_WRITABLE; 34112b27ed91de0192deee4e9feffcaf4aca4c78113Behdad Esfahbod blob->data = new_data; 34212b27ed91de0192deee4e9feffcaf4aca4c78113Behdad Esfahbod blob->user_data = new_data; 343e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = free; 3447f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod } 345f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 346fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 3477f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahboddone: 3487f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod mode = blob->mode; 3497f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 3507f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod hb_mutex_unlock (blob->lock); 3517f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 352977eeb714454630bd045bb11f58ff6397f10b143Behdad Esfahbod return mode == HB_MEMORY_MODE_WRITABLE; 353f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 354acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 355acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 356acdba3f90b232fc12fcb200dca2584481b339118Behdad EsfahbodHB_END_DECLS 357