00001
00002
00003
00004 #include "internal.h"
00005
00006
00007
00008
00009
00010 const char *tm_color_name[] = {
00011 "WHITE",
00012 "ECRU",
00013 "GREY",
00014 "BLACK",
00015
00016 "TOTAL",
00017
00018 "b",
00019 "n",
00020 "u",
00021 "p",
00022
00023 "O",
00024 "o",
00025 "P",
00026 "p",
00027 0
00028 };
00029
00030
00031 const char *tm_struct_name[] = {
00032 "FREE_BLOCK",
00033 "LIVE_BLOCK",
00034 "FREE_TYPE",
00035 "LIVE_TYPE",
00036 0
00037 };
00038
00039
00040 const char *tm_phase_name[] = {
00041 "ALLOC",
00042 "UNMARK",
00043 "ROOTS",
00044 "SCAN",
00045 "SWEEP",
00046 "Total",
00047 };
00048
00049
00050
00051
00052
00053
00054
00055
00056 FILE *tm_msg_file = 0;
00057 const char *tm_msg_prefix = "";
00058
00059
00060 const char *tm_msg_enable_default =
00061
00062
00063
00064 "FW"
00065
00066
00067 ;
00068
00069
00070 int tm_msg_enable_all = 0;
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 void tm_msg_enable(const char *codes, int enable)
00085 {
00086 const unsigned char *r;
00087
00088 enable = enable ? 1 : -1;
00089 for ( r = (const unsigned char *) codes; *r; ++ r ) {
00090
00091 if ( *r == '\1' ) {
00092 memset(tm.msg_enable_table, enable, sizeof(tm.msg_enable_table));
00093 break;
00094 } else {
00095 tm.msg_enable_table[*r] += enable;
00096 }
00097 }
00098 }
00099
00100
00101
00102
00103 void tm_msg(const char *format, ...)
00104 {
00105 va_list vap;
00106
00107
00108 if ( (tm.msg_ignored = ! tm.msg_enable_table[(unsigned char) format[0]]) )
00109 return;
00110
00111
00112 if ( ! *format )
00113 return;
00114
00115
00116 if ( ! tm_msg_file )
00117 tm_msg_file = stderr;
00118
00119
00120 fprintf(tm_msg_file, "%s%s%c %6lu t#%d[%lu] ",
00121 tm_msg_prefix,
00122 *tm_msg_prefix ? " " : "",
00123 tm_phase_name[tm.phase][0],
00124 (unsigned long) tm.alloc_id,
00125 tm.alloc_request_type ? tm.alloc_request_type->id : 0,
00126 (unsigned long) tm.alloc_request_size);
00127
00128
00129 if ( tm.alloc_pass > 1 )
00130 fprintf(tm_msg_file, "(pass %lu) ", (unsigned long) tm.alloc_pass);
00131
00132
00133 va_start(vap, format);
00134 vfprintf(tm_msg_file, format, vap);
00135 va_end(vap);
00136
00137
00138 fflush(tm_msg_file);
00139
00140 }
00141
00142
00143
00144
00145
00146 void tm_msg1(const char *format, ...)
00147 {
00148 va_list vap;
00149
00150
00151 if ( tm.msg_ignored )
00152 return;
00153
00154 if ( ! *format )
00155 return;
00156
00157 va_start(vap, format);
00158 vfprintf(tm_msg_file, format, vap);
00159 va_end(vap);
00160
00161 fflush(tm_msg_file);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 void tm_stop()
00176 {
00177 }
00178
00179
00180
00181
00182 void tm_fatal()
00183 {
00184 tm_msg("Fatal Aborting!\n");
00185
00186 tm_stop();
00187
00188 abort();
00189 }
00190
00191
00192
00193
00194 void tm_abort()
00195 {
00196 static int in_abort;
00197
00198 ++ in_abort;
00199
00200 if ( in_abort == 1 && tm.inited ) {
00201 tm_print_stats();
00202 }
00203
00204 -- in_abort;
00205
00206 tm_fatal();
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 void _tm_assert(const char *expr, const char *file, int lineno)
00219 {
00220 tm_msg("\n");
00221 tm_msg("Fatal assertion \"%s\" failed %s:%d ", expr, file, lineno);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 void tm_validate_lists()
00237 {
00238 int j;
00239 tm_type *t;
00240 tm_block *b;
00241 tm_node *node;
00242 size_t n[tm__LAST2];
00243 size_t bn[tm__LAST2];
00244 size_t tn[tm__LAST2];
00245
00246 memset(n, 0, sizeof(n));
00247 memset(bn, 0, sizeof(bn));
00248
00249 #if 0
00250 fprintf(tm_msg_file, "V");
00251 fflush(tm_msg_file);
00252 #endif
00253
00254
00255 tm_assert(tm_list_color(&tm.free_blocks) == tm_FREE_BLOCK);
00256 tm_list_LOOP(&tm.free_blocks, b);
00257 {
00258 _tm_block_validate(b);
00259 tm_assert(tm_list_color(b) == tm_FREE_BLOCK);
00260 tm_assert(b->type == 0);
00261 tm_assert(b->next_parcel == b->begin);
00262 }
00263 tm_list_LOOP_END;
00264
00265
00266 tm_assert(tm_list_color(&tm.types) == tm_LIVE_TYPE);
00267 tm_list_LOOP(&tm.types, t);
00268 {
00269 tm_assert(tm_list_color(t) == tm_LIVE_TYPE);
00270
00271
00272 memset(tn, 0, sizeof(n));
00273
00274
00275 bn[tm_B] = 0;
00276 tm_assert(tm_list_color(&t->blocks) == tm_LIVE_BLOCK);
00277 tm_list_LOOP(&t->blocks, b);
00278 {
00279 _tm_block_validate(b);
00280 tm_assert(tm_list_color(b) == tm_LIVE_BLOCK);
00281 tm_assert(b->type == t);
00282 ++ bn[tm_B];
00283 }
00284 tm_list_LOOP_END;
00285 tm_assert(bn[tm_B] == t->n[tm_B]);
00286
00287
00288 for ( j = 0;
00289 j < sizeof(t->color_list) / sizeof(t->color_list[0]);
00290 ++ j ) {
00291
00292 tm_assert(tm_list_color(&t->color_list[j]) == j);
00293 tm_list_LOOP(&t->color_list[j], node);
00294 {
00295 tm_assert(tm_node_color(node) == j);
00296 ++ tn[j];
00297 }
00298 tm_list_LOOP_END;
00299
00300 tm_assert(t->n[j] == tn[j]);
00301 tn[tm_TOTAL] += tn[j];
00302 n[j] += tn[j];
00303 n[tm_TOTAL] += tn[j];
00304 }
00305 tm_assert(t->n[tm_TOTAL] == tn[tm_TOTAL]);
00306 }
00307 tm_list_LOOP_END;
00308
00309
00310 tm_assert(n[tm_WHITE] == tm.n[tm_WHITE]);
00311 tm_assert(n[tm_ECRU] == tm.n[tm_ECRU]);
00312 tm_assert(n[tm_GREY] == tm.n[tm_GREY]);
00313 tm_assert(n[tm_BLACK] == tm.n[tm_BLACK]);
00314 tm_assert(n[tm_TOTAL] == tm.n[tm_TOTAL]);
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324 #ifndef _tm_sweep_is_error
00325
00326 int _tm_sweep_is_error = 0;
00327 #endif
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 int _tm_check_sweep_error()
00344 {
00345 tm_type *t;
00346 tm_node *n;
00347
00348
00349 if ( ! _tm_sweep_is_error ) {
00350 return 0;
00351 }
00352
00353
00354 if ( ! tm.n[tm_ECRU] ) {
00355 return 0;
00356 }
00357
00358
00359 tm_msg("Fatal %lu dead nodes; there should be no sweeping.\n", tm.n[tm_ECRU]);
00360 tm_stop();
00361
00362
00363
00364 tm_list_LOOP(&tm.types, t);
00365 {
00366 tm_list_LOOP(&t->color_list[tm_ECRU], n);
00367 {
00368 tm_assert_test(tm_node_color(n) == tm_ECRU);
00369 tm_msg("Fatal node %p color %s size %lu should not be sweeped!\n",
00370 (void*) n,
00371 tm_color_name[tm_node_color(n)],
00372 (unsigned long) t->size);
00373 {
00374 void ** vpa = tm_node_to_ptr(n);
00375 tm_msg("Fatal cons (%d, %p)\n", ((long) vpa[0]) >> 2, vpa[1]);
00376 }
00377 }
00378 tm_list_LOOP_END;
00379 }
00380 tm_list_LOOP_END;
00381
00382
00383 tm_print_stats();
00384
00385
00386 _tm_phase_init(tm_ROOT);
00387 _tm_root_scan_all();
00388
00389
00390 _tm_phase_init(tm_SCAN);
00391 _tm_node_scan_all();
00392
00393
00394 if ( tm.n[tm_ECRU] ) {
00395 tm_msg("Fatal after root mark: still missing %lu references.\n",
00396 (unsigned long) tm.n[tm_ECRU]);
00397 } else {
00398 tm_msg("Fatal after root mark: OK, missing references found!\n");
00399 }
00400
00401
00402 tm_list_LOOP(&tm.types, t);
00403 {
00404 tm_list_LOOP(&t->color_list[tm_ECRU], n);
00405 {
00406 tm_node_set_color(n, tm_node_to_block(n), tm_BLACK);
00407 }
00408 tm_list_LOOP_END;
00409 }
00410 tm_list_LOOP_END;
00411
00412
00413 _tm_phase_init(tm_UNMARK);
00414
00415
00416 tm_assert_test(tm.n[tm_ECRU] == 0);
00417
00418
00419 tm_stop();
00420
00421
00422 memset(&tm.ts_alloc.tw, 0, sizeof(tm.ts_alloc.tw));
00423
00424
00425 return 1;
00426 }
00427
00428
00429