lwp: Fix possible memory leak from scan-build
[openafs.git] / src / lwp / lwp.c
index de77680..3ff9afc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID("$Header$");
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
+#include <roken.h>
 
 /* allocate externs here */
 #define  LWP_KERNEL
 #include "lwp.h"
+
 #ifdef AFS_AIX32_ENV
 #include <ulimit.h>
 #include <sys/errno.h>
@@ -33,29 +30,15 @@ RCSID("$Header$");
 #include <sys/pseg.h>
 #include <sys/core.h>
 #pragma alloca
+int setlim(int limcon, uchar_t hard, int limit);
 #endif
-#ifdef AFS_SGI64_ENV
-extern char *getenv();
-#include <time.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
-#if    !defined(USE_PTHREADS) && !defined(USE_SOLARIS_THREADS)
 
-#ifdef AFS_OSF_ENV
-extern void *malloc(int size);
-extern void *realloc(void *ptr, int size);
-#endif
+#ifndef AFS_ARM_LINUX20_ENV
 #if defined(AFS_OSF_ENV) || defined(AFS_S390_LINUX20_ENV)
-extern int PRE_Block;          /* from preempt.c */
+int PRE_Block; /* Remnants of preemption support. */
 #else
-extern char PRE_Block;         /* from preempt.c */
+char PRE_Block;        /* Remnants of preemption support. */
+#endif
 #endif
 
 #define ON             1
@@ -102,21 +85,24 @@ extern char PRE_Block;             /* from preempt.c */
     ;                                                                  \
 } while (0)
 #endif
-\f
-static int Dispatcher();
-static int Create_Process_Part2();
-static int Exit_LWP();
-static afs_int32 Initialize_Stack();
-static int Stack_Used();
-char (*RC_to_ASCII());
-
-static void Abort_LWP();
-static void Overflow_Complain();
-static void Initialize_PCB();
-static void Dispose_of_Dead_PCB();
-static void Free_PCB();
-static int Internal_Signal();
-static purge_dead_pcbs();
+
+static void Dispatcher(void);
+static void Create_Process_Part2(void);
+static void Exit_LWP(void);
+static afs_int32 Initialize_Stack(char *stackptr, int stacksize);
+static int Stack_Used(char *stackptr, int stacksize);
+
+static void Abort_LWP(char *msg);
+static void Overflow_Complain(void);
+static void Initialize_PCB(PROCESS temp, int priority, char *stack,
+                          int stacksize, void *(*ep)(void *), void *parm,
+                          char *name);
+static void Dispose_of_Dead_PCB(PROCESS cur);
+static void Free_PCB(PROCESS pid);
+static int Internal_Signal(void *event);
+static int purge_dead_pcbs(void);
+static int LWP_MwaitProcess(int wcount, void *evlist[]);
+
 
 #define MAX_PRIORITIES (LWP_MAX_PRIORITY+1)
 
@@ -124,7 +110,9 @@ struct QUEUE {
     PROCESS head;
     int count;
 } runnable[MAX_PRIORITIES], blocked, qwaiting;
-/* Invariant for runnable queues: The head of each queue points to the currently running process if it is in that queue, or it points to the next process in that queue that should run. */
+/* Invariant for runnable queues: The head of each queue points to the
+ * currently running process if it is in that queue, or it points to the
+ * next process in that queue that should run. */
 
 /* Offset of stack field within pcb -- used by stack checking stuff */
 int stack_offset;
@@ -147,7 +135,7 @@ int lwp_nextindex;
 int lwp_MinStackSize = 0;
 
 static int
-lwp_remove(register PROCESS p, register struct QUEUE *q)
+lwp_remove(PROCESS p, struct QUEUE *q)
 {
     /* Special test for only element on queue */
     if (q->count == 1)
@@ -166,7 +154,7 @@ lwp_remove(register PROCESS p, register struct QUEUE *q)
 }
 
 static int
-insert(register PROCESS p, register struct QUEUE *q)
+insert(PROCESS p, struct QUEUE *q)
 {
     if (q->head == NULL) {     /* Queue is empty */
        q->head = p;
@@ -194,14 +182,14 @@ move(PROCESS p, struct QUEUE *from, struct QUEUE *to)
 /* Iterator macro */
 #define for_all_elts(var, q, body)\
        {\
-           register PROCESS var, _NEXT_;\
-           register int _I_;\
+           PROCESS var, _NEXT_;\
+           int _I_;\
            for (_I_=q.count, var = q.head; _I_>0; _I_--, var=_NEXT_) {\
                _NEXT_ = var -> next;\
                body\
            }\
        }
-\f
+
 /*                                                                         */
 /*****************************************************************************\
 *                                                                            *
@@ -236,7 +224,7 @@ static struct lwp_ctl *lwp_init = 0;
 int
 LWP_QWait(void)
 {
-    register PROCESS tp;
+    PROCESS tp;
     (tp = lwp_cpptr)->status = QWAITING;
     move(tp, &runnable[tp->priority], &qwaiting);
     Set_LWP_RC();
@@ -244,7 +232,7 @@ LWP_QWait(void)
 }
 
 int
-LWP_QSignal(register PROCESS pid)
+LWP_QSignal(PROCESS pid)
 {
     if (pid->status == QWAITING) {
        pid->status = READY;
@@ -256,7 +244,7 @@ LWP_QSignal(register PROCESS pid)
 
 #ifdef AFS_AIX32_ENV
 char *
-reserveFromStack(register afs_int32 size)
+reserveFromStack(afs_int32 size)
 {
     char *x;
     x = alloca(size);
@@ -265,7 +253,7 @@ reserveFromStack(register afs_int32 size)
 #endif
 
 int
-LWP_CreateProcess(int (*ep) (), int stacksize, int priority, void *parm,
+LWP_CreateProcess(void *(*ep) (void *), int stacksize, int priority, void *parm,
                  char *name, PROCESS * pid)
 {
     PROCESS temp, temp2;
@@ -293,7 +281,7 @@ LWP_CreateProcess(int (*ep) (), int stacksize, int priority, void *parm,
     /* Throw away all dead process control blocks */
     purge_dead_pcbs();
     if (lwp_init) {
-       temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
+       temp = malloc(sizeof(struct lwp_pcb));
        if (temp == NULL) {
            Set_LWP_RC();
            return LWP_ENOMEM;
@@ -310,8 +298,8 @@ LWP_CreateProcess(int (*ep) (), int stacksize, int priority, void *parm,
 #ifdef AFS_AIX32_ENV
        if (!stackptr) {
            /*
-            * The following signal action for AIX is necessary so that in case of a 
-            * crash (i.e. core is generated) we can include the user's data section 
+            * The following signal action for AIX is necessary so that in case of a
+            * crash (i.e. core is generated) we can include the user's data section
             * in the core dump. Unfortunately, by default, only a partial core is
             * generated which, in many cases, isn't too useful.
             *
@@ -329,7 +317,7 @@ LWP_CreateProcess(int (*ep) (), int stacksize, int priority, void *parm,
            /*
             * First we need to increase the default resource limits,
             * if necessary, so that we can guarantee that we have the
-            * resources to create the core file, but we can't always 
+            * resources to create the core file, but we can't always
             * do it as an ordinary user.
             */
            if (!geteuid()) {
@@ -349,11 +337,12 @@ LWP_CreateProcess(int (*ep) (), int stacksize, int priority, void *parm,
        stackmemory = stackptr;
 #else
 #ifdef AFS_DARWIN_ENV
-       if ((stackmemory = (char *)malloc(stacksize + STACK_ALIGN - 1)) == NULL)
+       if ((stackmemory = malloc(stacksize + STACK_ALIGN - 1)) == NULL)
 #else /* !AFS_DARWIN_ENV */
-       if ((stackmemory = (char *)malloc(stacksize + 7)) == NULL)
+       if ((stackmemory = malloc(stacksize + 7)) == NULL)
 #endif /* !AFS_DARWIN_ENV */
        {
+           free(temp);
            Set_LWP_RC();
            return LWP_ENOMEM;
        }
@@ -365,6 +354,8 @@ LWP_CreateProcess(int (*ep) (), int stacksize, int priority, void *parm,
 #endif /* !AFS_DARWIN_ENV */
 #endif
        if (priority < 0 || priority >= MAX_PRIORITIES) {
+           free(temp);
+           free(stackmemory);
            Set_LWP_RC();
            return LWP_EBADPRI;
        }
@@ -372,11 +363,13 @@ LWP_CreateProcess(int (*ep) (), int stacksize, int priority, void *parm,
        Initialize_PCB(temp, priority, stackmemory, stacksize, ep, parm, name);
        insert(temp, &runnable[priority]);
        temp2 = lwp_cpptr;
+#if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
        if (PRE_Block != 0)
            Abort_LWP("PRE_Block not 0");
 
        /* Gross hack: beware! */
        PRE_Block = 1;
+#endif
        lwp_cpptr = temp;
 #if defined(AFS_PARISC_LINUX24_ENV)
        savecontext(Create_Process_Part2, &temp2->context,
@@ -412,7 +405,8 @@ LWP_CreateProcess(int (*ep) (), int stacksize, int priority, void *parm,
        /* End of gross hack */
 
        Set_LWP_RC();
-       *pid = temp;
+       if (pid)
+           *pid = temp;
        return 0;
     } else
        return LWP_EINIT;
@@ -420,7 +414,7 @@ LWP_CreateProcess(int (*ep) (), int stacksize, int priority, void *parm,
 
 #ifdef AFS_AIX32_ENV
 int
-LWP_CreateProcess2(int (*ep) (), int stacksize, int priority, void *parm,
+LWP_CreateProcess2(void *(*ep) (void *), int stacksize, int priority, void *parm,
                   char *name, PROCESS * pid)
 {
     PROCESS temp, temp2;
@@ -443,7 +437,7 @@ LWP_CreateProcess2(int (*ep) (), int stacksize, int priority, void *parm,
     /* Throw away all dead process control blocks */
     purge_dead_pcbs();
     if (lwp_init) {
-       temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
+       temp = malloc(sizeof(struct lwp_pcb));
        if (temp == NULL) {
            Set_LWP_RC();
            return LWP_ENOMEM;
@@ -453,7 +447,7 @@ LWP_CreateProcess2(int (*ep) (), int stacksize, int priority, void *parm,
        else
            stacksize =
                STACK_ALIGN * ((stacksize + STACK_ALIGN - 1) / STACK_ALIGN);
-       if ((stackptr = (char *)malloc(stacksize)) == NULL) {
+       if ((stackptr = malloc(stacksize)) == NULL) {
            Set_LWP_RC();
            return LWP_ENOMEM;
        }
@@ -465,18 +459,21 @@ LWP_CreateProcess2(int (*ep) (), int stacksize, int priority, void *parm,
        Initialize_PCB(temp, priority, stackptr, stacksize, ep, parm, name);
        insert(temp, &runnable[priority]);
        temp2 = lwp_cpptr;
+#if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
        if (PRE_Block != 0)
            Abort_LWP("PRE_Block not 0");
 
        /* Gross hack: beware! */
        PRE_Block = 1;
+#endif
        lwp_cpptr = temp;
        savecontext(Create_Process_Part2, &temp2->context,
                    stackptr + stacksize - sizeof(void *));
        /* End of gross hack */
 
        Set_LWP_RC();
-       *pid = temp;
+       if (pid)
+           *pid = temp;
        return 0;
     } else
        return LWP_EINIT;
@@ -565,7 +562,7 @@ int
 Dump_Processes(void)
 {
     if (lwp_init) {
-       register int i;
+       int i;
        for (i = 0; i < MAX_PRIORITIES; i++)
            for_all_elts(x, runnable[i], {
                         printf("[Priority %d]\n", i);
@@ -600,7 +597,7 @@ LWP_InitializeProcessSupport(int priority, PROCESS * pid)
 {
     PROCESS temp;
     struct lwp_pcb dummy;
-    register int i;
+    int i;
     char *value;
 
     Debug(0, ("Entered LWP_InitializeProcessSupport"));
@@ -620,8 +617,8 @@ LWP_InitializeProcessSupport(int priority, PROCESS * pid)
     blocked.count = 0;
     qwaiting.head = NULL;
     qwaiting.count = 0;
-    lwp_init = (struct lwp_ctl *)malloc(sizeof(struct lwp_ctl));
-    temp = (PROCESS) malloc(sizeof(struct lwp_pcb));
+    lwp_init = malloc(sizeof(struct lwp_ctl));
+    temp = malloc(sizeof(struct lwp_pcb));
     if (lwp_init == NULL || temp == NULL)
        Abort_LWP("Insufficient Storage to Initialize LWP Support");
     LWPANCHOR.processcnt = 1;
@@ -633,7 +630,8 @@ LWP_InitializeProcessSupport(int priority, PROCESS * pid)
     savecontext(Dispatcher, &temp->context, NULL);
     LWPANCHOR.outersp = temp->context.topstack;
     Set_LWP_RC();
-    *pid = temp;
+    if (pid)
+       *pid = temp;
 
     /* get minimum stack size from the environment. this allows the  administrator
      * to change the lwp stack dynamically without getting a new binary version.
@@ -649,7 +647,7 @@ LWP_InitializeProcessSupport(int priority, PROCESS * pid)
 }
 
 int
-LWP_INTERNALSIGNAL(char *event, int yield)
+LWP_INTERNALSIGNAL(void *event, int yield)
 {                              /* signal the occurence of an event */
     Debug(2, ("Entered LWP_SignalProcess"));
     if (lwp_init) {
@@ -665,7 +663,7 @@ LWP_INTERNALSIGNAL(char *event, int yield)
 int
 LWP_TerminateProcessSupport(void)
 {                              /* terminate all LWP support */
-    register int i;
+    int i;
 
     Debug(0, ("Entered Terminate_Process_Support"));
     if (lwp_init == NULL)
@@ -688,9 +686,9 @@ LWP_TerminateProcessSupport(void)
 }
 
 int
-LWP_WaitProcess(char *event)
+LWP_WaitProcess(void *event)
 {                              /* wait on a single event */
-    char *tempev[2];
+    void *tempev[2];
 
     Debug(2, ("Entered Wait_Process"));
     if (event == NULL)
@@ -701,9 +699,9 @@ LWP_WaitProcess(char *event)
 }
 
 int
-LWP_MwaitProcess(int wcount, char *evlist[])
+LWP_MwaitProcess(int wcount, void *evlist[])
 {                              /* wait on m of n events */
-    register int ecount, i;
+    int ecount, i;
 
 
     Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount));
@@ -728,9 +726,8 @@ LWP_MwaitProcess(int wcount, char *evlist[])
        }
        if (ecount > lwp_cpptr->eventlistsize) {
 
-           lwp_cpptr->eventlist =
-               (char **)realloc(lwp_cpptr->eventlist,
-                                ecount * sizeof(char *));
+           lwp_cpptr->eventlist = realloc(lwp_cpptr->eventlist,
+                                          ecount * sizeof(void *));
            lwp_cpptr->eventlistsize = ecount;
        }
        for (i = 0; i < ecount; i++)
@@ -762,7 +759,7 @@ LWP_StackUsed(PROCESS pid, int *maxa, int *used)
        return LWP_NO_STACK;
     return LWP_SUCCESS;
 }
-\f
+
 /*
  *  The following functions are strictly
  *  INTERNAL to the LWP support package.
@@ -786,7 +783,7 @@ Abort_LWP(char *msg)
     return;
 }
 
-static int
+static void
 Create_Process_Part2(void)
 {                              /* creates a context for the new process */
     PROCESS temp;
@@ -796,17 +793,17 @@ Create_Process_Part2(void)
     savecontext(Dispatcher, &temp->context, NULL);
     (*temp->ep) (temp->parm);
     LWP_DestroyProcess(temp);
-    return 0;
+    return;
 }
 
 static int
-Delete_PCB(register PROCESS pid)
+Delete_PCB(PROCESS pid)
 {                              /* remove a PCB from the process list */
     Debug(4, ("Entered Delete_PCB"));
     lwp_remove(pid,
               (pid->blockflag || pid->status == WAITING
                || pid->status ==
-               DESTROYED ? &blocked : 
+               DESTROYED ? &blocked :
                (pid->status == QWAITING) ? &qwaiting :
                &runnable[pid->priority]));
     LWPANCHOR.processcnt--;
@@ -875,10 +872,10 @@ purge_dead_pcbs(void)
 
 int LWP_TraceProcesses = 0;
 
-static int
+static void
 Dispatcher(void)
 {                              /* Lightweight process dispatcher */
-    register int i;
+    int i;
 #ifdef DEBUG
     static int dispatch_count = 0;
 
@@ -926,8 +923,9 @@ Dispatcher(void)
 #endif
        printf("stackcheck = %u: stack = %u \n", lwp_cpptr->stackcheck,
               *(int *)lwp_cpptr->stack);
-       printf("topstack = 0x%x: stackptr = 0x%x: stacksize = 0x%x\n",
-              lwp_cpptr->context.topstack, lwp_cpptr->stack,
+       printf("topstack = 0x%" AFS_PTR_FMT ": stackptr = 0x%" AFS_PTR_FMT ": stacksize = 0x%x\n",
+              (void *)(uintptr_t)lwp_cpptr->context.topstack,
+              (void *)(uintptr_t)lwp_cpptr->stack,
               lwp_cpptr->stacksize);
 
        switch (lwp_overflowAction) {
@@ -961,11 +959,15 @@ Dispatcher(void)
        printf("Dispatch %d [PCB at 0x%x] \"%s\"\n", ++dispatch_count,
               runnable[i].head, runnable[i].head->name);
 #endif
+#if !defined(AFS_ARM_LINUX20_ENV) && !defined(AFS_ARM_DARWIN_ENV)
     if (PRE_Block != 1)
        Abort_LWP("PRE_Block not 1");
+#endif
     lwp_cpptr = runnable[i].head;
 
     returnto(&lwp_cpptr->context);
+
+    return; /* not reachable */
 }
 
 /* Complain of a stack overflow to stderr without using stdio. */
@@ -980,11 +982,15 @@ Overflow_Complain(void)
     currenttime = time(0);
     timeStamp = ctime(&currenttime);
     timeStamp[24] = 0;
-    write(2, timeStamp, strlen(timeStamp));
+    if (write(2, timeStamp, strlen(timeStamp)) < 0)
+       return;
 
-    write(2, msg1, strlen(msg1));
-    write(2, lwp_cpptr->name, strlen(lwp_cpptr->name));
-    write(2, msg2, strlen(msg2));
+    if (write(2, msg1, strlen(msg1)) < 0)
+       return;
+    if (write(2, lwp_cpptr->name, strlen(lwp_cpptr->name)) < 0)
+       return;
+    if (write(2, msg2, strlen(msg2)) < 0)
+       return;
 }
 
 static void
@@ -998,7 +1004,7 @@ Dispose_of_Dead_PCB(PROCESS cur)
 */
 }
 
-static int
+static void
 Exit_LWP(void)
 {
     abort();
@@ -1023,9 +1029,9 @@ Free_PCB(PROCESS pid)
 
 static void
 Initialize_PCB(PROCESS temp, int priority, char *stack, int stacksize,
-              int (*ep) (), void *parm, char *name)
+              void *(*ep) (void *), void *parm, char *name)
 {
-    register int i = 0;
+    int i = 0;
 
     Debug(4, ("Entered Initialize_PCB"));
     if (name != NULL)
@@ -1033,7 +1039,7 @@ Initialize_PCB(PROCESS temp, int priority, char *stack, int stacksize,
            i++;
     temp->name[31] = '\0';
     temp->status = READY;
-    temp->eventlist = (char **)malloc(EVINITSIZE * sizeof(char *));
+    temp->eventlist = malloc(EVINITSIZE * sizeof(void *));
     temp->eventlistsize = EVINITSIZE;
     temp->eventcnt = 0;
     temp->wakevent = 0;
@@ -1061,10 +1067,10 @@ Initialize_PCB(PROCESS temp, int priority, char *stack, int stacksize,
 }
 
 static int
-Internal_Signal(register char *event)
+Internal_Signal(void *event)
 {
     int rc = LWP_ENOWAIT;
-    register int i;
+    int i;
 
     Debug(0, ("Entered Internal_Signal [event id 0x%x]", event));
     if (!lwp_init)
@@ -1092,7 +1098,7 @@ Internal_Signal(register char *event)
 static afs_int32
 Initialize_Stack(char *stackptr, int stacksize)
 {
-    register int i;
+    int i;
 
     Debug(4, ("Entered Initialize_Stack"));
     if (lwp_stackUseEnabled)
@@ -1108,9 +1114,9 @@ Initialize_Stack(char *stackptr, int stacksize)
 }
 
 static int
-Stack_Used(register char *stackptr, int stacksize)
+Stack_Used(char *stackptr, int stacksize)
 {
-    register int i;
+    int i;
 
 #if defined(__hp9000s800) || defined(AFS_PARISC_LINUX24_ENV)
     if (*(afs_int32 *) (stackptr + stacksize - 4) == STACKMAGIC)
@@ -1141,15 +1147,15 @@ LWP_NewRock(int Tag, char *Value)
      * LWP_SUCCESS      Rock did not exist and a new one was used
      * LWP_EBADROCK     Rock already exists.
      * LWP_ENOROCKS     All rocks are in use.
-     * 
+     *
      * From the above semantics, you can only set a rock value once.  This is specifically
      * to prevent multiple users of the LWP package from accidentally using the same Tag
      * value and clobbering others.  You can always use one level of indirection to obtain
      * a rock whose contents can change.
      */
 {
-    register int i;
-    register struct rock *ra;  /* rock array */
+    int i;
+    struct rock *ra;   /* rock array */
 
     ra = lwp_cpptr->lwp_rlist;
 
@@ -1175,8 +1181,8 @@ LWP_GetRock(int Tag, char **Value)
      * LWP_EBADROCK     rock specified does not exist
      */
 {
-    register int i;
-    register struct rock *ra;
+    int i;
+    struct rock *ra;
 
     ra = lwp_cpptr->lwp_rlist;
 
@@ -1226,401 +1232,19 @@ setlim(int limcon, uchar_t hard, int limit)
     }
     return (0);
 }
-
-
-#ifdef notdef
-/*
- * Print the specific limit out
- */
-int
-plim(char *name, afs_int32 lc, uchar_t hard)
-{
-    struct rlimit rlim;
-    int lim;
-
-    printf("%s \t", name);
-    (void)getrlimit(lc, &rlim);
-    lim = hard ? rlim.rlim_max : rlim.rlim_cur;
-    if (lim == RLIM_INFINITY)
-       printf("unlimited");
-    printf("%d %s", lim / 1024, "kbytes");
-    printf("\n");
-}
-#endif
 #endif
 
 #ifdef AFS_SUN5_ENV
 int
-LWP_NoYieldSignal(char *event)
+LWP_NoYieldSignal(void *event)
 {
     return (LWP_INTERNALSIGNAL(event, 0));
 }
 
 int
-LWP_SignalProcess(char *event)
+LWP_SignalProcess(void *event)
 {
     return (LWP_INTERNALSIGNAL(event, 1));
 }
 
 #endif
-#else
-#ifdef USE_SOLARIS_THREADS
-#include <thread.h>
-#else
-#include "pthread.h"
-#endif
-#include <stdio.h>
-#include <assert.h>
-
-pthread_mutex_t lwp_mutex;     /* Mutex to ensure mutual exclusion of all LWP threads */
-
-PROCESS lwp_process_list;      /* List of LWP initiated threads */
-
-pthread_key_t lwp_process_key; /* Key associating lwp pid with thread */
-
-#define CHECK check(__LINE__);
-
-typedef struct event {
-    struct event *next;                /* next in hash chain */
-    char *event;               /* lwp event: an address */
-    int refcount;              /* Is it in use? */
-    pthread_cond_t cond;       /* Currently associated condition variable */
-    int seq;                   /* Sequence number: this is incremented
-                                * by wakeup calls; wait will not return until
-                                * it changes */
-} event_t;
-
-#define HASHSIZE 127
-event_t *hashtable[HASHSIZE];  /* Hash table for events */
-#define hash(event)    ((unsigned long) (event) % HASHSIZE);
-
-#if CMA_DEBUG || DEBUGF
-char *
-lwp_process_string(void)
-{
-    static char id[200];
-    PROCESS p;
-    LWP_CurrentProcess(&p);
-    sprintf(id, "PID %x <%s>", p, p->name);
-    return id;
-}
-#endif
-
-void
-lwp_unimplemented(char *interface)
-{
-    fprintf(stderr,
-           "cmalwp: %s is not currently implemented: program aborted\n",
-           interface);
-    exit(1);
-}
-
-static void
-lwpabort(char *interface)
-{
-    fprintf(stderr, "cmalwp: %s failed unexpectedly\n", interface);
-    abort();
-}
-
-int
-LWP_QWait(void)
-{
-    lwp_unimplemented("LWP_QWait");
-}
-
-int
-LWP_QSignal(int pid)
-{
-    lwp_unimplemented("LWP_QSignal");
-}
-
-/* Allocate and initialize an LWP process handle. The associated pthread handle
- * must be added by the caller, and the structure threaded onto the LWP active
- * process list by lwp_thread_process */
-static PROCESS
-lwp_alloc_process(char *name, pthread_startroutine_t ep, pthread_addr_t arg)
-{
-    PROCESS lp;
-    assert(lp = (PROCESS) malloc(sizeof(*lp)));
-    memset((char *)lp, 0, sizeof(*lp));
-    if (!name) {
-       char temp[100];
-       static procnum;
-       sprintf(temp, "unnamed_process_%04d", ++procnum);
-       assert(name = (char *)malloc(strlen(temp) + 1));
-       strcpy(name, temp);
-    }
-    lp->name = name;
-    lp->ep = ep;
-    lp->arg = arg;
-    return lp;
-}
-
-/* Thread the LWP process descriptor *lp onto the lwp active process list
- * and associate a back pointer to the process descriptor from the associated
- * thread */
-static
-lwp_thread_process(PROCESS lp)
-{
-    lp->next = lwp_process_list;
-    lwp_process_list = lp;
-    assert(!pthread_setspecific(lwp_process_key, (pthread_addr_t) lp));
-}
-
-/* The top-level routine used as entry point to explicitly created LWP
- * processes. This completes a few details of process creation left
- * out by LWP_CreateProcess and calls the user-specified entry point */
-static int
-lwp_top_level(pthread_addr_t argp)
-{
-    PROCESS lp = (PROCESS) argp;
-
-    assert(!pthread_mutex_lock(&lwp_mutex));
-    lwp_thread_process(lp);
-    (lp->ep) (lp->arg);
-    assert(!pthread_mutex_unlock(&lwp_mutex));
-    /* Should cleanup state */
-}
-
-int
-LWP_CreateProcess(pthread_startroutine_t ep, int stacksize, int priority,
-                 void *parm, char *name, PROCESS * pid)
-{
-    int status;
-    pthread_attr_t attr;
-    pthread_t handle;
-    PROCESS lp;
-
-#ifndef LWP_NO_PRIORITIES
-    if (!cmalwp_pri_inrange(priority))
-       return LWP_EBADPRI;
-#endif
-    assert(!pthread_attr_create(&attr));
-    assert(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
-    if (stacksize)
-       assert(!pthread_attr_setstacksize(&attr, stacksize));
-#ifndef BDE_THREADS
-    (void)pthread_attr_setinheritsched(&attr, PTHREAD_DEFAULT_SCHED);
-    (void)pthread_attr_setsched(&attr, SCHED_FIFO);
-#ifndef LWP_NO_PRIORITIES
-    (void)pthread_attr_setprio(&attr, cmalwp_lwppri_to_cmapri(priority));
-#endif
-#endif
-    lp = lwp_alloc_process(name, (pthread_startroutine_t) ep,
-                          (pthread_addr_t) parm);
-
-    /* allow new thread to run if higher priority */
-    assert(!pthread_mutex_unlock(&lwp_mutex));
-    /* process is only added to active list after first time it runs (it adds itself) */
-    status =
-       pthread_create(&lp->handle, attr,
-                      (pthread_startroutine_t) lwp_top_level,
-                      (pthread_addr_t) lp);
-    assert(!pthread_attr_delete(&attr));
-    assert(!pthread_mutex_lock(&lwp_mutex));
-    if (status != 0) {
-       free(lp);
-       return LWP_ENOMEM;
-    }
-    *pid = lp;
-    return LWP_SUCCESS;
-}
-
-PROCESS
-LWP_ActiveProcess(void)
-{                              /* returns pid of current process */
-    PROCESS pid;
-    assert(!pthread_getspecific(lwp_process_key, (pthread_addr_t *) & pid));
-    return pid;
-}
-
-int
-LWP_CurrentProcess(PROCESS * pid)
-{                              /* get pid of current process */
-    assert(!pthread_getspecific(lwp_process_key, (pthread_addr_t *) pid));
-    return LWP_SUCCESS;
-}
-
-int
-LWP_DestroyProcess(PROCESS pid)
-{                              /* destroy a lightweight process */
-    lwp_unimplemented("LWP_DestroyProcess");
-}
-
-int
-LWP_DispatchProcess(void)
-{                              /* explicit voluntary preemption */
-    assert(!pthread_mutex_unlock(&lwp_mutex));
-    pthread_yield();
-    assert(!pthread_mutex_lock(&lwp_mutex));
-    return LWP_SUCCESS;
-}
-
-static int
-lwp_process_key_destructor(void)
-{
-}
-
-int
-LWP_InitializeProcessSupport(int priority, PROCESS * pid)
-{
-    static int initialized = 0;
-    int status;
-    static PROCESS lp;
-    extern main;
-    int state;
-
-    if (initialized) {
-       *pid = lp;
-       return LWP_SUCCESS;
-    }
-#ifndef LWP_NO_PRIORITIES
-    if (priority < 0 || priority > LWP_MAX_PRIORITY)
-       return LWP_EBADPRI;
-#endif
-
-    /* Create pthread key to associate LWP process descriptor with each
-     * LWP-created thread */
-    assert(!pthread_keycreate(&lwp_process_key, (pthread_destructor_t)
-                             lwp_process_key_destructor));
-
-    lp = lwp_alloc_process("main process", main, 0);
-    lp->handle = pthread_self();
-    lwp_thread_process(lp);
-#ifndef LWP_NO_PRIORITIES
-    (void)pthread_setscheduler(pthread_self(), SCHED_FIFO,
-                              cmalwp_lwppri_to_cmapri(priority));
-
-#endif
-    assert(pthread_mutex_init(&lwp_mutex, MUTEX_FAST_NP) == 0);
-    assert(pthread_mutex_lock(&lwp_mutex) == 0);
-    initialized = 1;
-    *pid = lp;
-    return LWP_SUCCESS;
-}
-
-int
-LWP_TerminateProcessSupport(void)
-{                              /* terminate all LWP support */
-    lwp_unimplemented("LWP_TerminateProcessSupport");
-}
-
-/* Get and initialize event structure corresponding to lwp event (i.e. address) */
-static event_t *
-getevent(char *event)
-{
-    event_t *evp, *newp;
-    int hashcode;
-
-    hashcode = hash(event);
-    evp = hashtable[hashcode];
-    newp = 0;
-    while (evp) {
-       if (evp->event == event) {
-           evp->refcount++;
-           return evp;
-       }
-       if (evp->refcount == 0)
-           newp = evp;
-       evp = evp->next;
-    }
-    if (!newp) {
-       newp = (event_t *) malloc(sizeof(event_t));
-       assert(newp);
-       newp->next = hashtable[hashcode];
-       hashtable[hashcode] = newp;
-       assert(!pthread_cond_init(&newp->cond, ((pthread_condattr_t) 0)));
-       newp->seq = 0;
-    }
-    newp->event = event;
-    newp->refcount = 1;
-    return newp;
-}
-
-/* Release the specified event */
-#define relevent(evp) ((evp)->refcount--)
-
-int
-LWP_WaitProcess(char *event)
-{                              /* wait on a single event */
-    struct event *ev;
-    int seq;
-    debugf(("%s: wait process (%x)\n", lwp_process_string(), event));
-    if (event == NULL)
-       return LWP_EBADEVENT;
-    ev = getevent(event);
-    seq = ev->seq;
-    while (seq == ev->seq) {
-       assert(pthread_cond_wait(&ev->cond, &lwp_mutex) == 0);
-    }
-    debugf(("%s: Woken up (%x)\n", lwp_process_string(), event));
-    relevent(ev);
-    return LWP_SUCCESS;
-}
-
-int
-LWP_MwaitProcess(int wcount, char *evlist[])
-{                              /* wait on m of n events */
-    lwp_unimplemented("LWP_MWaitProcess");
-}
-
-int
-LWP_NoYieldSignal(char *event)
-{
-    struct event *ev;
-    debugf(("%s: no yield signal (%x)\n", lwp_process_string(), event));
-    if (event == NULL)
-       return LWP_EBADEVENT;
-    ev = getevent(event);
-    if (ev->refcount > 1) {
-       ev->seq++;
-       assert(pthread_cond_broadcast(&ev->cond) == 0);
-    }
-    relevent(ev);
-    return LWP_SUCCESS;
-}
-
-int
-LWP_SignalProcess(char *event)
-{
-    struct event *ev;
-    debugf(("%s: signal process (%x)\n", lwp_process_string(), event));
-    if (event == NULL)
-       return LWP_EBADEVENT;
-    ev = getevent(event);
-    if (ev->refcount > 1) {
-       ev->seq++;
-       assert(!pthread_mutex_unlock(&lwp_mutex));
-       assert(!pthread_cond_broadcast(&ev->cond));
-       pthread_yield();
-       assert(!pthread_mutex_lock(&lwp_mutex));
-    }
-    relevent(ev);
-    return LWP_SUCCESS;
-}
-
-int
-LWP_StackUsed(PROCESS pid, int *maxa, int *used)
-{
-    lwp_unimplemented("LWP_StackUsed");
-}
-
-int
-LWP_NewRock(int Tag, char *Value)
-{
-    lwp_unimplemented("LWP_NewRock");
-}
-
-int
-LWP_GetRock(int Tag, char **Value)
-{
-    lwp_unimplemented("LWP_GetRock");
-}
-
-int
-LWP_GetProcessPriority(PROCESS pid, int *priority)
-{                              /* returns process priority */
-    lwp_unimplemented("LWP_GetProcessPriority");
-}
-
-#endif /* USE_PTHREADS */