base_memory.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #include "fitz-internal.h"
  2. static void *
  3. do_scavenging_malloc(fz_context *ctx, unsigned int size)
  4. {
  5. void *p;
  6. int phase = 0;
  7. fz_lock(ctx, FZ_LOCK_ALLOC);
  8. do {
  9. p = ctx->alloc->malloc(ctx->alloc->user, size);
  10. if (p != NULL)
  11. {
  12. fz_unlock(ctx, FZ_LOCK_ALLOC);
  13. return p;
  14. }
  15. } while (fz_store_scavenge(ctx, size, &phase));
  16. fz_unlock(ctx, FZ_LOCK_ALLOC);
  17. return NULL;
  18. }
  19. static void *
  20. do_scavenging_realloc(fz_context *ctx, void *p, unsigned int size)
  21. {
  22. void *q;
  23. int phase = 0;
  24. fz_lock(ctx, FZ_LOCK_ALLOC);
  25. do {
  26. q = ctx->alloc->realloc(ctx->alloc->user, p, size);
  27. if (q != NULL)
  28. {
  29. fz_unlock(ctx, FZ_LOCK_ALLOC);
  30. return q;
  31. }
  32. } while (fz_store_scavenge(ctx, size, &phase));
  33. fz_unlock(ctx, FZ_LOCK_ALLOC);
  34. return NULL;
  35. }
  36. void *
  37. fz_malloc(fz_context *ctx, unsigned int size)
  38. {
  39. void *p;
  40. if (size == 0)
  41. return NULL;
  42. p = do_scavenging_malloc(ctx, size);
  43. if (!p)
  44. fz_throw(ctx, "malloc of %d bytes failed", size);
  45. return p;
  46. }
  47. void *
  48. fz_malloc_no_throw(fz_context *ctx, unsigned int size)
  49. {
  50. return do_scavenging_malloc(ctx, size);
  51. }
  52. void *
  53. fz_malloc_array(fz_context *ctx, unsigned int count, unsigned int size)
  54. {
  55. void *p;
  56. if (count == 0 || size == 0)
  57. return 0;
  58. if (count > UINT_MAX / size)
  59. fz_throw(ctx, "malloc of array (%d x %d bytes) failed (integer overflow)", count, size);
  60. p = do_scavenging_malloc(ctx, count * size);
  61. if (!p)
  62. fz_throw(ctx, "malloc of array (%d x %d bytes) failed", count, size);
  63. return p;
  64. }
  65. void *
  66. fz_malloc_array_no_throw(fz_context *ctx, unsigned int count, unsigned int size)
  67. {
  68. if (count == 0 || size == 0)
  69. return 0;
  70. if (count > UINT_MAX / size)
  71. {
  72. fprintf(stderr, "error: malloc of array (%d x %d bytes) failed (integer overflow)", count, size);
  73. return NULL;
  74. }
  75. return do_scavenging_malloc(ctx, count * size);
  76. }
  77. void *
  78. fz_calloc(fz_context *ctx, unsigned int count, unsigned int size)
  79. {
  80. void *p;
  81. if (count == 0 || size == 0)
  82. return 0;
  83. if (count > UINT_MAX / size)
  84. {
  85. fz_throw(ctx, "calloc (%d x %d bytes) failed (integer overflow)", count, size);
  86. }
  87. p = do_scavenging_malloc(ctx, count * size);
  88. if (!p)
  89. {
  90. fz_throw(ctx, "calloc (%d x %d bytes) failed", count, size);
  91. }
  92. memset(p, 0, count*size);
  93. return p;
  94. }
  95. void *
  96. fz_calloc_no_throw(fz_context *ctx, unsigned int count, unsigned int size)
  97. {
  98. void *p;
  99. if (count == 0 || size == 0)
  100. return 0;
  101. if (count > UINT_MAX / size)
  102. {
  103. fprintf(stderr, "error: calloc (%d x %d bytes) failed (integer overflow)\n", count, size);
  104. return NULL;
  105. }
  106. p = do_scavenging_malloc(ctx, count * size);
  107. if (p)
  108. {
  109. memset(p, 0, count*size);
  110. }
  111. return p;
  112. }
  113. void *
  114. fz_resize_array(fz_context *ctx, void *p, unsigned int count, unsigned int size)
  115. {
  116. void *np;
  117. if (count == 0 || size == 0)
  118. {
  119. fz_free(ctx, p);
  120. return 0;
  121. }
  122. if (count > UINT_MAX / size)
  123. fz_throw(ctx, "resize array (%d x %d bytes) failed (integer overflow)", count, size);
  124. np = do_scavenging_realloc(ctx, p, count * size);
  125. if (!np)
  126. fz_throw(ctx, "resize array (%d x %d bytes) failed", count, size);
  127. return np;
  128. }
  129. void *
  130. fz_resize_array_no_throw(fz_context *ctx, void *p, unsigned int count, unsigned int size)
  131. {
  132. if (count == 0 || size == 0)
  133. {
  134. fz_free(ctx, p);
  135. return 0;
  136. }
  137. if (count > UINT_MAX / size)
  138. {
  139. fprintf(stderr, "error: resize array (%d x %d bytes) failed (integer overflow)\n", count, size);
  140. return NULL;
  141. }
  142. return do_scavenging_realloc(ctx, p, count * size);
  143. }
  144. void
  145. fz_free(fz_context *ctx, void *p)
  146. {
  147. fz_lock(ctx, FZ_LOCK_ALLOC);
  148. ctx->alloc->free(ctx->alloc->user, p);
  149. fz_unlock(ctx, FZ_LOCK_ALLOC);
  150. }
  151. char *
  152. fz_strdup(fz_context *ctx, const char *s)
  153. {
  154. int len = strlen(s) + 1;
  155. char *ns = fz_malloc(ctx, len);
  156. memcpy(ns, s, len);
  157. return ns;
  158. }
  159. char *
  160. fz_strdup_no_throw(fz_context *ctx, const char *s)
  161. {
  162. int len = strlen(s) + 1;
  163. char *ns = fz_malloc_no_throw(ctx, len);
  164. if (ns)
  165. memcpy(ns, s, len);
  166. return ns;
  167. }
  168. static void *
  169. fz_malloc_default(void *opaque, unsigned int size)
  170. {
  171. return malloc(size);
  172. }
  173. static void *
  174. fz_realloc_default(void *opaque, void *old, unsigned int size)
  175. {
  176. return realloc(old, size);
  177. }
  178. static void
  179. fz_free_default(void *opaque, void *ptr)
  180. {
  181. free(ptr);
  182. }
  183. fz_alloc_context fz_alloc_default =
  184. {
  185. NULL,
  186. fz_malloc_default,
  187. fz_realloc_default,
  188. fz_free_default
  189. };
  190. static void
  191. fz_lock_default(void *user, int lock)
  192. {
  193. }
  194. static void
  195. fz_unlock_default(void *user, int lock)
  196. {
  197. }
  198. fz_locks_context fz_locks_default =
  199. {
  200. NULL,
  201. fz_lock_default,
  202. fz_unlock_default
  203. };
  204. #ifdef FITZ_DEBUG_LOCKING
  205. enum
  206. {
  207. FZ_LOCK_DEBUG_CONTEXT_MAX = 100
  208. };
  209. fz_context *fz_lock_debug_contexts[FZ_LOCK_DEBUG_CONTEXT_MAX];
  210. int fz_locks_debug[FZ_LOCK_DEBUG_CONTEXT_MAX][FZ_LOCK_MAX];
  211. static int find_context(fz_context *ctx)
  212. {
  213. int i;
  214. for (i = 0; i < FZ_LOCK_DEBUG_CONTEXT_MAX; i++)
  215. {
  216. if (fz_lock_debug_contexts[i] == ctx)
  217. return i;
  218. if (fz_lock_debug_contexts[i] == NULL)
  219. {
  220. int gottit = 0;
  221. /* We've not locked on this context before, so use
  222. * this one for this new context. We might have other
  223. * threads trying here too though so, so claim it
  224. * atomically. No one has locked on this context
  225. * before, so we are safe to take the ALLOC lock. */
  226. ctx->locks->lock(ctx->locks->user, FZ_LOCK_ALLOC);
  227. /* If it's still free, then claim it as ours,
  228. * otherwise we'll keep hunting. */
  229. if (fz_lock_debug_contexts[i] == NULL)
  230. {
  231. gottit = 1;
  232. fz_lock_debug_contexts[i] = ctx;
  233. }
  234. ctx->locks->unlock(ctx->locks->user, FZ_LOCK_ALLOC);
  235. if (gottit)
  236. return i;
  237. }
  238. }
  239. return -1;
  240. }
  241. void
  242. fz_assert_lock_held(fz_context *ctx, int lock)
  243. {
  244. int idx = find_context(ctx);
  245. if (idx < 0)
  246. return;
  247. if (fz_locks_debug[idx][lock] == 0)
  248. fprintf(stderr, "Lock %d not held when expected\n", lock);
  249. }
  250. void
  251. fz_assert_lock_not_held(fz_context *ctx, int lock)
  252. {
  253. int idx = find_context(ctx);
  254. if (idx < 0)
  255. return;
  256. if (fz_locks_debug[idx][lock] != 0)
  257. fprintf(stderr, "Lock %d held when not expected\n", lock);
  258. }
  259. void fz_lock_debug_lock(fz_context *ctx, int lock)
  260. {
  261. int i;
  262. int idx = find_context(ctx);
  263. if (idx < 0)
  264. return;
  265. if (fz_locks_debug[idx][lock] != 0)
  266. {
  267. fprintf(stderr, "Attempt to take lock %d when held already!\n", lock);
  268. }
  269. for (i = lock-1; i >= 0; i--)
  270. {
  271. if (fz_locks_debug[idx][i] != 0)
  272. {
  273. fprintf(stderr, "Lock ordering violation: Attempt to take lock %d when %d held already!\n", lock, i);
  274. }
  275. }
  276. fz_locks_debug[idx][lock] = 1;
  277. }
  278. void fz_lock_debug_unlock(fz_context *ctx, int lock)
  279. {
  280. int idx = find_context(ctx);
  281. if (idx < 0)
  282. return;
  283. if (fz_locks_debug[idx][lock] == 0)
  284. {
  285. fprintf(stderr, "Attempt to release lock %d when not held!\n", lock);
  286. }
  287. fz_locks_debug[idx][lock] = 0;
  288. }
  289. #endif