2010-09-21 14:22:38 +02:00
|
|
|
#include <minix/mthread.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "global.h"
|
2010-09-30 15:44:13 +02:00
|
|
|
#include "proto.h"
|
2010-09-21 14:22:38 +02:00
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* mthread_debug_f *
|
|
|
|
*===========================================================================*/
|
2011-07-27 11:30:26 +02:00
|
|
|
#ifdef MDEBUG
|
2012-03-25 20:25:53 +02:00
|
|
|
void mthread_debug_f(const char *file, int line, const char *msg)
|
2010-09-21 14:22:38 +02:00
|
|
|
{
|
|
|
|
/* Print debug message */
|
|
|
|
printf("MTH (%s:%d): %s\n", file, line, msg);
|
|
|
|
}
|
2011-07-27 11:30:26 +02:00
|
|
|
#endif
|
2010-09-21 14:22:38 +02:00
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* mthread_panic_f *
|
|
|
|
*===========================================================================*/
|
2011-07-27 11:30:26 +02:00
|
|
|
#ifdef MDEBUG
|
2012-03-25 20:25:53 +02:00
|
|
|
void mthread_panic_f(const char *file, int line, const char *msg)
|
2010-09-21 14:22:38 +02:00
|
|
|
{
|
|
|
|
/* Print panic message to stdout and exit */
|
2011-07-08 15:59:07 +02:00
|
|
|
volatile int *sf;
|
|
|
|
|
|
|
|
sf = NULL;
|
|
|
|
|
2010-09-30 15:44:13 +02:00
|
|
|
printf("mthread panic (%s:%d): ", file, line);
|
2011-07-08 15:59:07 +02:00
|
|
|
printf("%s", msg);
|
2010-09-21 14:22:38 +02:00
|
|
|
printf("\n");
|
2010-09-30 15:44:13 +02:00
|
|
|
fflush(stdout); /* Force debug print to screen */
|
2011-07-08 15:59:07 +02:00
|
|
|
*((int *) sf ) = 1; /* Cause segfault to generate trace */
|
2010-09-21 14:22:38 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
2011-07-27 11:30:26 +02:00
|
|
|
#else
|
2012-03-25 20:25:53 +02:00
|
|
|
void mthread_panic_s(void)
|
2011-07-27 11:30:26 +02:00
|
|
|
{
|
|
|
|
/* Silent panic */
|
|
|
|
volatile int *sf;
|
|
|
|
|
|
|
|
sf = NULL;
|
|
|
|
*((int *) sf ) = 1; /* Cause segfault to generate trace */
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
#endif
|
2010-09-21 14:22:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* mthread_verify_f *
|
|
|
|
*===========================================================================*/
|
|
|
|
#ifdef MDEBUG
|
2012-03-25 20:25:53 +02:00
|
|
|
void mthread_verify_f(char *file, int line)
|
2010-09-21 14:22:38 +02:00
|
|
|
{
|
|
|
|
/* Verify library state. It is assumed this function is never called from
|
|
|
|
* a spawned thread, but from the 'main' thread. The library should be
|
|
|
|
* quiescent; no mutexes, conditions, or threads in use. All threads are to
|
|
|
|
* be in DEAD state.
|
|
|
|
*/
|
2010-09-30 15:44:13 +02:00
|
|
|
mthread_thread_t t;
|
|
|
|
mthread_tcb_t *tcb;
|
2010-09-21 14:22:38 +02:00
|
|
|
int threads_ok = 1, conditions_ok = 1, mutexes_ok = 1, attributes_ok = 1;
|
|
|
|
|
2010-09-30 15:44:13 +02:00
|
|
|
for (t = (mthread_thread_t) 0; threads_ok && t < no_threads; t++) {
|
|
|
|
tcb = mthread_find_tcb(t);
|
|
|
|
if (tcb->m_state != MS_DEAD) threads_ok = 0;
|
|
|
|
}
|
2010-09-21 14:22:38 +02:00
|
|
|
|
|
|
|
conditions_ok = mthread_cond_verify();
|
|
|
|
mutexes_ok = mthread_mutex_verify();
|
|
|
|
attributes_ok = mthread_attr_verify();
|
|
|
|
|
|
|
|
printf("(%s:%d) VERIFY ", file, line);
|
|
|
|
printf("| threads: %s |", (threads_ok ? "ok": "NOT ok"));
|
|
|
|
printf("| cond: %s |", (conditions_ok ? "ok": "NOT ok"));
|
|
|
|
printf("| mutex: %s |", (mutexes_ok ? "ok": "NOT ok"));
|
|
|
|
printf("| attr: %s |", (attributes_ok ? "ok": "NOT ok"));
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
if(!threads_ok || !conditions_ok || !mutexes_ok)
|
|
|
|
mthread_panic("Library state corrupt\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* mthread_stats *
|
|
|
|
*===========================================================================*/
|
2012-03-25 20:25:53 +02:00
|
|
|
void mthread_stats(void)
|
2010-09-21 14:22:38 +02:00
|
|
|
{
|
2010-09-30 15:44:13 +02:00
|
|
|
mthread_thread_t t;
|
|
|
|
mthread_tcb_t *tcb;
|
2011-07-27 11:30:26 +02:00
|
|
|
int st_run, st_dead, st_cond, st_mutex, st_exit;
|
|
|
|
st_run = st_dead = st_cond = st_mutex = st_exit = 0;
|
2010-09-21 14:22:38 +02:00
|
|
|
|
2010-09-30 15:44:13 +02:00
|
|
|
for (t = (mthread_thread_t) 0; t < no_threads; t++) {
|
|
|
|
tcb = mthread_find_tcb(t);
|
|
|
|
switch(tcb->m_state) {
|
|
|
|
case MS_RUNNABLE: st_run++; break;
|
|
|
|
case MS_DEAD: st_dead++; break;
|
|
|
|
case MS_MUTEX: st_mutex++; break;
|
|
|
|
case MS_CONDITION: st_cond++; break;
|
|
|
|
case MS_EXITING: st_exit++; break;
|
2010-09-21 14:22:38 +02:00
|
|
|
default: mthread_panic("Unknown state");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-27 11:30:26 +02:00
|
|
|
printf("Pool: %-5d In use: %-5d R: %-5d D: %-5d M: %-5d C: %-5d E: %-5d\n",
|
2010-09-21 14:22:38 +02:00
|
|
|
no_threads, used_threads, st_run, st_dead, st_mutex, st_cond,
|
2011-07-27 11:30:26 +02:00
|
|
|
st_exit);
|
2010-09-21 14:22:38 +02:00
|
|
|
}
|
2011-07-27 11:30:26 +02:00
|
|
|
|
|
|
|
#endif
|
2012-03-30 11:16:46 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* mthread_stacktrace *
|
|
|
|
*===========================================================================*/
|
|
|
|
void mthread_stacktrace(mthread_thread_t t)
|
|
|
|
{
|
|
|
|
unsigned long bp, hbp, pc;
|
|
|
|
mthread_tcb_t *tcb;
|
|
|
|
ucontext_t *ctx;
|
|
|
|
mcontext_t *mtx;
|
|
|
|
struct stackframe_s *frame;
|
|
|
|
|
|
|
|
printf("thread %d: ", t);
|
|
|
|
|
|
|
|
tcb = mthread_find_tcb(t);
|
|
|
|
ctx = &tcb->m_context;
|
|
|
|
mtx = &ctx->uc_mcontext;
|
|
|
|
frame = &mtx->mc_p_reg;
|
|
|
|
bp = frame->fp;
|
|
|
|
|
|
|
|
while (bp) {
|
|
|
|
pc = ((unsigned long *) bp)[1];
|
|
|
|
hbp = ((unsigned long *) bp)[0];
|
|
|
|
|
|
|
|
printf("0x%lx ", (unsigned long) pc);
|
|
|
|
|
|
|
|
if (hbp != 0 && hbp <= bp) {
|
|
|
|
pc = -1;
|
|
|
|
printf("0x%lx ", (unsigned long) pc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
bp = hbp;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*
|
|
|
|
* mthread_stacktraces *
|
|
|
|
*===========================================================================*/
|
|
|
|
void mthread_stacktraces(void)
|
|
|
|
{
|
|
|
|
mthread_thread_t t;
|
|
|
|
|
|
|
|
mthread_stacktrace(MAIN_THREAD);
|
|
|
|
|
|
|
|
for (t = (mthread_thread_t) 0; t < no_threads; t++)
|
|
|
|
mthread_stacktrace(t);
|
|
|
|
}
|