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