diff --git a/src/lib/lwp/misc/echo.c b/src/lib/lwp/misc/echo.c deleted file mode 100644 index c0220f28..00000000 --- a/src/lib/lwp/misc/echo.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * server.c - * - * lwp (echo) connection handler server - * - */ - -#include -#include -#include -#include -#include -#include - -#define SP_ACCEPT 3 -#define SP_READER 3 - -#include "lwp.h" - -struct context { - struct lwpProc *us; - struct sockaddr_in addr; - int fd; -}; - -/*ARGSUSED*/ -int -readConn(argc, argv, ud) -int argc; -char **argv; -void *ud; -{ - struct context *ctx = (struct context *)ud; - char buf[1024]; - int n; - - while (1) { - printf("sleeping\n"); - lwpSleepFd(ctx->fd, LWP_FD_READ); - printf("waiting to read\n"); - if ((n = read(ctx->fd, buf, sizeof(buf))) <= 0) - break; - printf("got %d char\n", n); - lwpSleepFd(ctx->fd, LWP_FD_WRITE); - printf("waiting to write\n"); - if (write(ctx->fd, buf, n) < 0) - break; - printf("wrote %d char\n", n); - } - printf("process/fd %d exiting\n", ctx->fd); - close(ctx->fd); - lwpExit(); - /*NOTREACHED*/ -} - -int -acceptConn(argc, argv) -int argc; -char **argv; -{ - struct sockaddr_in sin; - int s; - int ns; - int len; - int maxfd; - struct context *ctx; - - if (argc != 2) { - fprintf(stderr, "Usage: %s port\n", *argv); - exit(-1); - } - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("inet socket"); - exit(-1); - } - sin.sin_family = AF_INET; - sin.sin_port = htons(atoi(argv[1])); - sin.sin_addr.s_addr = 0; - if (bind(s, &sin, sizeof(sin)) < 0) { - perror("inet socket bind"); - exit(-1); - } - if (listen(s, LISTENMAXCONN) < 0) { - perror("inet socket listen"); - exit(-1); - } - maxfd = getdtablesize() - 1; - while (1) { - lwpSleepFd(s, LWP_FD_READ); - len = sizeof(sin); - ns = accept(s, &sin, &len); - if (ns < 0) { - perror("accept"); - exit(-1); - } - if (ns == maxfd) { - fprintf(stderr, "no more connections"); - close(ns); - } - printf("got connection from %s\n", inet_ntoa(sin.sin_addr)); - ctx = (struct context *)malloc(sizeof(*ctx)); - ctx->addr = sin; - ctx->fd = ns; - ctx->us = lwpCreate(SP_READER, readConn, 8192, 0, 0, ctx); - } - /*NOTREACHED*/ -} - -int -main(argc, argv) -int argc; -char **argv; -{ - lwpInitSystem(1); - lwpCreate(SP_ACCEPT, acceptConn, 8192, argc, argv, 0); - lwpReschedule(); - /*NOTREACHED*/ -} diff --git a/src/lib/lwp/misc/lwp.h b/src/lib/lwp/misc/lwp.h deleted file mode 100644 index 13d8123f..00000000 --- a/src/lib/lwp/misc/lwp.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * lwp.h -- prototypes and structures for lightweight processes - * Copyright (C) 1991-3 Stephen Crane. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * author: Stephen Crane, (jsc@doc.ic.ac.uk), Department of Computing, - * Imperial College of Science, Technology and Medicine, 180 Queen's - * Gate, London SW7 2BZ, England. - */ -#ifndef _LWP_H -#define _LWP_H - -#include -#include - -/* process control block. do *not* change the position of context */ -struct lwpProc { - jmp_buf context; /* processor context area */ - void *sbtm; /* bottom of stack attached to it */ - int size; /* size of stack */ - void (*entry) (); /* entry point */ - int dead; /* whether the process can be rescheduled */ - int pri; /* which scheduling queue we're on */ - long runtime; /* time at which process is restarted */ - int fd; /* fd we're blocking on */ - int argc; /* initial arguments */ - char **argv; - void *ud; /* user data */ - struct lwpProc *next; -}; - -/* queue */ -struct lwpQueue { - struct lwpProc *head; - struct lwpProc *tail; -}; - -/* semaphore */ -struct lwpSem { - int count; - struct lwpQueue q; -}; - -#define LWP_FD_READ 0x1 -#define LWP_FD_WRITE 0x2 - -#define LWP_MAX_PRIO 8 - -struct lwpProc *lwpInitSystem(int); -struct lwpProc *lwpCreate(int, void (*)(void *), int, int, char **, void *); -void lwpExit(void); -void lwpTerminate(struct lwpProc *); -void lwpYield(void); -void lwpSleepFd(int fd, int flags); -void lwpSleepUntil(long until); -void lwpWakeupFd(struct lwpProc *); -void *lwpGetUD(struct lwpProc *); -void lwpSetUD(struct lwpProc *, char *); -int lwpSetPriority(int); -void lwpReschedule(); - -struct lwpSem *lwpCreateSem(int); -void lwpSignal(struct lwpSem *); -void lwpWait(struct lwpSem *); -void lwpSelect(int argc, char **argv); - -extern struct lwpProc *LwpCurrent; - -#endif /* _LWP_H */ diff --git a/src/lib/lwp/misc/lwp.tar.gz b/src/lib/lwp/misc/lwp.tar.gz deleted file mode 100644 index 72e71fb6..00000000 Binary files a/src/lib/lwp/misc/lwp.tar.gz and /dev/null differ diff --git a/src/lib/lwp/misc/lwp.tex b/src/lib/lwp/misc/lwp.tex deleted file mode 100644 index 2cfb2b53..00000000 --- a/src/lib/lwp/misc/lwp.tex +++ /dev/null @@ -1,189 +0,0 @@ -\documentstyle[tgrind, a4]{article} -\title{The {\sc Rex} lightweight process library} -\author{Stephen Crane\\ (jsc@doc.ic.ac.uk)\thanks{Thanks to Mark Little -(m.c.little@ncl.ac.uk) for the Linux port}} -\begin{document} -\maketitle -This document describes the interface to and the behaviour underlying -my threads library for Rex.\footnote{Available as lwp.tar.gz by anonymous -ftp from gummo.doc.ic.ac.uk:/rex. Rex (Esprit project 2080) was -axed by Men in Suits.} It has been tested on Sun-3, Sun-4, -Mips, 386-BSD and Linux systems. Counting semi-colons, it is -260 lines long, including support for the different architectures (this -figure includes variable- but not function-declarations). - -A word from our sponsor: -\begin{quote} -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but {\sc WITHOUT ANY WARRANTY}; without even the implied warranty of -{\sc MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE}. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this library; if not, write to the Free -Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -\end{quote} - -(Note that while this library is protected by the GNU copyleft, it is not -supported by the Free Software Foundation.) - -\section{Threads} -Threads are prioritised and -non-preemptive. Operations supported on threads are: -\begin{tgrind} -\L{\LB{}\Tab{8}{\K{struct} pcb *initlp (\K{int} priority)}} -\L{\LB{}\Tab{8}{\K{struct} pcb *creatp (priority, entry, size, argc, argv, envp)}} -\L{\LB{}\Tab{8}{\K{void} readyp (\K{struct} pcb *p)}} -\L{\LB{}\Tab{8}{\K{void} yieldp (\K{void})}} -\L{\LB{}\Tab{8}{\K{void} *getenvp (\K{struct} pcb *p)}} -\L{\LB{}\Tab{8}{\K{void} setenvp (\K{struct} pcb *p, \K{void} *)}} -\L{\LB{}\Tab{8}{\K{void} suicidep (\K{void})}} -\L{\LB{}\Tab{8}{\K{void} destroyp (\K{struct} pcb *p)}} -\end{tgrind} -\begin{description} -\item[initlp] initialises the threads runtime, creating a thread with -specified priority for the invoker. -\item[creatp] creates a new thread with specified {\em priority}, {\em -entry} point, with a stack of {\em size}, {\em argc} arguments in {\em -argv} and a user-defined environment pointer. -\item[getenvp] returns the environment pointer associated with the given -thread. If the thread is null, the current thread is assumed. -\item[setenvp] reassigns the environment pointer associated with the -given thread. -\item[readyp] makes the specified thread ready to run, or the current -thread if null. -\item[yieldp] makes the current thread ready to run. If no thread of -higher priority is runnable, the current thread will run. -\item[suicidep] marks the invoking thread as dead. It will never be -rescheduled. -\item[destroyp] marks the specified thread as dead. It will be removed -at the next reschedule. If it is currently running, it will be -unaffected until the next reschedule. -\end{description} - -\section{Semaphores} -For synchronisation, counting semaphores are provided. Available -operations are: -\begin{tgrind} -\L{\LB{}\Tab{8}{\K{struct} sem *creats (\K{int} count)}} -\L{\LB{}\Tab{8}{\K{void} signals (\K{struct} sem *s)}} -\L{\LB{}\Tab{8}{\K{void} waits (\K{struct} sem *s)}} -\end{tgrind} -\begin{description} -\item[creats] allocates a new semaphore from the heap and initialises its -count. -\item[signals] increments the semaphore's count, makes a waiting process -ready if there is one. If the readied process's priority is greater than -that of the signaller, a reschedule is done. -\item[waits] decrements the semaphore's count. If it becomes negative, -the current process is suspended and a reschedule is done. -\end{description} - -\section{Signals} -The library is concerned with two types of signal, {\sc sigio} and {\sc -sigalrm}. These signals are normally blocked until the null process is -scheduled. It uses {\tt sigpause()} to reenable them and wait for one -to arrive. While awaiting a signal, the null process `runs' at maximum -priority. Thus users will not be able to cause a reschedule from -their handlers. When {\tt sigpause()} returns, the signal will have -been handled and the null process drops back down to the lowest priority -and yields to any thread which has been made ready to run from the -user-level handler. - -These semantics make the library rather unresponsive to signals in the -presence of busy processes. If a more responsive system is required, -the constant {\sc LCOUNT} may be changed. This value determines the -number of times the {\tt reschedp ()} function must be called before -signals are re-enabled. If given a value of {\tt 1}, it will affect -context-switching time by about 50\%. Its default value is {\tt -1}. - -\subsection{Input and output} -Input and output present a problem to threads, because they require -calls to the underlying {\sc Unix} system, which will block not only -the invoking thread, but also all others in the process. Thus, in -general, a thread must wait until the descriptor on which I/O is to -be done becomes ready for the operation. This is done by trapping -{\sc sigio}. Two routines are provided: -\begin{tgrind} -\L{\LB{}\Tab{8}{\K{int} sigioset (\K{int} fd, \K{void} (*han) (\K{void} -*, \K{int}), \K{void} *ctx)}} -\L{\LB{}\Tab{8}{\K{int} sigioclr (\K{int} fd)}} -\end{tgrind} -The general model adopted for processing {\sc sigio} is to install a -{\em handler} routine for the I/O descriptor using {\em sigioset} and -remove it using {\em sigioclr}. The user is responsible for setting up -the device correctly to generate {\sc sigio}. When {\sc sigio} arrives -for the descriptor, the handler will be called with a context pointer -as its argument. (In C++, this context is the instance pointer of the -invoking thread.) - -\subsection{The timer} -A single routine is provided to block the invoking thread for the -specified time: -\begin{tgrind} -\L{\LB{}\Tab{8}{\K{void} delayp (\K{int} n)}} -\end{tgrind} -This routine blocks the invoker for {\em at least\/} the time specified. -If this is zero, a reschedule is done. Delays are implemented as a -delta queue, using {\sc sigalrm}. $n$ specifies a microsecond delay -which is of limited utility in practice. - -\section{Performance} -\begin{figure}[htb] -\begin{center} -\begin{tabular}{||l|c|c|c||} \hline -Arch & ctxsw & creat & comment \\ \hline -sun3 & 308 & 778 & 3/240 \\ \hline -386bsd & 186 & 464 & 486/33 \\ \hline -sun4 & 96 & 436 & IPX \\ \hline -sun4 & 59 & 212 & Sparc-10 \\ \hline -linux & 56 & 382 & 486-DX2/50 \\ \hline -mips & 17 & 85 & Decstation \\ \hline -\end{tabular} -\caption{Performance with architecture (times in microseconds).} -\end{center} -\end{figure} -\begin{description} -\item[sun3] has very lightweight process initialisation, compared with -context switching. -\item[sun4] has a high context switch time as a result of {\tt setjmp ()} and -{\tt longjmp ()} implementations. Process initialisation is also relatively -heavyweight: it requires two calls to {\tt setjmp ()} and one to {\tt longjmp -()}. -\item[mips] provides its own context switching in assembly language. -\end{description} - -\section{Porting to another architecture} -Although the threads library is quite portable, a few guidelines should -be observed when moving to a new architecture. - -\begin{itemize} -\item Create two new files for your architecture/kernel (e.g. {\tt sun4.c} -and {\tt sun4.h}). -The `.c' file should contain any routines which your version of {\sc Unix} is -missing and a thread initialisation routine: -\begin{tgrind} -\L{\LB{}\Tab{8}{\K{void} initp (\K{struct} pcb *, \K{void} *)}} -\end{tgrind} -The `.h' file contains any machine-specific definitions. -\item If {\tt setjmp ()} and {\tt longjmp ()} don't work on your machine -(for example the {\sc Ultrix} {\tt longjmp ()} implementation checks that -the frame being jumped to is an ancestor of the current one), you will -have to write {\tt savep ()} and {\tt restorep ()} and put the following -define into your machine-specific header file: -\begin{tgrind} -\L{\LB{}\Tab{8}{\K{\#define} OWN\_CONTEXT\_SWITCH}} -\end{tgrind} -\item Compile and run the three test programs: {\tt producer.c}, {\tt -timer.c} and {\tt bm.c}. -\item Add the name of the architecture to `config'. -\item Send {\tt new-arch.[ch]}, any context diffs for the rest of the -library and the output of {\tt bm.c} to {\tt jsc@doc.ic.ac.uk}. Also -please let me know where you got the library from. -\end{itemize} -\end{document}