Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2009 Red Hat, Inc. |
| 3 | * |
| 4 | * This is part of HarfBuzz, an OpenType Layout engine library. |
| 5 | * |
| 6 | * Permission is hereby granted, without written agreement and without |
| 7 | * license or royalty fees, to use, copy, modify, and distribute this |
| 8 | * software and its documentation for any purpose, provided that the |
| 9 | * above copyright notice and the following two paragraphs appear in |
| 10 | * all copies of this software. |
| 11 | * |
| 12 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| 13 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| 14 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
| 15 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 16 | * DAMAGE. |
| 17 | * |
| 18 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| 19 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 20 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
| 21 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| 22 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 23 | * |
| 24 | * Red Hat Author(s): Behdad Esfahbod |
| 25 | */ |
| 26 | |
| 27 | #include "hb-private.h" |
| 28 | |
| 29 | #include "hb-blob.h" |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 30 | |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 31 | #include <unistd.h> |
| 32 | #include <sys/mman.h> |
| 33 | |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 34 | struct _hb_blob_t { |
Behdad Esfahbod | e97a95f | 2009-08-01 19:05:44 -0400 | [diff] [blame] | 35 | hb_reference_count_t ref_count; |
| 36 | |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 37 | unsigned int length; |
| 38 | |
| 39 | hb_mutex_t lock; |
| 40 | /* the rest are protected by lock */ |
| 41 | |
| 42 | unsigned int lock_count; |
| 43 | hb_memory_mode_t mode; |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 44 | |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 45 | const char *data; |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 46 | |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 47 | hb_destroy_func_t destroy; |
| 48 | void *user_data; |
| 49 | }; |
| 50 | static hb_blob_t _hb_blob_nil = { |
Behdad Esfahbod | 35a7383 | 2009-08-01 19:30:31 -0400 | [diff] [blame] | 51 | HB_REFERENCE_COUNT_INVALID, /* ref_count */ |
Behdad Esfahbod | e97a95f | 2009-08-01 19:05:44 -0400 | [diff] [blame] | 52 | |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 53 | 0, /* length */ |
| 54 | |
| 55 | HB_MUTEX_INIT, /* lock */ |
| 56 | |
| 57 | 0, /* lock_count */ |
| 58 | HB_MEMORY_MODE_READONLY_NEVER_DUPLICATE, /* mode */ |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 59 | |
Behdad Esfahbod | 35a7383 | 2009-08-01 19:30:31 -0400 | [diff] [blame] | 60 | NULL, /* data */ |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 61 | |
Behdad Esfahbod | 35a7383 | 2009-08-01 19:30:31 -0400 | [diff] [blame] | 62 | NULL, /* destroy */ |
| 63 | NULL /* user_data */ |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 64 | }; |
| 65 | |
| 66 | static void |
| 67 | _hb_blob_destroy_user_data (hb_blob_t *blob) |
| 68 | { |
| 69 | if (blob->destroy) { |
| 70 | blob->destroy (blob->user_data); |
| 71 | blob->destroy = NULL; |
| 72 | blob->user_data = NULL; |
| 73 | } |
| 74 | } |
| 75 | |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 76 | static void |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 77 | _hb_blob_unlock_and_destroy (hb_blob_t *blob) |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 78 | { |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 79 | hb_blob_unlock (blob); |
| 80 | hb_blob_destroy (blob); |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 81 | } |
| 82 | |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 83 | hb_blob_t * |
| 84 | hb_blob_create (const char *data, |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 85 | unsigned int length, |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 86 | hb_memory_mode_t mode, |
| 87 | hb_destroy_func_t destroy, |
| 88 | void *user_data) |
| 89 | { |
| 90 | hb_blob_t *blob; |
| 91 | |
Behdad Esfahbod | 5fc22e6 | 2009-08-03 22:43:02 -0400 | [diff] [blame] | 92 | if (!length || !HB_OBJECT_DO_CREATE (hb_blob_t, blob)) { |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 93 | if (destroy) |
| 94 | destroy (user_data); |
| 95 | return &_hb_blob_nil; |
| 96 | } |
| 97 | |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 98 | hb_mutex_init (blob->lock); |
| 99 | blob->lock_count = 0; |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 100 | |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 101 | blob->data = data; |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 102 | blob->length = length; |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 103 | blob->mode = mode; |
| 104 | |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 105 | blob->destroy = destroy; |
| 106 | blob->user_data = user_data; |
| 107 | |
| 108 | if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { |
| 109 | blob->mode = HB_MEMORY_MODE_READONLY; |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 110 | if (!hb_blob_try_writeable (blob)) { |
| 111 | hb_blob_destroy (blob); |
| 112 | return &_hb_blob_nil; |
| 113 | } |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 114 | } |
| 115 | |
| 116 | return blob; |
| 117 | } |
| 118 | |
| 119 | hb_blob_t * |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 120 | hb_blob_create_sub_blob (hb_blob_t *parent, |
| 121 | unsigned int offset, |
| 122 | unsigned int length) |
| 123 | { |
| 124 | hb_blob_t *blob; |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 125 | const char *pdata; |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 126 | |
Behdad Esfahbod | 5fc22e6 | 2009-08-03 22:43:02 -0400 | [diff] [blame] | 127 | if (!length || offset >= parent->length || !HB_OBJECT_DO_CREATE (hb_blob_t, blob)) |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 128 | return &_hb_blob_nil; |
| 129 | |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 130 | pdata = hb_blob_lock (parent); |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 131 | |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 132 | blob->data = pdata + offset; |
| 133 | blob->length = MIN (length, parent->length - offset); |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 134 | |
| 135 | hb_mutex_lock (parent->lock); |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 136 | blob->mode = parent->mode; |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 137 | hb_mutex_unlock (parent->lock); |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 138 | |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 139 | blob->destroy = (hb_destroy_func_t) _hb_blob_unlock_and_destroy; |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 140 | blob->user_data = hb_blob_reference (parent); |
| 141 | |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 142 | return blob; |
| 143 | } |
| 144 | |
| 145 | hb_blob_t * |
| 146 | hb_blob_create_empty (void) |
| 147 | { |
| 148 | return &_hb_blob_nil; |
| 149 | } |
| 150 | |
| 151 | hb_blob_t * |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 152 | hb_blob_reference (hb_blob_t *blob) |
| 153 | { |
Behdad Esfahbod | c62b503 | 2009-08-01 19:54:49 -0400 | [diff] [blame] | 154 | HB_OBJECT_DO_REFERENCE (blob); |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 155 | } |
| 156 | |
Behdad Esfahbod | a12dd32 | 2009-08-01 21:36:15 -0400 | [diff] [blame] | 157 | unsigned int |
| 158 | hb_blob_get_reference_count (hb_blob_t *blob) |
| 159 | { |
| 160 | HB_OBJECT_DO_GET_REFERENCE_COUNT (blob); |
| 161 | } |
| 162 | |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 163 | void |
| 164 | hb_blob_destroy (hb_blob_t *blob) |
| 165 | { |
Behdad Esfahbod | c62b503 | 2009-08-01 19:54:49 -0400 | [diff] [blame] | 166 | HB_OBJECT_DO_DESTROY (blob); |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 167 | |
| 168 | _hb_blob_destroy_user_data (blob); |
| 169 | |
| 170 | free (blob); |
| 171 | } |
| 172 | |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 173 | unsigned int |
| 174 | hb_blob_get_length (hb_blob_t *blob) |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 175 | { |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 176 | return blob->length; |
| 177 | } |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 178 | |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 179 | const char * |
| 180 | hb_blob_lock (hb_blob_t *blob) |
| 181 | { |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 182 | if (HB_OBJECT_IS_INERT (blob)) |
| 183 | return NULL; |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 184 | |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 185 | hb_mutex_lock (blob->lock); |
| 186 | |
| 187 | blob->lock_count++; |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 188 | #if HB_DEBUG |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 189 | fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__, |
| 190 | blob->lock_count, blob->data); |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 191 | #endif |
| 192 | |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 193 | hb_mutex_unlock (blob->lock); |
| 194 | |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 195 | return blob->data; |
| 196 | } |
| 197 | |
| 198 | void |
| 199 | hb_blob_unlock (hb_blob_t *blob) |
| 200 | { |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 201 | if (HB_OBJECT_IS_INERT (blob)) |
| 202 | return; |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 203 | |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 204 | hb_mutex_lock (blob->lock); |
| 205 | |
| 206 | assert (blob->lock_count > 0); |
| 207 | blob->lock_count--; |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 208 | #if HB_DEBUG |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 209 | fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__, |
| 210 | hb_atomic_int_get (blob->lock_count), blob->data); |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 211 | #endif |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 212 | |
| 213 | hb_mutex_unlock (blob->lock); |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 214 | } |
| 215 | |
| 216 | hb_bool_t |
| 217 | hb_blob_is_writeable (hb_blob_t *blob) |
| 218 | { |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 219 | hb_memory_mode_t mode; |
| 220 | |
| 221 | if (HB_OBJECT_IS_INERT (blob)) |
| 222 | return FALSE; |
| 223 | |
| 224 | hb_mutex_lock (blob->lock); |
| 225 | |
| 226 | mode = blob->mode; |
| 227 | |
| 228 | hb_mutex_unlock (blob->lock); |
| 229 | |
| 230 | return mode == HB_MEMORY_MODE_WRITEABLE; |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | hb_bool_t |
| 234 | hb_blob_try_writeable_inplace (hb_blob_t *blob) |
| 235 | { |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 236 | hb_memory_mode_t mode; |
| 237 | |
| 238 | if (HB_OBJECT_IS_INERT (blob)) |
| 239 | return FALSE; |
| 240 | |
| 241 | hb_mutex_lock (blob->lock); |
| 242 | |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 243 | if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITEABLE) { |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 244 | unsigned int pagesize, mask, length; |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 245 | const char *addr; |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 246 | |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 247 | #if HB_DEBUG |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 248 | fprintf (stderr, "%p %s: making writeable\n", blob, __FUNCTION__); |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 249 | #endif |
| 250 | pagesize = (unsigned int) sysconf(_SC_PAGE_SIZE); |
| 251 | if ((unsigned int) -1 == pagesize) { |
| 252 | #if HB_DEBUG |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 253 | fprintf (stderr, "%p %s: %s\n", blob, __FUNCTION__, strerror (errno)); |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 254 | #endif |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 255 | goto done; |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 256 | } |
| 257 | #if HB_DEBUG |
| 258 | fprintf (stderr, "%p %s: pagesize is %u\n", blob, __FUNCTION__, pagesize); |
| 259 | #endif |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 260 | |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 261 | mask = ~(pagesize-1); |
| 262 | addr = (const char *) (((size_t) blob->data) & mask); |
| 263 | length = (const char *) (((size_t) blob->data + blob->length + pagesize-1) & mask) - addr; |
| 264 | #if HB_DEBUG |
| 265 | fprintf (stderr, "%p %s: calling mprotect on [%p..%p] (%d bytes)\n", |
| 266 | blob, __FUNCTION__, |
| 267 | addr, addr+length, length); |
| 268 | #endif |
| 269 | if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) { |
| 270 | #if HB_DEBUG |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 271 | fprintf (stderr, "%p %s: %s\n", blob, __FUNCTION__, strerror (errno)); |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 272 | #endif |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 273 | goto done; |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 274 | } |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 275 | |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 276 | blob->mode = HB_MEMORY_MODE_WRITEABLE; |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 277 | |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 278 | #if HB_DEBUG |
| 279 | fprintf (stderr, "%p %s: successfully made [%p..%p] (%d bytes) writeable\n", |
| 280 | blob, __FUNCTION__, |
| 281 | addr, addr+length, length); |
| 282 | #endif |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 283 | } |
| 284 | |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 285 | done: |
| 286 | mode = blob->mode; |
| 287 | |
| 288 | hb_mutex_unlock (blob->lock); |
| 289 | |
| 290 | return mode == HB_MEMORY_MODE_WRITEABLE; |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 291 | } |
| 292 | |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 293 | hb_bool_t |
| 294 | hb_blob_try_writeable (hb_blob_t *blob) |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 295 | { |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 296 | hb_memory_mode_t mode; |
| 297 | |
| 298 | if (HB_OBJECT_IS_INERT (blob)) |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 299 | return FALSE; |
| 300 | |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 301 | hb_mutex_lock (blob->lock); |
| 302 | |
| 303 | if (blob->mode == HB_MEMORY_MODE_READONLY_NEVER_DUPLICATE) |
| 304 | goto done; |
| 305 | |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 306 | if (blob->mode == HB_MEMORY_MODE_READONLY) |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 307 | { |
| 308 | char *new_data; |
| 309 | |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 310 | #if HB_DEBUG |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 311 | fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__, |
| 312 | blob->lock_count, blob->data); |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 313 | #endif |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 314 | |
| 315 | if (blob->lock_count) |
| 316 | goto done; |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 317 | |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 318 | new_data = malloc (blob->length); |
| 319 | if (new_data) { |
Behdad Esfahbod | 7acb389 | 2009-08-05 15:20:34 -0400 | [diff] [blame] | 320 | #if HB_DEBUG |
| 321 | fprintf (stderr, "%p %s: dupped successfully -> %p\n", blob, __FUNCTION__, blob->data); |
| 322 | #endif |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 323 | memcpy (new_data, blob->data, blob->length); |
| 324 | blob->data = new_data; |
| 325 | blob->mode = HB_MEMORY_MODE_WRITEABLE; |
Behdad Esfahbod | a264424 | 2009-08-03 17:53:29 -0400 | [diff] [blame] | 326 | _hb_blob_destroy_user_data (blob); |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 327 | } |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 328 | } |
Behdad Esfahbod | fc6c940 | 2009-08-03 21:27:08 -0400 | [diff] [blame] | 329 | |
Behdad Esfahbod | 7f3d5c8 | 2009-08-06 13:33:51 -0400 | [diff] [blame] | 330 | done: |
| 331 | mode = blob->mode; |
| 332 | |
| 333 | hb_mutex_unlock (blob->lock); |
| 334 | |
| 335 | if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITEABLE) |
| 336 | return hb_blob_try_writeable_inplace (blob); |
| 337 | |
| 338 | return mode == HB_MEMORY_MODE_WRITEABLE; |
Behdad Esfahbod | f0954d1 | 2009-07-30 15:33:57 -0400 | [diff] [blame] | 339 | } |