PageRenderTime 66ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/libreoffice-3.6.0.2/dmake/dbug/malloc/malloc.c

#
C | 627 lines | 340 code | 82 blank | 205 comment | 48 complexity | e4a9f533e446e6591b4b30a94040481d MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, AGPL-1.0, BSD-3-Clause-No-Nuclear-License-2014, GPL-3.0, LGPL-3.0
  1. /*
  2. * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
  3. * You may copy, distribute, and use this software as long as this
  4. * copyright statement is not removed.
  5. */
  6. #include <stdio.h>
  7. #include <fcntl.h>
  8. #include "malloc.h"
  9. #include "tostring.h"
  10. /*
  11. * Function: malloc()
  12. *
  13. * Purpose: memory allocator
  14. *
  15. * Arguments: size - size of data area needed
  16. *
  17. * Returns: pointer to allocated area, or NULL if unable
  18. * to allocate addtional data.
  19. *
  20. * Narrative:
  21. *
  22. */
  23. #ifndef lint
  24. static
  25. char rcs_hdr[] = "$Id: malloc.c,v 1.2 2006-07-25 10:08:36 rt Exp $";
  26. #endif
  27. extern int malloc_checking;
  28. char * malloc_data_start;
  29. char * malloc_data_end;
  30. struct mlist * malloc_end;
  31. int malloc_errfd = 2;
  32. int malloc_errno;
  33. int malloc_fatal_level = M_HANDLE_CORE;
  34. struct mlist malloc_start;
  35. int malloc_warn_level;
  36. void malloc_memset();
  37. char *
  38. malloc(size)
  39. unsigned int size;
  40. {
  41. char * func = "malloc";
  42. char * getenv();
  43. void malloc_fatal();
  44. void malloc_init();
  45. void malloc_split();
  46. void malloc_warning();
  47. unsigned int need;
  48. struct mlist * oldptr;
  49. struct mlist * ptr;
  50. char * sbrk();
  51. /*
  52. * If this is the first call to malloc...
  53. */
  54. if( malloc_data_start == (char *) 0 )
  55. {
  56. malloc_init();
  57. }
  58. /*
  59. * If malloc chain checking is on, go do it.
  60. */
  61. if( malloc_checking )
  62. {
  63. (void) malloc_chain_check(1);
  64. }
  65. /*
  66. * always make sure there is at least on extra byte in the malloc
  67. * area so that we can verify that the user does not overrun the
  68. * data area.
  69. */
  70. size++;
  71. /*
  72. * Now look for a free area of memory of size bytes...
  73. */
  74. oldptr = NULL;
  75. for(ptr = &malloc_start; ; ptr = ptr->next)
  76. {
  77. /*
  78. * Since the malloc chain is a forward only chain, any
  79. * pointer that we get should always be positioned in
  80. * memory following the previous pointer. If this is not
  81. * so, we must have a corrupted chain.
  82. */
  83. if( ptr )
  84. {
  85. if( ptr<oldptr )
  86. {
  87. malloc_errno = M_CODE_CHAIN_BROKE;
  88. malloc_fatal(func);
  89. return(NULL);
  90. }
  91. oldptr = ptr;
  92. }
  93. else if( oldptr != malloc_end )
  94. {
  95. /*
  96. * This should never happen. If it does, then
  97. * we got a real problem.
  98. */
  99. malloc_errno = M_CODE_NO_END;
  100. malloc_fatal(func);
  101. return(NULL);
  102. }
  103. /*
  104. * if this element is already in use...
  105. */
  106. if( ptr && ((ptr->flag & M_INUSE) != 0) )
  107. {
  108. continue;
  109. }
  110. /*
  111. * if there isn't room for this block..
  112. */
  113. if( ptr && (ptr->s.size < size) )
  114. {
  115. continue;
  116. }
  117. /*
  118. * If ptr is null, we have run out of memory and must sbrk more
  119. */
  120. if( ptr == NULL )
  121. {
  122. need = (size + M_SIZE) * (size > 10*1024 ? 1:2);
  123. if( need < M_BLOCKSIZE )
  124. {
  125. need = M_BLOCKSIZE;
  126. }
  127. else if( need & (M_BLOCKSIZE-1) )
  128. {
  129. need &= ~(M_BLOCKSIZE-1);
  130. need += M_BLOCKSIZE;
  131. }
  132. ptr = (struct mlist *) sbrk((int)need);
  133. if( ptr == (struct mlist *) -1 )
  134. {
  135. malloc_errno = M_CODE_NOMORE_MEM;
  136. malloc_fatal(func);
  137. }
  138. malloc_data_end = sbrk((int)0);
  139. ptr->prev = oldptr;
  140. ptr->next = (struct mlist *) 0;
  141. ptr->s.size = need - M_SIZE;
  142. ptr->flag = M_MAGIC;
  143. oldptr->next = ptr;
  144. malloc_end = ptr;
  145. } /* if( ptr ==... */
  146. /*
  147. * Now ptr points to a memory location that can store
  148. * this data, so lets go to work.
  149. */
  150. ptr->r_size = size; /* save requested size */
  151. ptr->flag |= M_INUSE;
  152. /*
  153. * split off unneeded data area in this block, if possible...
  154. */
  155. malloc_split(ptr);
  156. /*
  157. * re-adjust the requested size so that it is what the user
  158. * actually requested...
  159. */
  160. ptr->r_size--;
  161. /*
  162. * just to make sure that noone is misusing malloced
  163. * memory without initializing it, lets set it to
  164. * all '\01's. We call local_memset() because memset()
  165. * may be checking for malloc'd ptrs and this isn't
  166. * a malloc'd ptr yet.
  167. */
  168. malloc_memset(ptr->data,M_FILL,(int)ptr->s.size);
  169. return( ptr->data);
  170. } /* for(... */
  171. } /* malloc(... */
  172. /*
  173. * Function: malloc_split()
  174. *
  175. * Purpose: to split a malloc segment if there is enough room at the
  176. * end of the segment that isn't being used
  177. *
  178. * Arguments: ptr - pointer to segment to split
  179. *
  180. * Returns: nothing of any use.
  181. *
  182. * Narrative:
  183. * get the needed size of the module
  184. * round the size up to appropriat boundry
  185. * calculate amount of left over space
  186. * if there is enough left over space
  187. * create new malloc block out of remainder
  188. * if next block is free
  189. * join the two blocks together
  190. * fill new empty block with free space filler
  191. * re-adjust pointers and size of current malloc block
  192. *
  193. *
  194. *
  195. * Mod History:
  196. * 90/01/27 cpcahil Initial revision.
  197. */
  198. void
  199. malloc_split(ptr)
  200. struct mlist * ptr;
  201. {
  202. extern struct mlist * malloc_end;
  203. void malloc_join();
  204. int rest;
  205. int size;
  206. struct mlist * tptr;
  207. size = ptr->r_size;
  208. /*
  209. * roundup size to the appropriate boundry
  210. */
  211. M_ROUNDUP(size);
  212. /*
  213. * figure out how much room is left in the array.
  214. * if there is enough room, create a new mlist
  215. * structure there.
  216. */
  217. if( ptr->s.size > size )
  218. {
  219. rest = ptr->s.size - size;
  220. }
  221. else
  222. {
  223. rest = 0;
  224. }
  225. if( rest > (M_SIZE+M_RND) )
  226. {
  227. tptr = (struct mlist *) (ptr->data+size);
  228. tptr->prev = ptr;
  229. tptr->next = ptr->next;
  230. tptr->flag = M_MAGIC;
  231. tptr->s.size = rest - M_SIZE;
  232. /*
  233. * If possible, join this segment with the next one
  234. */
  235. malloc_join(tptr, tptr->next,0,0);
  236. if( tptr->next )
  237. {
  238. tptr->next->prev = tptr;
  239. }
  240. malloc_memset(tptr->data,M_FREE_FILL, (int)tptr->s.size);
  241. ptr->next = tptr;
  242. ptr->s.size = size;
  243. if( malloc_end == ptr )
  244. {
  245. malloc_end = tptr;
  246. }
  247. }
  248. } /* malloc_split(... */
  249. /*
  250. * Function: malloc_join()
  251. *
  252. * Purpose: to join two malloc segments together (if possible)
  253. *
  254. * Arguments: ptr - pointer to segment to join to.
  255. * nextptr - pointer to next segment to join to ptr.
  256. *
  257. * Returns: nothing of any values.
  258. *
  259. * Narrative:
  260. *
  261. * Mod History:
  262. * 90/01/27 cpcahil Initial revision.
  263. */
  264. void
  265. malloc_join(ptr,nextptr, inuse_override, fill_flag)
  266. struct mlist * ptr;
  267. struct mlist * nextptr;
  268. int inuse_override;
  269. int fill_flag;
  270. {
  271. unsigned int newsize;
  272. if( ptr && ! (inuse_override || (ptr->flag & M_INUSE)) &&
  273. nextptr && ! (nextptr->flag & M_INUSE) &&
  274. ((ptr->data+ptr->s.size) == (char *) nextptr) )
  275. {
  276. if( malloc_end == nextptr )
  277. {
  278. malloc_end = ptr;
  279. }
  280. ptr->next = nextptr->next;
  281. newsize = nextptr->s.size + M_SIZE;
  282. /*
  283. * if we are to fill and this segment is in use,
  284. * fill in with M_FILL newly added space...
  285. */
  286. if(fill_flag && (ptr->flag & M_INUSE) )
  287. {
  288. malloc_memset(ptr->data+ptr->s.size,
  289. M_FILL, (int)(nextptr->s.size + M_SIZE));
  290. }
  291. ptr->s.size += newsize;
  292. if( ptr->next )
  293. {
  294. ptr->next->prev = ptr;
  295. }
  296. }
  297. } /* malloc_join(... */
  298. /*
  299. * The following mess is just to ensure that the versions of these functions in
  300. * the current library are included (to make sure that we don't accidentaly get
  301. * the libc versions. (This is the lazy man's -u ld directive)
  302. */
  303. void free();
  304. int strcmp();
  305. int memcmp();
  306. char * realloc();
  307. void (*malloc_void_funcs[])() =
  308. {
  309. free,
  310. };
  311. int (*malloc_int_funcs[])() =
  312. {
  313. strcmp,
  314. memcmp,
  315. };
  316. char * (*malloc_char_star_funcs[])() =
  317. {
  318. realloc,
  319. };
  320. /*
  321. * This is malloc's own memset which is used without checking the parameters.
  322. */
  323. void
  324. malloc_memset(ptr,byte,len)
  325. char * ptr;
  326. char byte;
  327. int len;
  328. {
  329. while(len-- > 0)
  330. {
  331. *ptr++ = byte;
  332. }
  333. } /* malloc_memset(... */
  334. /*
  335. * Function: malloc_fatal()
  336. *
  337. * Purpose: to display fatal error message and take approrpriate action
  338. *
  339. * Arguments: funcname - name of function calling this routine
  340. *
  341. * Returns: nothing of any value
  342. *
  343. * Narrative:
  344. *
  345. * Notes: This routine does not make use of any libc functions to build
  346. * and/or disply the error message. This is due to the fact that
  347. * we are probably at a point where malloc is having a real problem
  348. * and we don't want to call any function that may use malloc.
  349. */
  350. void
  351. malloc_fatal(funcname)
  352. char * funcname;
  353. {
  354. char errbuf[128];
  355. void exit();
  356. void malloc_err_handler();
  357. extern char * malloc_err_strings[];
  358. extern int malloc_errno;
  359. extern int malloc_fatal_level;
  360. char * s;
  361. char * t;
  362. s = errbuf;
  363. t = "Fatal error: ";
  364. while( *s = *t++)
  365. {
  366. s++;
  367. }
  368. t = funcname;
  369. while( *s = *t++)
  370. {
  371. s++;
  372. }
  373. t = "(): ";
  374. while( *s = *t++)
  375. {
  376. s++;
  377. }
  378. t = malloc_err_strings[malloc_errno];
  379. while( *s = *t++)
  380. {
  381. s++;
  382. }
  383. *(s++) = '\n';
  384. if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
  385. {
  386. (void) write(2,"I/O error to error file\n",(unsigned)24);
  387. exit(110);
  388. }
  389. malloc_err_handler(malloc_fatal_level);
  390. } /* malloc_fatal(... */
  391. /*
  392. * Function: malloc_warning()
  393. *
  394. * Purpose: to display warning error message and take approrpriate action
  395. *
  396. * Arguments: funcname - name of function calling this routine
  397. *
  398. * Returns: nothing of any value
  399. *
  400. * Narrative:
  401. *
  402. * Notes: This routine does not make use of any libc functions to build
  403. * and/or disply the error message. This is due to the fact that
  404. * we are probably at a point where malloc is having a real problem
  405. * and we don't want to call any function that may use malloc.
  406. */
  407. void
  408. malloc_warning(funcname)
  409. char * funcname;
  410. {
  411. char errbuf[128];
  412. void exit();
  413. void malloc_err_handler();
  414. extern char * malloc_err_strings[];
  415. extern int malloc_errno;
  416. extern int malloc_warn_level;
  417. char * s;
  418. char * t;
  419. s = errbuf;
  420. t = "Warning: ";
  421. while( *s = *t++)
  422. {
  423. s++;
  424. }
  425. t = funcname;
  426. while( *s = *t++)
  427. {
  428. s++;
  429. }
  430. t = "(): ";
  431. while( *s = *t++)
  432. {
  433. s++;
  434. }
  435. t = malloc_err_strings[malloc_errno];
  436. while( *s = *t++)
  437. {
  438. s++;
  439. }
  440. *(s++) = '\n';
  441. if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
  442. {
  443. (void) write(2,"I/O error to error file\n",(unsigned)24);
  444. exit(110);
  445. }
  446. malloc_err_handler(malloc_warn_level);
  447. } /* malloc_warning(... */
  448. /*
  449. * Function: malloc_err_handler()
  450. *
  451. * Purpose: to take the appropriate action for warning and/or fatal
  452. * error conditions.
  453. *
  454. * Arguments: level - error handling level
  455. *
  456. * Returns: nothing of any value
  457. *
  458. * Narrative:
  459. *
  460. * Notes: This routine does not make use of any libc functions to build
  461. * and/or disply the error message. This is due to the fact that
  462. * we are probably at a point where malloc is having a real problem
  463. * and we don't want to call any function that may use malloc.
  464. */
  465. void
  466. malloc_err_handler(level)
  467. {
  468. void exit();
  469. void malloc_dump();
  470. extern int malloc_errfd;
  471. if( level & M_HANDLE_DUMP )
  472. {
  473. malloc_dump(malloc_errfd);
  474. }
  475. switch( level & ~M_HANDLE_DUMP )
  476. {
  477. /*
  478. * If we are to drop a core file and exit
  479. */
  480. case M_HANDLE_ABORT:
  481. (void) abort();
  482. break;
  483. /*
  484. * If we are to exit..
  485. */
  486. case M_HANDLE_EXIT:
  487. exit(200);
  488. break;
  489. #ifndef __MSDOS__
  490. /*
  491. * If we are to dump a core, but keep going on our merry way
  492. */
  493. case M_HANDLE_CORE:
  494. {
  495. int pid;
  496. /*
  497. * fork so child can abort (and dump core)
  498. */
  499. if( (pid = fork()) == 0 )
  500. {
  501. (void) write(2,"Child dumping core\n",
  502. (unsigned)9);
  503. (void) abort();
  504. }
  505. /*
  506. * wait for child to finish dumping core
  507. */
  508. while( wait((int *)0) != pid)
  509. {
  510. }
  511. /*
  512. * Move core file to core.pid.cnt so
  513. * multiple cores don't overwrite each
  514. * other.
  515. */
  516. if( access("core",0) == 0 )
  517. {
  518. static int corecnt;
  519. char filenam[32];
  520. filenam[0] = 'c';
  521. filenam[1] = 'o';
  522. filenam[2] = 'r';
  523. filenam[3] = 'e';
  524. filenam[4] = '.';
  525. (void)tostring(filenam+5,getpid(),
  526. 5, B_DEC, '0');
  527. filenam[10] = '.';
  528. (void)tostring(filenam+11,corecnt++,
  529. 3, B_DEC, '0');
  530. filenam[14] = '\0';
  531. (void) unlink(filenam);
  532. if( link("core",filenam) == 0)
  533. {
  534. (void) unlink("core");
  535. }
  536. }
  537. }
  538. #endif
  539. /*
  540. * If we are to just ignore the error and keep on processing
  541. */
  542. case M_HANDLE_IGNORE:
  543. break;
  544. } /* switch(... */
  545. } /* malloc_err_handler(... */