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) LT_libs = $(MT_LIBS)
all: liboafs_lwpcompat.la liblwpcompat_pic.la \ 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 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 exc_handling.o : exc_handling.c
.PHONY: test
test: ${TOP_LIBDIR}/liblwp.a
cd test && $(MAKE) all
# #
# Install targets # Install targets
# #
@ -219,5 +223,6 @@ buildtools: ${TOP_LIBDIR}/liblwp.a depinstall
clean: clean:
$(LT_CLEAN) $(LT_CLEAN)
$(RM) -f *.o *.a core AFS_component_version_number.c $(RM) -f *.o *.a core AFS_component_version_number.c
cd test && $(MAKE) clean
include ../config/Makefile.version include ../config/Makefile.version

View File

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

View File

@ -13,14 +13,10 @@ include @TOP_OBJDIR@/src/config/Makefile.lwp
INCDIRS= -I.. -I${DESTDIR}/include INCDIRS= -I.. -I${DESTDIR}/include
LIBS= ../liblwp.a LIBS= ../liblwp.a
system noversion: test all: test selclient selserver test_key rw
test: test.c liblwp.a
${CC} -p ${CFLAGS} test.c -o test ${LIBS}
testlwp.o : testlwp.c
${CC} -c -p ${CFLAGS} testlwp.c ${LIBS}
test: test.o ${LIBS}
$(AFS_LDRULE) test.o ${LIBS}
selclient.o: selclient.c seltest.h selclient.o: selclient.c seltest.h
@ -35,7 +31,7 @@ selserver: selserver.o selsubs.o ${LIBS}
selsubs.o: selsubs.c seltest.h selsubs.o: selsubs.c seltest.h
test_key: test_key.o 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 rw: rw.o $(LIBS) $(TOP_LIBDIR)/libopr.a
$(AFS_LDRULE) 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 <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/types.h> #include <sys/types.h>
@ -58,16 +59,12 @@
#include "lwp.h" #include "lwp.h"
#include "seltest.h" #include "seltest.h"
/* Put this in lwp.h? */ static void sendTest(int, int, int, int);
extern int IOMGR_Select(int, fd_set *, fd_set *, fd_set *, struct timeval *); static void sendEnd(int);
static int nSigIO = 0;
void sendTest(int, int, int, int); static void
void sendEnd(int); sigIO(int sig)
int nSigIO = 0;
void
sigIO()
{ {
nSigIO++; nSigIO++;
} }
@ -75,7 +72,8 @@ sigIO()
char *program; char *program;
Usage() static void
Usage(void)
{ {
printf printf
("Usage: selclient [-fd n] [-oob] [-soob] [-delay n] [-end] [-write n] host port\n"); ("Usage: selclient [-fd n] [-oob] [-soob] [-delay n] [-end] [-write n] host port\n");
@ -88,10 +86,10 @@ Usage()
exit(1); exit(1);
} }
int
main(int ac, char **av) main(int ac, char **av)
{ {
int i; int i;
int on = 1;
char *hostname = 0; char *hostname = 0;
struct hostent *hostent; struct hostent *hostent;
int host; /* net order. */ int host; /* net order. */
@ -103,7 +101,6 @@ main(int ac, char **av)
int putOOB = 0; int putOOB = 0;
int delay = 5; int delay = 5;
int doEnd = 0; int doEnd = 0;
int doWrite = 0;
int writeSize = 0; int writeSize = 0;
program = av[0]; program = av[0];
@ -137,7 +134,6 @@ main(int ac, char **av)
Usage(); Usage();
} }
} else if (!strcmp("-write", av[i])) { } else if (!strcmp("-write", av[i])) {
doWrite = 1;
if (++i >= ac) { if (++i >= ac) {
printf("%s: Missing size for -write option.\n", program); printf("%s: Missing size for -write option.\n", program);
Usage(); Usage();
@ -227,12 +223,14 @@ main(int ac, char **av)
sendTest(sockFD, delay, reqOOB, writeSize); sendTest(sockFD, delay, reqOOB, writeSize);
} }
close(sockFD); close(sockFD);
return 0;
} }
/* sendTest /* sendTest
*/ */
int writeIndex; static int writeIndex;
void static void
sendTest(int sockFD, int delay, int reqOOB, int size) sendTest(int sockFD, int delay, int reqOOB, int size)
{ {
char *buf, *bufTest; char *buf, *bufTest;
@ -292,13 +290,13 @@ sendTest(int sockFD, int delay, int reqOOB, int size)
(void)time(&etime); (void)time(&etime);
if (etime - stime > 1) { if (etime - stime > 1) {
Log("Waited %d seconds to write at offset %d.\n", Log("Waited %d seconds to write at offset %d.\n",
etime - stime, i); (int)(etime - stime), i);
} }
stime = etime; stime = etime;
nbytes = write(sockFD, &buf[i], 1); nbytes = write(sockFD, &buf[i], 1);
(void)time(&etime); (void)time(&etime);
if (etime - stime > 1) { 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); assert(nbytes == 1);
FD_CLR(sockFD, wfds); FD_CLR(sockFD, wfds);
@ -321,7 +319,7 @@ sendTest(int sockFD, int delay, int reqOOB, int size)
Log("Compared %d bytes.\n", size); Log("Compared %d bytes.\n", size);
} }
void static void
sendEnd(int fd) sendEnd(int fd)
{ {
selcmd_t sc; selcmd_t sc;

View File

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

View File

@ -22,33 +22,19 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <string.h> #include <string.h>
#include <sys/time.h> #include <sys/time.h>
#include <time.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netdb.h> #include <netdb.h>
#include <signal.h> #include <signal.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <assert.h> #include <assert.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h>
#include "lwp.h" #include "lwp.h"
#include "seltest.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 /* 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. * 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. * Open file descriptors until file descriptor n or higher is returned.
*/ */
#include <sys/stat.h>
void void
OpenFDs(n) OpenFDs(int n)
int n;
{ {
int i; int i;
struct stat sbuf; struct stat sbuf;
@ -158,8 +142,8 @@ Log(char *fmt, ...)
ltime = localtime(&tt); ltime = localtime(&tt);
LWP_CurrentProcess(&pid); LWP_CurrentProcess(&pid);
fprintf(stderr, "%s 0x%x %02d:%02d:%02d.%d: ", program ? program : "", fprintf(stderr, "%s %p %02d:%02d:%02d.%d: ", program ? program : "",
pid, ltime->tm_hour, ltime->tm_min, ltime->tm_sec, now.tv_usec); pid, ltime->tm_hour, ltime->tm_min, ltime->tm_sec, (int)now.tv_usec);
va_start(args, fmt); va_start(args, fmt);

View File

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

View File

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