Clean up mthread

This commit is contained in:
Thomas Veerman
2011-07-27 09:30:26 +00:00
parent b67a7fca8c
commit 9b43de2cb3
10 changed files with 111 additions and 132 deletions

View File

@@ -5,13 +5,10 @@
#include "global.h"
#include "proto.h"
#define FALLBACK_CTX (&(fallback.m_context))
FORWARD _PROTOTYPE( void mthread_fallback, (void) );
FORWARD _PROTOTYPE( int mthread_increase_thread_pool, (void) );
FORWARD _PROTOTYPE( void mthread_thread_init, (mthread_thread_t thread,
mthread_attr_t *tattr,
void (*proc)(void *),
void *(*proc)(void *),
void *arg) );
FORWARD _PROTOTYPE( void mthread_thread_reset, (mthread_thread_t thread));
@@ -45,7 +42,7 @@ mthread_thread_t r;
PUBLIC int mthread_create(threadid, tattr, proc, arg)
mthread_thread_t *threadid;
mthread_attr_t *tattr;
void (*proc)(void *);
void *(*proc)(void *);
void *arg;
{
/* Register procedure proc for execution in a thread. */
@@ -111,7 +108,6 @@ PUBLIC void mthread_exit(value)
void *value;
{
/* Make a thread stop running and store the result value. */
int fallback_exit = 0;
mthread_tcb_t *tcb;
mthread_init(); /* Make sure libmthread is initialized */
@@ -123,13 +119,6 @@ void *value;
mthread_cleanup_values();
/* When we're called from the fallback thread, the fallback thread
* will invoke the scheduler. However, if the thread itself called
* mthread_exit, _we_ will have to wake up the scheduler.
*/
if (tcb->m_state == MS_FALLBACK_EXITING)
fallback_exit = 1;
tcb->m_result = value;
tcb->m_state = MS_EXITING;
@@ -145,42 +134,9 @@ void *value;
*/
}
/* The fallback thread does a mthread_schedule. If we're not running from
* that thread, we have to do it ourselves.
*/
if (!fallback_exit)
mthread_schedule();
}
/*===========================================================================*
* mthread_fallback *
*===========================================================================*/
PRIVATE void mthread_fallback(void)
{
/* The libmthread fallback thread. The idea is that every thread calls
* mthread_exit(...) to stop running when it has nothing to do anymore.
* However, in case a thread forgets to do that, the whole process exit()s and
* that might be a bit problematic. Therefore, all threads will run this
* fallback thread when they exit, giving the scheduler a chance to fix the
* situation.
*/
mthread_tcb_t *tcb;
tcb = mthread_find_tcb(current_thread);
tcb->m_state = MS_FALLBACK_EXITING;
mthread_exit(NULL);
/* Reconstruct fallback context for next invocation */
makecontext(FALLBACK_CTX, (void (*) (void)) mthread_fallback, 0);
/* Let another thread run */
mthread_schedule();
}
/*===========================================================================*
* mthread_find_tcb *
*===========================================================================*/
@@ -288,15 +244,6 @@ PUBLIC void mthread_init(void)
mthread_init_keys();
mthread_init_scheduler();
/* Initialize the fallback thread */
if (mthread_getcontext(FALLBACK_CTX) == -1)
mthread_panic("Could not initialize fallback thread");
FALLBACK_CTX->uc_link = &(mainthread.m_context);
FALLBACK_CTX->uc_stack.ss_sp = fallback_stack;
FALLBACK_CTX->uc_stack.ss_size = STACKSZ;
memset(fallback_stack, '\0', STACKSZ);
makecontext(FALLBACK_CTX, (void (*) (void)) mthread_fallback, 0);
initialized = 1;
}
}
@@ -399,7 +346,7 @@ PUBLIC mthread_thread_t mthread_self(void)
PRIVATE void mthread_thread_init(thread, tattr, proc, arg)
mthread_thread_t thread;
mthread_attr_t *tattr;
void (*proc)(void *);
void *(*proc)(void *);
void *arg;
{
/* Initialize a thread so that it, when unsuspended, will run the given
@@ -414,7 +361,7 @@ void *arg;
tcb = mthread_find_tcb(thread);
tcb->m_next = NULL;
tcb->m_state = MS_DEAD;
tcb->m_proc = (void *(*)(void *)) proc; /* Yikes */
tcb->m_proc = proc;
tcb->m_arg = arg;
/* Threads use a copy of the provided attributes. This way, if another
* thread modifies the attributes (such as detach state), already running
@@ -429,10 +376,9 @@ void *arg;
if (mthread_cond_init(&(tcb->m_exited), NULL) != 0)
mthread_panic("Could not initialize thread");
/* First set the fallback thread, */
tcb->m_context.uc_link = FALLBACK_CTX;
tcb->m_context.uc_link = NULL;
/* then construct this thread's context to run procedure proc. */
/* Construct this thread's context to run procedure proc. */
if (mthread_getcontext(&(tcb->m_context)) == -1)
mthread_panic("Failed to initialize context state");

View File

@@ -2,8 +2,8 @@
#include "global.h"
#include "proto.h"
PRIVATE struct __mthread_cond *vc_front, *vc_rear;
#ifdef MTHREAD_STRICT
PRIVATE struct __mthread_cond *vc_front, *vc_rear;
FORWARD _PROTOTYPE( void mthread_cond_add, (mthread_cond_t *c) );
FORWARD _PROTOTYPE( void mthread_cond_remove, (mthread_cond_t *c) );
FORWARD _PROTOTYPE( int mthread_cond_valid, (mthread_cond_t *c) );
@@ -19,8 +19,10 @@ FORWARD _PROTOTYPE( int mthread_cond_valid, (mthread_cond_t *c) );
*===========================================================================*/
PUBLIC void mthread_init_valid_conditions(void)
{
#ifdef MTHREAD_STRICT
/* Initialize condition variable list */
vc_front = vc_rear = NULL;
#endif
}

View File

@@ -16,7 +16,7 @@
#define MTHREAD_NOT_INUSE 0xdefec7
typedef enum {
MS_CONDITION, MS_DEAD, MS_EXITING, MS_FALLBACK_EXITING, MS_MUTEX, MS_RUNNABLE
MS_CONDITION, MS_DEAD, MS_EXITING, MS_MUTEX, MS_RUNNABLE
} mthread_state_t;
struct __mthread_tcb {
@@ -40,10 +40,8 @@ EXTERN mthread_thread_t current_thread;
EXTERN mthread_queue_t free_threads;
EXTERN mthread_queue_t run_queue; /* FIFO of runnable threads */
EXTERN mthread_tcb_t **threads;
EXTERN mthread_tcb_t fallback;
EXTERN mthread_tcb_t mainthread;
EXTERN int no_threads;
EXTERN int used_threads;
EXTERN int running_main_thread;
EXTERN char fallback_stack[STACKSZ];

View File

@@ -3,6 +3,7 @@
#include "global.h"
#include "proto.h"
PRIVATE int keys_used = 0;
PRIVATE struct {
int used;
int nvalues;
@@ -34,6 +35,7 @@ PUBLIC int mthread_key_create(mthread_key_t *key, void (*destructor)(void *))
mthread_key_t k;
mthread_init(); /* Make sure libmthread is initialized */
keys_used = 1;
/* We do not yet allocate storage space for the values here, because we can
* not estimate how many threads will be created in the common case that the
@@ -150,6 +152,8 @@ PUBLIC void mthread_cleanup_values(void)
void *value;
int found;
if (!keys_used) return; /* Only clean up if we used any keys at all */
/* Any of the destructors may set a new value on any key, so we may have to
* loop over the table of keys multiple times. This implementation has no
* protection against infinite loops in this case.

View File

@@ -6,18 +6,18 @@
/*===========================================================================*
* mthread_debug_f *
*===========================================================================*/
#ifdef MDEBUG
PUBLIC void mthread_debug_f(const char *file, int line, const char *msg)
{
/* Print debug message */
#ifdef MDEBUG
printf("MTH (%s:%d): %s\n", file, line, msg);
#endif
}
#endif
/*===========================================================================*
* mthread_panic_f *
*===========================================================================*/
#ifdef MDEBUG
PUBLIC void mthread_panic_f(const char *file, int line, const char *msg)
{
/* Print panic message to stdout and exit */
@@ -32,6 +32,17 @@ PUBLIC void mthread_panic_f(const char *file, int line, const char *msg)
*((int *) sf ) = 1; /* Cause segfault to generate trace */
exit(1);
}
#else
PUBLIC void mthread_panic_s(void)
{
/* Silent panic */
volatile int *sf;
sf = NULL;
*((int *) sf ) = 1; /* Cause segfault to generate trace */
exit(1);
}
#endif
/*===========================================================================*
@@ -68,9 +79,6 @@ PUBLIC void mthread_verify_f(char *file, int line)
if(!threads_ok || !conditions_ok || !mutexes_ok)
mthread_panic("Library state corrupt\n");
}
#else
PUBLIC void mthread_verify_f(char *f, int l) { ; }
#endif
/*===========================================================================*
@@ -80,8 +88,8 @@ PUBLIC void mthread_stats(void)
{
mthread_thread_t t;
mthread_tcb_t *tcb;
int st_run, st_dead, st_cond, st_mutex, st_exit, st_fbexit;
st_run = st_dead = st_cond = st_mutex = st_exit = st_fbexit = 0;
int st_run, st_dead, st_cond, st_mutex, st_exit;
st_run = st_dead = st_cond = st_mutex = st_exit = 0;
for (t = (mthread_thread_t) 0; t < no_threads; t++) {
tcb = mthread_find_tcb(t);
@@ -91,13 +99,13 @@ PUBLIC void mthread_stats(void)
case MS_MUTEX: st_mutex++; break;
case MS_CONDITION: st_cond++; break;
case MS_EXITING: st_exit++; break;
case MS_FALLBACK_EXITING: st_fbexit++; break;
default: mthread_panic("Unknown state");
}
}
printf("Pool: %-5d In use: %-5d R: %-5d D: %-5d M: %-5d C: %-5d E: %-5d"
"F: %-5d\n",
printf("Pool: %-5d In use: %-5d R: %-5d D: %-5d M: %-5d C: %-5d E: %-5d\n",
no_threads, used_threads, st_run, st_dead, st_mutex, st_cond,
st_exit, st_fbexit);
st_exit);
}
#endif

View File

@@ -2,8 +2,8 @@
#include "global.h"
#include "proto.h"
PRIVATE struct __mthread_mutex *vm_front, *vm_rear;
#ifdef MTHREAD_STRICT
PRIVATE struct __mthread_mutex *vm_front, *vm_rear;
FORWARD _PROTOTYPE( void mthread_mutex_add, (mthread_mutex_t *m) );
FORWARD _PROTOTYPE( void mthread_mutex_remove, (mthread_mutex_t *m) );
#else
@@ -16,8 +16,10 @@ FORWARD _PROTOTYPE( void mthread_mutex_remove, (mthread_mutex_t *m) );
*===========================================================================*/
PUBLIC void mthread_init_valid_mutexes(void)
{
#ifdef MTHREAD_STRICT
/* Initialize list of valid mutexes */
vm_front = vm_rear = NULL;
#endif
}
@@ -135,14 +137,10 @@ mthread_mutex_t *mutex; /* Mutex that is to be locked */
return(EINVAL);
else if (m->mm_owner == NO_THREAD) { /* Not locked */
m->mm_owner = current_thread;
if (current_thread == MAIN_THREAD)
mthread_debug("MAIN_THREAD now mutex owner\n");
} else if (m->mm_owner == current_thread) {
return(EDEADLK);
} else {
mthread_queue_add(&m->mm_queue, current_thread);
if (m->mm_owner == MAIN_THREAD)
mthread_dump_queue(&m->mm_queue);
mthread_suspend(MS_MUTEX);
}
@@ -244,10 +242,10 @@ mthread_mutex_t *m;
loopitem = vm_front;
while (loopitem != NULL) {
if (loopitem == *m)
return(1);
if (loopitem == *m)
return(1);
loopitem = loopitem->mm_next;
loopitem = loopitem->mm_next;
}
return(0);
@@ -266,13 +264,15 @@ PUBLIC int mthread_mutex_verify(void)
mthread_init(); /* Make sure mthreads is initialized */
#ifdef MTHREAD_STRICT
loopitem = vm_front;
while (loopitem != NULL) {
printf("mutex corruption: owner: %d\n", loopitem->mm_owner);
loopitem = loopitem->next;
loopitem = loopitem->mm_next;
r = 0;
}
#endif
return(r);
}

View File

@@ -21,12 +21,18 @@ _PROTOTYPE( void mthread_init_keys, (void) );
_PROTOTYPE( void mthread_cleanup_values, (void) );
/* misc.c */
#ifdef MDEBUG
#define mthread_panic(m) mthread_panic_f(__FILE__, __LINE__, (m))
_PROTOTYPE( void mthread_panic_f, (const char *file, int line,
const char *msg) );
#define mthread_debug(m) mthread_debug_f(__FILE__, __LINE__, (m))
_PROTOTYPE( void mthread_debug_f, (const char *file, int line,
const char *msg) );
#else
_PROTOTYPE( void mthread_panic_s, (void) );
# define mthread_panic(m) mthread_panic_s()
# define mthread_debug(m)
#endif
/* mutex.c */
_PROTOTYPE( void mthread_init_valid_mutexes, (void) );
@@ -49,7 +55,9 @@ _PROTOTYPE( void mthread_suspend, (mthread_state_t state) );
_PROTOTYPE( void mthread_unsuspend, (mthread_thread_t thread) );
/* queue.c */
#ifdef MDEBUG
_PROTOTYPE( void mthread_dump_queue, (mthread_queue_t *queue) );
#endif
_PROTOTYPE( void mthread_queue_init, (mthread_queue_t *queue) );
_PROTOTYPE( void mthread_queue_add, (mthread_queue_t *queue,
mthread_thread_t thread) );

View File

@@ -54,6 +54,7 @@ mthread_queue_t *queue;
/*===========================================================================*
* mthread_dump_queue *
*===========================================================================*/
#ifdef MDEBUG
PUBLIC void mthread_dump_queue(queue)
mthread_queue_t *queue;
{
@@ -61,39 +62,30 @@ mthread_queue_t *queue;
mthread_tcb_t *t;
mthread_thread_t tid;
threshold = no_threads;
#ifdef MDEBUG
printf("Dumping queue: ");
#endif
if(queue->mq_head != NULL) {
t = queue->mq_head;
if (t == &mainthread) tid = MAIN_THREAD;
else tid = t->m_tid;
#ifdef MDEBUG
printf("%d ", tid);
#endif
count++;
t = t->m_next;
while (t != NULL) {
if (t == &mainthread) tid = MAIN_THREAD;
else tid = t->m_tid;
#ifdef MDEBUG
printf("%d ", tid);
#endif
t = t->m_next;
count++;
if (count > threshold) break;
}
} else {
#ifdef MDEBUG
printf("[empty]");
#endif
}
#ifdef MDEBUG
printf("\n");
#endif
}
#endif
/*===========================================================================*
* mthread_queue_remove *