mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 15:00:12 +00:00
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:
parent
378a483560
commit
e4d8329619
@ -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
|
||||
|
4
src/lwp/test/.gitignore
vendored
4
src/lwp/test/.gitignore
vendored
@ -3,3 +3,7 @@
|
||||
# to check that you haven't inadvertently ignored any tracked files.
|
||||
|
||||
/rw
|
||||
/selclient
|
||||
/selserver
|
||||
/test
|
||||
/test_key
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user