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