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