dbmalloc.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /***********************************************************************
  6. **
  7. ** Name: dbmalloc.c
  8. **
  9. ** Description: Testing malloc (OBSOLETE)
  10. **
  11. ** Modification History:
  12. ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
  13. ** The debug mode will print all of the printfs associated with this test.
  14. ** The regress mode will be the default mode. Since the regress tool limits
  15. ** the output to a one line status:PASS or FAIL,all of the printf statements
  16. ** have been handled with an if (debug_mode) statement.
  17. ***********************************************************************/
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <time.h>
  21. #include <string.h>
  22. #include "nspr.h"
  23. void
  24. usage
  25. (
  26. void
  27. )
  28. {
  29. fprintf(stderr, "Usage: dbmalloc ('-m'|'-s') '-f' num_fails ('-d'|'-n') filename [...]\n");
  30. exit(0);
  31. }
  32. typedef struct node_struct
  33. {
  34. struct node_struct *next, *prev;
  35. int line;
  36. char value[4];
  37. }
  38. node_t,
  39. *node_pt;
  40. node_pt get_node(const char *line)
  41. {
  42. node_pt rv;
  43. int l = strlen(line);
  44. rv = (node_pt)PR_MALLOC(sizeof(node_t) + l + 1 - 4);
  45. if( (node_pt)0 == rv ) {
  46. return (node_pt)0;
  47. }
  48. memcpy(&rv->value[0], line, l+1);
  49. rv->next = rv->prev = (node_pt)0;
  50. return rv;
  51. }
  52. void
  53. dump
  54. (
  55. const char *name,
  56. node_pt node,
  57. int mf,
  58. int debug
  59. )
  60. {
  61. if( (node_pt)0 != node->prev ) {
  62. dump(name, node->prev, mf, debug);
  63. }
  64. if( 0 != debug ) {
  65. printf("[%s]: %6d: %s", name, node->line, node->value);
  66. }
  67. if( node->line == mf ) {
  68. fprintf(stderr, "[%s]: Line %d was allocated!\n", name, node->line);
  69. }
  70. if( (node_pt)0 != node->next ) {
  71. dump(name, node->next, mf, debug);
  72. }
  73. return;
  74. }
  75. void
  76. release
  77. (
  78. node_pt node
  79. )
  80. {
  81. if( (node_pt)0 != node->prev ) {
  82. release(node->prev);
  83. }
  84. if( (node_pt)0 != node->next ) {
  85. release(node->next);
  86. }
  87. PR_DELETE(node);
  88. }
  89. int
  90. t2
  91. (
  92. const char *name,
  93. int mf,
  94. int debug
  95. )
  96. {
  97. int rv;
  98. FILE *fp;
  99. int l = 0;
  100. node_pt head = (node_pt)0;
  101. char buffer[ BUFSIZ ];
  102. fp = fopen(name, "r");
  103. if( (FILE *)0 == fp )
  104. {
  105. fprintf(stderr, "[%s]: Cannot open \"%s.\"\n", name, name);
  106. return -1;
  107. }
  108. /* fgets mallocs a buffer, first time through. */
  109. if( (char *)0 == fgets(buffer, BUFSIZ, fp) )
  110. {
  111. fprintf(stderr, "[%s]: \"%s\" is empty.\n", name, name);
  112. (void)fclose(fp);
  113. return -1;
  114. }
  115. rewind(fp);
  116. if( PR_SUCCESS != PR_ClearMallocCount() )
  117. {
  118. fprintf(stderr, "[%s]: Cannot clear malloc count.\n", name);
  119. (void)fclose(fp);
  120. return -1;
  121. }
  122. if( PR_SUCCESS != PR_SetMallocCountdown(mf) )
  123. {
  124. fprintf(stderr, "[%s]: Cannot set malloc countdown to %d\n", name, mf);
  125. (void)fclose(fp);
  126. return -1;
  127. }
  128. while( fgets(buffer, BUFSIZ, fp) )
  129. {
  130. node_pt n;
  131. node_pt *w = &head;
  132. if( (strlen(buffer) == (BUFSIZ-1)) && (buffer[BUFSIZ-2] != '\n') ) {
  133. buffer[BUFSIZ-2] == '\n';
  134. }
  135. l++;
  136. n = get_node(buffer);
  137. if( (node_pt)0 == n )
  138. {
  139. printf("[%s]: Line %d: malloc failure!\n", name, l);
  140. continue;
  141. }
  142. n->line = l;
  143. while( 1 )
  144. {
  145. int comp;
  146. if( (node_pt)0 == *w )
  147. {
  148. *w = n;
  149. break;
  150. }
  151. comp = strcmp((*w)->value, n->value);
  152. if( comp < 0 ) {
  153. w = &(*w)->next;
  154. }
  155. else {
  156. w = &(*w)->prev;
  157. }
  158. }
  159. }
  160. (void)fclose(fp);
  161. dump(name, head, mf, debug);
  162. rv = PR_GetMallocCount();
  163. PR_ClearMallocCountdown();
  164. release(head);
  165. return rv;
  166. }
  167. int nf = 0;
  168. int debug = 0;
  169. void
  170. test
  171. (
  172. const char *name
  173. )
  174. {
  175. int n, i;
  176. extern int nf, debug;
  177. printf("[%s]: starting test 0\n", name);
  178. n = t2(name, 0, debug);
  179. if( -1 == n ) {
  180. return;
  181. }
  182. printf("[%s]: test 0 had %ld allocations.\n", name, n);
  183. if( 0 >= n ) {
  184. return;
  185. }
  186. for( i = 0; i < nf; i++ )
  187. {
  188. int which = rand() % n;
  189. if( 0 == which ) {
  190. printf("[%s]: starting test %d -- no allocation should fail\n", name, i+1);
  191. }
  192. else {
  193. printf("[%s]: starting test %d -- allocation %d should fail\n", name, i+1, which);
  194. }
  195. (void)t2(name, which, debug);
  196. printf("[%s]: test %d done.\n", name, i+1);
  197. }
  198. return;
  199. }
  200. int main(int argc, char **argv)
  201. {
  202. int okay = 0;
  203. int multithread = 0;
  204. struct threadlist
  205. {
  206. struct threadlist *next;
  207. PRThread *thread;
  208. }
  209. *threadhead = (struct threadlist *)0;
  210. extern int nf, debug;
  211. srand(time(0));
  212. PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
  213. PR_STDIO_INIT();
  214. printf("[main]: We %s using the debugging malloc.\n",
  215. PR_IsDebuggingMalloc() ? "ARE" : "ARE NOT");
  216. while( argv++, --argc )
  217. {
  218. if( '-' == argv[0][0] )
  219. {
  220. switch( argv[0][1] )
  221. {
  222. case 'f':
  223. nf = atoi(argv[0][2] ? &argv[0][2] :
  224. --argc ? *++argv : "0");
  225. break;
  226. case 'd':
  227. debug = 1;
  228. break;
  229. case 'n':
  230. debug = 0;
  231. break;
  232. case 'm':
  233. multithread = 1;
  234. break;
  235. case 's':
  236. multithread = 0;
  237. break;
  238. default:
  239. usage();
  240. break;
  241. }
  242. }
  243. else
  244. {
  245. FILE *fp = fopen(*argv, "r");
  246. if( (FILE *)0 == fp )
  247. {
  248. fprintf(stderr, "Cannot open \"%s.\"\n", *argv);
  249. continue;
  250. }
  251. okay++;
  252. (void)fclose(fp);
  253. if( multithread )
  254. {
  255. struct threadlist *n;
  256. n = (struct threadlist *)malloc(sizeof(struct threadlist));
  257. if( (struct threadlist *)0 == n )
  258. {
  259. fprintf(stderr, "This is getting tedious. \"%s\"\n", *argv);
  260. continue;
  261. }
  262. n->next = threadhead;
  263. n->thread = PR_CreateThread(PR_USER_THREAD, (void (*)(void *))test,
  264. *argv, PR_PRIORITY_NORMAL,
  265. PR_LOCAL_THREAD, PR_JOINABLE_THREAD,
  266. 0);
  267. if( (PRThread *)0 == n->thread )
  268. {
  269. fprintf(stderr, "Can't create thread for \"%s.\"\n", *argv);
  270. continue;
  271. }
  272. else
  273. {
  274. threadhead = n;
  275. }
  276. }
  277. else
  278. {
  279. test(*argv);
  280. }
  281. }
  282. }
  283. if( okay == 0 ) {
  284. usage();
  285. }
  286. else while( (struct threadlist *)0 != threadhead )
  287. {
  288. struct threadlist *x = threadhead->next;
  289. (void)PR_JoinThread(threadhead->thread);
  290. PR_DELETE(threadhead);
  291. threadhead = x;
  292. }
  293. return 0;
  294. }