lwp: Build src/lwp/test

Make the src/lwp/test directory built by default, by 'cd'ing into 'test'
from src/lwp after building the lwp library. Also fix numerous errors
and warnings to get the directory buildable, including:

- Change many functions to be declared with proper prototypes
- Change many functions and variables to be 'static', since they are
  only used inside one compilation unit
- Remove several unused variables
- Include stdlib.h for exit() et al, string.h for strcmp(), fcntl.h for
  open(), time.h for localtime() et al, and arpa/inet.h for inet_ntoa().
- Make main() return an int
- Change various signal handler callbacks to be the proper type
- Change LWP_CreateProcess callbacks to be the proper type
- Use %p to print various pointers, instead of 0x%x
- Cast various time-based variables to int for printing with %d
- Remove extra prototypes for IOMGR_Select()
- Give accept() a socklen_t* instead of an int*
- Remove the unused make targets 'system' and 'noversion'
- Update the make rule for the 'test' program to use modern conventions
  and use AFS_LDRULE, and avoid passing -p to the compiler
- Remove unnecessary links to util.a
- Remove testlwp.c, which has no main() and isn't linked by
  anything else
- In selserver.c:handleWrite(), declare 'c' as an unsigned char (so we can
  compare against END_DATA, which is larger than a signed char), and use
  'c' as the byte read in from read(), so 'c' is not used uninitialized.
- Change test.c to use LWP_WaitProcess() instead of LWP_MwaitProcess().
  LWP_MwaitProcess() has no callers outside of lwp, and was declared
  static, effectively making it private, in commit ff988ead4e
  (lwp-protoize-20080310).

Also add the built test programs to .gitignore.

Change-Id: I6958a78ae271dbcb865df5d7f30019ba05160b56
Reviewed-on: https://gerrit.openafs.org/16014
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Michael Meffie <mmeffie@sinenomine.net>
This commit is contained in:
Andrew Deason 2025-01-03 12:49:56 -06:00 committed by Michael Meffie
parent 378a483560
commit e4d8329619
9 changed files with 91 additions and 749 deletions

View File

@ -23,7 +23,7 @@ LT_deps = $(top_builddir)/src/opr/liboafs_opr.la
LT_libs = $(MT_LIBS)
all: liboafs_lwpcompat.la liblwpcompat_pic.la \
${TOP_LIBDIR}/liblwp.a depinstall
${TOP_LIBDIR}/liblwp.a depinstall test
depinstall: ${TOP_INCDIR}/lock.h ${TOP_INCDIR}/lwp.h ${TOP_INCDIR}/timer.h
@ -192,6 +192,10 @@ threadname.o : threadname.c
exc_handling.o : exc_handling.c
.PHONY: test
test: ${TOP_LIBDIR}/liblwp.a
cd test && $(MAKE) all
#
# Install targets
#
@ -219,5 +223,6 @@ buildtools: ${TOP_LIBDIR}/liblwp.a depinstall
clean:
$(LT_CLEAN)
$(RM) -f *.o *.a core AFS_component_version_number.c
cd test && $(MAKE) clean
include ../config/Makefile.version

View File

@ -3,3 +3,7 @@
# to check that you haven't inadvertently ignored any tracked files.
/rw
/selclient
/selserver
/test
/test_key

View File

@ -13,14 +13,10 @@ include @TOP_OBJDIR@/src/config/Makefile.lwp
INCDIRS= -I.. -I${DESTDIR}/include
LIBS= ../liblwp.a
system noversion: test
test: test.c liblwp.a
${CC} -p ${CFLAGS} test.c -o test ${LIBS}
testlwp.o : testlwp.c
${CC} -c -p ${CFLAGS} testlwp.c ${LIBS}
all: test selclient selserver test_key rw
test: test.o ${LIBS}
$(AFS_LDRULE) test.o ${LIBS}
selclient.o: selclient.c seltest.h
@ -35,7 +31,7 @@ selserver: selserver.o selsubs.o ${LIBS}
selsubs.o: selsubs.c seltest.h
test_key: test_key.o
$(AFS_LDRULE) test_key.o ${LIBS} ${TOP_LIBDIR}/util.a
$(AFS_LDRULE) test_key.o ${LIBS}
rw: rw.o $(LIBS) $(TOP_LIBDIR)/libopr.a
$(AFS_LDRULE) rw.o $(LIBS) $(TOP_LIBDIR)/libopr.a

View File

@ -41,6 +41,7 @@
#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/types.h>
@ -58,16 +59,12 @@
#include "lwp.h"
#include "seltest.h"
/* Put this in lwp.h? */
extern int IOMGR_Select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
static void sendTest(int, int, int, int);
static void sendEnd(int);
void sendTest(int, int, int, int);
void sendEnd(int);
int nSigIO = 0;
void
sigIO()
static int nSigIO = 0;
static void
sigIO(int sig)
{
nSigIO++;
}
@ -75,7 +72,8 @@ sigIO()
char *program;
Usage()
static void
Usage(void)
{
printf
("Usage: selclient [-fd n] [-oob] [-soob] [-delay n] [-end] [-write n] host port\n");
@ -88,10 +86,10 @@ Usage()
exit(1);
}
int
main(int ac, char **av)
{
int i;
int on = 1;
char *hostname = 0;
struct hostent *hostent;
int host; /* net order. */
@ -103,7 +101,6 @@ main(int ac, char **av)
int putOOB = 0;
int delay = 5;
int doEnd = 0;
int doWrite = 0;
int writeSize = 0;
program = av[0];
@ -137,7 +134,6 @@ main(int ac, char **av)
Usage();
}
} else if (!strcmp("-write", av[i])) {
doWrite = 1;
if (++i >= ac) {
printf("%s: Missing size for -write option.\n", program);
Usage();
@ -227,12 +223,14 @@ main(int ac, char **av)
sendTest(sockFD, delay, reqOOB, writeSize);
}
close(sockFD);
return 0;
}
/* sendTest
*/
int writeIndex;
void
static int writeIndex;
static void
sendTest(int sockFD, int delay, int reqOOB, int size)
{
char *buf, *bufTest;
@ -292,13 +290,13 @@ sendTest(int sockFD, int delay, int reqOOB, int size)
(void)time(&etime);
if (etime - stime > 1) {
Log("Waited %d seconds to write at offset %d.\n",
etime - stime, i);
(int)(etime - stime), i);
}
stime = etime;
nbytes = write(sockFD, &buf[i], 1);
(void)time(&etime);
if (etime - stime > 1) {
Log("Waited %d seconds IN write.\n", etime - stime);
Log("Waited %d seconds IN write.\n", (int)(etime - stime));
}
assert(nbytes == 1);
FD_CLR(sockFD, wfds);
@ -321,7 +319,7 @@ sendTest(int sockFD, int delay, int reqOOB, int size)
Log("Compared %d bytes.\n", size);
}
void
static void
sendEnd(int fd)
{
selcmd_t sc;

View File

@ -49,6 +49,7 @@
#include <string.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <sys/ioctl.h>
@ -59,15 +60,11 @@
#include "lwp.h"
#include "seltest.h"
extern int IOMGR_Select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
void sendTest(int, int, int);
void handleRequest(char *);
static void * handleRequest(void *);
/* Server Pool */
#define MAX_THREADS 5
int nThreads = 0;
static int nThreads = 0;
typedef struct {
#define CH_FREE 0
@ -79,12 +76,12 @@ typedef struct {
PROCESS ch_pid;
} clientHandle_t;
void handleWrite(clientHandle_t *, selcmd_t *);
static void handleWrite(clientHandle_t *, selcmd_t *);
clientHandle_t clientHandles[MAX_THREADS];
static clientHandle_t clientHandles[MAX_THREADS];
clientHandle_t *
getClientHandle()
static clientHandle_t *
getClientHandle(void)
{
int i;
for (i = 0; i < MAX_THREADS; i++) {
@ -99,15 +96,15 @@ getClientHandle()
return NULL; /* quiet compiler. */
}
int nSigIO = 0;
void
sigIO()
static int nSigIO = 0;
static void
sigIO(int sig)
{
nSigIO++;
}
Usage()
static void
Usage(void)
{
printf("Usage: selserver [-fd n] [-syssel] port\n");
printf("\t-fd n\tUse file descriptor n for socket.\n");
@ -116,6 +113,7 @@ Usage()
char *program;
int
main(int ac, char **av)
{
int i;
@ -123,10 +121,9 @@ main(int ac, char **av)
short port = -1; /* host order. */
int setFD = 0;
struct sockaddr_in saddr;
int acceptFD;
clientHandle_t *clientHandle;
int code;
int addr_len;
socklen_t addr_len;
PROCESS pid;
fd_set *rfds, *wfds, *efds;
int sockFD;
@ -266,7 +263,7 @@ main(int ac, char **av)
exit(1);
}
Log("Main - signalling LWP 0x%x\n", &clientHandle->ch_state);
Log("Main - signalling LWP %p\n", &clientHandle->ch_state);
LWP_NoYieldSignal(&clientHandle->ch_state);
assertNullFDSet(sockFD, rfds);
assertNullFDSet(-1, wfds);
@ -276,19 +273,19 @@ main(int ac, char **av)
Die(1, "(main) No data to read.\n");
}
}
return 0;
}
void
handleRequest(char *arg)
static void *
handleRequest(void *arg)
{
clientHandle_t *ch = (clientHandle_t *) arg;
clientHandle_t *ch = arg;
selcmd_t sc;
struct stat sbuf;
int code = 0;
int c_errno = 0;
while (1) {
Log("(handleRequest) going to sleep on 0x%x\n", &ch->ch_state);
Log("(handleRequest) going to sleep on %p\n", &ch->ch_state);
LWP_WaitProcess(&ch->ch_state);
assert(ch->ch_state == CH_INUSE);
@ -340,10 +337,12 @@ handleRequest(char *arg)
ch->ch_fd = 0;
ch->ch_state = CH_FREE;
}
return NULL;
}
int write_I = 0;
void
static int write_I = 0;
static void
handleWrite(clientHandle_t * ch, selcmd_t * sc)
{
int i;
@ -351,7 +350,6 @@ handleWrite(clientHandle_t * ch, selcmd_t * sc)
char *buf;
int code;
int scode;
char c;
int nbytes;
rfds = IOMGR_AllocFDSet();
@ -363,7 +361,7 @@ handleWrite(clientHandle_t * ch, selcmd_t * sc)
IOMGR_Sleep(sc->sc_delay);
}
Log("(handleWrite 0x%x) waking after %d second sleep.\n", ch->ch_pid,
Log("(handleWrite %p) waking after %d second sleep.\n", ch->ch_pid,
sc->sc_delay);
if (sc->sc_flags & SC_WAIT_OOB)
@ -385,10 +383,12 @@ handleWrite(clientHandle_t * ch, selcmd_t * sc)
assert(scode > 0);
if (FD_ISSET(ch->ch_fd, rfds)) {
unsigned char c;
assert(i < sc->sc_info);
code = read(ch->ch_fd, &buf[i], 1);
code = read(ch->ch_fd, &c, 1);
buf[i] = c;
i++;
write_I++;
if (code != 1) {

View File

@ -22,33 +22,19 @@
#include <sys/socket.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "lwp.h"
#include "seltest.h"
#ifdef NEEDS_ALLOCFDSET
/* Include these if testing against 32 bit fd_set IOMGR. */
fd_set *
IOMGR_AllocFDSet(void)
{
fd_set *tmp = calloc(1, sizeof(fd_set));
return tmp;
}
void
IOMGR_FreeFDSet(fd_set * fds)
{
free(fds);
}
#endif
/* The TCP spec calls for writing at least one byte of OOB data which is
* read by the receiver using recv with the MSG_OOB flag set.
*/
@ -93,10 +79,8 @@ assertNullFDSet(int fd, fd_set * fds)
*
* Open file descriptors until file descriptor n or higher is returned.
*/
#include <sys/stat.h>
void
OpenFDs(n)
int n;
OpenFDs(int n)
{
int i;
struct stat sbuf;
@ -158,8 +142,8 @@ Log(char *fmt, ...)
ltime = localtime(&tt);
LWP_CurrentProcess(&pid);
fprintf(stderr, "%s 0x%x %02d:%02d:%02d.%d: ", program ? program : "",
pid, ltime->tm_hour, ltime->tm_min, ltime->tm_sec, now.tv_usec);
fprintf(stderr, "%s %p %02d:%02d:%02d.%d: ", program ? program : "",
pid, ltime->tm_hour, ltime->tm_min, ltime->tm_sec, (int)now.tv_usec);
va_start(args, fmt);

View File

@ -11,28 +11,29 @@
#include <afs/param.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include "lwp.h"
char semaphore;
static char semaphore;
int
OtherProcess()
static void *
OtherProcess(void *arg)
{
for (;;) {
LWP_SignalProcess(&semaphore);
}
return NULL;
}
main(argc, argv)
int argc;
char *argv[];
int
main(int argc, char *argv[])
{
struct timeval t1, t2;
int pid, otherpid;
int i, count, x;
char *waitarray[2];
static char c[] = "OtherProcess";
count = atoi(argv[1]);
@ -42,15 +43,15 @@ main(argc, argv)
(OtherProcess, 4096, 0, 0, c,
(PROCESS *) & otherpid) == LWP_SUCCESS);
waitarray[0] = &semaphore;
waitarray[1] = 0;
gettimeofday(&t1, NULL);
for (i = 0; i < count; i++) {
LWP_MwaitProcess(1, waitarray, 1);
LWP_WaitProcess(&semaphore);
}
gettimeofday(&t2, NULL);
x = (t2.tv_sec - t1.tv_sec) * 1000000 + (t2.tv_usec - t1.tv_usec);
printf("%d milliseconds for %d MWaits (%f usec per Mwait and Signal)\n",
x / 1000, count, (float)(x / count));
return 0;
}

View File

@ -22,6 +22,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef AFS_NT40_ENV
#include <time.h>
@ -32,10 +34,10 @@
#include <lwp.h>
/* prototypes */
void interTest();
void lineTest();
static void interTest(void);
static void lineTest(void);
void
static void
Usage(void)
{
printf("Usage: test_key [-nobuf] [-delay seconds [-iters n]]\n");
@ -53,10 +55,10 @@ Usage(void)
}
int waitingForAnswer = 0;
static int waitingForAnswer = 0;
static void
PrintDots()
PrintDots(void)
{
static struct timeval constSleepTime = { 1, 0 };
struct timeval sleepTime;
@ -71,17 +73,17 @@ PrintDots()
}
}
static int
DotWriter(char *junk)
static void *
DotWriter(void *junk)
{
while (1) {
LWP_WaitProcess(&waitingForAnswer);
PrintDots();
}
return 0;
return NULL;
}
void
int
main(int ac, char **av)
{
int delay = 0;
@ -155,15 +157,14 @@ main(int ac, char **av)
printf("\nNo data available on this iteration.\n");
}
}
return 0;
}
/* interTest() : wait for key press and beep to remind user every five
* seconds.
*/
void
interTest()
static void
interTest(void)
{
char ch;
int rc;
@ -188,10 +189,9 @@ interTest()
/* lineTest() : wait until a whole line has been entered before processing.
*/
void
lineTest()
static void
lineTest(void)
{
char ch;
int rc;
char line[256];

View File

@ -1,646 +0,0 @@
/*
* 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
*/
/*******************************************************************\
* *
* Information Technology Center *
* Carnegie-Mellon University *
* *
* *
\*******************************************************************/
/* allocate externs here */
#include <afsconfig.h>
#include <afs/param.h>
#define LWP_KERNEL
#include "lwp.h"
#define NULL 0
#define ON 1
#define OFF 0
#define TRUE 1
#define FALSE 0
#define READY (1<<1)
#define WAITING (1<<2)
#define DESTROYED (1<<3)
#define MAXINT (~(1<<((sizeof(int)*8)-1)))
#define MINSTACK 44
/* Debugging macro */
#ifdef DEBUG
#define Debug(level, msg)\
if (lwp_debug && lwp_debug >= level) {\
printf("***LWP (0x%x): ", lwp_cpptr);\
printf msg;\
putchar('\n');\
}
#else
#define Debug(level, msg)
#endif
int Dispatcher();
int Create_Process_Part2();
int Exit_LWP();
int Initialize_Stack(), Stack_Used();
char (*RC_to_ASCII());
#define MAX_PRIORITIES (LWP_MAX_PRIORITY+1)
struct QUEUE {
PROCESS head;
int count;
} runnable[MAX_PRIORITIES], blocked;
/* Offset of stack field within pcb -- used by stack checking stuff */
int stack_offset;
static remove(p, q)
PROCESS p;
struct QUEUE *q;
{
/* Special test for only element on queue */
if (q->count == 1)
q -> head = NULL;
else {
/* Not only element, do normal remove */
p -> next -> prev = p -> prev;
p -> prev -> next = p -> next;
}
/* See if head pointing to this element */
if (q->head == p) q -> head = p -> next;
q->count--;
p -> next = p -> prev = NULL;
}
static insert(p, q)
PROCESS p;
struct QUEUE *q;
{
if (q->head == NULL) { /* Queue is empty */
q -> head = p;
p -> next = p -> prev = p;
} else { /* Regular insert */
p -> prev = q -> head -> prev;
q -> head -> prev -> next = p;
q -> head -> prev = p;
p -> next = q -> head;
}
q->count++;
}
static move(p, from, to)
PROCESS p;
struct QUEUE *from, *to;
{
remove(p, from);
insert(p, to);
}
/* Iterator macro */
#define for_all_elts(var, q, body)\
{\
PROCESS var, _NEXT_;\
int _I_;\
for (_I_=q.count, var = q.head; _I_>0; _I_--, var=_NEXT_) {\
_NEXT_ = var -> next;\
body\
}\
}
/* */
/*****************************************************************************\
* *
* Following section documents the Assembler interfaces used by LWP code *
* *
\*****************************************************************************/
/*
savecontext(int (*ep)(), struct lwp_context *savearea, char *sp);
Stub for Assembler routine that will
save the current SP value in the passed
context savearea and call the function
whose entry point is in ep. If the sp
parameter is NULL, the current stack is
used, otherwise sp becomes the new stack
pointer.
returnto(struct lwp_context *savearea);
Stub for Assembler routine that will
restore context from a passed savearea
and return to the restored C frame.
*/
/* Macro to force a re-schedule. Strange name is historical */
#define Set_LWP_RC(dummy) savecontext(Dispatcher, &lwp_cpptr->context, NULL)
static struct lwp_ctl *lwp_init;
int LWP_CreateProcess(ep, stacksize, priority, parm, name, pid)
int (*ep)();
int stacksize, priority;
char *parm;
char *name;
PROCESS *pid;
{
PROCESS temp, temp2;
char *stackptr;
Debug(0, ("Entered LWP_CreateProcess"))
/* Throw away all dead process control blocks */
purge_dead_pcbs();
if (lwp_init) {
temp = malloc (sizeof (struct lwp_pcb));
if (temp == NULL) {
Set_LWP_RC();
return LWP_ENOMEM;
}
if (stacksize < MINSTACK)
stacksize = 1000;
else
stacksize = 4 * ((stacksize+3) / 4);
if ((stackptr = malloc(stacksize)) == NULL) {
Set_LWP_RC();
return LWP_ENOMEM;
}
if (priority < 0 || priority >= MAX_PRIORITIES) {
Set_LWP_RC();
return LWP_EBADPRI;
}
#ifdef DEBUG
#ifdef STACK_USED
Initialize_Stack(stackptr, stacksize);
#endif
#endif
Initialize_PCB(temp, priority, stackptr, stacksize, ep, parm, name);
insert(temp, &runnable[priority]);
temp2 = lwp_cpptr;
lwp_cpptr = temp;
savecontext(Create_Process_Part2, &temp2->context, stackptr+stacksize-4);
Set_LWP_RC();
*pid = temp;
return 0;
} else
return LWP_EINIT;
}
int LWP_CurrentProcess(pid) /* returns pid of current process */
PROCESS *pid;
{
Debug(0, ("Entered Current_Process"))
if (lwp_init) {
*pid = lwp_cpptr;
return LWP_SUCCESS;
} else
return LWP_EINIT;
}
#define LWPANCHOR (*lwp_init)
int LWP_DestroyProcess(pid) /* destroy a lightweight process */
PROCESS pid;
{
PROCESS temp;
Debug(0, ("Entered Destroy_Process"))
if (lwp_init) {
if (lwp_cpptr != pid) {
Dispose_of_Dead_PCB(pid);
Set_LWP_RC();
} else {
pid -> status = DESTROYED;
move(pid, &runnable[pid->priority], &blocked);
temp = lwp_cpptr;
savecontext(Dispatcher, &(temp -> context),
&(LWPANCHOR.dsptchstack[(sizeof LWPANCHOR.dsptchstack)-4]));
}
return LWP_SUCCESS;
} else
return LWP_EINIT;
}
int LWP_DispatchProcess() /* explicit voluntary preemption */
{
Debug(2, ("Entered Dispatch_Process"))
if (lwp_init) {
Set_LWP_RC();
return LWP_SUCCESS;
} else
return LWP_EINIT;
}
#ifdef DEBUG
Dump_Processes()
{
if (lwp_init) {
int i;
for (i=0; i<MAX_PRIORITIES; i++)
for_all_elts(x, runnable[i], {
printf("[Priority %d]\n", i);
Dump_One_Process(x);
})
for_all_elts(x, blocked, { Dump_One_Process(x); })
} else
printf("***LWP: LWP support not initialized\n");
}
#endif
int LWP_GetProcessPriority(pid, priority) /* returns process priority */
PROCESS pid;
int *priority;
{
Debug(0, ("Entered Get_Process_Priority"))
if (lwp_init) {
*priority = pid -> priority;
return 0;
} else
return LWP_EINIT;
}
int LWP_InitializeProcessSupport(priority, pid)
int priority;
PROCESS *pid;
{
PROCESS temp;
struct lwp_pcb dummy;
int i;
Debug(0, ("Entered LWP_InitializeProcessSupport"))
if (lwp_init != NULL) return LWP_EINIT;
/* Set up offset for stack checking -- do this as soon as possible */
stack_offset = (char *) &dummy.stack - (char *) &dummy;
if (priority >= MAX_PRIORITIES) return LWP_EBADPRI;
for (i=0; i<MAX_PRIORITIES; i++) {
runnable[i].head = NULL;
runnable[i].count = 0;
}
blocked.head = NULL;
blocked.count = 0;
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;
LWPANCHOR.outerpid = temp;
LWPANCHOR.outersp = NULL;
Initialize_PCB(temp, priority, NULL, 0, NULL, NULL, "Main Process [created by LWP]");
insert(temp, &runnable[priority]);
savecontext(Dispatcher, &temp->context, NULL);
LWPANCHOR.outersp = temp -> context.topstack;
Set_LWP_RC();
*pid = temp;
return LWP_SUCCESS;
}
int LWP_INTERNALSIGNAL(event, yield) /* signal the occurence of an event */
char *event;
int yield;
{
Debug(2, ("Entered LWP_SignalProcess"))
if (lwp_init) {
int rc;
rc = Internal_Signal(event);
if (yield) Set_LWP_RC();
return rc;
} else
return LWP_EINIT;
}
int LWP_TerminateProcessSupport(void) /* terminate all LWP support */
{
int pc;
int i;
Debug(0, ("Entered Terminate_Process_Support"))
if (lwp_init == NULL) return LWP_EINIT;
if (lwp_cpptr != LWPANCHOR.outerpid)
Abort_LWP("Terminate_Process_Support invoked from wrong process!");
pc = LWPANCHOR.processcnt-1;
for (i=0; i<MAX_PRIORITIES; i++)
for_all_elts(cur, runnable[i], { Free_PCB(cur); })
for_all_elts(cur, blocked, { Free_PCB(cur); })
free(lwp_init);
lwp_init = NULL;
return LWP_SUCCESS;
}
int LWP_WaitProcess(event) /* wait on a single event */
char *event;
{
char *tempev[2];
Debug(2, ("Entered Wait_Process"))
if (event == NULL) return LWP_EBADEVENT;
tempev[0] = event;
tempev[1] = NULL;
return LWP_MwaitProcess(1, tempev);
}
int LWP_MwaitProcess(wcount, evlist, ecount) /* wait on m of n events */
int wcount, ecount;
char *evlist[];
{
Debug(0, ("Entered Mwait_Process [waitcnt = %d]", wcount))
if (ecount == 0) {
Set_LWP_RC();
return LWP_EBADCOUNT;
}
if (lwp_init) {
if (wcount>ecount || wcount<0) {
Set_LWP_RC();
return LWP_EBADCOUNT;
}
if (ecount > LWP_MAX_EVENTS) {
Set_LWP_RC();
return LWP_EBADCOUNT;
}
if (ecount == 1)
lwp_cpptr->eventlist[0] = evlist[0];
else
memcpy(lwp_cpptr->eventlist, evlist, ecount*sizeof(char *));
if (wcount > 0) {
lwp_cpptr -> status = WAITING;
move(lwp_cpptr, &runnable[lwp_cpptr->priority], &blocked);
}
lwp_cpptr -> wakevent = 0;
lwp_cpptr -> waitcnt = wcount;
lwp_cpptr -> eventcnt = ecount;
Set_LWP_RC();
return LWP_SUCCESS;
}
return LWP_EINIT;
}
int LWP_StackUsed(pid, max, used)
PROCESS pid;
int *max, *used;
{
#define NO_STACK_STUFF
#ifdef DEBUG
#ifdef STACK_USED
#undef NO_STACK_STUFF
#endif
#endif
#ifdef NO_STACK_STUFF
return LWP_NO_STACK;
#else
*max = pid -> stacksize;
*used = Stack_Used(pid->stack, *max);
return LWP_SUCCESS;
#endif
}
/*
* The following functions are strictly
* INTERNAL to the LWP support package.
*/
static Abort_LWP(msg)
char *msg;
{
struct lwp_context tempcontext;
Debug(0, ("Entered Abort_LWP"))
printf("***LWP: %s\n",msg);
printf("***LWP: Abort --- dumping PCBs ...\n");
#ifdef DEBUG
Dump_Processes();
#endif
if (LWPANCHOR.outersp == NULL)
Exit_LWP();
else
savecontext(Exit_LWP, &tempcontext, LWPANCHOR.outersp);
}
static Create_Process_Part2 () /* creates a context for the new process */
{
PROCESS temp;
Debug(2, ("Entered Create_Process_Part2"))
temp = lwp_cpptr; /* Get current process id */
savecontext(Dispatcher, &temp->context, NULL);
(*temp->ep)(temp->parm);
LWP_DestroyProcess(temp);
}
static Delete_PCB(pid) /* remove a PCB from the process list */
PROCESS pid;
{
Debug(4, ("Entered Delete_PCB"))
remove(pid, (pid->blockflag || pid->status==WAITING || pid->status==DESTROYED
? &blocked
: &runnable[pid->priority]));
LWPANCHOR.processcnt--;
}
#ifdef DEBUG
static Dump_One_Process(pid)
PROCESS pid;
{
int i;
printf("***LWP: Process Control Block at 0x%x\n", pid);
printf("***LWP: Name: %s\n", pid->name);
if (pid->ep != NULL)
printf("***LWP: Initial entry point: 0x%x\n", pid->ep);
if (pid->blockflag) printf("BLOCKED and ");
switch (pid->status) {
case READY: printf("READY"); break;
case WAITING: printf("WAITING"); break;
case DESTROYED: printf("DESTROYED"); break;
default: printf("unknown");
}
putchar('\n');
printf("***LWP: Priority: %d \tInitial parameter: 0x%x\n",
pid->priority, pid->parm);
if (pid->stacksize != 0) {
printf("***LWP: Stacksize: %d \tStack base address: 0x%x\n",
pid->stacksize, pid->stack);
printf("***LWP: HWM stack usage: ");
printf("%d\n", Stack_Used(pid->stack,pid->stacksize));
free (pid->stack);
}
printf("***LWP: Current Stack Pointer: 0x%x\n", pid->context.topstack);
if (pid->eventcnt > 0) {
printf("***LWP: Number of events outstanding: %d\n", pid->waitcnt);
printf("***LWP: Event id list:");
for (i=0;i<pid->eventcnt;i++)
printf(" 0x%x", pid->eventlist[i]);
putchar('\n');
}
if (pid->wakevent>0)
printf("***LWP: Number of last wakeup event: %d\n", pid->wakevent);
}
#endif
static purge_dead_pcbs()
{
for_all_elts(cur, blocked, { if (cur->status == DESTROYED) Dispose_of_Dead_PCB(cur); })
}
int LWP_TraceProcesses = 0;
static Dispatcher() /* Lightweight process dispatcher */
{
int i;
#ifdef DEBUG
static int dispatch_count = 0;
if (LWP_TraceProcesses > 0) {
for (i=0; i<MAX_PRIORITIES; i++) {
printf("[Priority %d, runnable (%d):", i, runnable[i].count);
for_all_elts(p, runnable[i], {
printf(" \"%s\"", p->name);
})
puts("]");
}
printf("[Blocked (%d):", blocked.count);
for_all_elts(p, blocked, {
printf(" \"%s\"", p->name);
})
puts("]");
}
#endif
for (i=MAX_PRIORITIES-1; i>=0; i--)
if (runnable[i].head != NULL) break;
if (i < 0) Abort_LWP("No READY processes");
#ifdef DEBUG
if (LWP_TraceProcesses > 0)
printf("Dispatch %d [PCB at 0x%x] \"%s\"\n", ++dispatch_count, runnable[i].head, runnable[i].head->name);
#endif
lwp_cpptr = runnable[i].head;
runnable[i].head = runnable[i].head -> next;
returnto(&lwp_cpptr->context);
}
static Dispose_of_Dead_PCB (cur)
PROCESS cur;
{
Debug(4, ("Entered Dispose_of_Dead_PCB"))
Delete_PCB(cur);
Free_PCB(cur);
/*
Internal_Signal(cur);
*/
}
static Exit_LWP()
{
abort();
}
static Free_PCB(pid)
PROCESS pid;
{
Debug(4, ("Entered Free_PCB"))
if (pid -> stack != NULL) {
Debug(0, ("HWM stack usage: %d, [PCB at 0x%x]",
Stack_Used(pid->stack,pid->stacksize), pid))
free(pid -> stack);
}
free(pid);
}
static Initialize_PCB(temp, priority, stack, stacksize, ep, parm, name)
PROCESS temp;
int (*ep)();
int stacksize, priority;
char *parm;
char *name,*stack;
{
int i = 0;
Debug(4, ("Entered Initialize_PCB"))
if (name != NULL)
while (((temp -> name[i] = name[i]) != '\0') && (i < 31)) i++;
temp -> name[31] = '\0';
temp -> status = READY;
temp -> eventcnt = 0;
temp -> wakevent = 0;
temp -> waitcnt = 0;
temp -> blockflag = 0;
temp -> priority = priority;
temp -> stack = stack;
temp -> stacksize = stacksize;
temp -> ep = ep;
temp -> parm = parm;
temp -> misc = NULL; /* currently unused */
temp -> next = NULL;
temp -> prev = NULL;
}
static int Internal_Signal(event)
char *event;
{
int rc = LWP_ENOWAIT;
int i;
Debug(0, ("Entered Internal_Signal [event id 0x%x]", event))
if (!lwp_init) return LWP_EINIT;
if (event == NULL) return LWP_EBADEVENT;
for_all_elts(temp, blocked, {
if (temp->status == WAITING)
for (i=0; i < temp->eventcnt; i++) {
if (temp -> eventlist[i] == event) {
temp -> eventlist[i] = NULL;
rc = LWP_SUCCESS;
Debug(0, ("Signal satisfied for PCB 0x%x", temp))
if (--temp->waitcnt == 0) {
temp -> status = READY;
temp -> wakevent = i+1;
move(temp, &blocked, &runnable[temp->priority]);
break;
}
}
}
})
return rc;
}
#ifdef DEBUG
#ifdef STACK_USED
static Initialize_Stack(stackptr, stacksize)
char *stackptr;
int stacksize;
{
int i;
Debug(4, ("Entered Initialize_Stack"))
for (i=0; i<stacksize; i++) stackptr[i] = i & 0xff;
}
static int Stack_Used(stackptr, stacksize)
char *stackptr;
int stacksize;
{
int i;
for (i=0;i<stacksize;i++)
if ((unsigned char) stackptr[i] != (i & 0xff))
return (stacksize-i);
return 0;
}
#endif
#endif