OpenBSD_malloc_Linux.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995
  1. /* Version 1.83 for Linux.
  2. * Compilation: gcc -shared -fPIC -O2 OpenBSD_malloc_Linux.c -o malloc.so
  3. * Launching: LD_PRELOAD=/path/to/malloc.so firefox
  4. */
  5. /* $OpenBSD: malloc.c,v 1.83 2006/05/14 19:53:40 otto Exp $ */
  6. /*
  7. * ----------------------------------------------------------------------------
  8. * "THE BEER-WARE LICENSE" (Revision 42):
  9. * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
  10. * can do whatever you want with this stuff. If we meet some day, and you think
  11. * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
  12. * ----------------------------------------------------------------------------
  13. */
  14. /*
  15. * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
  16. * related to internal conditions and consistency in malloc.c. This has
  17. * a noticeable runtime performance hit, and generally will not do you
  18. * any good unless you fiddle with the internals of malloc or want
  19. * to catch random pointer corruption as early as possible.
  20. */
  21. #ifndef MALLOC_EXTRA_SANITY
  22. #undef MALLOC_EXTRA_SANITY
  23. #endif
  24. /*
  25. * Defining MALLOC_STATS will enable you to call malloc_dump() and set
  26. * the [dD] options in the MALLOC_OPTIONS environment variable.
  27. * It has no run-time performance hit, but does pull in stdio...
  28. */
  29. #ifndef MALLOC_STATS
  30. #undef MALLOC_STATS
  31. #endif
  32. /*
  33. * What to use for Junk. This is the byte value we use to fill with
  34. * when the 'J' option is enabled.
  35. */
  36. #define SOME_JUNK 0xd0 /* as in "Duh" :-) */
  37. #include <sys/types.h>
  38. #include <sys/time.h>
  39. #include <sys/resource.h>
  40. #include <sys/param.h>
  41. #include <sys/mman.h>
  42. #include <sys/uio.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <unistd.h>
  47. #include <fcntl.h>
  48. #include <limits.h>
  49. #include <errno.h>
  50. #include <err.h>
  51. //#include "thread_private.h"
  52. /*
  53. * The basic parameters you can tweak.
  54. *
  55. * malloc_pageshift pagesize = 1 << malloc_pageshift
  56. * It's probably best if this is the native
  57. * page size, but it shouldn't have to be.
  58. *
  59. * malloc_minsize minimum size of an allocation in bytes.
  60. * If this is too small it's too much work
  61. * to manage them. This is also the smallest
  62. * unit of alignment used for the storage
  63. * returned by malloc/realloc.
  64. *
  65. */
  66. static int align = 0;
  67. static size_t g_alignment = 0;
  68. extern int __libc_enable_secure;
  69. static int issetugid(void)
  70. {
  71. if (__libc_enable_secure) return 1;
  72. if (getuid() != geteuid()) return 1;
  73. if (getgid() != getegid()) return 1;
  74. return 0;
  75. }
  76. #define PGSHIFT 12
  77. #define MADV_FREE MADV_DONTNEED
  78. #include <pthread.h>
  79. static pthread_mutex_t gen_mutex = PTHREAD_MUTEX_INITIALIZER;
  80. #define _MALLOC_LOCK_INIT() {;}
  81. #define _MALLOC_LOCK() {pthread_mutex_lock(&gen_mutex);}
  82. #define _MALLOC_UNLOCK() {pthread_mutex_unlock(&gen_mutex);}
  83. #if defined(__sparc__)
  84. #define malloc_pageshift 13U
  85. #endif /* __sparc__ */
  86. #ifndef malloc_pageshift
  87. #define malloc_pageshift (PGSHIFT)
  88. #endif
  89. /*
  90. * No user serviceable parts behind this point.
  91. *
  92. * This structure describes a page worth of chunks.
  93. */
  94. struct pginfo {
  95. struct pginfo *next; /* next on the free list */
  96. void *page; /* Pointer to the page */
  97. u_short size; /* size of this page's chunks */
  98. u_short shift; /* How far to shift for this size chunks */
  99. u_short free; /* How many free chunks */
  100. u_short total; /* How many chunk */
  101. u_long bits[1];/* Which chunks are free */
  102. };
  103. /* How many bits per u_long in the bitmap */
  104. #define MALLOC_BITS (NBBY * sizeof(u_long))
  105. /*
  106. * This structure describes a number of free pages.
  107. */
  108. struct pgfree {
  109. struct pgfree *next; /* next run of free pages */
  110. struct pgfree *prev; /* prev run of free pages */
  111. void *page; /* pointer to free pages */
  112. void *pdir; /* pointer to the base page's dir */
  113. size_t size; /* number of bytes free */
  114. };
  115. /*
  116. * Magic values to put in the page_directory
  117. */
  118. #define MALLOC_NOT_MINE ((struct pginfo*) 0)
  119. #define MALLOC_FREE ((struct pginfo*) 1)
  120. #define MALLOC_FIRST ((struct pginfo*) 2)
  121. #define MALLOC_FOLLOW ((struct pginfo*) 3)
  122. #define MALLOC_MAGIC ((struct pginfo*) 4)
  123. #ifndef malloc_minsize
  124. #define malloc_minsize 16UL
  125. #endif
  126. #if !defined(malloc_pagesize)
  127. #define malloc_pagesize (1UL<<malloc_pageshift)
  128. #endif
  129. #if ((1UL<<malloc_pageshift) != malloc_pagesize)
  130. #error "(1UL<<malloc_pageshift) != malloc_pagesize"
  131. #endif
  132. #ifndef malloc_maxsize
  133. #define malloc_maxsize ((malloc_pagesize)>>1)
  134. #endif
  135. /* A mask for the offset inside a page. */
  136. #define malloc_pagemask ((malloc_pagesize)-1)
  137. #define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
  138. #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
  139. #define index2ptr(idx) ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift))
  140. /* Set when initialization has been done */
  141. static unsigned int malloc_started;
  142. /* Number of free pages we cache */
  143. static unsigned int malloc_cache = 16;
  144. /* Structure used for linking discrete directory pages. */
  145. struct pdinfo {
  146. struct pginfo **base;
  147. struct pdinfo *prev;
  148. struct pdinfo *next;
  149. u_long dirnum;
  150. };
  151. static struct pdinfo *last_dir; /* Caches to the last and previous */
  152. static struct pdinfo *prev_dir; /* referenced directory pages. */
  153. static size_t pdi_off;
  154. static u_long pdi_mod;
  155. #define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
  156. #define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
  157. #define PI_IDX(index) ((index) / pdi_mod)
  158. #define PI_OFF(index) ((index) % pdi_mod)
  159. /* The last index in the page directory we care about */
  160. static u_long last_index;
  161. /* Pointer to page directory. Allocated "as if with" malloc */
  162. static struct pginfo **page_dir;
  163. /* Free pages line up here */
  164. static struct pgfree free_list;
  165. /* Abort(), user doesn't handle problems. */
  166. static int malloc_abort = 2;
  167. /* Are we trying to die ? */
  168. static int suicide;
  169. #ifdef MALLOC_STATS
  170. /* dump statistics */
  171. static int malloc_stats;
  172. #endif
  173. /* avoid outputting warnings? */
  174. static int malloc_silent;
  175. /* always realloc ? */
  176. static int malloc_realloc;
  177. /* mprotect free pages PROT_NONE? */
  178. static int malloc_freeprot;
  179. /* use guard pages after allocations? */
  180. static size_t malloc_guard = 0;
  181. static size_t malloc_guarded;
  182. /* align pointers to end of page? */
  183. static int malloc_ptrguard;
  184. static int malloc_hint = 1;
  185. /* xmalloc behaviour ? */
  186. static int malloc_xmalloc;
  187. /* zero fill ? */
  188. static int malloc_zero;
  189. /* junk fill ? */
  190. static int malloc_junk;
  191. #ifdef __FreeBSD__
  192. /* utrace ? */
  193. static int malloc_utrace;
  194. struct ut {
  195. void *p;
  196. size_t s;
  197. void *r;
  198. };
  199. void utrace(struct ut *, int);
  200. #define UTRACE(a, b, c) \
  201. if (malloc_utrace) \
  202. {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
  203. #else /* !__FreeBSD__ */
  204. #define UTRACE(a,b,c)
  205. #endif
  206. /* Status of malloc. */
  207. static int malloc_active;
  208. /* Allocated memory. */
  209. static size_t malloc_used;
  210. /* My last break. */
  211. static caddr_t malloc_brk;
  212. /* One location cache for free-list holders. */
  213. static struct pgfree *px;
  214. /* Compile-time options. */
  215. char *malloc_options;
  216. /* Name of the current public function. */
  217. static char *malloc_func;
  218. #define MMAP(size) \
  219. mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
  220. -1, (off_t)0)
  221. /*
  222. * Necessary function declarations.
  223. */
  224. static void *imalloc(size_t size);
  225. static void ifree(void *ptr);
  226. static void *irealloc(void *ptr, size_t size);
  227. static void *malloc_bytes(size_t size);
  228. /*
  229. * Function for page directory lookup.
  230. */
  231. static int
  232. pdir_lookup(u_long index, struct pdinfo ** pdi)
  233. {
  234. struct pdinfo *spi;
  235. u_long pidx = PI_IDX(index);
  236. if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
  237. *pdi = last_dir;
  238. else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
  239. *pdi = prev_dir;
  240. else if (last_dir != NULL && prev_dir != NULL) {
  241. if ((PD_IDX(last_dir->dirnum) > pidx) ?
  242. (PD_IDX(last_dir->dirnum) - pidx) :
  243. (pidx - PD_IDX(last_dir->dirnum))
  244. < (PD_IDX(prev_dir->dirnum) > pidx) ?
  245. (PD_IDX(prev_dir->dirnum) - pidx) :
  246. (pidx - PD_IDX(prev_dir->dirnum)))
  247. *pdi = last_dir;
  248. else
  249. *pdi = prev_dir;
  250. if (PD_IDX((*pdi)->dirnum) > pidx) {
  251. for (spi = (*pdi)->prev;
  252. spi != NULL && PD_IDX(spi->dirnum) > pidx;
  253. spi = spi->prev)
  254. *pdi = spi;
  255. if (spi != NULL)
  256. *pdi = spi;
  257. } else
  258. for (spi = (*pdi)->next;
  259. spi != NULL && PD_IDX(spi->dirnum) <= pidx;
  260. spi = spi->next)
  261. *pdi = spi;
  262. } else {
  263. *pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
  264. for (spi = *pdi;
  265. spi != NULL && PD_IDX(spi->dirnum) <= pidx;
  266. spi = spi->next)
  267. *pdi = spi;
  268. }
  269. return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 :
  270. (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1);
  271. }
  272. #ifdef MALLOC_STATS
  273. void
  274. malloc_dump(int fd)
  275. {
  276. char buf[1024];
  277. struct pginfo **pd;
  278. struct pgfree *pf;
  279. struct pdinfo *pi;
  280. u_long j;
  281. pd = page_dir;
  282. pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);
  283. /* print out all the pages */
  284. for (j = 0; j <= last_index;) {
  285. snprintf(buf, sizeof buf, "%08lx %5lu ", j << malloc_pageshift, j);
  286. write(fd, buf, strlen(buf));
  287. if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
  288. for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
  289. if (!PI_OFF(++j)) {
  290. if ((pi = pi->next) == NULL ||
  291. PD_IDX(pi->dirnum) != PI_IDX(j))
  292. break;
  293. pd = pi->base;
  294. j += pdi_mod;
  295. }
  296. }
  297. j--;
  298. snprintf(buf, sizeof buf, ".. %5lu not mine\n", j);
  299. write(fd, buf, strlen(buf));
  300. } else if (pd[PI_OFF(j)] == MALLOC_FREE) {
  301. for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
  302. if (!PI_OFF(++j)) {
  303. if ((pi = pi->next) == NULL ||
  304. PD_IDX(pi->dirnum) != PI_IDX(j))
  305. break;
  306. pd = pi->base;
  307. j += pdi_mod;
  308. }
  309. }
  310. j--;
  311. snprintf(buf, sizeof buf, ".. %5lu free\n", j);
  312. write(fd, buf, strlen(buf));
  313. } else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
  314. for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
  315. if (!PI_OFF(++j)) {
  316. if ((pi = pi->next) == NULL ||
  317. PD_IDX(pi->dirnum) != PI_IDX(j))
  318. break;
  319. pd = pi->base;
  320. j += pdi_mod;
  321. }
  322. }
  323. j--;
  324. snprintf(buf, sizeof buf, ".. %5lu in use\n", j);
  325. write(fd, buf, strlen(buf));
  326. } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
  327. snprintf(buf, sizeof buf, "(%p)\n", pd[PI_OFF(j)]);
  328. write(fd, buf, strlen(buf));
  329. } else {
  330. snprintf(buf, sizeof buf, "%p %d (of %d) x %d @ %p --> %p\n",
  331. pd[PI_OFF(j)], pd[PI_OFF(j)]->free,
  332. pd[PI_OFF(j)]->total, pd[PI_OFF(j)]->size,
  333. pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
  334. write(fd, buf, strlen(buf));
  335. }
  336. if (!PI_OFF(++j)) {
  337. if ((pi = pi->next) == NULL)
  338. break;
  339. pd = pi->base;
  340. j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod;
  341. }
  342. }
  343. for (pf = free_list.next; pf; pf = pf->next) {
  344. snprintf(buf, sizeof buf, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
  345. pf, pf->page, (char *)pf->page + pf->size,
  346. pf->size, pf->prev, pf->next);
  347. write(fd, buf, strlen(buf));
  348. if (pf == pf->next) {
  349. snprintf(buf, sizeof buf, "Free_list loops\n");
  350. write(fd, buf, strlen(buf));
  351. break;
  352. }
  353. }
  354. /* print out various info */
  355. snprintf(buf, sizeof buf, "Minsize\t%lu\n", malloc_minsize);
  356. write(fd, buf, strlen(buf));
  357. snprintf(buf, sizeof buf, "Maxsize\t%lu\n", malloc_maxsize);
  358. write(fd, buf, strlen(buf));
  359. snprintf(buf, sizeof buf, "Pagesize\t%lu\n", malloc_pagesize);
  360. write(fd, buf, strlen(buf));
  361. snprintf(buf, sizeof buf, "Pageshift\t%u\n", malloc_pageshift);
  362. write(fd, buf, strlen(buf));
  363. snprintf(buf, sizeof buf, "In use\t%lu\n", (u_long) malloc_used);
  364. write(fd, buf, strlen(buf));
  365. snprintf(buf, sizeof buf, "Guarded\t%lu\n", (u_long) malloc_guarded);
  366. write(fd, buf, strlen(buf));
  367. }
  368. #endif /* MALLOC_STATS */
  369. extern char *__progname;
  370. static void
  371. wrterror(char *p)
  372. {
  373. char *q = " error: ";
  374. struct iovec iov[5];
  375. iov[0].iov_base = __progname;
  376. iov[0].iov_len = strlen(__progname);
  377. iov[1].iov_base = malloc_func;
  378. iov[1].iov_len = strlen(malloc_func);
  379. iov[2].iov_base = q;
  380. iov[2].iov_len = strlen(q);
  381. iov[3].iov_base = p;
  382. iov[3].iov_len = strlen(p);
  383. iov[4].iov_base = "\n";
  384. iov[4].iov_len = 1;
  385. writev(STDERR_FILENO, iov, 5);
  386. suicide = 1;
  387. #ifdef MALLOC_STATS
  388. if (malloc_stats)
  389. malloc_dump(STDERR_FILENO);
  390. #endif /* MALLOC_STATS */
  391. malloc_active--;
  392. if (malloc_abort)
  393. abort();
  394. }
  395. static void
  396. wrtwarning(char *p)
  397. {
  398. char *q = " warning: ";
  399. struct iovec iov[5];
  400. if (malloc_abort)
  401. wrterror(p);
  402. else if (malloc_silent)
  403. return;
  404. iov[0].iov_base = __progname;
  405. iov[0].iov_len = strlen(__progname);
  406. iov[1].iov_base = malloc_func;
  407. iov[1].iov_len = strlen(malloc_func);
  408. iov[2].iov_base = q;
  409. iov[2].iov_len = strlen(q);
  410. iov[3].iov_base = p;
  411. iov[3].iov_len = strlen(p);
  412. iov[4].iov_base = "\n";
  413. iov[4].iov_len = 1;
  414. writev(STDERR_FILENO, iov, 5);
  415. }
  416. #ifdef MALLOC_STATS
  417. static void
  418. malloc_exit(void)
  419. {
  420. char *q = "malloc() warning: Couldn't dump stats\n";
  421. int save_errno = errno, fd;
  422. fd = open("malloc.out", O_RDWR|O_APPEND);
  423. if (fd != -1) {
  424. malloc_dump(fd);
  425. close(fd);
  426. } else
  427. write(STDERR_FILENO, q, strlen(q));
  428. errno = save_errno;
  429. }
  430. #endif /* MALLOC_STATS */
  431. /*
  432. * Allocate aligned mmaped chunk
  433. */
  434. static void *MMAP_A(size_t pages, size_t alignment)
  435. {
  436. void *j;
  437. if (pages%malloc_pagesize != 0)
  438. pages = pages - pages%malloc_pagesize + malloc_pagesize;
  439. size_t first_size = pages + alignment - malloc_pagesize;
  440. void *p = MMAP(first_size);
  441. size_t rest = ((size_t)p) % alignment;
  442. j = (rest == 0) ? p : (void*) ((size_t)p + alignment - rest);
  443. size_t begin = (size_t)j - (size_t)p;
  444. if (begin != 0) munmap(p, begin);
  445. size_t end = (size_t)p + first_size - ((size_t)j + pages);
  446. if(end != 0) munmap( (void*) ((size_t)j + pages), end);
  447. return j;
  448. }
  449. /*
  450. * Allocate a number of pages from the OS
  451. */
  452. static void *
  453. map_pages(size_t pages)
  454. {
  455. struct pdinfo *pi, *spi;
  456. struct pginfo **pd;
  457. u_long idx, pidx, lidx;
  458. caddr_t result, tail;
  459. u_long index, lindex;
  460. void *pdregion = NULL;
  461. size_t dirs, cnt;
  462. pages <<= malloc_pageshift;
  463. if (!align)
  464. result = MMAP(pages + malloc_guard);
  465. else {
  466. result = MMAP_A(pages + malloc_guard, g_alignment);
  467. }
  468. if (result == MAP_FAILED) {
  469. #ifdef MALLOC_EXTRA_SANITY
  470. wrtwarning("(ES): map_pages fails");
  471. #endif /* MALLOC_EXTRA_SANITY */
  472. errno = ENOMEM;
  473. return (NULL);
  474. }
  475. index = ptr2index(result);
  476. tail = result + pages + malloc_guard;
  477. lindex = ptr2index(tail) - 1;
  478. if (malloc_guard)
  479. mprotect(result + pages, malloc_guard, PROT_NONE);
  480. pidx = PI_IDX(index);
  481. lidx = PI_IDX(lindex);
  482. if (tail > malloc_brk) {
  483. malloc_brk = tail;
  484. last_index = lindex;
  485. }
  486. dirs = lidx - pidx;
  487. /* Insert directory pages, if needed. */
  488. if (pdir_lookup(index, &pi) != 0)
  489. dirs++;
  490. if (dirs > 0) {
  491. pdregion = MMAP(malloc_pagesize * dirs);
  492. if (pdregion == MAP_FAILED) {
  493. munmap(result, tail - result);
  494. #ifdef MALLOC_EXTRA_SANITY
  495. wrtwarning("(ES): map_pages fails");
  496. #endif
  497. errno = ENOMEM;
  498. return (NULL);
  499. }
  500. }
  501. cnt = 0;
  502. for (idx = pidx, spi = pi; idx <= lidx; idx++) {
  503. if (pi == NULL || PD_IDX(pi->dirnum) != idx) {
  504. pd = (struct pginfo **)((char *)pdregion +
  505. cnt * malloc_pagesize);
  506. cnt++;
  507. memset(pd, 0, malloc_pagesize);
  508. pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);
  509. pi->base = pd;
  510. pi->prev = spi;
  511. pi->next = spi->next;
  512. pi->dirnum = idx * (malloc_pagesize /
  513. sizeof(struct pginfo *));
  514. if (spi->next != NULL)
  515. spi->next->prev = pi;
  516. spi->next = pi;
  517. }
  518. if (idx > pidx && idx < lidx) {
  519. pi->dirnum += pdi_mod;
  520. } else if (idx == pidx) {
  521. if (pidx == lidx) {
  522. pi->dirnum += (u_long)(tail - result) >>
  523. malloc_pageshift;
  524. } else {
  525. pi->dirnum += pdi_mod - PI_OFF(index);
  526. }
  527. } else {
  528. pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
  529. }
  530. #ifdef MALLOC_EXTRA_SANITY
  531. if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) {
  532. wrterror("(ES): pages directory overflow");
  533. errno = EFAULT;
  534. return (NULL);
  535. }
  536. #endif /* MALLOC_EXTRA_SANITY */
  537. if (idx == pidx && pi != last_dir) {
  538. prev_dir = last_dir;
  539. last_dir = pi;
  540. }
  541. spi = pi;
  542. pi = spi->next;
  543. }
  544. #ifdef MALLOC_EXTRA_SANITY
  545. if (cnt > dirs)
  546. wrtwarning("(ES): cnt > dirs");
  547. #endif /* MALLOC_EXTRA_SANITY */
  548. if (cnt < dirs)
  549. munmap((char *)pdregion + cnt * malloc_pagesize,
  550. (dirs - cnt) * malloc_pagesize);
  551. return (result);
  552. }
  553. /*
  554. * Initialize the world
  555. */
  556. static void
  557. malloc_init(void)
  558. {
  559. char *p, b[64];
  560. int i, j, save_errno = errno;
  561. _MALLOC_LOCK_INIT();
  562. #ifdef MALLOC_EXTRA_SANITY
  563. malloc_junk = 1;
  564. #endif /* MALLOC_EXTRA_SANITY */
  565. for (i = 0; i < 3; i++) {
  566. switch (i) {
  567. case 0:
  568. j = readlink("/etc/malloc.conf", b, sizeof b - 1);
  569. if (j <= 0)
  570. continue;
  571. b[j] = '\0';
  572. p = b;
  573. break;
  574. case 1:
  575. if (issetugid() == 0)
  576. p = getenv("MALLOC_OPTIONS");
  577. else
  578. continue;
  579. break;
  580. case 2:
  581. p = malloc_options;
  582. break;
  583. default:
  584. p = NULL;
  585. }
  586. for (; p != NULL && *p != '\0'; p++) {
  587. switch (*p) {
  588. case '>':
  589. malloc_cache <<= 1;
  590. break;
  591. case '<':
  592. malloc_cache >>= 1;
  593. break;
  594. case 'a':
  595. malloc_abort = 0;
  596. break;
  597. case 'A':
  598. malloc_abort = 1;
  599. break;
  600. #ifdef MALLOC_STATS
  601. case 'd':
  602. malloc_stats = 0;
  603. break;
  604. case 'D':
  605. malloc_stats = 1;
  606. break;
  607. #endif /* MALLOC_STATS */
  608. case 'f':
  609. malloc_freeprot = 0;
  610. break;
  611. case 'F':
  612. malloc_freeprot = 1;
  613. break;
  614. case 'g':
  615. malloc_guard = 0;
  616. break;
  617. case 'G':
  618. malloc_guard = malloc_pagesize;
  619. break;
  620. case 'h':
  621. malloc_hint = 0;
  622. break;
  623. case 'H':
  624. malloc_hint = 1;
  625. break;
  626. case 'j':
  627. malloc_junk = 0;
  628. break;
  629. case 'J':
  630. malloc_junk = 1;
  631. break;
  632. case 'n':
  633. malloc_silent = 0;
  634. break;
  635. case 'N':
  636. malloc_silent = 1;
  637. break;
  638. case 'p':
  639. malloc_ptrguard = 0;
  640. break;
  641. case 'P':
  642. malloc_ptrguard = 1;
  643. break;
  644. case 'r':
  645. malloc_realloc = 0;
  646. break;
  647. case 'R':
  648. malloc_realloc = 1;
  649. break;
  650. #ifdef __FreeBSD__
  651. case 'u':
  652. malloc_utrace = 0;
  653. break;
  654. case 'U':
  655. malloc_utrace = 1;
  656. break;
  657. #endif /* __FreeBSD__ */
  658. case 'x':
  659. malloc_xmalloc = 0;
  660. break;
  661. case 'X':
  662. malloc_xmalloc = 1;
  663. break;
  664. case 'z':
  665. malloc_zero = 0;
  666. break;
  667. case 'Z':
  668. malloc_zero = 1;
  669. break;
  670. default:
  671. j = malloc_abort;
  672. malloc_abort = 0;
  673. wrtwarning("unknown char in MALLOC_OPTIONS");
  674. malloc_abort = j;
  675. break;
  676. }
  677. }
  678. }
  679. UTRACE(0, 0, 0);
  680. /*
  681. * We want junk in the entire allocation, and zero only in the part
  682. * the user asked for.
  683. */
  684. if (malloc_zero)
  685. malloc_junk = 1;
  686. #ifdef MALLOC_STATS
  687. if (malloc_stats && (atexit(malloc_exit) == -1))
  688. wrtwarning("atexit(2) failed."
  689. " Will not be able to dump malloc stats on exit");
  690. #endif /* MALLOC_STATS */
  691. /* Allocate one page for the page directory. */
  692. page_dir = (struct pginfo **)MMAP(malloc_pagesize);
  693. if (page_dir == MAP_FAILED) {
  694. wrterror("mmap(2) failed, check limits");
  695. errno = ENOMEM;
  696. return;
  697. }
  698. pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1);
  699. pdi_mod = pdi_off / sizeof(struct pginfo *);
  700. last_dir = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
  701. last_dir->base = page_dir;
  702. last_dir->prev = last_dir->next = NULL;
  703. last_dir->dirnum = malloc_pageshift;
  704. /* Been here, done that. */
  705. malloc_started++;
  706. /* Recalculate the cache size in bytes, and make sure it's nonzero. */
  707. if (!malloc_cache)
  708. malloc_cache++;
  709. malloc_cache <<= malloc_pageshift;
  710. errno = save_errno;
  711. }
  712. /*
  713. * Allocate a number of complete pages
  714. */
  715. static void *
  716. malloc_pages(size_t size)
  717. {
  718. void *p, *delay_free = NULL, *tp;
  719. int i;
  720. struct pginfo **pd;
  721. struct pdinfo *pi;
  722. u_long pidx, index;
  723. struct pgfree *pf;
  724. size = pageround(size) + malloc_guard;
  725. p = NULL;
  726. /* Look for free pages before asking for more */
  727. if (!align)
  728. for (pf = free_list.next; pf; pf = pf->next) {
  729. #ifdef MALLOC_EXTRA_SANITY
  730. if (pf->size & malloc_pagemask) {
  731. wrterror("(ES): junk length entry on free_list");
  732. errno = EFAULT;
  733. return (NULL);
  734. }
  735. if (!pf->size) {
  736. wrterror("(ES): zero length entry on free_list");
  737. errno = EFAULT;
  738. return (NULL);
  739. }
  740. if (pf->page > (pf->page + pf->size)) {
  741. wrterror("(ES): sick entry on free_list");
  742. errno = EFAULT;
  743. return (NULL);
  744. }
  745. if ((pi = pf->pdir) == NULL) {
  746. wrterror("(ES): invalid page directory on free-list");
  747. errno = EFAULT;
  748. return (NULL);
  749. }
  750. if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
  751. wrterror("(ES): directory index mismatch on free-list");
  752. errno = EFAULT;
  753. return (NULL);
  754. }
  755. pd = pi->base;
  756. if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
  757. wrterror("(ES): non-free first page on free-list");
  758. errno = EFAULT;
  759. return (NULL);
  760. }
  761. pidx = PI_IDX(ptr2index((pf->page) + (pf->size)) - 1);
  762. for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
  763. pi = pi->next)
  764. ;
  765. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  766. wrterror("(ES): last page not referenced in page directory");
  767. errno = EFAULT;
  768. return (NULL);
  769. }
  770. pd = pi->base;
  771. if (pd[PI_OFF(ptr2index((pf->page) + (pf->size)) - 1)] != MALLOC_FREE) {
  772. wrterror("(ES): non-free last page on free-list");
  773. errno = EFAULT;
  774. return (NULL);
  775. }
  776. #endif /* MALLOC_EXTRA_SANITY */
  777. if (pf->size < size)
  778. continue;
  779. if (pf->size == size) {
  780. p = pf->page;
  781. pi = pf->pdir;
  782. if (pf->next != NULL)
  783. pf->next->prev = pf->prev;
  784. pf->prev->next = pf->next;
  785. delay_free = pf;
  786. break;
  787. }
  788. p = pf->page;
  789. pf->page = (char *) pf->page + size;
  790. pf->size -= size;
  791. pidx = PI_IDX(ptr2index(pf->page));
  792. for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
  793. pi = pi->next)
  794. ;
  795. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  796. wrterror("(ES): hole in directories");
  797. errno = EFAULT;
  798. return (NULL);
  799. }
  800. tp = pf->pdir;
  801. pf->pdir = pi;
  802. pi = tp;
  803. break;
  804. }
  805. size -= malloc_guard;
  806. #ifdef MALLOC_EXTRA_SANITY
  807. if (p != NULL && pi != NULL) {
  808. pidx = PD_IDX(pi->dirnum);
  809. pd = pi->base;
  810. }
  811. if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
  812. wrterror("(ES): allocated non-free page on free-list");
  813. errno = EFAULT;
  814. return (NULL);
  815. }
  816. #endif /* MALLOC_EXTRA_SANITY */
  817. if (p != NULL && (malloc_guard || malloc_freeprot))
  818. mprotect(p, size, PROT_READ | PROT_WRITE);
  819. size >>= malloc_pageshift;
  820. /* Map new pages */
  821. if (p == NULL)
  822. p = map_pages(size);
  823. if (p != NULL) {
  824. index = ptr2index(p);
  825. pidx = PI_IDX(index);
  826. pdir_lookup(index, &pi);
  827. #ifdef MALLOC_EXTRA_SANITY
  828. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  829. wrterror("(ES): mapped pages not found in directory");
  830. errno = EFAULT;
  831. return (NULL);
  832. }
  833. #endif /* MALLOC_EXTRA_SANITY */
  834. if (pi != last_dir) {
  835. prev_dir = last_dir;
  836. last_dir = pi;
  837. }
  838. pd = pi->base;
  839. pd[PI_OFF(index)] = MALLOC_FIRST;
  840. for (i = 1; i < size; i++) {
  841. if (!PI_OFF(index + i)) {
  842. pidx++;
  843. pi = pi->next;
  844. #ifdef MALLOC_EXTRA_SANITY
  845. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  846. wrterror("(ES): hole in mapped pages directory");
  847. errno = EFAULT;
  848. return (NULL);
  849. }
  850. #endif /* MALLOC_EXTRA_SANITY */
  851. pd = pi->base;
  852. }
  853. pd[PI_OFF(index + i)] = MALLOC_FOLLOW;
  854. }
  855. if (malloc_guard) {
  856. if (!PI_OFF(index + i)) {
  857. pidx++;
  858. pi = pi->next;
  859. #ifdef MALLOC_EXTRA_SANITY
  860. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  861. wrterror("(ES): hole in mapped pages directory");
  862. errno = EFAULT;
  863. return (NULL);
  864. }
  865. #endif /* MALLOC_EXTRA_SANITY */
  866. pd = pi->base;
  867. }
  868. pd[PI_OFF(index + i)] = MALLOC_FIRST;
  869. }
  870. malloc_used += size << malloc_pageshift;
  871. malloc_guarded += malloc_guard;
  872. if (malloc_junk)
  873. memset(p, SOME_JUNK, size << malloc_pageshift);
  874. }
  875. if (delay_free) {
  876. if (px == NULL)
  877. px = delay_free;
  878. else
  879. ifree(delay_free);
  880. }
  881. return (p);
  882. }
  883. /*
  884. * Allocate a page of fragments
  885. */
  886. static __inline__ int
  887. malloc_make_chunks(int bits)
  888. {
  889. struct pginfo *bp, **pd;
  890. struct pdinfo *pi;
  891. #ifdef MALLOC_EXTRA_SANITY
  892. u_long pidx;
  893. #endif /* MALLOC_EXTRA_SANITY */
  894. void *pp;
  895. long i, k;
  896. size_t l;
  897. /* Allocate a new bucket */
  898. pp = malloc_pages((size_t) malloc_pagesize);
  899. if (pp == NULL)
  900. return (0);
  901. /* Find length of admin structure */
  902. l = sizeof *bp - sizeof(u_long);
  903. l += sizeof(u_long) *
  904. (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS);
  905. /* Don't waste more than two chunks on this */
  906. /*
  907. * If we are to allocate a memory protected page for the malloc(0)
  908. * case (when bits=0), it must be from a different page than the
  909. * pginfo page.
  910. * --> Treat it like the big chunk alloc, get a second data page.
  911. */
  912. if (bits != 0 && (1UL << (bits)) <= l + l) {
  913. bp = (struct pginfo *) pp;
  914. } else {
  915. bp = (struct pginfo *) imalloc(l);
  916. if (bp == NULL) {
  917. ifree(pp);
  918. return (0);
  919. }
  920. }
  921. /* memory protect the page allocated in the malloc(0) case */
  922. if (bits == 0) {
  923. bp->size = 0;
  924. bp->shift = 1;
  925. i = malloc_minsize - 1;
  926. while (i >>= 1)
  927. bp->shift++;
  928. bp->total = bp->free = malloc_pagesize >> bp->shift;
  929. bp->page = pp;
  930. k = mprotect(pp, malloc_pagesize, PROT_NONE);
  931. if (k < 0) {
  932. ifree(pp);
  933. ifree(bp);
  934. return (0);
  935. }
  936. } else {
  937. bp->size = (1UL << bits);
  938. bp->shift = bits;
  939. bp->total = bp->free = malloc_pagesize >> bits;
  940. bp->page = pp;
  941. }
  942. /* set all valid bits in the bitmap */
  943. k = bp->total;
  944. i = 0;
  945. /* Do a bunch at a time */
  946. for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS)
  947. bp->bits[i / MALLOC_BITS] = ~0UL;
  948. for (; i < k; i++)
  949. bp->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
  950. k = (long)l;
  951. if (bp == bp->page) {
  952. /* Mark the ones we stole for ourselves */
  953. for (i = 0; k > 0; i++) {
  954. bp->bits[i / MALLOC_BITS] &= ~(1UL << (i % MALLOC_BITS));
  955. bp->free--;
  956. bp->total--;
  957. k -= (1 << bits);
  958. }
  959. }
  960. /* MALLOC_LOCK */
  961. pdir_lookup(ptr2index(pp), &pi);
  962. #ifdef MALLOC_EXTRA_SANITY
  963. pidx = PI_IDX(ptr2index(pp));
  964. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  965. wrterror("(ES): mapped pages not found in directory");
  966. errno = EFAULT;
  967. return (0);
  968. }
  969. #endif /* MALLOC_EXTRA_SANITY */
  970. if (pi != last_dir) {
  971. prev_dir = last_dir;
  972. last_dir = pi;
  973. }
  974. pd = pi->base;
  975. pd[PI_OFF(ptr2index(pp))] = bp;
  976. bp->next = page_dir[bits];
  977. page_dir[bits] = bp;
  978. /* MALLOC_UNLOCK */
  979. return (1);
  980. }
  981. /*
  982. * Allocate a fragment
  983. */
  984. static void *
  985. malloc_bytes(size_t size)
  986. {
  987. int i, j;
  988. size_t k;
  989. u_long u, *lp;
  990. struct pginfo *bp;
  991. /* Don't bother with anything less than this */
  992. /* unless we have a malloc(0) requests */
  993. if (size != 0 && size < malloc_minsize)
  994. size = malloc_minsize;
  995. /* Find the right bucket */
  996. if (size == 0)
  997. j = 0;
  998. else {
  999. j = 1;
  1000. i = size - 1;
  1001. while (i >>= 1)
  1002. j++;
  1003. }
  1004. /* If it's empty, make a page more of that size chunks */
  1005. if (page_dir[j] == NULL && !malloc_make_chunks(j))
  1006. return (NULL);
  1007. bp = page_dir[j];
  1008. /* Find first word of bitmap which isn't empty */
  1009. for (lp = bp->bits; !*lp; lp++);
  1010. /* Find that bit, and tweak it */
  1011. u = 1;
  1012. k = 0;
  1013. while (!(*lp & u)) {
  1014. u += u;
  1015. k++;
  1016. }
  1017. if (malloc_guard) {
  1018. /* Walk to a random position. */
  1019. // i = arc4random() % bp->free;
  1020. i = rand() % bp->free;
  1021. while (i > 0) {
  1022. u += u;
  1023. k++;
  1024. if (k >= MALLOC_BITS) {
  1025. lp++;
  1026. u = 1;
  1027. k = 0;
  1028. }
  1029. #ifdef MALLOC_EXTRA_SANITY
  1030. if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
  1031. wrterror("chunk overflow");
  1032. errno = EFAULT;
  1033. return (NULL);
  1034. }
  1035. #endif /* MALLOC_EXTRA_SANITY */
  1036. if (*lp & u)
  1037. i--;
  1038. }
  1039. }
  1040. *lp ^= u;
  1041. /* If there are no more free, remove from free-list */
  1042. if (!--bp->free) {
  1043. page_dir[j] = bp->next;
  1044. bp->next = NULL;
  1045. }
  1046. /* Adjust to the real offset of that chunk */
  1047. k += (lp - bp->bits) * MALLOC_BITS;
  1048. k <<= bp->shift;
  1049. if (malloc_junk && bp->size != 0)
  1050. memset((char *)bp->page + k, SOME_JUNK, (size_t)bp->size);
  1051. return ((u_char *) bp->page + k);
  1052. }
  1053. /*
  1054. * Magic so that malloc(sizeof(ptr)) is near the end of the page.
  1055. */
  1056. #define PTR_GAP (malloc_pagesize - sizeof(void *))
  1057. #define PTR_SIZE (sizeof(void *))
  1058. #define PTR_ALIGNED(p) (((unsigned long)p & malloc_pagemask) == PTR_GAP)
  1059. /*
  1060. * Allocate a piece of memory
  1061. */
  1062. static void *
  1063. imalloc(size_t size)
  1064. {
  1065. void *result;
  1066. int ptralloc = 0;
  1067. if (!malloc_started)
  1068. malloc_init();
  1069. if (suicide)
  1070. abort();
  1071. /* does not matter if malloc_bytes fails */
  1072. if (px == NULL)
  1073. px = malloc_bytes(sizeof *px);
  1074. if (malloc_ptrguard && size == PTR_SIZE) {
  1075. ptralloc = 1;
  1076. size = malloc_pagesize;
  1077. }
  1078. if ((size + malloc_pagesize) < size) { /* Check for overflow */
  1079. result = NULL;
  1080. errno = ENOMEM;
  1081. } else if (size <= malloc_maxsize)
  1082. result = malloc_bytes(size);
  1083. else
  1084. result = malloc_pages(size);
  1085. if (malloc_abort == 1 && result == NULL)
  1086. wrterror("allocation failed");
  1087. if (malloc_zero && result != NULL)
  1088. memset(result, 0, size);
  1089. if (result && ptralloc)
  1090. return ((char *) result + PTR_GAP);
  1091. return (result);
  1092. }
  1093. /*
  1094. * Change the size of an allocation.
  1095. */
  1096. static void *
  1097. irealloc(void *ptr, size_t size)
  1098. {
  1099. void *p;
  1100. size_t osize;
  1101. u_long index, i;
  1102. struct pginfo **mp;
  1103. struct pginfo **pd;
  1104. struct pdinfo *pi;
  1105. #ifdef MALLOC_EXTRA_SANITY
  1106. u_long pidx;
  1107. #endif /* MALLOC_EXTRA_SANITY */
  1108. if (suicide)
  1109. abort();
  1110. if (!malloc_started) {
  1111. wrtwarning("malloc() has never been called");
  1112. return (NULL);
  1113. }
  1114. if (malloc_ptrguard && PTR_ALIGNED(ptr)) {
  1115. if (size <= PTR_SIZE)
  1116. return (ptr);
  1117. p = imalloc(size);
  1118. if (p)
  1119. memcpy(p, ptr, PTR_SIZE);
  1120. ifree(ptr);
  1121. return (p);
  1122. }
  1123. index = ptr2index(ptr);
  1124. if (index < malloc_pageshift) {
  1125. wrtwarning("junk pointer, too low to make sense");
  1126. return (NULL);
  1127. }
  1128. if (index > last_index) {
  1129. wrtwarning("junk pointer, too high to make sense");
  1130. return (NULL);
  1131. }
  1132. pdir_lookup(index, &pi);
  1133. #ifdef MALLOC_EXTRA_SANITY
  1134. pidx = PI_IDX(index);
  1135. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  1136. wrterror("(ES): mapped pages not found in directory");
  1137. errno = EFAULT;
  1138. return (NULL);
  1139. }
  1140. #endif /* MALLOC_EXTRA_SANITY */
  1141. if (pi != last_dir) {
  1142. prev_dir = last_dir;
  1143. last_dir = pi;
  1144. }
  1145. pd = pi->base;
  1146. mp = &pd[PI_OFF(index)];
  1147. if (*mp == MALLOC_FIRST) { /* Page allocation */
  1148. /* Check the pointer */
  1149. if ((u_long) ptr & malloc_pagemask) {
  1150. wrtwarning("modified (page-) pointer");
  1151. return (NULL);
  1152. }
  1153. /* Find the size in bytes */
  1154. i = index;
  1155. if (!PI_OFF(++i)) {
  1156. pi = pi->next;
  1157. if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
  1158. pi = NULL;
  1159. if (pi != NULL)
  1160. pd = pi->base;
  1161. }
  1162. for (osize = malloc_pagesize;
  1163. pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
  1164. osize += malloc_pagesize;
  1165. if (!PI_OFF(++i)) {
  1166. pi = pi->next;
  1167. if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
  1168. pi = NULL;
  1169. if (pi != NULL)
  1170. pd = pi->base;
  1171. }
  1172. }
  1173. if (!malloc_realloc && size <= osize &&
  1174. size > osize - malloc_pagesize) {
  1175. if (malloc_junk)
  1176. memset((char *)ptr + size, SOME_JUNK, osize - size);
  1177. return (ptr); /* ..don't do anything else. */
  1178. }
  1179. } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
  1180. /* Check the pointer for sane values */
  1181. if ((u_long) ptr & ((1UL << ((*mp)->shift)) - 1)) {
  1182. wrtwarning("modified (chunk-) pointer");
  1183. return (NULL);
  1184. }
  1185. /* Find the chunk index in the page */
  1186. i = ((u_long) ptr & malloc_pagemask) >> (*mp)->shift;
  1187. /* Verify that it isn't a free chunk already */
  1188. if ((*mp)->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
  1189. wrtwarning("chunk is already free");
  1190. return (NULL);
  1191. }
  1192. osize = (*mp)->size;
  1193. if (!malloc_realloc && size <= osize &&
  1194. (size > osize / 2 || osize == malloc_minsize)) {
  1195. if (malloc_junk)
  1196. memset((char *) ptr + size, SOME_JUNK, osize - size);
  1197. return (ptr); /* ..don't do anything else. */
  1198. }
  1199. } else {
  1200. wrtwarning("irealloc: pointer to wrong page");
  1201. return (NULL);
  1202. }
  1203. p = imalloc(size);
  1204. if (p != NULL) {
  1205. /* copy the lesser of the two sizes, and free the old one */
  1206. /* Don't move from/to 0 sized region !!! */
  1207. if (osize != 0 && size != 0) {
  1208. if (osize < size)
  1209. memcpy(p, ptr, osize);
  1210. else
  1211. memcpy(p, ptr, size);
  1212. }
  1213. ifree(ptr);
  1214. }
  1215. return (p);
  1216. }
  1217. /*
  1218. * Free a sequence of pages
  1219. */
  1220. static __inline__ void
  1221. free_pages(void *ptr, u_long index, struct pginfo * info)
  1222. {
  1223. u_long i, pidx, lidx;
  1224. size_t l, cachesize = 0;
  1225. struct pginfo **pd;
  1226. struct pdinfo *pi, *spi;
  1227. struct pgfree *pf, *pt = NULL;
  1228. caddr_t tail;
  1229. if (info == MALLOC_FREE) {
  1230. wrtwarning("page is already free");
  1231. return;
  1232. }
  1233. if (info != MALLOC_FIRST) {
  1234. wrtwarning("free_pages: pointer to wrong page");
  1235. return;
  1236. }
  1237. if ((u_long) ptr & malloc_pagemask) {
  1238. wrtwarning("modified (page-) pointer");
  1239. return;
  1240. }
  1241. /* Count how many pages and mark them free at the same time */
  1242. pidx = PI_IDX(index);
  1243. pdir_lookup(index, &pi);
  1244. #ifdef MALLOC_EXTRA_SANITY
  1245. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  1246. wrterror("(ES): mapped pages not found in directory");
  1247. errno = EFAULT;
  1248. return;
  1249. }
  1250. #endif /* MALLOC_EXTRA_SANITY */
  1251. spi = pi; /* Save page index for start of region. */
  1252. pd = pi->base;
  1253. pd[PI_OFF(index)] = MALLOC_FREE;
  1254. i = 1;
  1255. if (!PI_OFF(index + i)) {
  1256. pi = pi->next;
  1257. if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i))
  1258. pi = NULL;
  1259. else
  1260. pd = pi->base;
  1261. }
  1262. while (pi != NULL && pd[PI_OFF(index + i)] == MALLOC_FOLLOW) {
  1263. pd[PI_OFF(index + i)] = MALLOC_FREE;
  1264. i++;
  1265. if (!PI_OFF(index + i)) {
  1266. if ((pi = pi->next) == NULL ||
  1267. PD_IDX(pi->dirnum) != PI_IDX(index + i))
  1268. pi = NULL;
  1269. else
  1270. pd = pi->base;
  1271. }
  1272. }
  1273. l = i << malloc_pageshift;
  1274. if (malloc_junk)
  1275. memset(ptr, SOME_JUNK, l);
  1276. malloc_used -= l;
  1277. malloc_guarded -= malloc_guard;
  1278. if (malloc_guard) {
  1279. #ifdef MALLOC_EXTRA_SANITY
  1280. if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) {
  1281. wrterror("(ES): hole in mapped pages directory");
  1282. errno = EFAULT;
  1283. return;
  1284. }
  1285. #endif /* MALLOC_EXTRA_SANITY */
  1286. pd[PI_OFF(index + i)] = MALLOC_FREE;
  1287. l += malloc_guard;
  1288. }
  1289. tail = (caddr_t)ptr + l;
  1290. if (malloc_hint)
  1291. madvise(ptr, l, MADV_FREE);
  1292. if (malloc_freeprot)
  1293. mprotect(ptr, l, PROT_NONE);
  1294. /* Add to free-list. */
  1295. if (px == NULL && (px = malloc_bytes(sizeof *px)) == NULL)
  1296. goto not_return;
  1297. px->page = ptr;
  1298. px->pdir = spi;
  1299. px->size = l;
  1300. if (free_list.next == NULL) {
  1301. /* Nothing on free list, put this at head. */
  1302. px->next = NULL;
  1303. px->prev = &free_list;
  1304. free_list.next = px;
  1305. pf = px;
  1306. px = NULL;
  1307. } else {
  1308. /*
  1309. * Find the right spot, leave pf pointing to the modified
  1310. * entry.
  1311. */
  1312. /* Race ahead here, while calculating cache size. */
  1313. for (pf = free_list.next;
  1314. (caddr_t)ptr > ((caddr_t)pf->page + pf->size)
  1315. && pf->next != NULL;
  1316. pf = pf->next)
  1317. cachesize += pf->size;
  1318. /* Finish cache size calculation. */
  1319. pt = pf;
  1320. while (pt) {
  1321. cachesize += pt->size;
  1322. pt = pt->next;
  1323. }
  1324. if ((caddr_t)pf->page > tail) {
  1325. /* Insert before entry */
  1326. px->next = pf;
  1327. px->prev = pf->prev;
  1328. pf->prev = px;
  1329. px->prev->next = px;
  1330. pf = px;
  1331. px = NULL;
  1332. } else if (((caddr_t)pf->page + pf->size) == ptr) {
  1333. /* Append to the previous entry. */
  1334. cachesize -= pf->size;
  1335. pf->size += l;
  1336. if (pf->next != NULL &&
  1337. pf->next->page == ((caddr_t)pf->page + pf->size)) {
  1338. /* And collapse the next too. */
  1339. pt = pf->next;
  1340. pf->size += pt->size;
  1341. pf->next = pt->next;
  1342. if (pf->next != NULL)
  1343. pf->next->prev = pf;
  1344. }
  1345. } else if (pf->page == tail) {
  1346. /* Prepend to entry. */
  1347. cachesize -= pf->size;
  1348. pf->size += l;
  1349. pf->page = ptr;
  1350. pf->pdir = spi;
  1351. } else if (pf->next == NULL) {
  1352. /* Append at tail of chain. */
  1353. px->next = NULL;
  1354. px->prev = pf;
  1355. pf->next = px;
  1356. pf = px;
  1357. px = NULL;
  1358. } else {
  1359. wrterror("freelist is destroyed");
  1360. errno = EFAULT;
  1361. return;
  1362. }
  1363. }
  1364. if (pf->pdir != last_dir) {
  1365. prev_dir = last_dir;
  1366. last_dir = pf->pdir;
  1367. }
  1368. /* Return something to OS ? */
  1369. if (pf->size > (malloc_cache - cachesize)) {
  1370. /*
  1371. * Keep the cache intact. Notice that the '>' above guarantees that
  1372. * the pf will always have at least one page afterwards.
  1373. */
  1374. if (munmap((char *) pf->page + (malloc_cache - cachesize),
  1375. pf->size - (malloc_cache - cachesize)) != 0)
  1376. goto not_return;
  1377. tail = (caddr_t)pf->page + pf->size;
  1378. lidx = ptr2index(tail) - 1;
  1379. pf->size = malloc_cache - cachesize;
  1380. index = ptr2index((caddr_t)pf->page + pf->size);
  1381. pidx = PI_IDX(index);
  1382. if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx)
  1383. prev_dir = NULL; /* Will be wiped out below ! */
  1384. for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
  1385. pi = pi->next)
  1386. ;
  1387. spi = pi;
  1388. if (pi != NULL && PD_IDX(pi->dirnum) == pidx) {
  1389. pd = pi->base;
  1390. for (i = index; i <= lidx;) {
  1391. if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
  1392. pd[PI_OFF(i)] = MALLOC_NOT_MINE;
  1393. #ifdef MALLOC_EXTRA_SANITY
  1394. if (!PD_OFF(pi->dirnum)) {
  1395. wrterror("(ES): pages directory underflow");
  1396. errno = EFAULT;
  1397. return;
  1398. }
  1399. #endif /* MALLOC_EXTRA_SANITY */
  1400. pi->dirnum--;
  1401. }
  1402. #ifdef MALLOC_EXTRA_SANITY
  1403. else
  1404. wrtwarning("(ES): page already unmapped");
  1405. #endif /* MALLOC_EXTRA_SANITY */
  1406. i++;
  1407. if (!PI_OFF(i)) {
  1408. /*
  1409. * If no page in that dir, free
  1410. * directory page.
  1411. */
  1412. if (!PD_OFF(pi->dirnum)) {
  1413. /* Remove from list. */
  1414. if (spi == pi)
  1415. spi = pi->prev;
  1416. if (pi->prev != NULL)
  1417. pi->prev->next = pi->next;
  1418. if (pi->next != NULL)
  1419. pi->next->prev = pi->prev;
  1420. pi = pi->next;
  1421. munmap(pd, malloc_pagesize);
  1422. } else
  1423. pi = pi->next;
  1424. if (pi == NULL ||
  1425. PD_IDX(pi->dirnum) != PI_IDX(i))
  1426. break;
  1427. pd = pi->base;
  1428. }
  1429. }
  1430. if (pi && !PD_OFF(pi->dirnum)) {
  1431. /* Resulting page dir is now empty. */
  1432. /* Remove from list. */
  1433. if (spi == pi) /* Update spi only if first. */
  1434. spi = pi->prev;
  1435. if (pi->prev != NULL)
  1436. pi->prev->next = pi->next;
  1437. if (pi->next != NULL)
  1438. pi->next->prev = pi->prev;
  1439. pi = pi->next;
  1440. munmap(pd, malloc_pagesize);
  1441. }
  1442. }
  1443. if (pi == NULL && malloc_brk == tail) {
  1444. /* Resize down the malloc upper boundary. */
  1445. last_index = index - 1;
  1446. malloc_brk = index2ptr(index);
  1447. }
  1448. /* XXX: We could realloc/shrink the pagedir here I guess. */
  1449. if (pf->size == 0) { /* Remove from free-list as well. */
  1450. if (px)
  1451. ifree(px);
  1452. if ((px = pf->prev) != &free_list) {
  1453. if (pi == NULL && last_index == (index - 1)) {
  1454. if (spi == NULL) {
  1455. malloc_brk = NULL;
  1456. i = 11;
  1457. } else {
  1458. pd = spi->base;
  1459. if (PD_IDX(spi->dirnum) < pidx)
  1460. index =
  1461. ((PD_IDX(spi->dirnum) + 1) *
  1462. pdi_mod) - 1;
  1463. for (pi = spi, i = index;
  1464. pd[PI_OFF(i)] == MALLOC_NOT_MINE;
  1465. i--)
  1466. #ifdef MALLOC_EXTRA_SANITY
  1467. if (!PI_OFF(i)) {
  1468. pi = pi->prev;
  1469. if (pi == NULL || i == 0)
  1470. break;
  1471. pd = pi->base;
  1472. i = (PD_IDX(pi->dirnum) + 1) * pdi_mod;
  1473. }
  1474. #else /* !MALLOC_EXTRA_SANITY */
  1475. {
  1476. }
  1477. #endif /* MALLOC_EXTRA_SANITY */
  1478. malloc_brk = index2ptr(i + 1);
  1479. }
  1480. last_index = i;
  1481. }
  1482. if ((px->next = pf->next) != NULL)
  1483. px->next->prev = px;
  1484. } else {
  1485. if ((free_list.next = pf->next) != NULL)
  1486. free_list.next->prev = &free_list;
  1487. }
  1488. px = pf;
  1489. last_dir = prev_dir;
  1490. prev_dir = NULL;
  1491. }
  1492. }
  1493. not_return:
  1494. if (pt != NULL)
  1495. ifree(pt);
  1496. }
  1497. /*
  1498. * Free a chunk, and possibly the page it's on, if the page becomes empty.
  1499. */
  1500. /* ARGSUSED */
  1501. static __inline__ void
  1502. free_bytes(void *ptr, u_long index, struct pginfo * info)
  1503. {
  1504. struct pginfo **mp, **pd;
  1505. struct pdinfo *pi;
  1506. #ifdef MALLOC_EXTRA_SANITY
  1507. u_long pidx;
  1508. #endif /* MALLOC_EXTRA_SANITY */
  1509. void *vp;
  1510. long i;
  1511. /* Find the chunk number on the page */
  1512. i = ((u_long) ptr & malloc_pagemask) >> info->shift;
  1513. if ((u_long) ptr & ((1UL << (info->shift)) - 1)) {
  1514. wrtwarning("modified (chunk-) pointer");
  1515. return;
  1516. }
  1517. if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
  1518. wrtwarning("chunk is already free");
  1519. return;
  1520. }
  1521. if (malloc_junk && info->size != 0)
  1522. memset(ptr, SOME_JUNK, (size_t)info->size);
  1523. info->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
  1524. info->free++;
  1525. if (info->size != 0)
  1526. mp = page_dir + info->shift;
  1527. else
  1528. mp = page_dir;
  1529. if (info->free == 1) {
  1530. /* Page became non-full */
  1531. /* Insert in address order */
  1532. while (*mp != NULL && (*mp)->next != NULL &&
  1533. (*mp)->next->page < info->page)
  1534. mp = &(*mp)->next;
  1535. info->next = *mp;
  1536. *mp = info;
  1537. return;
  1538. }
  1539. if (info->free != info->total)
  1540. return;
  1541. /* Find & remove this page in the queue */
  1542. while (*mp != info) {
  1543. mp = &((*mp)->next);
  1544. #ifdef MALLOC_EXTRA_SANITY
  1545. if (!*mp) {
  1546. wrterror("(ES): Not on queue");
  1547. errno = EFAULT;
  1548. return;
  1549. }
  1550. #endif /* MALLOC_EXTRA_SANITY */
  1551. }
  1552. *mp = info->next;
  1553. /* Free the page & the info structure if need be */
  1554. pdir_lookup(ptr2index(info->page), &pi);
  1555. #ifdef MALLOC_EXTRA_SANITY
  1556. pidx = PI_IDX(ptr2index(info->page));
  1557. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  1558. wrterror("(ES): mapped pages not found in directory");
  1559. errno = EFAULT;
  1560. return;
  1561. }
  1562. #endif /* MALLOC_EXTRA_SANITY */
  1563. if (pi != last_dir) {
  1564. prev_dir = last_dir;
  1565. last_dir = pi;
  1566. }
  1567. pd = pi->base;
  1568. pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;
  1569. /* If the page was mprotected, unprotect it before releasing it */
  1570. if (info->size == 0)
  1571. mprotect(info->page, malloc_pagesize, PROT_READ | PROT_WRITE);
  1572. vp = info->page; /* Order is important ! */
  1573. if (vp != (void *) info)
  1574. ifree(info);
  1575. ifree(vp);
  1576. }
  1577. static void
  1578. ifree(void *ptr)
  1579. {
  1580. struct pginfo *info, **pd;
  1581. u_long index;
  1582. #ifdef MALLOC_EXTRA_SANITY
  1583. u_long pidx;
  1584. #endif /* MALLOC_EXTRA_SANITY */
  1585. struct pdinfo *pi;
  1586. if (!malloc_started) {
  1587. wrtwarning("malloc() has never been called");
  1588. return;
  1589. }
  1590. /* If we're already sinking, don't make matters any worse. */
  1591. if (suicide)
  1592. return;
  1593. if (malloc_ptrguard && PTR_ALIGNED(ptr))
  1594. ptr = (char *) ptr - PTR_GAP;
  1595. index = ptr2index(ptr);
  1596. if (index < malloc_pageshift) {
  1597. warnx("(%p)", ptr);
  1598. wrtwarning("ifree: junk pointer, too low to make sense");
  1599. return;
  1600. }
  1601. if (index > last_index) {
  1602. warnx("(%p)", ptr);
  1603. wrtwarning("ifree: junk pointer, too high to make sense");
  1604. return;
  1605. }
  1606. pdir_lookup(index, &pi);
  1607. #ifdef MALLOC_EXTRA_SANITY
  1608. pidx = PI_IDX(index);
  1609. if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
  1610. wrterror("(ES): mapped pages not found in directory");
  1611. errno = EFAULT;
  1612. return;
  1613. }
  1614. #endif /* MALLOC_EXTRA_SANITY */
  1615. if (pi != last_dir) {
  1616. prev_dir = last_dir;
  1617. last_dir = pi;
  1618. }
  1619. pd = pi->base;
  1620. info = pd[PI_OFF(index)];
  1621. if (info < MALLOC_MAGIC)
  1622. free_pages(ptr, index, info);
  1623. else
  1624. free_bytes(ptr, index, info);
  1625. /* does not matter if malloc_bytes fails */
  1626. if (px == NULL)
  1627. px = malloc_bytes(sizeof *px);
  1628. return;
  1629. }
  1630. /*
  1631. * Common function for handling recursion. Only
  1632. * print the error message once, to avoid making the problem
  1633. * potentially worse.
  1634. */
  1635. static void
  1636. malloc_recurse(void)
  1637. {
  1638. static int noprint;
  1639. if (noprint == 0) {
  1640. noprint = 1;
  1641. wrtwarning("recursive call");
  1642. }
  1643. malloc_active--;
  1644. _MALLOC_UNLOCK();
  1645. errno = EDEADLK;
  1646. }
  1647. /*
  1648. * These are the public exported interface routines.
  1649. */
  1650. void *
  1651. malloc(size_t size)
  1652. {
  1653. void *r;
  1654. if (!align)
  1655. _MALLOC_LOCK();
  1656. malloc_func = " in malloc():";
  1657. if (malloc_active++) {
  1658. malloc_recurse();
  1659. return (NULL);
  1660. }
  1661. r = imalloc(size);
  1662. UTRACE(0, size, r);
  1663. malloc_active--;
  1664. if (!align)
  1665. _MALLOC_UNLOCK();
  1666. if (malloc_xmalloc && r == NULL) {
  1667. wrterror("out of memory");
  1668. errno = ENOMEM;
  1669. }
  1670. return (r);
  1671. }
  1672. void
  1673. free(void *ptr)
  1674. {
  1675. /* This is legal. XXX quick path */
  1676. if (ptr == NULL)
  1677. return;
  1678. _MALLOC_LOCK();
  1679. malloc_func = " in free():";
  1680. if (malloc_active++) {
  1681. malloc_recurse();
  1682. return;
  1683. }
  1684. ifree(ptr);
  1685. UTRACE(ptr, 0, 0);
  1686. malloc_active--;
  1687. _MALLOC_UNLOCK();
  1688. return;
  1689. }
  1690. void *
  1691. realloc(void *ptr, size_t size)
  1692. {
  1693. void *r;
  1694. _MALLOC_LOCK();
  1695. malloc_func = " in realloc():";
  1696. if (malloc_active++) {
  1697. malloc_recurse();
  1698. return (NULL);
  1699. }
  1700. if (ptr == NULL)
  1701. r = imalloc(size);
  1702. else
  1703. r = irealloc(ptr, size);
  1704. UTRACE(ptr, size, r);
  1705. malloc_active--;
  1706. _MALLOC_UNLOCK();
  1707. if (malloc_xmalloc && r == NULL) {
  1708. wrterror("out of memory");
  1709. errno = ENOMEM;
  1710. }
  1711. return (r);
  1712. }
  1713. #if defined(__i386__)||defined(__arm__)||defined(__powerpc__)
  1714. #define SIZE_MAX 0xffffffff
  1715. #endif
  1716. #if defined(__x86_64__)
  1717. #define SIZE_MAX 0xffffffffffffffff
  1718. #endif
  1719. void *
  1720. calloc(size_t num, size_t size)
  1721. {
  1722. void *p;
  1723. if (num && SIZE_MAX / num < size) {
  1724. fprintf(stderr,"OOOOPS");
  1725. errno = ENOMEM;
  1726. return NULL;
  1727. }
  1728. size *= num;
  1729. p = malloc(size);
  1730. if (p)
  1731. memset(p, 0, size);
  1732. return(p);
  1733. }
  1734. static int ispowerof2 (size_t a) {
  1735. size_t b;
  1736. for (b = 1ULL << (sizeof(size_t)*NBBY - 1); b > 1; b >>= 1)
  1737. if (b == a)
  1738. return 1;
  1739. return 0;
  1740. }
  1741. int posix_memalign(void **memptr, size_t alignment, size_t size)
  1742. {
  1743. void *r;
  1744. if ((alignment < PTR_SIZE) || (alignment%PTR_SIZE != 0)) return EINVAL;
  1745. if (!ispowerof2(alignment)) return EINVAL;
  1746. if (alignment < malloc_minsize) alignment = malloc_minsize;
  1747. size_t max = alignment > size ? alignment : size;
  1748. if (alignment <= malloc_pagesize)
  1749. r = malloc(max);
  1750. else {
  1751. _MALLOC_LOCK();
  1752. align = 1;
  1753. g_alignment = alignment;
  1754. r = malloc(size);
  1755. align=0;
  1756. _MALLOC_UNLOCK();
  1757. }
  1758. *memptr = r;
  1759. if (!r) return ENOMEM;
  1760. return 0;
  1761. }
  1762. void *memalign(size_t boundary, size_t size)
  1763. {
  1764. void *r;
  1765. posix_memalign(&r, boundary, size);
  1766. return r;
  1767. }
  1768. void *valloc(size_t size)
  1769. {
  1770. void *r;
  1771. posix_memalign(&r, malloc_pagesize, size);
  1772. return r;
  1773. }