michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /*********************************************************************** michael@0: ** michael@0: ** Name: dbmalloc.c michael@0: ** michael@0: ** Description: Testing malloc (OBSOLETE) michael@0: ** michael@0: ** Modification History: michael@0: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. michael@0: ** The debug mode will print all of the printfs associated with this test. michael@0: ** The regress mode will be the default mode. Since the regress tool limits michael@0: ** the output to a one line status:PASS or FAIL,all of the printf statements michael@0: ** have been handled with an if (debug_mode) statement. michael@0: ***********************************************************************/ michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include "nspr.h" michael@0: michael@0: void michael@0: usage michael@0: ( michael@0: void michael@0: ) michael@0: { michael@0: fprintf(stderr, "Usage: dbmalloc ('-m'|'-s') '-f' num_fails ('-d'|'-n') filename [...]\n"); michael@0: exit(0); michael@0: } michael@0: michael@0: typedef struct node_struct michael@0: { michael@0: struct node_struct *next, *prev; michael@0: int line; michael@0: char value[4]; michael@0: } michael@0: node_t, michael@0: *node_pt; michael@0: michael@0: node_pt get_node(const char *line) michael@0: { michael@0: node_pt rv; michael@0: int l = strlen(line); michael@0: rv = (node_pt)PR_MALLOC(sizeof(node_t) + l + 1 - 4); michael@0: if( (node_pt)0 == rv ) return (node_pt)0; michael@0: memcpy(&rv->value[0], line, l+1); michael@0: rv->next = rv->prev = (node_pt)0; michael@0: return rv; michael@0: } michael@0: michael@0: void michael@0: dump michael@0: ( michael@0: const char *name, michael@0: node_pt node, michael@0: int mf, michael@0: int debug michael@0: ) michael@0: { michael@0: if( (node_pt)0 != node->prev ) dump(name, node->prev, mf, debug); michael@0: if( 0 != debug ) printf("[%s]: %6d: %s", name, node->line, node->value); michael@0: if( node->line == mf ) fprintf(stderr, "[%s]: Line %d was allocated!\n", name, node->line); michael@0: if( (node_pt)0 != node->next ) dump(name, node->next, mf, debug); michael@0: return; michael@0: } michael@0: michael@0: void michael@0: release michael@0: ( michael@0: node_pt node michael@0: ) michael@0: { michael@0: if( (node_pt)0 != node->prev ) release(node->prev); michael@0: if( (node_pt)0 != node->next ) release(node->next); michael@0: PR_DELETE(node); michael@0: } michael@0: michael@0: int michael@0: t2 michael@0: ( michael@0: const char *name, michael@0: int mf, michael@0: int debug michael@0: ) michael@0: { michael@0: int rv; michael@0: FILE *fp; michael@0: int l = 0; michael@0: node_pt head = (node_pt)0; michael@0: char buffer[ BUFSIZ ]; michael@0: michael@0: fp = fopen(name, "r"); michael@0: if( (FILE *)0 == fp ) michael@0: { michael@0: fprintf(stderr, "[%s]: Cannot open \"%s.\"\n", name, name); michael@0: return -1; michael@0: } michael@0: michael@0: /* fgets mallocs a buffer, first time through. */ michael@0: if( (char *)0 == fgets(buffer, BUFSIZ, fp) ) michael@0: { michael@0: fprintf(stderr, "[%s]: \"%s\" is empty.\n", name, name); michael@0: (void)fclose(fp); michael@0: return -1; michael@0: } michael@0: michael@0: rewind(fp); michael@0: michael@0: if( PR_SUCCESS != PR_ClearMallocCount() ) michael@0: { michael@0: fprintf(stderr, "[%s]: Cannot clear malloc count.\n", name); michael@0: (void)fclose(fp); michael@0: return -1; michael@0: } michael@0: michael@0: if( PR_SUCCESS != PR_SetMallocCountdown(mf) ) michael@0: { michael@0: fprintf(stderr, "[%s]: Cannot set malloc countdown to %d\n", name, mf); michael@0: (void)fclose(fp); michael@0: return -1; michael@0: } michael@0: michael@0: while( fgets(buffer, BUFSIZ, fp) ) michael@0: { michael@0: node_pt n; michael@0: node_pt *w = &head; michael@0: michael@0: if( (strlen(buffer) == (BUFSIZ-1)) && (buffer[BUFSIZ-2] != '\n') ) michael@0: buffer[BUFSIZ-2] == '\n'; michael@0: michael@0: l++; michael@0: michael@0: n = get_node(buffer); michael@0: if( (node_pt)0 == n ) michael@0: { michael@0: printf("[%s]: Line %d: malloc failure!\n", name, l); michael@0: continue; michael@0: } michael@0: michael@0: n->line = l; michael@0: michael@0: while( 1 ) michael@0: { michael@0: int comp; michael@0: michael@0: if( (node_pt)0 == *w ) michael@0: { michael@0: *w = n; michael@0: break; michael@0: } michael@0: michael@0: comp = strcmp((*w)->value, n->value); michael@0: if( comp < 0 ) w = &(*w)->next; michael@0: else w = &(*w)->prev; michael@0: } michael@0: } michael@0: michael@0: (void)fclose(fp); michael@0: michael@0: dump(name, head, mf, debug); michael@0: michael@0: rv = PR_GetMallocCount(); michael@0: PR_ClearMallocCountdown(); michael@0: michael@0: release(head); michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: int nf = 0; michael@0: int debug = 0; michael@0: michael@0: void michael@0: test michael@0: ( michael@0: const char *name michael@0: ) michael@0: { michael@0: int n, i; michael@0: michael@0: extern int nf, debug; michael@0: michael@0: printf("[%s]: starting test 0\n", name); michael@0: n = t2(name, 0, debug); michael@0: if( -1 == n ) return; michael@0: printf("[%s]: test 0 had %ld allocations.\n", name, n); michael@0: michael@0: if( 0 >= n ) return; michael@0: michael@0: for( i = 0; i < nf; i++ ) michael@0: { michael@0: int which = rand() % n; michael@0: if( 0 == which ) printf("[%s]: starting test %d -- no allocation should fail\n", name, i+1); michael@0: else printf("[%s]: starting test %d -- allocation %d should fail\n", name, i+1, which); michael@0: (void)t2(name, which, debug); michael@0: printf("[%s]: test %d done.\n", name, i+1); michael@0: } michael@0: michael@0: return; michael@0: } michael@0: michael@0: int main(int argc, char **argv) michael@0: { michael@0: int okay = 0; michael@0: int multithread = 0; michael@0: michael@0: struct threadlist michael@0: { michael@0: struct threadlist *next; michael@0: PRThread *thread; michael@0: } michael@0: *threadhead = (struct threadlist *)0; michael@0: michael@0: extern int nf, debug; michael@0: michael@0: srand(time(0)); michael@0: michael@0: PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); michael@0: PR_STDIO_INIT(); michael@0: michael@0: printf("[main]: We %s using the debugging malloc.\n", michael@0: PR_IsDebuggingMalloc() ? "ARE" : "ARE NOT"); michael@0: michael@0: while( argv++, --argc ) michael@0: { michael@0: if( '-' == argv[0][0] ) michael@0: { michael@0: switch( argv[0][1] ) michael@0: { michael@0: case 'f': michael@0: nf = atoi(argv[0][2] ? &argv[0][2] : michael@0: --argc ? *++argv : "0"); michael@0: break; michael@0: case 'd': michael@0: debug = 1; michael@0: break; michael@0: case 'n': michael@0: debug = 0; michael@0: break; michael@0: case 'm': michael@0: multithread = 1; michael@0: break; michael@0: case 's': michael@0: multithread = 0; michael@0: break; michael@0: default: michael@0: usage(); michael@0: break; michael@0: } michael@0: } michael@0: else michael@0: { michael@0: FILE *fp = fopen(*argv, "r"); michael@0: if( (FILE *)0 == fp ) michael@0: { michael@0: fprintf(stderr, "Cannot open \"%s.\"\n", *argv); michael@0: continue; michael@0: } michael@0: michael@0: okay++; michael@0: (void)fclose(fp); michael@0: if( multithread ) michael@0: { michael@0: struct threadlist *n; michael@0: michael@0: n = (struct threadlist *)malloc(sizeof(struct threadlist)); michael@0: if( (struct threadlist *)0 == n ) michael@0: { michael@0: fprintf(stderr, "This is getting tedious. \"%s\"\n", *argv); michael@0: continue; michael@0: } michael@0: michael@0: n->next = threadhead; michael@0: n->thread = PR_CreateThread(PR_USER_THREAD, (void (*)(void *))test, michael@0: *argv, PR_PRIORITY_NORMAL, michael@0: PR_LOCAL_THREAD, PR_JOINABLE_THREAD, michael@0: 0); michael@0: if( (PRThread *)0 == n->thread ) michael@0: { michael@0: fprintf(stderr, "Can't create thread for \"%s.\"\n", *argv); michael@0: continue; michael@0: } michael@0: else michael@0: { michael@0: threadhead = n; michael@0: } michael@0: } michael@0: else michael@0: { michael@0: test(*argv); michael@0: } michael@0: } michael@0: } michael@0: michael@0: if( okay == 0 ) usage(); michael@0: else while( (struct threadlist *)0 != threadhead ) michael@0: { michael@0: struct threadlist *x = threadhead->next; michael@0: (void)PR_JoinThread(threadhead->thread); michael@0: PR_DELETE(threadhead); michael@0: threadhead = x; michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: