]> Zhao Yanbai Git Server - minix.git/commitdiff
Clean up mthread
authorThomas Veerman <thomas@minix3.org>
Wed, 27 Jul 2011 09:30:26 +0000 (09:30 +0000)
committerThomas Veerman <thomas@minix3.org>
Wed, 27 Jul 2011 09:30:26 +0000 (09:30 +0000)
common/include/minix/mthread.h
lib/libmthread/allocate.c
lib/libmthread/condition.c
lib/libmthread/global.h
lib/libmthread/key.c
lib/libmthread/misc.c
lib/libmthread/mutex.c
lib/libmthread/proto.h
lib/libmthread/queue.c
test/test59.c

index 19012dfbe81b16b73ac3a2af865cf57aefe2db4e..dfefbda88659f70640e5c91d4f0459be1f8a8050 100644 (file)
@@ -9,9 +9,6 @@
 #include <ucontext.h>
 #include <errno.h>
 #include <stdlib.h>
-#ifndef __NBSD_LIBC
-#include <alloca.h>
-#endif
 #include <limits.h>
 #ifdef __NBSD_LIBC
 #include <sys/signal.h>
@@ -32,16 +29,20 @@ typedef struct {
 struct __mthread_mutex {
   mthread_queue_t mm_queue;    /* Queue of threads blocked on this mutex */
   mthread_thread_t mm_owner;   /* Thread ID that currently owns mutex */
+#ifdef MTHREAD_STRICT
   struct __mthread_mutex *mm_prev;
   struct __mthread_mutex *mm_next;
+#endif
   unsigned int mm_magic;
 };
 typedef struct __mthread_mutex *mthread_mutex_t;
 
 struct __mthread_cond {
   struct __mthread_mutex *mc_mutex;    /* Associate mutex with condition */
+#ifdef MTHREAD_STRICT
   struct __mthread_cond *mc_prev;
   struct __mthread_cond *mc_next;
+#endif
   unsigned int mc_magic;
 };
 typedef struct __mthread_cond *mthread_cond_t;
@@ -64,7 +65,7 @@ typedef struct __mthread_attr *mthread_attr_t;
 /* allocate.c */
 _PROTOTYPE( int mthread_create, (mthread_thread_t *thread,
                                 mthread_attr_t *tattr,
-                                void (*proc)(void *), void *arg)       );
+                                void *(*proc)(void *), void *arg)      );
 _PROTOTYPE( int mthread_detach, (mthread_thread_t thread)              );
 _PROTOTYPE( int mthread_equal, (mthread_thread_t l, mthread_thread_t r)        );
 _PROTOTYPE( void mthread_exit, (void *value)                           );
index 854ef96b6c548f8ca2026a626947ff637768498b..c16fe40e3b282c8377e1cb92aefc59e375417b3a 100644 (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");
 
index 3a2b48d045d62a2215bc0ea487bdfb488c447264..c65f0fdf578a6e011159de096b876eeb92ab13bb 100644 (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
 }
 
 
index 30e480e28d28af21b80ea6c9ec2f1afee6a4e057..acd80cac2a6f6e38cf5c1877c413867183da92ef 100644 (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];
 
index 5ad11494d9d0d2d7728b96cd4c8bfec7e6213839..01c6b84b0832208593b739335dd0a7051ec6ad9c 100644 (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.
index 57e94bb3993c5f7d424ef439aae834fd922c2a92..e90ac40b3afdf33089e228432d299839a8a211c7 100644 (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
index 0515556b9a82a1824b46236b06ea1fb86546d026..80dec87debaa0012ea4639aa4bed3aa1f2472058 100644 (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);
 }
index 2212c2fa51e45f1aaace1dc4587420da5031ef2d..19619ea50dfbdd7bec2af907bd9cf77528765668 100644 (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)           );
index 1ae68d5d02faeada4dd22a340250e53eac4c6e7e..266c69677790fdcd344cf520dd6e3d0e53946fcc 100644 (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                         *
index 844e8d4b4698c6e91f548e28722a040beef4d3dc..57b3c771ff3523c3db9f583d48a1452de9efc7f1 100644 (file)
@@ -3,6 +3,7 @@
  * lets you check the internal integrity of the library. */
 #include <stdio.h>
 #include <minix/mthread.h>
+#include <signal.h>
 
 #define thread_t mthread_thread_t
 #define mutex_t mthread_mutex_t
@@ -38,16 +39,18 @@ PRIVATE int first;
 #define THRESH1 3
 #define THRESH2 8
 #define MEG 1024*1024
-#define MAGIC 0xb4a3f1c2
-
-FORWARD _PROTOTYPE( void thread_a, (void *arg)                         );
-FORWARD _PROTOTYPE( void thread_b, (void *arg)                         );
-FORWARD _PROTOTYPE( void thread_c, (void *arg)                         );
-FORWARD _PROTOTYPE( void thread_d, (void *arg)                         );
+#define MAGIC ((signed) 0xb4a3f1c2)
+
+FORWARD _PROTOTYPE( void destr_a, (void *arg)                          );
+FORWARD _PROTOTYPE( void destr_b, (void *arg)                          );
+FORWARD _PROTOTYPE( void *thread_a, (void *arg)                                );
+FORWARD _PROTOTYPE( void *thread_b, (void *arg)                                );
+FORWARD _PROTOTYPE( void *thread_c, (void *arg)                                );
+FORWARD _PROTOTYPE( void *thread_d, (void *arg)                                );
 FORWARD _PROTOTYPE( void thread_e, (void)                              );
-FORWARD _PROTOTYPE( void thread_f, (void *arg)                         );
-FORWARD _PROTOTYPE( void thread_g, (void *arg)                         );
-FORWARD _PROTOTYPE( void thread_h, (void *arg)                         );
+FORWARD _PROTOTYPE( void *thread_f, (void *arg)                                );
+FORWARD _PROTOTYPE( void *thread_g, (void *arg)                                );
+FORWARD _PROTOTYPE( void *thread_h, (void *arg)                                );
 FORWARD _PROTOTYPE( void test_scheduling, (void)                       );
 FORWARD _PROTOTYPE( void test_mutex, (void)                            );
 FORWARD _PROTOTYPE( void test_condition, (void)                                );
@@ -58,34 +61,38 @@ FORWARD _PROTOTYPE( void err, (int subtest, int error)                      );
 /*===========================================================================*
  *                             thread_a                                     *
  *===========================================================================*/
-PRIVATE void thread_a(void *arg) {
+PRIVATE void *thread_a(void *arg) {
   th_a++;
+  return(NULL);
 }
 
 
 /*===========================================================================*
  *                             thread_b                                     *
  *===========================================================================*/
-PRIVATE void thread_b(void *arg) {
+PRIVATE void *thread_b(void *arg) {
   th_b++;
   if (mthread_once(&once, thread_e) != 0) err(10, 1);
+  return(NULL);
 }
 
 
 /*===========================================================================*
  *                             thread_c                                     *
  *===========================================================================*/
-PRIVATE void thread_c(void *arg) {
+PRIVATE void *thread_c(void *arg) {
   th_c++;
+  return(NULL);
 }
 
 
 /*===========================================================================*
  *                             thread_d                                     *
  *===========================================================================*/
-PRIVATE void thread_d(void *arg) {
+PRIVATE void *thread_d(void *arg) {
   th_d++;
   mthread_exit(NULL); /* Thread wants to stop running */
+  return(NULL);
 }
 
 
@@ -100,31 +107,33 @@ PRIVATE void thread_e(void) {
 /*===========================================================================*
  *                             thread_f                                     *
  *===========================================================================*/
-PRIVATE void thread_f(void *arg) {
+PRIVATE void *thread_f(void *arg) {
   if (mthread_mutex_lock(condition_mutex) != 0) err(12, 1);
   th_f++;
   if (mthread_cond_signal(&condition) != 0) err(12, 2);
   if (mthread_mutex_unlock(condition_mutex) != 0) err(12, 3);
+  return(NULL);
 }
 
 
 /*===========================================================================*
  *                             thread_g                                     *
  *===========================================================================*/
-PRIVATE void thread_g(void *arg) {
+PRIVATE void *thread_g(void *arg) {
   char bigarray[MTHREAD_STACK_MIN + 1];
   if (mthread_mutex_lock(condition_mutex) != 0) err(13, 1);
   memset(bigarray, '\0', MTHREAD_STACK_MIN + 1); /* Actually allocate it */
   th_g++;
   if (mthread_cond_signal(&condition) != 0) err(13, 2);
   if (mthread_mutex_unlock(condition_mutex) != 0) err(13, 3);
+  return(NULL);
 }
 
 
 /*===========================================================================*
  *                             thread_h                                     *
  *===========================================================================*/
-PRIVATE void thread_h(void *arg) {
+PRIVATE void *thread_h(void *arg) {
   char bigarray[2 * MEG];
   int reply;
   if (mthread_mutex_lock(condition_mutex) != 0) err(14, 1);
@@ -134,6 +143,7 @@ PRIVATE void thread_h(void *arg) {
   if (mthread_mutex_unlock(condition_mutex) != 0) err(14, 3);
   reply = *((int *) arg); 
   mthread_exit((void *) reply);
+  return(NULL);
 }
 
 
@@ -154,7 +164,7 @@ PRIVATE void err(int sub, int error) {
  *===========================================================================*/
 PRIVATE void test_scheduling(void)
 {
-  int i;
+  unsigned int i;
   thread_t t[7];
 
 #ifdef MDEBUG
@@ -217,10 +227,9 @@ PRIVATE void test_scheduling(void)
 /*===========================================================================*
  *                             mutex_a                                      *
  *===========================================================================*/
-PRIVATE void mutex_a(void *arg)
+PRIVATE void *mutex_a(void *arg)
 {
   mutex_t *mu = (mutex_t *) arg;
-  mutex_t mu2;
 
   VERIFY_MUTEX(0, 0, 0, 3, 1);
   if (mthread_mutex_lock(&mu[0]) != 0) err(3, 2);
@@ -267,13 +276,14 @@ PRIVATE void mutex_a(void *arg)
   if (mthread_mutex_unlock(NULL) == 0) err(3, 19);
 
   if (mthread_mutex_unlock(&mu[2]) != 0) err(3, 20);
+  return(NULL);
 }
 
 
 /*===========================================================================*
  *                             mutex_b                                      *
  *===========================================================================*/
-PRIVATE void mutex_b(void *arg)
+PRIVATE void *mutex_b(void *arg)
 {
   mutex_t *mu = (mutex_t *) arg;
 
@@ -302,13 +312,14 @@ PRIVATE void mutex_b(void *arg)
 
   if (mthread_mutex_unlock(&mu[1]) != 0) err(4, 8);
   mutex_b_step = 4;
+  return(NULL);
 }
 
 
 /*===========================================================================*
  *                             mutex_c                                      *
  *===========================================================================*/
-PRIVATE void mutex_c(void *arg)
+PRIVATE void *mutex_c(void *arg)
 {
   mutex_t *mu = (mutex_t *) arg;
 
@@ -329,6 +340,7 @@ PRIVATE void mutex_c(void *arg)
 
   if (mthread_mutex_unlock(&mu[0]) != 0) err(5, 9);
   mutex_c_step = 4;
+  return(NULL);
 }
 
 
@@ -337,7 +349,7 @@ PRIVATE void mutex_c(void *arg)
  *===========================================================================*/
 PRIVATE void test_mutex(void)
 {
-  int i;
+  unsigned int i;
   thread_t t[3];
 #ifdef MDEBUG
   mthread_verify();
@@ -381,7 +393,7 @@ PRIVATE void test_mutex(void)
 /*===========================================================================*
  *                                     cond_a                               *
  *===========================================================================*/
-PRIVATE void cond_a(void *arg)
+PRIVATE void *cond_a(void *arg)
 {
   cond_t c;
   int did_count = 0;
@@ -406,6 +418,7 @@ PRIVATE void cond_a(void *arg)
 
   /* Try faulty addresses */
   if (mthread_mutex_lock(condition_mutex) != 0) err(6, 7);
+#ifdef MTHREAD_STRICT
   /* Condition c is not initialized, so whatever we do with it should fail. */
   if (mthread_cond_wait(&c, condition_mutex) == 0) err(6, 8);
   if (mthread_cond_wait(NULL, condition_mutex) == 0) err(6, 9);
@@ -415,19 +428,21 @@ PRIVATE void cond_a(void *arg)
   /* Try again with an unlocked mutex */
   if (mthread_cond_wait(&c, condition_mutex) == 0) err(6, 12);
   if (mthread_cond_signal(&c) == 0) err(6, 13);
+#endif
 
   /* And again with an unlocked mutex, but initialized c */
   if (mthread_cond_init(&c, NULL) != 0) err(6, 14);
   if (mthread_cond_wait(&c, condition_mutex) == 0) err(6, 15);
   if (mthread_cond_signal(&c) != 0) err(6, 16);/*c.f., 6.10 this should work!*/
   if (mthread_cond_destroy(&c) != 0) err(6, 17);
+  return(NULL);
 }
 
 
 /*===========================================================================*
  *                                     cond_b                               *
  *===========================================================================*/
-PRIVATE void cond_b(void *arg)
+PRIVATE void *cond_b(void *arg)
 {
   int did_count = 0;
   while(1) {
@@ -448,14 +463,14 @@ PRIVATE void cond_b(void *arg)
 
   if (!(did_count >= count - (THRESH2 - THRESH1 + 1))) err(7, 6);
 
+  return(NULL);
 }
 
 /*===========================================================================*
  *                             cond_broadcast                               *
  *===========================================================================*/
-PRIVATE void cond_broadcast(void *arg)
+PRIVATE void *cond_broadcast(void *arg)
 {
-  int rounds = 0;
   if (mthread_mutex_lock(condition_mutex) != 0) err(9, 1);
 
   while(!condition_met) 
@@ -466,6 +481,7 @@ PRIVATE void cond_broadcast(void *arg)
   if (mthread_mutex_lock(count_mutex) != 0) err(9, 4);
   count++;
   if (mthread_mutex_unlock(count_mutex) != 0) err(9, 5);
+  return(NULL);
 }
 
 /*===========================================================================*
@@ -474,7 +490,7 @@ PRIVATE void cond_broadcast(void *arg)
 PRIVATE void test_condition(void)
 {
 #define NTHREADS 10
-  int i, r;
+  int i;
   thread_t t[2], s[NTHREADS];
   count_mutex = &mu[0];
   condition_mutex = &mu[1];
@@ -498,7 +514,7 @@ PRIVATE void test_condition(void)
   if (mthread_create(&t[0], NULL, cond_a, NULL) != 0) err(8, 4);
   if (mthread_create(&t[1], NULL, cond_b, NULL) != 0) err(8, 5);
 
-  for (i = 0; i < (sizeof(t) / sizeof(thread_t)); i++) 
+  for (i = 0; i < (sizeof(t) / sizeof(thread_t)); i++)
        if (mthread_join(t[i], NULL) != 0) err(8, 6);
 
   if (mthread_mutex_destroy(count_mutex) != 0) err(8, 7);
@@ -564,7 +580,7 @@ PRIVATE void test_attributes(void)
   attr_t tattr;
   thread_t tid;
   int detachstate = -1, status = 0;
-  int i, no_ints, stack_untouched = 1;
+  unsigned int i, no_ints, stack_untouched = 1;
   void *stackaddr, *newstackaddr;
   int *stackp;
   size_t stacksize, newstacksize;
@@ -720,7 +736,7 @@ PRIVATE void test_attributes(void)
 #endif
 
   if (mthread_join(tid, (void *) &status) != 0) err(11, 69);
-  if (status != stacksize) err(11, 70);
+  if ((size_t) status != stacksize) err(11, 70);
   if (mthread_attr_destroy(&tattr) != 0) err(11, 71); 
   if (mthread_mutex_destroy(condition_mutex) != 0) err(11, 72);
   if (mthread_cond_destroy(&condition) != 0) err(11, 73);
@@ -759,7 +775,7 @@ PRIVATE void destr_b(void *value)
 /*===========================================================================*
  *                             key_a                                        *
  *===========================================================================*/
-PRIVATE void key_a(void *arg)
+PRIVATE void *key_a(void *arg)
 {
   int i;
 
@@ -785,12 +801,13 @@ PRIVATE void key_a(void *arg)
 
   /* If a key's value is set to NULL, its destructor must not be called. */
   if (mthread_setspecific(key[4], NULL) != 0) err(17, 5);
+  return(NULL);
 }
 
 /*===========================================================================*
  *                             key_b                                        *
  *===========================================================================*/
-PRIVATE void key_b(void *arg)
+PRIVATE void *key_b(void *arg)
 {
   int i;
 
@@ -810,12 +827,13 @@ PRIVATE void key_b(void *arg)
   if (mthread_key_delete(key[3]) != 0) err(18, 3);
 
   mthread_exit(NULL);
+  return(NULL);
 }
 
 /*===========================================================================*
  *                             key_c                                        *
  *===========================================================================*/
-PRIVATE void key_c(void *arg)
+PRIVATE void *key_c(void *arg)
 {
   /* The only thing that this thread should do, is set a value. */
   if (mthread_setspecific(key[0], (void *) mthread_self()) != 0) err(19, 1);
@@ -824,6 +842,7 @@ PRIVATE void key_c(void *arg)
 
   if (!mthread_equal((thread_t) mthread_getspecific(key[0]), mthread_self()))
        err(19, 2);
+  return(NULL);
 }
 
 /*===========================================================================*
@@ -919,5 +938,6 @@ int main(void)
   test_attributes();
   test_keys();
   quit();
+  return(0);   /* Not reachable */
 }