ru.po from igor, intl tweaks, picon fixes for last chkin, snap motion event on btns
[goodguy/history.git] / cinelerra-5.1 / guicast / bctrace.C
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5
6 #include "bctrace.h"
7
8 BC_Trace *BC_Trace::global_trace = 0;
9 int trace_memory = 0;
10 int trace_locks = 1;
11
12 BC_Trace::BC_Trace()
13 {
14 }
15 BC_Trace::~BC_Trace()
16 {
17 }
18
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;
24
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;
29
30 trace_item::trace_item(bc_trace_t &t) : table(t) { ++table.size; }
31 trace_item::~trace_item() { --table.size; }
32
33 extern "C" void dump()
34 {
35         BC_Trace::dump_traces();
36         BC_Trace::dump_locks();
37         BC_Trace::dump_buffers();
38 }
39
40 #define TOTAL_TRACES 16
41
42 void BC_Trace::new_trace(const char *text)
43 {
44         if(!global_trace) return;
45         execution_table.lock();
46         execution_item *it;
47         if( execution_table.size >= TOTAL_TRACES ) {
48                 it = (execution_item *)execution_table.first;
49                 execution_table.remove_pointer(it);
50         }
51         else
52                 it = new execution_item();
53         it->set(text);
54         execution_table.append(it);
55         execution_table.unlock();
56 }
57
58 void BC_Trace::new_trace(const char *file, const char *function, int line)
59 {
60         char string[BCTEXTLEN];
61         snprintf(string, BCTEXTLEN, "%s: %s: %d", file, function, line);
62         new_trace(string);
63 }
64
65 void BC_Trace::delete_traces()
66 {
67         if(!global_trace) return;
68         execution_table.lock();
69         execution_table.clear();
70         execution_table.unlock();
71 }
72
73 void BC_Trace::enable_locks()
74 {
75         lock_table.lock();
76         trace_locks = 1;
77         lock_table.unlock();
78 }
79
80 void BC_Trace::disable_locks()
81 {
82         lock_table.lock();
83         trace_locks = 0;
84         while( lock_table.last ) {
85                 lock_item *p = (lock_item*)lock_table.last;
86                 p->info->trace = 0;
87                 lock_table.remove_pointer(p);  lock_free.append(p);
88         }
89         lock_free.clear();
90         lock_table.unlock();
91 }
92
93 // no canceling with lock held
94 void BC_Trace::lock_locks(const char *s)
95 {
96         lock_table.lock();
97         last_lock_thread = pthread_self();
98         last_lock_title = s;
99         last_lock_location = 0;
100 }
101
102 void BC_Trace::unlock_locks()
103 {
104         lock_table.unlock();
105 }
106
107 #define TOTAL_LOCKS 256
108
109 int BC_Trace::set_lock(const char *title, const char *loc, trace_info *info)
110 {
111         if( !global_trace || !trace_locks ) return 0;
112         lock_table.lock();
113         last_lock_thread = pthread_self();
114         last_lock_title = title;
115         last_lock_location = loc;
116         lock_item *it;
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);
122         }
123         else
124                 it = new lock_item();
125         it->set(info, title, loc);
126         lock_table.append(it);
127         info->trace = (void *)it;
128         lock_table.unlock();
129         return it->id;
130 }
131
132 void BC_Trace::set_lock2(int table_id, trace_info *info)
133 {
134         if( !global_trace || !trace_locks ) return;
135         lock_table.lock();
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;
140         }
141         if( p ) {
142                 info->trace = (void *)p;
143                 p->is_owner = 1;
144                 p->tid = pthread_self();
145         }
146         lock_table.unlock();
147 }
148
149 void BC_Trace::unset_lock2(int table_id, trace_info *info)
150 {
151         if( !global_trace || !trace_locks ) return;
152         lock_table.lock();
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;
157         }
158         else
159                 info->trace = 0;
160         if( p ) { lock_table.remove_pointer(p);  lock_free.append(p); }
161         lock_table.unlock();
162 }
163
164 void BC_Trace::unset_lock(trace_info *info)
165 {
166         if( !global_trace || !trace_locks ) return;
167         lock_table.lock();
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;
172         }
173         else
174                 info->trace = 0;
175         if( p ) { lock_table.remove_pointer(p);  lock_free.append(p); }
176         lock_table.unlock();
177 }
178
179
180 void BC_Trace::unset_all_locks(trace_info *info)
181 {
182         if( !global_trace || !trace_locks ) return;
183         lock_table.lock();
184         lock_item *p = (lock_item*)lock_table.first;
185         while( p ) {
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);
189         }
190         lock_table.unlock();
191 }
192
193 void BC_Trace::clear_locks_tid(pthread_t tid)
194 {
195         if( !global_trace || !trace_locks ) return;
196         lock_table.lock();
197         lock_item *p = (lock_item*)lock_table.first;
198         while( p ) {
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);
202         }
203         lock_table.unlock();
204 }
205
206
207 void BC_Trace::enable_memory()
208 {
209         trace_memory = 1;
210 }
211
212 void BC_Trace::disable_memory()
213 {
214         trace_memory = 0;
215 }
216
217
218 void BC_Trace::set_buffer(int size, void *ptr, const char* loc)
219 {
220         if(!global_trace) return;
221         if(!trace_memory) return;
222         memory_table.lock();
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();
226 }
227
228 int BC_Trace::unset_buffer(void *ptr)
229 {
230         if(!global_trace) return 0;
231         if(!trace_memory) return 0;
232         memory_table.lock();
233         memory_item *p = (memory_item*)memory_table.first;
234         for( ; p!=0 && p->ptr!=ptr; p=(memory_item*)p->next );
235         if( p ) delete p;
236         memory_table.unlock();
237         return !p ? 1 : 0;
238 }
239
240 #ifdef TRACE_MEMORY
241
242 void* operator new(size_t size)
243 {
244         void *result = malloc(size);
245         BUFFER(size, result, "new");
246         return result;
247 }
248
249 void* operator new[](size_t size)
250 {
251         void *result = malloc(size);
252         BUFFER(size, result, "new []");
253         return result;
254 }
255
256 void operator delete(void *ptr)
257 {
258         UNBUFFER(ptr);
259         free(ptr);
260 }
261
262 void operator delete[](void *ptr)
263 {
264         UNBUFFER(ptr);
265         free(ptr);
266 }
267
268 #endif
269
270 void BC_Trace::dump_traces(FILE *fp)
271 {
272 // Dump trace table
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);
276         }
277 }
278
279 void BC_Trace::dump_locks(FILE *fp)
280 {
281 // Dump lock table
282 #ifdef TRACE_LOCKS
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 ? " *" : "");
288         }
289 #endif
290 }
291
292 void BC_Trace::dump_buffers(FILE *fp)
293 {
294 #ifdef TRACE_MEMORY
295         memory_table.lock();
296 // Dump buffer table
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);
301         }
302         memory_table.unlock();
303 #endif
304 }
305
306 void BC_Trace::delete_temps()
307 {
308         file_table.lock();
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);
314                 ::remove(p->value);
315                 delete p;
316         }
317         file_table.unlock();
318 }
319
320 void BC_Trace::reset_locks()
321 {
322         lock_table.unlock();
323 }
324
325 void BC_Trace::set_temp(char *string)
326 {
327         file_table.lock();
328         file_item *it = new file_item();
329         it->set(string);
330         file_table.append(it);
331         file_table.unlock();
332 }
333
334 void BC_Trace::unset_temp(char *string)
335 {
336         file_table.lock();
337         file_item *p = (file_item *)file_table.last;
338         for( ; p!=0 && strcmp(p->value,string); p=(file_item*)p->previous );
339         if( p ) delete p;
340         file_table.unlock();
341 }
342
343
344 #ifdef TRACE_THREADS
345
346 TheLock TheLocker::the_lock;
347 TheList TheList::the_list;
348 TheChk TheChk::the_chk;
349
350 int lock_item::table_id = 0;
351
352 void TheList::dbg_add(pthread_t tid, pthread_t owner, const char *nm)
353 {
354         TheLocker the_locker;
355         int i = the_list.size();
356         while( --i >= 0 && the_list[i]->tid != tid );
357         if( i >= 0 ) {
358                 printf("dbg_add, dup %016lx %s %s\n",
359                         (unsigned long)tid, nm, the_list[i]->name);
360                 return;
361         }
362         the_list.append(new TheDbg(tid, owner, nm));
363 }
364
365 void TheList::dbg_del(pthread_t tid)
366 {
367         TheLocker the_locker;
368         int i = the_list.size();
369         while( --i >= 0 && the_list[i]->tid != tid );
370         if( i < 0 ) {
371                 printf("dbg_del, mis %016lx\n",(unsigned long)tid);
372                 return;
373         }
374         the_list.remove_object_number(i);
375 }
376
377
378 void TheList::dump_threads(FILE *fp)
379 {
380         int i = the_list.size();
381         while( --i >= 0 ) {
382                 fprintf(fp, "thread 0x%012lx, owner 0x%012lx, %s\n",
383                         (unsigned long)the_list[i]->tid, (unsigned long)the_list[i]->owner,
384                         the_list[i]->name);
385         }
386 }
387
388 #else
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)
392 {
393 }
394 #endif
395
396 void BC_Trace::dump_threads(FILE *fp)
397 {
398         TheList::dump_threads(fp);
399 }
400
401