OpenBSD_malloc_Linux.c 44 KB

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