- Refactor mthread structure fields to prevent name clashes

- Remove sanity checks for initialized mutexes and condition variables. This
  significantly boosts performance. The checks can be turned back on by
  compiling libmthread with MTHREAD_STRICT. According to POSIX operations on
  uninitialized variables are a MAY fail if, therefore allowing this
  optimization.
- Test59 has to be accommodated to the lack of sanity checks on uninitialized
  variables in the library. It specifically tests for them and will run into
  segfaults when the checks are absent in the library.
- Fix a few bugs related to the scheduler
- Do some general code cleanups
This commit is contained in:
Thomas Veerman 2011-03-18 10:29:54 +00:00
parent 03a7d0e8ae
commit c8d0edc06a
10 changed files with 178 additions and 146 deletions

View file

@ -24,31 +24,33 @@ typedef void * mthread_mutexattr_t;
struct __mthread_tcb;
typedef struct {
struct __mthread_tcb *head;
struct __mthread_tcb *tail;
struct __mthread_tcb *mq_head;
struct __mthread_tcb *mq_tail;
} mthread_queue_t;
struct __mthread_mutex {
mthread_queue_t queue; /* Queue of threads blocked on this mutex */
mthread_thread_t owner; /* Thread ID that currently owns mutex */
struct __mthread_mutex *prev;
struct __mthread_mutex *next;
mthread_queue_t mm_queue; /* Queue of threads blocked on this mutex */
mthread_thread_t mm_owner; /* Thread ID that currently owns mutex */
struct __mthread_mutex *mm_prev;
struct __mthread_mutex *mm_next;
unsigned int mm_magic;
};
typedef struct __mthread_mutex *mthread_mutex_t;
struct __mthread_cond {
struct __mthread_mutex *mutex; /* Associate mutex with condition */
struct __mthread_cond *prev;
struct __mthread_cond *next;
struct __mthread_mutex *mc_mutex; /* Associate mutex with condition */
struct __mthread_cond *mc_prev;
struct __mthread_cond *mc_next;
unsigned int mc_magic;
};
typedef struct __mthread_cond *mthread_cond_t;
struct __mthread_attr {
size_t a_stacksize;
char *a_stackaddr;
int a_detachstate;
struct __mthread_attr *prev;
struct __mthread_attr *next;
size_t ma_stacksize;
char *ma_stackaddr;
int ma_detachstate;
struct __mthread_attr *ma_prev;
struct __mthread_attr *ma_next;
};
typedef struct __mthread_attr *mthread_attr_t;
@ -106,12 +108,7 @@ _PROTOTYPE( void mthread_verify_f, (char *f, int l) );
_PROTOTYPE( int mthread_mutex_destroy, (mthread_mutex_t *mutex) );
_PROTOTYPE( int mthread_mutex_init, (mthread_mutex_t *mutex,
mthread_mutexattr_t *mattr) );
#if 0
_PROTOTYPE( int mthread_mutex_lock, (mthread_mutex_t *mutex) );
#endif
_PROTOTYPE( int mthread_mutex_lock_f, (mthread_mutex_t *mutex,
char *file, int line) );
#define mthread_mutex_lock(x) mthread_mutex_lock_f(x, __FILE__, __LINE__)
_PROTOTYPE( int mthread_mutex_trylock, (mthread_mutex_t *mutex) );
_PROTOTYPE( int mthread_mutex_unlock, (mthread_mutex_t *mutex) );

View file

@ -100,11 +100,11 @@ mthread_thread_t detach;
if (tcb->m_state == MS_DEAD) {
errno = ESRCH;
return(-1);
} else if (tcb->m_attr.a_detachstate != MTHREAD_CREATE_DETACHED) {
} else if (tcb->m_attr.ma_detachstate != MTHREAD_CREATE_DETACHED) {
if (tcb->m_state == MS_EXITING)
mthread_thread_stop(detach);
else
tcb->m_attr.a_detachstate = MTHREAD_CREATE_DETACHED;
tcb->m_attr.ma_detachstate = MTHREAD_CREATE_DETACHED;
}
return(0);
@ -138,7 +138,7 @@ void *value;
tcb->m_result = value;
tcb->m_state = MS_EXITING;
if (tcb->m_attr.a_detachstate == MTHREAD_CREATE_DETACHED) {
if (tcb->m_attr.ma_detachstate == MTHREAD_CREATE_DETACHED) {
mthread_thread_stop(current_thread);
} else {
/* Joinable thread; notify possibly waiting thread */
@ -283,7 +283,7 @@ PUBLIC void mthread_init(void)
* not enter this clause.
*/
if (getcontext(&(mainthread.m_context)) == -1)
if (mthread_getcontext(&(mainthread.m_context)) == -1)
mthread_panic("Couldn't save state for main thread");
current_thread = MAIN_THREAD;
@ -293,7 +293,7 @@ PUBLIC void mthread_init(void)
mthread_init_scheduler();
/* Initialize the fallback thread */
if (getcontext(FALLBACK_CTX) == -1)
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;
@ -331,7 +331,7 @@ void **value;
if (tcb->m_state == MS_DEAD) {
errno = ESRCH;
return(-1);
} else if (tcb->m_attr.a_detachstate == MTHREAD_CREATE_DETACHED) {
} else if (tcb->m_attr.ma_detachstate == MTHREAD_CREATE_DETACHED) {
errno = EINVAL;
return(-1);
}
@ -445,11 +445,11 @@ void *arg;
tcb->m_context.uc_link = FALLBACK_CTX;
/* then construct this thread's context to run procedure proc. */
if (getcontext(&(tcb->m_context)) == -1)
if (mthread_getcontext(&(tcb->m_context)) == -1)
mthread_panic("Failed to initialize context state");
stacksize = tcb->m_attr.a_stacksize;
stackaddr = tcb->m_attr.a_stackaddr;
stacksize = tcb->m_attr.ma_stacksize;
stackaddr = tcb->m_attr.ma_stackaddr;
if (stacksize == (size_t) 0)
stacksize = (size_t) MTHREAD_STACK_MIN;
@ -488,9 +488,10 @@ mthread_thread_t thread;
rt->m_arg = NULL;
rt->m_result = NULL;
rt->m_cond = NULL;
if (rt->m_context.uc_stack.ss_sp)
if (rt->m_context.uc_stack.ss_sp) {
free(rt->m_context.uc_stack.ss_sp); /* Free allocated stack */
rt->m_context.uc_stack.ss_sp = NULL;
rt->m_context.uc_stack.ss_sp = NULL;
}
rt->m_context.uc_stack.ss_size = 0;
rt->m_context.uc_link = NULL;
}

View file

@ -27,13 +27,13 @@ mthread_attr_t *a;
if (va_front == NULL) { /* Empty list */
va_front = *a;
(*a)->prev = NULL;
(*a)->ma_prev = NULL;
} else {
va_rear->next = *a;
(*a)->prev = va_rear;
va_rear->ma_next = *a;
(*a)->ma_prev = va_rear;
}
(*a)->next = NULL;
(*a)->ma_next = NULL;
va_rear = *a;
}
@ -89,9 +89,9 @@ mthread_attr_t *attr; /* Attribute */
if ((a = malloc(sizeof(struct __mthread_attr))) == NULL)
return(-1);
a->a_detachstate = MTHREAD_CREATE_JOINABLE;
a->a_stackaddr = NULL;
a->a_stacksize = (size_t) 0;
a->ma_detachstate = MTHREAD_CREATE_JOINABLE;
a->ma_stackaddr = NULL;
a->ma_stacksize = (size_t) 0;
*attr = (mthread_attr_t) a;
mthread_attr_add(attr); /* Validate attribute: attribute now in use */
@ -122,7 +122,7 @@ int *detachstate;
return(-1);
}
*detachstate = a->a_detachstate;
*detachstate = a->ma_detachstate;
return(0);
}
@ -155,7 +155,7 @@ int detachstate;
return(-1);
}
a->a_detachstate = detachstate;
a->ma_detachstate = detachstate;
return(0);
}
@ -185,8 +185,8 @@ size_t *stacksize;
return(-1);
}
*stackaddr = a->a_stackaddr;
*stacksize = a->a_stacksize;
*stackaddr = a->ma_stackaddr;
*stacksize = a->ma_stacksize;
return(0);
}
@ -215,7 +215,7 @@ size_t *stacksize;
return(-1);
}
*stacksize = a->a_stacksize;
*stacksize = a->ma_stacksize;
return(0);
}
@ -249,8 +249,8 @@ size_t stacksize;
* the cost of some memory if needed).
*/
a->a_stackaddr = stackaddr;
a->a_stacksize = stacksize;
a->ma_stackaddr = stackaddr;
a->ma_stacksize = stacksize;
return(0);
}
@ -279,7 +279,7 @@ size_t stacksize;
return(-1);
}
a->a_stacksize = stacksize;
a->ma_stacksize = stacksize;
return(0);
}
@ -293,15 +293,15 @@ mthread_attr_t *a;
{
/* Remove attribute from list of valid, initialized attributes */
if ((*a)->prev == NULL)
va_front = (*a)->next;
if ((*a)->ma_prev == NULL)
va_front = (*a)->ma_next;
else
(*a)->prev->next = (*a)->next;
(*a)->ma_prev->ma_next = (*a)->ma_next;
if ((*a)->next == NULL)
va_rear = (*a)->prev;
if ((*a)->ma_next == NULL)
va_rear = (*a)->ma_prev;
else
(*a)->next->prev = (*a)->prev;
(*a)->ma_next->ma_prev = (*a)->ma_prev;
}
@ -322,7 +322,7 @@ mthread_attr_t *a;
if (loopitem == *a)
return(1);
loopitem = loopitem->next;
loopitem = loopitem->ma_next;
}
return(0);
@ -343,7 +343,7 @@ PUBLIC int mthread_attr_verify(void)
loopitem = va_front;
while (loopitem != NULL) {
loopitem = loopitem->next;
loopitem = loopitem->ma_next;
return(0);
}

View file

@ -3,9 +3,15 @@
#include "proto.h"
PRIVATE struct __mthread_cond *vc_front, *vc_rear;
#ifdef MTHREAD_STRICT
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) );
#else
# define mthread_cond_add(c) ((*c)->mc_magic = MTHREAD_INIT_MAGIC)
# define mthread_cond_remove(c) ((*c)->mc_magic = MTHREAD_NOT_INUSE)
# define mthread_cond_valid(c) ((*c)->mc_magic == MTHREAD_INIT_MAGIC)
#endif
#define MAIN_COND mainthread.m_cond
/*===========================================================================*
@ -21,6 +27,7 @@ PUBLIC void mthread_init_valid_conditions(void)
/*===========================================================================*
* mthread_cond_add *
*===========================================================================*/
#ifdef MTHREAD_STRICT
PRIVATE void mthread_cond_add(c)
mthread_cond_t *c;
{
@ -28,16 +35,16 @@ mthread_cond_t *c;
if (vc_front == NULL) { /* Empty list */
vc_front = *c;
(*c)->prev = NULL;
(*c)->mc_prev = NULL;
} else {
vc_rear->next = *c;
(*c)->prev = vc_rear;
vc_rear->mc_next = *c;
(*c)->mc_prev = vc_rear;
}
(*c)->next = NULL;
(*c)->mc_next = NULL;
vc_rear = *c;
}
#endif
/*===========================================================================*
* mthread_cond_broadcast *
@ -51,12 +58,10 @@ mthread_cond_t *cond;
mthread_init(); /* Make sure libmthread is initialized */
if(cond == NULL) {
if (cond == NULL) {
errno = EINVAL;
return(-1);
}
if (!mthread_cond_valid(cond)) {
} else if (!mthread_cond_valid(cond)) {
errno = EINVAL;
return(-1);
}
@ -90,9 +95,7 @@ mthread_cond_t *cond;
if (cond == NULL) {
errno = EINVAL;
return(-1);
}
if (!mthread_cond_valid(cond)) {
} else if (!mthread_cond_valid(cond)) {
errno = EINVAL;
return(-1);
}
@ -106,7 +109,7 @@ mthread_cond_t *cond;
for (t = (mthread_thread_t) 0; t < no_threads; t++) {
tcb = mthread_find_tcb(t);
if(tcb->m_state == MS_CONDITION && tcb->m_cond == *cond){
if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond){
errno = EBUSY;
return(-1);
}
@ -140,17 +143,19 @@ mthread_condattr_t *cattr;
errno = ENOSYS;
return(-1);
}
if (mthread_cond_valid(cond)) {
#ifdef MTHREAD_STRICT
else if (mthread_cond_valid(cond)) {
/* Already initialized */
errno = EBUSY;
return(-1);
}
if ((c = malloc(sizeof(struct __mthread_cond))) == NULL)
}
#endif
else if ((c = malloc(sizeof(struct __mthread_cond))) == NULL) {
errno = ENOMEM;
return(-1);
}
c->mutex = NULL;
c->mc_mutex = NULL;
*cond = (mthread_cond_t) c;
mthread_cond_add(cond);
@ -161,23 +166,24 @@ mthread_condattr_t *cattr;
/*===========================================================================*
* mthread_cond_remove *
*===========================================================================*/
#ifdef MTHREAD_STRICT
PRIVATE void mthread_cond_remove(c)
mthread_cond_t *c;
{
/* Remove condition from list of valid, initialized conditions */
if ((*c)->prev == NULL)
vc_front = (*c)->next;
if ((*c)->mc_prev == NULL)
vc_front = (*c)->mc_next;
else
(*c)->prev->next = (*c)->next;
(*c)->mc_prev->mc_next = (*c)->mc_next;
if ((*c)->next == NULL)
vc_rear = (*c)->prev;
if ((*c)->mc_next == NULL)
vc_rear = (*c)->mc_prev;
else
(*c)->next->prev = (*c)->prev;
(*c)->mc_next->mc_prev = (*c)->mc_prev;
}
#endif
/*===========================================================================*
* mthread_cond_signal *
@ -191,12 +197,10 @@ mthread_cond_t *cond;
mthread_init(); /* Make sure libmthread is initialized */
if(cond == NULL) {
if (cond == NULL) {
errno = EINVAL;
return(-1);
}
if (!mthread_cond_valid(cond)) {
} else if (!mthread_cond_valid(cond)) {
errno = EINVAL;
return(-1);
}
@ -207,7 +211,7 @@ mthread_cond_t *cond;
for (t = (mthread_thread_t) 0; t < no_threads; t++) {
tcb = mthread_find_tcb(t);
if(tcb->m_state == MS_CONDITION && tcb->m_cond == *cond){
if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond){
mthread_unsuspend(t);
break;
}
@ -220,24 +224,27 @@ mthread_cond_t *cond;
/*===========================================================================*
* mthread_cond_valid *
*===========================================================================*/
#ifdef MTHREAD_STRICT
PRIVATE int mthread_cond_valid(c)
mthread_cond_t *c;
{
/* Check to see if cond is on the list of valid conditions */
struct __mthread_cond *loopitem;
mthread_init();
loopitem = vc_front;
while (loopitem != NULL) {
if (loopitem == *c)
return(1);
loopitem = loopitem->next;
loopitem = loopitem->mc_next;
}
return(0);
}
#endif
/*===========================================================================*
* mthread_cond_verify *
@ -281,7 +288,7 @@ mthread_mutex_t *mutex;
return(-1);
}
c->mutex = m; /* Remember we're using this mutex in a cond_wait */
c->mc_mutex = m; /* Remember we're using this mutex in a cond_wait */
if (mthread_mutex_unlock(mutex) != 0) /* Fails when we're not the owner */
return(-1);
@ -290,7 +297,7 @@ mthread_mutex_t *mutex;
mthread_suspend(MS_CONDITION);
/* When execution returns here, the condition was met. Lock mutex again. */
c->mutex = NULL; /* Forget about this mutex */
c->mc_mutex = NULL; /* Forget about this mutex */
tcb->m_cond = NULL; /* ... and condition var */
if (mthread_mutex_lock(mutex) != 0)
return(-1);

View file

@ -12,6 +12,8 @@
#define MAIN_THREAD -1
#define NO_THREAD -2
#define isokthreadid(i) (i == MAIN_THREAD || (i >= 0 && i < no_threads))
#define MTHREAD_INIT_MAGIC 0xca11ab1e
#define MTHREAD_NOT_INUSE 0xdefec7
typedef enum {
MS_CONDITION, MS_DEAD, MS_EXITING, MS_FALLBACK_EXITING, MS_MUTEX, MS_RUNNABLE

View file

@ -3,8 +3,13 @@
#include "proto.h"
PRIVATE struct __mthread_mutex *vm_front, *vm_rear;
#ifdef MTHREAD_STRICT
FORWARD _PROTOTYPE( void mthread_mutex_add, (mthread_mutex_t *m) );
FORWARD _PROTOTYPE( void mthread_mutex_remove, (mthread_mutex_t *m) );
#else
# define mthread_mutex_add(m) ((*m)->mm_magic = MTHREAD_INIT_MAGIC)
# define mthread_mutex_remove(m) ((*m)->mm_magic = MTHREAD_NOT_INUSE)
#endif
/*===========================================================================*
* mthread_init_valid_mutexes *
@ -19,6 +24,7 @@ PUBLIC void mthread_init_valid_mutexes(void)
/*===========================================================================*
* mthread_mutex_add *
*===========================================================================*/
#ifdef MTHREAD_STRICT
PRIVATE void mthread_mutex_add(m)
mthread_mutex_t *m;
{
@ -26,16 +32,16 @@ mthread_mutex_t *m;
if (vm_front == NULL) { /* Empty list */
vm_front = *m;
(*m)->prev = NULL;
(*m)->mm_prev = NULL;
} else {
vm_rear->next = *m;
(*m)->prev = vm_rear;
vm_rear->mm_next = *m;
(*m)->mm_prev = vm_rear;
}
(*m)->next = NULL;
(*m)->mm_next = NULL;
vm_rear = *m;
}
#endif
/*===========================================================================*
* mthread_mutex_destroy *
@ -58,8 +64,7 @@ mthread_mutex_t *mutex;
if (!mthread_mutex_valid(mutex)) {
errno = EINVAL;
return(-1);
} else if ((*mutex)->owner != NO_THREAD) {
printf("mutex owner is %d, so not destroying\n", (*mutex)->owner);
} else if ((*mutex)->mm_owner != NO_THREAD) {
errno = EBUSY;
return(-1);
}
@ -68,7 +73,7 @@ mthread_mutex_t *mutex;
for (t = (mthread_thread_t) 0; t < no_threads; t++) {
tcb = mthread_find_tcb(t);
if (tcb->m_state == MS_CONDITION) {
if (tcb->m_cond != NULL && tcb->m_cond->mutex == *mutex) {
if (tcb->m_cond != NULL && tcb->m_cond->mc_mutex == *mutex) {
errno = EBUSY;
return(-1);
}
@ -103,16 +108,20 @@ mthread_mutexattr_t *mattr; /* Mutex attribute */
} else if (mattr != NULL) {
errno = ENOSYS;
return(-1);
} else if (mthread_mutex_valid(mutex)) {
}
#ifdef MTHREAD_STRICT
else if (mthread_mutex_valid(mutex)) {
errno = EBUSY;
return(-1);
}
if ((m = malloc(sizeof(struct __mthread_mutex))) == NULL)
#endif
else if ((m = malloc(sizeof(struct __mthread_mutex))) == NULL) {
errno = ENOMEM;
return(-1);
}
mthread_queue_init( &(m->queue) );
m->owner = NO_THREAD;
mthread_queue_init(&m->mm_queue);
m->mm_owner = NO_THREAD;
*mutex = (mthread_mutex_t) m;
mthread_mutex_add(mutex); /* Validate mutex; mutex now in use */
@ -122,10 +131,8 @@ mthread_mutexattr_t *mattr; /* Mutex attribute */
/*===========================================================================*
* mthread_mutex_lock *
*===========================================================================*/
PUBLIC int mthread_mutex_lock_f(mutex, file, line)
PUBLIC int mthread_mutex_lock(mutex)
mthread_mutex_t *mutex; /* Mutex that is to be locked */
char file[NAME_MAX + 1];
int line;
{
/* Try to lock this mutex. If already locked, append the current thread to
* FIFO queue associated with this mutex and suspend the thread. */
@ -143,17 +150,17 @@ int line;
if (!mthread_mutex_valid(&m)) {
errno = EINVAL;
return(-1);
} else if (m->owner == NO_THREAD) { /* Not locked */
m->owner = current_thread;
} 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->owner == current_thread) {
} else if (m->mm_owner == current_thread) {
errno = EDEADLK;
return(-1);
} else {
mthread_queue_add( &(m->queue), current_thread);
if (m->owner == MAIN_THREAD)
mthread_dump_queue(&(m->queue));
mthread_queue_add(&m->mm_queue, current_thread);
if (m->mm_owner == MAIN_THREAD)
mthread_dump_queue(&m->mm_queue);
mthread_suspend(MS_MUTEX);
}
@ -165,22 +172,23 @@ int line;
/*===========================================================================*
* mthread_mutex_remove *
*===========================================================================*/
#ifdef MTHREAD_STRICT
PRIVATE void mthread_mutex_remove(m)
mthread_mutex_t *m;
{
/* Remove mutex from list of valid, initialized mutexes */
if ((*m)->prev == NULL)
vm_front = (*m)->next;
if ((*m)->mm_prev == NULL)
vm_front = (*m)->mm_next;
else
(*m)->prev->next = (*m)->next;
(*m)->mm_prev->mm_next = (*m)->mm_next;
if ((*m)->next == NULL)
vm_rear = (*m)->prev;
if ((*m)->mm_next == NULL)
vm_rear = (*m)->mm_prev;
else
(*m)->next->prev = (*m)->prev;
(*m)->mm_next->mm_prev = (*m)->mm_prev;
}
#endif
/*===========================================================================*
* mthread_mutex_trylock *
@ -203,8 +211,8 @@ mthread_mutex_t *mutex; /* Mutex that is to be locked */
if (!mthread_mutex_valid(&m)) {
errno = EINVAL;
return(-1);
} else if (m->owner == NO_THREAD) {
m->owner = current_thread;
} else if (m->mm_owner == NO_THREAD) {
m->mm_owner = current_thread;
return(0);
}
@ -235,13 +243,13 @@ mthread_mutex_t *mutex; /* Mutex that is to be unlocked */
if (!mthread_mutex_valid(&m)) {
errno = EINVAL;
return(-1);
} else if (m->owner != current_thread) {
} else if (m->mm_owner != current_thread) {
errno = EPERM;
return(-1); /* Can't unlock a mutex locked by another thread. */
}
m->owner = mthread_queue_remove( &(m->queue) );
if (m->owner != NO_THREAD) mthread_unsuspend(m->owner);
m->mm_owner = mthread_queue_remove(&m->mm_queue);
if (m->mm_owner != NO_THREAD) mthread_unsuspend(m->mm_owner);
return(0);
}
@ -249,6 +257,7 @@ mthread_mutex_t *mutex; /* Mutex that is to be unlocked */
/*===========================================================================*
* mthread_mutex_valid *
*===========================================================================*/
#ifdef MTHREAD_STRICT
PUBLIC int mthread_mutex_valid(m)
mthread_mutex_t *m;
{
@ -263,12 +272,12 @@ mthread_mutex_t *m;
if (loopitem == *m)
return(1);
loopitem = loopitem->next;
loopitem = loopitem->mm_next;
}
return(0);
}
#endif
/*===========================================================================*
* mthread_mutex_verify *
@ -285,7 +294,7 @@ PUBLIC int mthread_mutex_verify(void)
loopitem = vm_front;
while (loopitem != NULL) {
printf("mutex corruption: owner: %d\n", loopitem->owner);
printf("mutex corruption: owner: %d\n", loopitem->mm_owner);
loopitem = loopitem->next;
r = 0;
}

View file

@ -26,7 +26,13 @@ _PROTOTYPE( void mthread_debug_f, (const char *file, int line,
/* mutex.c */
_PROTOTYPE( void mthread_init_valid_mutexes, (void) );
#ifdef MTHREAD_STRICT
_PROTOTYPE( int mthread_mutex_valid, (mthread_mutex_t *mutex) );
#else
# define mthread_mutex_valid(x) ((*x)->mm_magic == MTHREAD_INIT_MAGIC)
#endif
#ifdef MDEBUG
_PROTOTYPE( int mthread_mutex_verify, (void) );
#endif

View file

@ -21,10 +21,10 @@ mthread_thread_t thread;
last = mthread_find_tcb(thread);
if (mthread_queue_isempty(queue)) {
queue->head = queue->tail = last;
queue->mq_head = queue->mq_tail = last;
} else {
queue->tail->m_next = last;
queue->tail = last; /* 'last' is the new last in line */
queue->mq_tail->m_next = last;
queue->mq_tail = last; /* 'last' is the new last in line */
}
}
@ -37,7 +37,7 @@ mthread_queue_t *queue; /* Queue that has to be initialized */
{
/* Initialize queue to a known state */
queue->head = queue->tail = NULL;
queue->mq_head = queue->mq_tail = NULL;
}
@ -47,7 +47,7 @@ mthread_queue_t *queue; /* Queue that has to be initialized */
PUBLIC int mthread_queue_isempty(queue)
mthread_queue_t *queue;
{
return(queue->head == NULL);
return(queue->mq_head == NULL);
}
@ -64,8 +64,8 @@ mthread_queue_t *queue;
#ifdef MDEBUG
printf("Dumping queue: ");
#endif
if(queue->head != NULL) {
t = queue->head;
if(queue->mq_head != NULL) {
t = queue->mq_head;
if (t == &mainthread) tid = MAIN_THREAD;
else tid = t->m_tid;
#ifdef MDEBUG
@ -106,18 +106,18 @@ mthread_queue_t *queue; /* Queue we want a thread from */
mthread_tcb_t *tcb;
/* Calculate thread id from queue head */
if (queue->head == NULL) thread = NO_THREAD;
else if (queue->head == &mainthread) thread = MAIN_THREAD;
else thread = (queue->head->m_tid);
if (queue->mq_head == NULL) thread = NO_THREAD;
else if (queue->mq_head == &mainthread) thread = MAIN_THREAD;
else thread = (queue->mq_head->m_tid);
if (thread != NO_THREAD) { /* i.e., this queue is not empty */
tcb = queue->head;
if (queue->head == queue->tail) {
tcb = queue->mq_head;
if (queue->mq_head == queue->mq_tail) {
/* Queue holds only one thread */
queue->head = queue->tail = NULL; /* So mark thread empty */
queue->mq_head = queue->mq_tail = NULL; /* So mark thread empty */
} else {
/* Second thread in line is the new first */
queue->head = queue->head->m_next;
queue->mq_head = queue->mq_head->m_next;
}
tcb->m_next = NULL; /* This thread is no longer part of a queue */

View file

@ -55,11 +55,9 @@ PUBLIC void mthread_schedule(void)
/* We're running the last runnable spawned thread. Return to main
* thread as there is no work left.
*/
running_main_thread = 1;
current_thread = MAIN_THREAD;
} else {
current_thread = mthread_queue_remove(&run_queue);
running_main_thread = 0; /* Running thread after swap */
}
/* Find thread entries in tcb... */
@ -70,6 +68,9 @@ PUBLIC void mthread_schedule(void)
new_ctx = &(new_tcb->m_context);
old_ctx = &(old_tcb->m_context);
/* Are we running the 'main' thread after swap? */
running_main_thread = (current_thread == MAIN_THREAD);
if (swapcontext(old_ctx, new_ctx) == -1)
mthread_panic("Could not swap context");
@ -156,10 +157,7 @@ PUBLIC int mthread_yield(void)
if (mthread_queue_isempty(&run_queue)) { /* No point in yielding. */
return(-1);
} else if (current_thread == NO_THREAD) {
/* Can't yield this thread, but still give other threads a chance to
* run.
*/
mthread_schedule();
/* Can't yield this thread */
return(-1);
}

View file

@ -222,12 +222,16 @@ PRIVATE void mutex_a(void *arg)
/* Trying to acquire lock again should fail with EDEADLK */
if (mthread_mutex_lock(&mu[0]) != -1) err(3, 2);
if (errno != EDEADLK) err(3, 3);
#ifdef MTHREAD_STRICT
/* Try to acquire lock on uninitialized mutex; should fail with EINVAL */
/* Note: this check only works when libmthread is compiled with
* MTHREAD_STRICT turned on. In POSIX this situation is a MAY fail if... */
if (mthread_mutex_lock(&mu2) != -1) {
err(3, 4);
mthread_mutex_unlock(&mu2);
}
if (errno != EINVAL) err(3, 5);
errno = 0;
if (mthread_mutex_trylock(&mu2) != -1) {
@ -235,6 +239,7 @@ PRIVATE void mutex_a(void *arg)
mthread_mutex_unlock(&mu2);
}
if (errno != EINVAL) err(3, 7);
#endif
if (mthread_mutex_trylock(&mu[1]) != 0) err(3, 8);
mutex_a_step = 1;
@ -502,8 +507,12 @@ PRIVATE void test_condition(void)
if (mthread_mutex_destroy(condition_mutex) != 0) err(8, 8);
if (mthread_cond_destroy(&condition) != 0) err(8, 9);
#ifdef MTHREAD_STRICT
/* Let's try to destroy it again. Should fails as it's uninitialized. */
/* Note: this only works when libmthread is compiled with MTHREAD_STRICT. In
* POSIX this situation is a MAY fail if... */
if (mthread_cond_destroy(&condition) == 0) err(8, 10);
#endif
#ifdef MDEBUG
mthread_verify();
@ -538,8 +547,11 @@ PRIVATE void test_condition(void)
if (mthread_mutex_destroy(condition_mutex) != 0) err(8, 21);
if (mthread_cond_destroy(&condition) != 0) err(8, 22);
#ifdef MTHREAD_STRICT
/* Again, destroying the condition variable twice shouldn't work */
/* See previous note about MTHREAD_STRICT */
if (mthread_cond_destroy(&condition) == 0) err(8, 23);
#endif
#ifdef MDEBUG
mthread_verify();