1 #include <minix/mthread.h> 2 #include <stdio.h> 3 #include "global.h" 4 #include "proto.h" 5 6 /*===========================================================================* 7 * mthread_debug_f * 8 *===========================================================================*/ 9 #ifdef MDEBUG 10 void mthread_debug_f(const char *file, int line, const char *msg) 11 { 12 /* Print debug message */ 13 printf("MTH (%s:%d): %s\n", file, line, msg); 14 } 15 #endif 16 17 /*===========================================================================* 18 * mthread_panic_f * 19 *===========================================================================*/ 20 #ifdef MDEBUG 21 void mthread_panic_f(const char *file, int line, const char *msg) 22 { 23 /* Print panic message to stdout and exit */ 24 volatile int *sf; 25 26 sf = NULL; 27 28 printf("mthread panic (%s:%d): ", file, line); 29 printf("%s", msg); 30 printf("\n"); 31 fflush(stdout); /* Force debug print to screen */ 32 *((int *) sf ) = 1; /* Cause segfault to generate trace */ 33 exit(1); 34 } 35 #else 36 void mthread_panic_s(void) 37 { 38 /* Silent panic */ 39 volatile int *sf; 40 41 sf = NULL; 42 *((volatile int *) sf ) = 1; /* Cause segfault to generate trace */ 43 exit(1); 44 } 45 #endif 46 47 48 /*===========================================================================* 49 * mthread_verify_f * 50 *===========================================================================*/ 51 #ifdef MDEBUG 52 void mthread_verify_f(char *file, int line) 53 { 54 /* Verify library state. It is assumed this function is never called from 55 * a spawned thread, but from the 'main' thread. The library should be 56 * quiescent; no mutexes, conditions, or threads in use. All threads are to 57 * be in DEAD state. 58 */ 59 mthread_thread_t t; 60 mthread_tcb_t *tcb; 61 int threads_ok = 1, conditions_ok = 1, mutexes_ok = 1, attributes_ok = 1; 62 63 for (t = (mthread_thread_t) 0; threads_ok && t < no_threads; t++) { 64 tcb = mthread_find_tcb(t); 65 if (tcb->m_state != MS_DEAD) threads_ok = 0; 66 } 67 68 conditions_ok = mthread_cond_verify(); 69 mutexes_ok = mthread_mutex_verify(); 70 attributes_ok = mthread_attr_verify(); 71 72 printf("(%s:%d) VERIFY ", file, line); 73 printf("| threads: %s |", (threads_ok ? "ok": "NOT ok")); 74 printf("| cond: %s |", (conditions_ok ? "ok": "NOT ok")); 75 printf("| mutex: %s |", (mutexes_ok ? "ok": "NOT ok")); 76 printf("| attr: %s |", (attributes_ok ? "ok": "NOT ok")); 77 printf("\n"); 78 79 if(!threads_ok || !conditions_ok || !mutexes_ok) 80 mthread_panic("Library state corrupt\n"); 81 } 82 83 84 /*===========================================================================* 85 * mthread_stats * 86 *===========================================================================*/ 87 void mthread_stats(void) 88 { 89 mthread_thread_t t; 90 mthread_tcb_t *tcb; 91 int st_run, st_dead, st_cond, st_mutex, st_exit; 92 st_run = st_dead = st_cond = st_mutex = st_exit = 0; 93 94 for (t = (mthread_thread_t) 0; t < no_threads; t++) { 95 tcb = mthread_find_tcb(t); 96 switch(tcb->m_state) { 97 case MS_RUNNABLE: st_run++; break; 98 case MS_DEAD: st_dead++; break; 99 case MS_MUTEX: st_mutex++; break; 100 case MS_CONDITION: st_cond++; break; 101 case MS_EXITING: st_exit++; break; 102 default: mthread_panic("Unknown state"); 103 } 104 } 105 106 printf("Pool: %-5d In use: %-5d R: %-5d D: %-5d M: %-5d C: %-5d E: %-5d\n", 107 no_threads, used_threads, st_run, st_dead, st_mutex, st_cond, 108 st_exit); 109 } 110 111 #endif 112 113 114 /*===========================================================================* 115 * mthread_stacktrace * 116 *===========================================================================*/ 117 void mthread_stacktrace(mthread_thread_t t) 118 { 119 #ifdef __i386__ /* stacktrace only implemented on x86 */ 120 unsigned long bp, hbp, pc; 121 mthread_tcb_t *tcb; 122 ucontext_t *ctx; 123 124 tcb = mthread_find_tcb(t); 125 ctx = &tcb->m_context; 126 127 if (t != MAIN_THREAD && ctx->uc_stack.ss_size == 0) 128 return; /* no stack, no stacktrace */ 129 130 printf("thread %d: ", t); 131 132 bp = _UC_MACHINE_EBP(ctx); 133 134 while (bp) { 135 pc = ((unsigned long *) bp)[1]; 136 hbp = ((unsigned long *) bp)[0]; 137 138 printf("0x%lx ", (unsigned long) pc); 139 140 if (hbp != 0 && hbp <= bp) { 141 pc = -1; 142 printf("0x%lx ", (unsigned long) pc); 143 break; 144 } 145 bp = hbp; 146 } 147 148 printf("\n"); 149 #endif 150 } 151 152 /*===========================================================================* 153 * mthread_stacktraces * 154 *===========================================================================*/ 155 void mthread_stacktraces(void) 156 { 157 mthread_thread_t t; 158 159 mthread_stacktrace(MAIN_THREAD); 160 161 for (t = (mthread_thread_t) 0; t < no_threads; t++) 162 mthread_stacktrace(t); 163 } 164