qmalloc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * malloc
  11. *
  12. * Uses Quickfit (see SIGPLAN Notices October 1988)
  13. * with allocator from Kernighan & Ritchie
  14. *
  15. * This is a placeholder.
  16. */
  17. #include "u.h"
  18. #include "../port/lib.h"
  19. #include "mem.h"
  20. #include "dat.h"
  21. #include "fns.h"
  22. #include <pool.h>
  23. typedef double Align;
  24. typedef union Header Header;
  25. typedef struct Qlist Qlist;
  26. union Header {
  27. struct {
  28. Header* next;
  29. uint size;
  30. } s;
  31. Align al;
  32. };
  33. struct Qlist {
  34. Lock lk;
  35. Header* first;
  36. uint nalloc;
  37. };
  38. enum {
  39. Unitsz = sizeof(Header), /* 16 bytes on amd64 */
  40. };
  41. #define NUNITS(n) (HOWMANY(n, Unitsz) + 1)
  42. #define NQUICK ((512/Unitsz)+1) /* 33 on amd64 */
  43. static Qlist quicklist[NQUICK+1];
  44. static Header misclist;
  45. static Header *rover;
  46. static unsigned tailsize;
  47. static unsigned tailnunits;
  48. static Header *tailbase;
  49. static Header *tailptr;
  50. static Header checkval;
  51. static int morecore(unsigned);
  52. enum
  53. {
  54. QSmalign = 0,
  55. QSmalignquick,
  56. QSmalignrover,
  57. QSmalignfront,
  58. QSmalignback,
  59. QSmaligntail,
  60. QSmalignnottail,
  61. QSmalloc,
  62. QSmallocrover,
  63. QSmalloctail,
  64. QSfree,
  65. QSfreetail,
  66. QSfreequick,
  67. QSfreenext,
  68. QSfreeprev,
  69. QSmax
  70. };
  71. static void qfreeinternal(void*);
  72. static int qstats[QSmax];
  73. static char* qstatstr[QSmax] = {
  74. [QSmalign] "malign",
  75. [QSmalignquick] "malignquick",
  76. [QSmalignrover] "malignrover",
  77. [QSmalignfront] "malignfront",
  78. [QSmalignback] "malignback",
  79. [QSmaligntail] "maligntail",
  80. [QSmalignnottail] "malignnottail",
  81. [QSmalloc] "malloc",
  82. [QSmallocrover] "mallocrover",
  83. [QSmalloctail] "malloctail",
  84. [QSfree] "free",
  85. [QSfreetail] "freetail",
  86. [QSfreequick] "freequick",
  87. [QSfreenext] "freenext",
  88. [QSfreeprev] "freeprev",
  89. };
  90. static Lock mainlock;
  91. #define MLOCK ilock(&mainlock)
  92. #define MUNLOCK iunlock(&mainlock)
  93. #define QLOCK(l) ilock(l)
  94. #define QUNLOCK(l) iunlock(l)
  95. #define tailalloc(p, n) ((p)=tailptr, tailsize -= (n), tailptr+=(n),\
  96. (p)->s.size=(n), (p)->s.next = &checkval)
  97. #define ISPOWEROF2(x) (/*((x) != 0) && */!((x) & ((x)-1)))
  98. #define ALIGNHDR(h, a) (Header*)((((uintptr)(h))+((a)-1)) & ~((a)-1))
  99. /*
  100. * From libc malloc.c to *draw devices
  101. */
  102. static void* sbrkalloc(uint32_t);
  103. static int sbrkmerge(void*, void*);
  104. static void poolprint(Pool*, char*, ...);
  105. static void ppanic(Pool*, char*, ...);
  106. static void plock(Pool*);
  107. static void punlock(Pool*);
  108. extern void abort(void);
  109. extern void* sbrk(uint32_t);
  110. typedef struct Private Private;
  111. struct Private {
  112. Lock lk;
  113. char* end;
  114. char msg[256]; /* a rock for messages to be printed at unlock */
  115. };
  116. static Private pmainpriv;
  117. static Pool pmainmem = {
  118. .name= "Main",
  119. .maxsize= 4*1024*1024,
  120. .minarena= 128*1024,
  121. .quantum= 32,
  122. .alloc= sbrkalloc,
  123. .merge= sbrkmerge,
  124. .flags= /*POOL_TOLERANCE|POOL_ANTAGONISM|POOL_PARANOIA|*/0,
  125. .lock= plock,
  126. .unlock= punlock,
  127. .print= poolprint,
  128. .panic= ppanic,
  129. .private= &pmainpriv,
  130. };
  131. static Private pimagpriv;
  132. static Pool pimagmem = {
  133. .name= "Image",
  134. .maxsize= 16*1024*1024,
  135. .minarena= 2*1024*1024,
  136. .quantum= 32,
  137. .alloc= sbrkalloc,
  138. .merge= sbrkmerge,
  139. .flags= 0,
  140. .lock= plock,
  141. .unlock= punlock,
  142. .print= poolprint,
  143. .panic= ppanic,
  144. .private= &pimagpriv,
  145. };
  146. Pool* mainmem = &pmainmem;
  147. Pool* imagmem = &pimagmem;
  148. /*
  149. * we do minimal bookkeeping so we can tell pool
  150. * whether two blocks are adjacent and thus mergeable.
  151. */
  152. static void*
  153. sbrkalloc(uint32_t n)
  154. {
  155. uint32_t *x;
  156. n += 2*sizeof(uint32_t); /* two longs for us */
  157. x = sbrk(n);
  158. if(x == (void*)-1)
  159. return nil;
  160. x[0] = (n+7)&~7; /* sbrk rounds size up to mult. of 8 */
  161. x[1] = 0xDeadBeef;
  162. return x+2;
  163. }
  164. static int
  165. sbrkmerge(void *x, void *y)
  166. {
  167. uint32_t *lx, *ly;
  168. lx = x;
  169. if(lx[-1] != 0xDeadBeef)
  170. abort();
  171. if((uint8_t*)lx+lx[-2] == (uint8_t*)y) {
  172. ly = y;
  173. lx[-2] += ly[-2];
  174. return 1;
  175. }
  176. return 0;
  177. }
  178. /*
  179. * because we can't print while we're holding the locks,
  180. * we have the save the message and print it once we let go.
  181. */
  182. static void
  183. poolprint(Pool *p, char *fmt, ...)
  184. {
  185. va_list v;
  186. Private *pv;
  187. pv = p->private;
  188. va_start(v, fmt);
  189. pv->end = vseprint(pv->end, &pv->msg[sizeof pv->msg], fmt, v);
  190. va_end(v);
  191. }
  192. static void
  193. ppanic(Pool *p, char *fmt, ...)
  194. {
  195. va_list v;
  196. Private *pv;
  197. char msg[sizeof pv->msg];
  198. pv = p->private;
  199. va_start(v, fmt);
  200. vseprint(pv->end, &pv->msg[sizeof pv->msg], fmt, v);
  201. va_end(v);
  202. memmove(msg, pv->msg, sizeof msg);
  203. iunlock(&pv->lk);
  204. panic("%s", msg);
  205. }
  206. static void
  207. plock(Pool *p)
  208. {
  209. Private *pv;
  210. pv = p->private;
  211. ilock(&pv->lk);
  212. pv->lk._pc = getcallerpc(&p);
  213. pv->end = pv->msg;
  214. }
  215. static void
  216. punlock(Pool *p)
  217. {
  218. Private *pv;
  219. char msg[sizeof pv->msg];
  220. pv = p->private;
  221. if(pv->end == pv->msg){
  222. iunlock(&pv->lk);
  223. return;
  224. }
  225. memmove(msg, pv->msg, sizeof msg);
  226. pv->end = pv->msg;
  227. iunlock(&pv->lk);
  228. iprint("%.*s", sizeof pv->msg, msg);
  229. }
  230. /*
  231. * Experiment: per-core quick lists.
  232. * change quicklist to be
  233. * static Qlist quicklist[MACHMAX][NQUICK+1];
  234. * and define QLIST to be quicklist[machp()->machno]
  235. *
  236. * using quicklist[machp()->machno] runs out of memory soon.
  237. * using quicklist[machp()->machno%4] yields times worse than using quicklist!
  238. */
  239. #define QLIST quicklist
  240. static void*
  241. qmallocalign(usize nbytes, uintptr_t align, int32_t offset, usize span)
  242. {
  243. Qlist *qlist;
  244. uintptr_t aligned;
  245. Header **pp, *p, *q, *r;
  246. uint naligned, nunits, n;
  247. if(nbytes == 0 || offset != 0 || span != 0)
  248. return nil;
  249. if(!ISPOWEROF2(align) || align < sizeof(Header))
  250. return nil;
  251. qstats[QSmalign]++;
  252. nunits = NUNITS(nbytes);
  253. if(nunits <= NQUICK){
  254. /*
  255. * Look for a conveniently aligned block
  256. * on one of the quicklists.
  257. */
  258. qlist = &QLIST[nunits];
  259. QLOCK(&qlist->lk);
  260. pp = &qlist->first;
  261. for(p = *pp; p != nil; p = p->s.next){
  262. if(ALIGNED(p+1, align)){
  263. *pp = p->s.next;
  264. p->s.next = &checkval;
  265. QUNLOCK(&qlist->lk);
  266. qstats[QSmalignquick]++;
  267. return p+1;
  268. }
  269. pp = &p->s.next;
  270. }
  271. QUNLOCK(&qlist->lk);
  272. }
  273. MLOCK;
  274. if(nunits > tailsize) {
  275. /* hard way */
  276. if((q = rover) != nil){
  277. do {
  278. p = q->s.next;
  279. if(p->s.size < nunits)
  280. continue;
  281. aligned = ALIGNED(p+1, align);
  282. naligned = NUNITS(align)-1;
  283. if(!aligned && p->s.size < nunits+naligned)
  284. continue;
  285. /*
  286. * This block is big enough, remove it
  287. * from the list.
  288. */
  289. q->s.next = p->s.next;
  290. rover = q;
  291. qstats[QSmalignrover]++;
  292. /*
  293. * Free any runt in front of the alignment.
  294. */
  295. if(!aligned){
  296. r = p;
  297. p = ALIGNHDR(p+1, align) - 1;
  298. n = p - r;
  299. p->s.size = r->s.size - n;
  300. r->s.size = n;
  301. r->s.next = &checkval;
  302. qfreeinternal(r+1);
  303. qstats[QSmalignfront]++;
  304. }
  305. /*
  306. * Free any residue after the aligned block.
  307. */
  308. if(p->s.size > nunits){
  309. r = p+nunits;
  310. r->s.size = p->s.size - nunits;
  311. r->s.next = &checkval;
  312. qstats[QSmalignback]++;
  313. qfreeinternal(r+1);
  314. p->s.size = nunits;
  315. }
  316. p->s.next = &checkval;
  317. MUNLOCK;
  318. return p+1;
  319. } while((q = p) != rover);
  320. }
  321. if((n = morecore(nunits)) == 0){
  322. MUNLOCK;
  323. return nil;
  324. }
  325. tailsize += n;
  326. }
  327. q = ALIGNHDR(tailptr+1, align);
  328. if(q == tailptr+1){
  329. tailalloc(p, nunits);
  330. qstats[QSmaligntail]++;
  331. }
  332. else{
  333. naligned = NUNITS(align)-1;
  334. if(tailsize < nunits+naligned){
  335. /*
  336. * There are at least nunits,
  337. * get enough for alignment.
  338. */
  339. if((n = morecore(naligned)) == 0){
  340. MUNLOCK;
  341. return nil;
  342. }
  343. tailsize += n;
  344. }
  345. /*
  346. * Save the residue before the aligned allocation
  347. * and free it after the tail pointer has been bumped
  348. * for the main allocation.
  349. */
  350. n = q-tailptr - 1;
  351. tailalloc(r, n);
  352. tailalloc(p, nunits);
  353. qstats[QSmalignnottail]++;
  354. qfreeinternal(r+1);
  355. }
  356. MUNLOCK;
  357. return p+1;
  358. }
  359. static void*
  360. qmalloc(usize nbytes)
  361. {
  362. Qlist *qlist;
  363. Header *p, *q;
  364. uint nunits, n;
  365. ///* FIXME: (ignore for now)
  366. if(nbytes == 0)
  367. return nil;
  368. //*/
  369. qstats[QSmalloc]++;
  370. nunits = NUNITS(nbytes);
  371. if(nunits <= NQUICK){
  372. qlist = &QLIST[nunits];
  373. QLOCK(&qlist->lk);
  374. if((p = qlist->first) != nil){
  375. qlist->first = p->s.next;
  376. qlist->nalloc++;
  377. QUNLOCK(&qlist->lk);
  378. p->s.next = &checkval;
  379. return p+1;
  380. }
  381. QUNLOCK(&qlist->lk);
  382. }
  383. MLOCK;
  384. if(nunits > tailsize) {
  385. /* hard way */
  386. if((q = rover) != nil){
  387. do {
  388. p = q->s.next;
  389. if(p->s.size >= nunits) {
  390. if(p->s.size > nunits) {
  391. p->s.size -= nunits;
  392. p += p->s.size;
  393. p->s.size = nunits;
  394. } else
  395. q->s.next = p->s.next;
  396. p->s.next = &checkval;
  397. rover = q;
  398. qstats[QSmallocrover]++;
  399. MUNLOCK;
  400. return p+1;
  401. }
  402. } while((q = p) != rover);
  403. }
  404. if((n = morecore(nunits)) == 0){
  405. MUNLOCK;
  406. return nil;
  407. }
  408. tailsize += n;
  409. }
  410. qstats[QSmalloctail]++;
  411. tailalloc(p, nunits);
  412. MUNLOCK;
  413. return p+1;
  414. }
  415. static void
  416. qfreeinternal(void* ap)
  417. {
  418. Qlist *qlist;
  419. Header *p, *q;
  420. uint nunits;
  421. if(ap == nil)
  422. return;
  423. qstats[QSfree]++;
  424. p = (Header*)ap - 1;
  425. if((nunits = p->s.size) == 0 || p->s.next != &checkval)
  426. panic("malloc: corrupt allocation arena\n");
  427. if(tailptr != nil && p+nunits == tailptr) {
  428. /* block before tail */
  429. tailptr = p;
  430. tailsize += nunits;
  431. qstats[QSfreetail]++;
  432. return;
  433. }
  434. if(nunits <= NQUICK) {
  435. qlist = &QLIST[nunits];
  436. QLOCK(&qlist->lk);
  437. p->s.next = qlist->first;
  438. qlist->first = p;
  439. QUNLOCK(&qlist->lk);
  440. qstats[QSfreequick]++;
  441. return;
  442. }
  443. if((q = rover) == nil) {
  444. q = &misclist;
  445. q->s.size = 0;
  446. q->s.next = q;
  447. }
  448. for(; !(p > q && p < q->s.next); q = q->s.next)
  449. if(q >= q->s.next && (p > q || p < q->s.next))
  450. break;
  451. if(p+p->s.size == q->s.next) {
  452. p->s.size += q->s.next->s.size;
  453. p->s.next = q->s.next->s.next;
  454. qstats[QSfreenext]++;
  455. } else
  456. p->s.next = q->s.next;
  457. if(q+q->s.size == p) {
  458. q->s.size += p->s.size;
  459. q->s.next = p->s.next;
  460. qstats[QSfreeprev]++;
  461. } else
  462. q->s.next = p;
  463. rover = q;
  464. }
  465. uint32_t
  466. msize(void* ap)
  467. {
  468. Header *p;
  469. uint nunits;
  470. if(ap == nil)
  471. return 0;
  472. p = (Header*)ap - 1;
  473. if((nunits = p->s.size) == 0 || p->s.next != &checkval)
  474. panic("malloc: corrupt allocation arena\n");
  475. return (nunits-1) * sizeof(Header);
  476. }
  477. static void
  478. mallocreadfmt(char* s, char* e)
  479. {
  480. char *p;
  481. Header *q;
  482. int i, n, t;
  483. Qlist *qlist;
  484. p = seprint(s, e,
  485. "%llud memory\n"
  486. "%d pagesize\n"
  487. "%llud kernel\n",
  488. (uint64_t)conf.npage*PGSZ,
  489. PGSZ,
  490. (uint64_t)conf.npage-conf.upages);
  491. t = 0;
  492. for(i = 0; i <= NQUICK; i++) {
  493. n = 0;
  494. qlist = &QLIST[i];
  495. QLOCK(&qlist->lk);
  496. for(q = qlist->first; q != nil; q = q->s.next){
  497. // if(q->s.size != i)
  498. // p = seprint(p, e, "q%d\t%#p\t%ud\n",
  499. // i, q, q->s.size);
  500. n++;
  501. }
  502. QUNLOCK(&qlist->lk);
  503. // if(n != 0)
  504. // p = seprint(p, e, "q%d %d\n", i, n);
  505. t += n * i*sizeof(Header);
  506. }
  507. p = seprint(p, e, "quick: %ud bytes total\n", t);
  508. MLOCK;
  509. if((q = rover) != nil){
  510. i = t = 0;
  511. do {
  512. t += q->s.size;
  513. i++;
  514. // p = seprint(p, e, "m%d\t%#p\n", q->s.size, q);
  515. } while((q = q->s.next) != rover);
  516. p = seprint(p, e, "rover: %d blocks %ud bytes total\n",
  517. i, t*sizeof(Header));
  518. }
  519. p = seprint(p, e, "total allocated %lud, %ud remaining\n",
  520. (tailptr-tailbase)*sizeof(Header), tailnunits*sizeof(Header));
  521. for(i = 0; i < nelem(qstats); i++){
  522. if(qstats[i] == 0)
  523. continue;
  524. p = seprint(p, e, "%s %ud\n", qstatstr[i], qstats[i]);
  525. }
  526. MUNLOCK;
  527. }
  528. int32_t
  529. mallocreadsummary(Chan* c, void *a, int32_t n, int32_t offset)
  530. {
  531. char *alloc;
  532. alloc = malloc(16*READSTR);
  533. mallocreadfmt(alloc, alloc+16*READSTR);
  534. n = readstr(offset, a, n, alloc);
  535. free(alloc);
  536. return n;
  537. }
  538. void
  539. mallocsummary(void)
  540. {
  541. Header *q;
  542. int i, n, t;
  543. Qlist *qlist;
  544. t = 0;
  545. for(i = 0; i <= NQUICK; i++) {
  546. n = 0;
  547. qlist = &QLIST[i];
  548. QLOCK(&qlist->lk);
  549. for(q = qlist->first; q != nil; q = q->s.next){
  550. if(q->s.size != i)
  551. DBG("q%d\t%#p\t%ud\n", i, q, q->s.size);
  552. n++;
  553. }
  554. QUNLOCK(&qlist->lk);
  555. t += n * i*sizeof(Header);
  556. }
  557. print("quick: %ud bytes total\n", t);
  558. MLOCK;
  559. if((q = rover) != nil){
  560. i = t = 0;
  561. do {
  562. t += q->s.size;
  563. i++;
  564. } while((q = q->s.next) != rover);
  565. }
  566. MUNLOCK;
  567. if(i != 0){
  568. print("rover: %d blocks %ud bytes total\n",
  569. i, t*sizeof(Header));
  570. }
  571. print("total allocated %lud, %ud remaining\n",
  572. (tailptr-tailbase)*sizeof(Header), tailnunits*sizeof(Header));
  573. for(i = 0; i < nelem(qstats); i++){
  574. if(qstats[i] == 0)
  575. continue;
  576. print("%s %ud\n", qstatstr[i], qstats[i]);
  577. }
  578. }
  579. void
  580. free(void* ap)
  581. {
  582. MLOCK;
  583. qfreeinternal(ap);
  584. MUNLOCK;
  585. }
  586. void*
  587. malloc(uint32_t size)
  588. {
  589. void* v;
  590. if((v = qmalloc(size)) != nil)
  591. memset(v, 0, size);
  592. return v;
  593. }
  594. void*
  595. mallocz(uint32_t size, int clr)
  596. {
  597. void *v;
  598. if((v = qmalloc(size)) != nil && clr)
  599. memset(v, 0, size);
  600. return v;
  601. }
  602. void*
  603. mallocalign(uint32_t nbytes, uint32_t align, int32_t offset, uint32_t span)
  604. {
  605. void *v;
  606. /*
  607. * Should this memset or should it be left to the caller?
  608. */
  609. if((v = qmallocalign(nbytes, align, offset, span)) != nil)
  610. memset(v, 0, nbytes);
  611. return v;
  612. }
  613. void*
  614. smalloc(uint32_t size)
  615. {
  616. Proc *up = externup();
  617. void *v;
  618. while((v = malloc(size)) == nil)
  619. tsleep(&up->sleep, return0, 0, 100);
  620. memset(v, 0, size);
  621. return v;
  622. }
  623. void*
  624. realloc(void* ap, uint32_t size)
  625. {
  626. void *v;
  627. Header *p;
  628. uint32_t osize;
  629. uint nunits, ounits;
  630. /*
  631. * Easy stuff:
  632. * free and return nil if size is 0
  633. * (implementation-defined behaviour);
  634. * behave like malloc if ap is nil;
  635. * check for arena corruption;
  636. * do nothing if units are the same.
  637. */
  638. if(size == 0){
  639. MLOCK;
  640. qfreeinternal(ap);
  641. MUNLOCK;
  642. return nil;
  643. }
  644. if(ap == nil)
  645. return qmalloc(size);
  646. p = (Header*)ap - 1;
  647. if((ounits = p->s.size) == 0 || p->s.next != &checkval)
  648. panic("realloc: corrupt allocation arena\n");
  649. if((nunits = NUNITS(size)) == ounits)
  650. return ap;
  651. /*
  652. * Slightly harder:
  653. * if this allocation abuts the tail, try to just
  654. * adjust the tailptr.
  655. */
  656. MLOCK;
  657. if(tailptr != nil && p+ounits == tailptr){
  658. if(ounits > nunits){
  659. p->s.size = nunits;
  660. tailsize += ounits-nunits;
  661. MUNLOCK;
  662. return ap;
  663. }
  664. if(tailsize >= nunits-ounits){
  665. p->s.size = nunits;
  666. tailsize -= nunits-ounits;
  667. MUNLOCK;
  668. return ap;
  669. }
  670. }
  671. MUNLOCK;
  672. /*
  673. * Worth doing if it's a small reduction?
  674. * Do it anyway if <= NQUICK?
  675. if((ounits-nunits) < 2)
  676. return ap;
  677. */
  678. /*
  679. * Too hard (or can't be bothered):
  680. * allocate, copy and free.
  681. * What does the standard say for failure here?
  682. */
  683. if((v = qmalloc(size)) != nil){
  684. osize = (ounits-1)*sizeof(Header);
  685. if(size < osize)
  686. osize = size;
  687. memmove(v, ap, osize);
  688. MLOCK;
  689. qfreeinternal(ap);
  690. MUNLOCK;
  691. }
  692. return v;
  693. }
  694. void
  695. setmalloctag(void* v, uint32_t i)
  696. {
  697. }
  698. void
  699. mallocinit(void)
  700. {
  701. if(tailptr != nil)
  702. return;
  703. tailbase = UINT2PTR(sys->vmunused);
  704. tailptr = tailbase;
  705. tailnunits = NUNITS(sys->vmend - sys->vmunused);
  706. print("base %#p ptr %#p nunits %ud\n", tailbase, tailptr, tailnunits);
  707. }
  708. static int
  709. morecore(uint nunits)
  710. {
  711. /*
  712. * First (simple) cut.
  713. * Pump it up when you don't really need it.
  714. * Pump it up until you can feel it.
  715. */
  716. if(nunits < NUNITS(128*KiB))
  717. nunits = NUNITS(128*KiB);
  718. if(nunits > tailnunits)
  719. nunits = tailnunits;
  720. tailnunits -= nunits;
  721. return nunits;
  722. }