xref: /minix3/minix/lib/libmthread/misc.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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