8 BC_Trace *BC_Trace::global_trace = 0;
19 bc_trace_mutex execution_table;
20 bc_trace_mutex memory_table;
21 bc_trace_mutex lock_table;
22 bc_trace_list lock_free;
23 bc_trace_mutex file_table;
25 // incase lock set after task ends
26 static pthread_t last_lock_thread = 0;
27 static const char *last_lock_title = 0;
28 static const char *last_lock_location = 0;
30 trace_item::trace_item(bc_trace_t &t) : table(t) { ++table.size; }
31 trace_item::~trace_item() { --table.size; }
33 extern "C" void dump()
35 BC_Trace::dump_traces();
36 BC_Trace::dump_locks();
37 BC_Trace::dump_buffers();
40 #define TOTAL_TRACES 16
42 void BC_Trace::new_trace(const char *text)
44 if(!global_trace) return;
45 execution_table.lock();
47 if( execution_table.size >= TOTAL_TRACES ) {
48 it = (execution_item *)execution_table.first;
49 execution_table.remove_pointer(it);
52 it = new execution_item();
54 execution_table.append(it);
55 execution_table.unlock();
58 void BC_Trace::new_trace(const char *file, const char *function, int line)
60 char string[BCTEXTLEN];
61 snprintf(string, BCTEXTLEN, "%s: %s: %d", file, function, line);
65 void BC_Trace::delete_traces()
67 if(!global_trace) return;
68 execution_table.lock();
69 execution_table.clear();
70 execution_table.unlock();
73 void BC_Trace::enable_locks()
80 void BC_Trace::disable_locks()
84 while( lock_table.last ) {
85 lock_item *p = (lock_item*)lock_table.last;
87 lock_table.remove_pointer(p); lock_free.append(p);
93 // no canceling with lock held
94 void BC_Trace::lock_locks(const char *s)
97 last_lock_thread = pthread_self();
99 last_lock_location = 0;
102 void BC_Trace::unlock_locks()
107 #define TOTAL_LOCKS 256
109 int BC_Trace::set_lock(const char *title, const char *loc, trace_info *info)
111 if( !global_trace || !trace_locks ) return 0;
113 last_lock_thread = pthread_self();
114 last_lock_title = title;
115 last_lock_location = loc;
117 if( (it=(lock_item*)lock_free.first) != 0 )
118 lock_free.remove_pointer(it);
119 else if( lock_table.size >= TOTAL_LOCKS ) {
120 it = (lock_item*)lock_table.first;
121 lock_table.remove_pointer(it);
124 it = new lock_item();
125 it->set(info, title, loc);
126 lock_table.append(it);
127 info->trace = (void *)it;
132 void BC_Trace::set_lock2(int table_id, trace_info *info)
134 if( !global_trace || !trace_locks ) return;
136 lock_item *p = (lock_item *)info->trace;
137 if( !p || p->id != table_id ) {
138 p = (lock_item*)lock_table.last;
139 while( p && p->id != table_id ) p = (lock_item*)p->previous;
142 info->trace = (void *)p;
144 p->tid = pthread_self();
149 void BC_Trace::unset_lock2(int table_id, trace_info *info)
151 if( !global_trace || !trace_locks ) return;
153 lock_item *p = (lock_item *)info->trace;
154 if( !p || p->id != table_id ) {
155 p = (lock_item*)lock_table.last;
156 while( p && p->id != table_id ) p = (lock_item*)p->previous;
160 if( p ) { lock_table.remove_pointer(p); lock_free.append(p); }
164 void BC_Trace::unset_lock(trace_info *info)
166 if( !global_trace || !trace_locks ) return;
168 lock_item *p = (lock_item *)info->trace;
169 if( !p || p->info!=info || !p->is_owner ) {
170 p = (lock_item*)lock_table.last;
171 while( p && ( p->info!=info || !p->is_owner ) ) p = (lock_item*)p->previous;
175 if( p ) { lock_table.remove_pointer(p); lock_free.append(p); }
180 void BC_Trace::unset_all_locks(trace_info *info)
182 if( !global_trace || !trace_locks ) return;
184 lock_item *p = (lock_item*)lock_table.first;
186 lock_item *lp = p; p = (lock_item*)p->next;
187 if( lp->info != info ) continue;
188 lock_table.remove_pointer(lp); lock_free.append(lp);
193 void BC_Trace::clear_locks_tid(pthread_t tid)
195 if( !global_trace || !trace_locks ) return;
197 lock_item *p = (lock_item*)lock_table.first;
199 lock_item *lp = p; p = (lock_item*)p->next;
200 if( lp->tid != tid ) continue;
201 lock_table.remove_pointer(lp); lock_free.append(lp);
207 void BC_Trace::enable_memory()
212 void BC_Trace::disable_memory()
218 void BC_Trace::set_buffer(int size, void *ptr, const char* loc)
220 if(!global_trace) return;
221 if(!trace_memory) return;
223 //printf("BC_Trace::set_buffer %p %s\n", ptr, loc);
224 memory_table.append(new memory_item(size, ptr, loc));
225 memory_table.unlock();
228 int BC_Trace::unset_buffer(void *ptr)
230 if(!global_trace) return 0;
231 if(!trace_memory) return 0;
233 memory_item *p = (memory_item*)memory_table.first;
234 for( ; p!=0 && p->ptr!=ptr; p=(memory_item*)p->next );
236 memory_table.unlock();
242 void* operator new(size_t size)
244 void *result = malloc(size);
245 BUFFER(size, result, "new");
249 void* operator new[](size_t size)
251 void *result = malloc(size);
252 BUFFER(size, result, "new []");
256 void operator delete(void *ptr)
262 void operator delete[](void *ptr)
270 void BC_Trace::dump_traces(FILE *fp)
273 for( trace_item *tp=execution_table.first; tp!=0; tp=tp->next ) {
274 execution_item *p=(execution_item*)tp;
275 fprintf(fp," %s\n", (char*)p->value);
279 void BC_Trace::dump_locks(FILE *fp)
283 fprintf(fp,"signal_entry: lock table size=%d\n", lock_table.size);
284 for( trace_item *tp=lock_table.first; tp!=0; tp=tp->next ) {
285 lock_item *p=(lock_item*)tp;
286 fprintf(fp," %p %s %s %p%s\n", p->info, p->title,
287 p->loc, (void*)p->tid, p->is_owner ? " *" : "");
292 void BC_Trace::dump_buffers(FILE *fp)
297 fprintf(fp,"BC_Trace::dump_buffers: buffer table size=%d\n", memory_table.size);
298 for( trace_item *tp=memory_table.first; tp!=0; tp=tp->next ) {
299 memory_item *p=(memory_item*)tp;
300 fprintf(fp," %d %p %s\n", p->size, p->ptr, p->loc);
302 memory_table.unlock();
306 void BC_Trace::delete_temps()
309 if( file_table.size )
310 printf("BC_Trace::delete_temps: deleting %d temp files\n", file_table.size);
311 while( file_table.first ) {
312 file_item *p = (file_item*)file_table.first;
313 printf(" %s\n", p->value);
320 void BC_Trace::reset_locks()
325 void BC_Trace::set_temp(char *string)
328 file_item *it = new file_item();
330 file_table.append(it);
334 void BC_Trace::unset_temp(char *string)
337 file_item *p = (file_item *)file_table.last;
338 for( ; p!=0 && strcmp(p->value,string); p=(file_item*)p->previous );
346 TheLock TheLocker::the_lock;
347 TheList TheList::the_list;
348 TheChk TheChk::the_chk;
350 int lock_item::table_id = 0;
352 void TheList::dbg_add(pthread_t tid, pthread_t owner, const char *nm)
354 TheLocker the_locker;
355 int i = the_list.size();
356 while( --i >= 0 && the_list[i]->tid != tid );
358 printf("dbg_add, dup %016lx %s %s\n",
359 (unsigned long)tid, nm, the_list[i]->name);
362 the_list.append(new TheDbg(tid, owner, nm));
365 void TheList::dbg_del(pthread_t tid)
367 TheLocker the_locker;
368 int i = the_list.size();
369 while( --i >= 0 && the_list[i]->tid != tid );
371 printf("dbg_del, mis %016lx\n",(unsigned long)tid);
374 the_list.remove_object_number(i);
378 void TheList::dump_threads(FILE *fp)
380 int i = the_list.size();
382 fprintf(fp, "thread 0x%012lx, owner 0x%012lx, %s\n",
383 (unsigned long)the_list[i]->tid, (unsigned long)the_list[i]->owner,
389 #define dbg_add(t, o, nm) do {} while(0)
390 #define dbg_del(t) do {} while(0)
391 void TheList::dump_threads(FILE *fp)
396 void BC_Trace::dump_threads(FILE *fp)
398 TheList::dump_threads(fp);
402 void BC_Trace::dump_shm_stat(const char *fn, FILE *fp)
404 char path[BCTEXTLEN];
405 sprintf(path, "/proc/sys/kernel/%s",fn);
406 FILE *sfp = fopen(path,"r");
409 fscanf(sfp, "%ju", &v);
411 fprintf(fp, "%s = %ju\n", fn, v);
414 void BC_Trace::dump_shm_stats(FILE *fp)
416 dump_shm_stat("shmall", fp);
417 dump_shm_stat("shmmax", fp);
418 dump_shm_stat("shmmni", fp);
419 FILE *sfp = fopen("/proc/sysvipc/shm","r");
421 char line[BCTEXTLEN];
423 if( !fgets(line,sizeof(line), sfp) ) return;
424 int64_t used = 0, other = 0;
425 int n_used = 0, n_other = 0;
426 while( fgets(line,sizeof(line), sfp) ) {
427 int key, shmid, perms, cpid, lpid, uid, gid, cuid, cgid;
428 int64_t size, nattch, atime, dtime, ctime, rss, swap;
430 "%d %d %o %ju %u %u %ju %u %u %u %u %ju %ju %ju %ju %ju",
431 &key, &shmid, &perms, &size, &cpid, &lpid, &nattch,
432 &uid, &gid, &cuid, &cgid, &atime, &dtime, &ctime,
433 &rss, &swap) != 16 ) break;
444 fprintf(fp, "shmused = %jd (%d items)\n", used, n_used);
445 fprintf(fp, "shmother = %jd (%d items)\n", other, n_other);