home *** CD-ROM | disk | FTP | other *** search
- Subject: v14i096: Shared memory emulation for 4.2BSD, Part03/04
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: libes@cme-durer.ARPA (Don Libes)
- Posting-number: Volume 14, Issue 96
- Archive-name: sharedmem/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 4)."
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'doc/usenix/abstract.trf' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'doc/usenix/abstract.trf'\"
- else
- echo shar: Extracting \"'doc/usenix/abstract.trf'\" \(6265 characters\)
- sed "s/^X//" >'doc/usenix/abstract.trf' <<'END_OF_FILE'
- X.RP
- X.TL
- XUser-Level Shared Variables (in a Hierarchical Control Environment)
- X.AU
- XDon Libes
- X.AI
- XFactory Automation Systems Division
- XNational Bureau of Standards
- XGaithersburg, MD 20899
- X.PP
- XWe have implemented a shared variable system for UNIX 4.2 that emulates a
- Xshared or common memory.
- X.IP \(bu
- XShared variables provide an alternate style of communications
- Xto message passing or pipes.
- X.IP \(bu
- XThis system is all user level code and requires no kernel
- Xmodifications. It is accessible from a variety of languages.
- X.IP \(bu
- XWe are using this system in a real application - an automated
- Xfactory.
- X.PP
- X.SH
- XI User View
- X.PP
- XA server, the Common Memory Manager (CMM), acts on requests to access shared
- Xvariables. Typical requests are read, write, and declare. Variables are
- Xstructured and have attributes such as type, protection, lifetime, and
- Xownership. Variable type checking is performed at runtime startup, since
- Xprocesses are loosely connected.
- X.PP
- XSome of the more interesting attributes of these shared variables are:
- X.PP
- X.I
- Xlifetime and "shelf life".
- X.R
- XIn a real time environment, the system must
- Xsurvive a process dying or getting bogged down temporarily. When the useful
- Xlifetime of a variable's value has expired, other processes are free to
- Xmanipulate the variable, for instance, by redeclaring or writing it. This
- Xattribute allows a "god" process to notice unexpected process deaths and
- Xrestart processes or transfer control to other processes. For less
- Xcritical variables (such as an infrequently updated sensor value), processes
- Xmight note a "stale" value, and make a projection that will carry them over
- Xuntil the variable writer catches up to its duties.
- X.PP
- X.I
- Xwrite count, timestamp, authorstamp.
- X.R
- XBy marking each variable with how many
- Xtimes or when it has been written, handshaking can be performed for the
- Xusers. The archetypal example from the automation environment is the
- Xcommand "hit nail with hammer". If the supervisor runs more quickly than
- Xthe subordinate, without handshaking, the subordinate may never see the
- Xcommand (i.e. nail is not hit). If the subordinate runs more quickly than
- Xthe supervisor, without handshaking, the subordinate may execute the same
- Xcommand twice (i.e. nail is hit more than once)
- X.PP
- X.I
- Xwakeup.
- X.R
- XVariables can be marked with a list of processes to be notified upon
- Xvalue change. This was originally added for efficiency, so that servers,
- Xfor example, would not have to loop just waiting for new values. It has
- Xturned out to be extremely useful for debugging. Rather than inserting
- Xprintf statements in existing code and recompiling, it is possible to create
- Xa debug module that simply prints out variables when they change. We have
- Xalso used it for a graphics monitor that continuously displays the state of
- Xthe entire system. This wakeup attribute forces a queuing discipline on a
- Xvariable.
- X.PP
- X.I
- Xnon-exclusive write.
- X.R
- XVariables can be declared read or write, exclusively or
- Xnonexclusively. By default, writes are exclusive, meaning that only one
- Xprocess can write a variable during its lifetime. Non-exclusive write has
- Xno such restriction, allowing multiple processes to write the same variable.
- XOne use of this might be a server listening on a socket. Any client can
- Xrequest service by writing the variable associated with the socket. Another
- Xuse is to allow a debug process to insert a new value without modifying the
- Xvariable's normal writer.
- X.PP
- X.SH
- XII 4.2BSD Implementation
- X.PP
- XThe Shared Variable System consists of three layers. The lowest level
- Xsimulates a common memory facility such as is available in System V. On top
- Xof this are the procedures that transform common memory into common
- Xvariables. Above this is another level that provides handshaking, if
- Xnecessary. All levels run as user-level code and require no kernel
- Xmodifications.
- X.PP
- X4.2BSD has no common memory facility. Our system provides one via a
- Xuser-level server that stores variables in its own memory space which is
- Xprivate to it. Access to variables is therefore strictly through the valid
- Xrequests to the CMM server.
- X.PP
- XClient processes keep their own local version of the common variables until
- Xit is convenient for them to synchronize with the CMM. By calling
- X.I cm_sync() ,
- Xthe user and the common memory server become synchronized. This
- Xcall is noninterruptible for the CMM since the server completely processes
- Xrequests in the order that they are received.
- X.PP
- XThe Shared Variables System is written in C and uses the 4.2 interprocess
- Xcommunication system. Thus, the common memory as well as the clients can be
- Xdistributed. An interface exists for Franz Lisp.
- X.PP
- X.SH
- XIII An application - manufacturing automation
- X.PP
- XWhile the CMM is a general tool, it is currently being used at the National
- XBureau of Standards in the Automated Manufacturing Research Facility, a
- Xproject in manufacturing automation. This project requires communication
- Xbetween stationary and mobile robots, machine tools, their controllers, and
- Xhigher-level cell and factory management computers. The processes are
- Xorganized in a control hierarchy, much like the organization of a
- Xconventional factory.
- X.PP
- XFor the purposes of hierarchical control, one can imagine that processes in
- Xthe system communicate along hierarchical channels. Each process runs
- Xasynchronously, communicating only with its superior and subordinate
- Xprocesses.
- X.PP
- XLogically however, communication is performed using the common memory model.
- XFor example, a process sending commands to a subordinate writes the
- Xinformation in a well-known common memory variable. The subordinate reads
- Xthe information out of the common memory variable, noting whether or not it
- Xcontains a new value.
- X.PP
- XIn reality, there are small groups of processes and processors that directly
- Xcommunicate with each other, some using physical common memory and some
- Xsimulating common memory. Each cluster representing a piece of common
- Xmemory can choose to replicate any other portion of another cluster's common
- Xmemory. An underlying network invisibly supplies this service of keeping
- Xall the common memories synchronized. The result is effectively one of a
- Xconsolidated common memory, with a very consistent and easy means of
- Xcommunication between processes.
- END_OF_FILE
- if test 6265 -ne `wc -c <'doc/usenix/abstract.trf'`; then
- echo shar: \"'doc/usenix/abstract.trf'\" unpacked with wrong size!
- fi
- # end of 'doc/usenix/abstract.trf'
- fi
- if test -f 'src/cm_usr1.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/cm_usr1.c'\"
- else
- echo shar: Extracting \"'src/cm_usr1.c'\" \(8111 characters\)
- sed "s/^X//" >'src/cm_usr1.c' <<'END_OF_FILE'
- X/*
- X
- XThese are the user functions uses in manipulating common memory variables.
- XThe primary functions are:
- X
- Xcm_init(process_name,host,debug_level)
- Xcm_declare(name,type,role,period)
- Xcm_undeclare(variable)
- Xcm_sync(wait)
- Xcm_exit()
- X*/
- X
- X/* real code begins here */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <strings.h>
- X#include <sys/file.h> /* for open(/dev/null) hack */
- X#include "inet.h"
- X
- X#include "cm_constants.h"
- X#include "cm_sd.h"
- X#include "cm_var.h"
- X#include "cm_interface.h"
- X#include "cm_sync.h"
- X#include "cm_slot.h"
- X#include "cm_msg.h"
- X#include "cm_time.h"
- X
- Xextern int errno;
- X
- Xstatic struct msg *omsg, *imsg;
- X
- Xint server_socket;
- Xint maxfds;
- X
- Xint cm_init();
- Xcm_variable *cm_declare();
- Xcm_variable *firstuservar(), *nextuservar();
- Xcm_write();
- Xstruct user_variable *cm_read();
- Xcm_sync();
- Xstruct slot *nextslot();
- Xcm_variable *get_variable();
- X
- Xchar *malloc();
- Xstatic composemsg();
- X
- X/* real definitions begin here */
- X
- Xint
- Xcm_init(name,host,debug_level)
- Xchar *name;
- Xchar *host; /* host running cmm. 0 or "" means local host */
- Xint debug_level;
- X{
- X set_cm_debug_level(debug_level);
- X set_cm_process_name(name);
- X if (0 > (server_socket = initport(PORT_NUMBER(CM_PORT),CLIENT,
- X SOCK_STREAM,host))) return(E_CM_INIT_FAILED);
- X
- X maxfds = getdtablesize();
- X cm_time_init();
- X
- X if (!(imsg = (struct msg *)malloc(CM_MSGSIZE))) {
- X fprintf(stderr,"init: failed malloc(imsg)\n");
- X exit(-1);
- X }
- X if (!(omsg = (struct msg *)malloc(CM_MSGSIZE))) {
- X fprintf(stderr,"init: failed malloc(omsg)\n");
- X exit(-1);
- X }
- X return(0);
- X}
- X
- X/* the following call is important if you plan on restarting cm connections
- Xserveral times in one process. It runs around deallocating memory that has
- Xbeen allocated by cm_sd_copy.
- X*/
- Xcm_exit()
- X{
- X cm_variable *v;
- X
- X close(server_socket);
- X
- X for (v=next_user_variable((struct user_variable *)0);v;
- X v=next_user_variable(v)) {
- X if (!v->count) continue; /* never set */
- X cm_sd_free(&v->data);
- X }
- X}
- X
- Xcm_variable *
- Xcm_declare(name,role)
- Xchar *name;
- Xunsigned int role; /* READER, WRITER, XWRITER, WAKEUP */
- X{
- X cm_variable *v;
- X
- X if (!(v = get_variable(name))) {
- X fprintf(stderr,"cannot get_variable(%s)\n",name);
- X return(NULL);
- X }
- X if (role) {
- X /* you gave no way to "or out" these bits, you twit! */
- X if (role & CM_ROLE_READER) v->role.reader = TRUE;
- X if (role & CM_ROLE_XWRITER) v->role.xwriter = TRUE;
- X if (role & CM_ROLE_NONXWRITER) v->role.nonxwriter = TRUE;
- X if (role & CM_ROLE_WAKEUP) v->role.wakeup = TRUE;
- X }
- X/* if (cmd_assoc != 0) v->command_association = cmd_assoc;*/
- X
- X v->status.declared = TRUE;
- X return(v);
- X}
- X
- Xcm_undeclare(v)
- Xcm_variable *v;
- X{
- X v->status.undeclared = TRUE;
- X}
- X
- X/* returns negative for failure or 0 for success */
- Xcm_sync(wait_opts)
- Xint wait_opts;
- X{
- X int slots; /* number of slots in incoming message */
- X int query; /* TRUE, if we are requesting an ack from the cmm */
- X int rc = 0;
- X int cc;
- X int selector;
- X struct slot *s;
- X int processed_msg = FALSE; /* true if we have received and
- X processed at least one msg in
- X this call to cm_sync */
- X
- X if ((0 == message_waiting(server_socket))
- X && (wait_opts & CM_WAIT_READ)) {
- X /* no messages waiting, so provoke the cmm to give us some */
- X query = TRUE;
- X } else query = FALSE;
- X
- X composemsg(omsg);
- X if (query) omsg->read_wait = TRUE;
- X if (omsg->slots || query) {
- X print_msg(omsg);
- X cc = sized_write(server_socket,omsg,omsg->size);
- X if (cc != omsg->size) {
- X fprintf(stderr,"%s%s\n","failed to send msg to cmm. ",
- X "cmm disappeared?");
- X exit(0);
- X }
- X eprintf(2,"sent msg to server (%d)\n",cc);
- X } /* no slots in msg, so no msg not sent to server */
- X while (TRUE) {
- X /* poll first */
- X selector = 1<<server_socket;
- X if (-1 == (cc = message_waiting(server_socket))) {
- X rc = E_CMM_DIED;
- X break;
- X }
- X /* wait rules are as follows:
- XWAIT: WAIT_AT_MOST_ONCE WAIT_FOR_ALL
- Xno msg waiting select/return select/return
- X msg waiting select/return select/select
- X
- XNO_WAIT: WAIT_AT_MOST_ONCE WAIT_FOR_ALL
- Xno msg waiting return/return return/return
- X msg waiting select/return select/select
- X
- XWhere x/y means:
- XDo x if no messages have been processed in this call to cm_sync, and
- XDo y if at least one message has been processed in this call to cm_sync.
- X
- XFor example:
- XIf user specified NO_WAIT|WAIT_AT_MOST_ONCE, no message is waiting and
- Xat least one message has been processed, we return.
- X*/
- X /* catagorize by the conditions that return, which are
- X implemented by "break".
- X */
- X if (wait_opts & CM_NO_WAIT) {
- X if (cc == 0) break; /* no msg waiting */
- X } else if (wait_opts & CM_WAIT_AT_MOST_ONCE) {
- X if (processed_msg) break;
- X } else if (processed_msg && (cc == 0)) break;
- X
- X /* That was amazingly simpler to code then to say!!! */
- X
- X /* wait until someone responds */
- X selector = 1<<server_socket;
- X if (-1 == select(maxfds,&selector,(int *)0,(int *)0,
- X (struct timeval *)NULL)) {
- X rc = E_CMM_DIED;
- X break;
- X } else {
- X if (0 >= (cc = sized_read(server_socket,imsg,CM_MSGSIZE))) {
- X rc = E_CMM_DIED;
- X break;
- X }
- X processed_msg = TRUE;
- X s = imsg->data;
- X print_msg(imsg);
- X if (imsg->version != CMM_VERSION) {
- X if (imsg->version > CMM_VERSION) {
- X fprintf(stderr,"cm library (v%d) is %s than cmm (v%d)",
- X CMM_VERSION,
- X ((imsg->version > CMM_VERSION)?"older":"newer"),
- X imsg->version);
- X }
- X return(E_CM_WRONG_VERSION);
- X }
- X
- X slots = imsg->slots;
- X s = imsg->data;
- X for (;;) {
- X if (s == NULL || slots == 0) break;
- X if (0 > user_decode_slot(s)) {
- X printf("bad slot encountered...aborting msg \n");
- X break;
- X }
- X eprintf(6,"slot = %x ",s);
- X eprintf(6,"slot->name %s ",s->s_name);
- X eprintf(6,"slot->size %x\n",s->s_size);
- X
- X s = nextslot(imsg,s);
- X slots--;
- X }
- X }
- X }
- X return(rc);
- X}
- X
- X/* returns -1 if cmm died, 0 if no message waiting, >0 if message waiting */
- Xstatic int
- Xmessage_waiting(fd)
- Xint fd;
- X{
- X int selector = 1<<fd;
- X
- X return(select(maxfds,&selector,(int *)0,(int *)0,&cm_period_zero));
- X}
- X
- X/*
- Xgo through our variables looking for ones that we have written or declared.
- XStuff them all into a buffer and send this message to the cmm.
- XBy looking at all variables only once, we get rid of duplicates. I.e. the
- Xuser may have written a value more than once before syncing.
- X*/
- Xstatic composemsg(m)
- Xstruct msg *m; /* outgoing msg */
- X{
- X int size;
- X cm_variable *v;
- X
- X init_msg(m);
- X
- X for (v=next_user_variable((struct user_variable *)0);v;
- X v=next_user_variable(v)) {
- X if (v->status.declared) {
- X eprintf(6,"adding declare slot for %s\n",v->name);
- X size = put_slot_declare(m,v->name,
- X/* &v->role,v->command_association); */
- X &v->role,0);
- X if (size > 0) v->status.declared = FALSE;
- X }
- X if (v->status.written) {
- X eprintf(6,"adding write slot for %s\n",v->name);
- X size = put_slot_write(m,v->name,&v->data,
- X v->command_association);
- X if (size > 0) v->status.written = FALSE;
- X }
- X if (v->status.undeclared) {
- X eprintf(6,"adding undeclare slot for %s\n",v->name);
- X size = put_slot_undeclare(m,v->name);
- X if (size > 0) {
- X cm_sd_free(&v->data);
- X v->status.inuse = FALSE;
- X }
- X }
- X }
- X#if 0
- X /* this should be last, because when the manager receives it, */
- X /* any current values going into the message queue are zapped. */
- X /* This way, the user will not get any duplicate values. */
- X if (query) put_slot_read(m);
- X#endif
- X}
- X
- Xcm_print_variable(name)
- Xchar *name;
- X{
- X cm_variable *v;
- X
- X if (!(v = get_variable(name))) {
- X fprintf(stderr,"cannot get_variable(%s)\n",name);
- X }
- X
- X printf("name = %s\n",v->name);
- X printf("role.reader = %d\n",v->role.reader);
- X printf("role.nonxwriter = %d\n",v->role.nonxwriter);
- X printf("role.wakeup = %d\n",v->role.wakeup);
- X printf("role.xwriter = %d\n",v->role.xwriter);
- X printf("count = %d\n",v->count);
- X printf("cmd assoc = %d\n",v->command_association);
- X printf("status.inuse = %d\n",v->status.inuse);
- X printf("status.written = %d\n",v->status.written);
- X printf("status.declared = %d\n",v->status.declared);
- X printf("status.undeclared = %d\n",v->status.undeclared);
- X}
- END_OF_FILE
- if test 8111 -ne `wc -c <'src/cm_usr1.c'`; then
- echo shar: \"'src/cm_usr1.c'\" unpacked with wrong size!
- fi
- # end of 'src/cm_usr1.c'
- fi
- if test -f 'src/franz/config.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/franz/config.h'\"
- else
- echo shar: Extracting \"'src/franz/config.h'\" \(16909 characters\)
- sed "s/^X//" >'src/franz/config.h' <<'END_OF_FILE'
- X/* -[Wed Jun 12 08:00:31 1985 by jkf]-
- X * config.h $Locker: $
- X * configuration dependent info
- X *
- X * $Header: config.h,v 40.37 85/07/21 10:49:29 layer Exp $
- X *
- X * (c) copyright 1982, Regents of the University of California
- X * Enhancements (c) copyright 1984, Franz Inc., Oakland California
- X */
- X
- X/*
- X * this file contains three types of parameters
- X * 1) those parameters which each site may wish to modify to
- X * personalize lisp.
- X * 2) those flags which are machine or operating system dependent
- X * and thus which should not be modified.
- X * 3) those which should be of type (1) but by the time the customer
- X * has received lisp, the setting of the flag has been hardwired
- X * in. We are trying to reduce flags of this type, but a few still
- X * exist.
- X *
- X * In the description of each flag we will note its class from the
- X * list above (class 1,2 or 3).
- X *
- X */
- X
- X/*
- X** The type of machine and os this is to run on will come from
- X** the file lconf.h.
- X*/
- X# ifndef NoLconf
- X# include "lconf.h"
- X# endif
- X
- X
- X/* GCSTRINGS - (class 3)
- X * define this if you want the garbage collector to reclaim
- X * strings. It is not normally set because in typical applications the
- X * expense of collecting strings is not worth the amount of space
- X * retrieved
- X */
- X
- X/* #define GCSTRINGS */
- X
- X/*
- X * NAMESIZE (class 1) - size of the internal stack for holding
- X * local (non-special) variables. The size allocated is
- X * NAMESIZE + 4*NAMEINC, the stack growing by NAMINC each
- X * time it overflows (so that overflows can be handled in lisp).
- X * NAMINC is a class 1 constant.
- X */
- X#define NAMESIZE 3072
- X#define NAMINC 50
- X
- X/*
- X * MVR (class 3) handle multiple value returns
- X */
- X#define MVR
- X#define MMVR 20
- X
- X/*
- X** HASHT (class 3) include the hash table package
- X*/
- X#define HASHT
- X
- X/* DOMAIN - (class 3) this is put on the (status features) list and
- X * is the value of (status domain)
- X */
- X#define DOMAIN "franz-inc"
- X
- X/*
- X * Machine/os dependent flags: (class 2)
- X * All flags are of the ifdef/ifndef variety.
- X * Flags whose names are followed by * must be specified with a value.
- X * Some flags have default values, when noted.
- X * Only those flags so documented may be changed by the customer
- X * The meaning of the flags are as follows
- X * machine (choose one):
- X * m_vax a vax of any type (780,750, etc)
- X * m_68k a 68000 or 68010
- X * os (choose one if in the list, or else omit)
- X * os_vms dec's vms os
- X * os_masscomp masscomp's version of 4.2
- X * os_sun4 sun 4bsd or newer
- X * os_unisoft unisoft variant
- X * OFFSET* lowest address (where nil will be stored)
- X * TTSIZE* max number of 512 bytes pages for text and data
- X * !This may be altered!
- X * XstackSize size of alternate stack if SPISFP is defined
- X * unisys3botch something is wrong with initialization of data space
- X * SPISFP the stack pointer is also the frame pointer, so we can't
- X * push tempories on the C stack (we have to use an alternate
- X * stack)
- X * NPINREG np and lbot are stored in registers rather than global
- X * variables
- X * DefDmpmode* default dump mode (expressed in octal-like decimal)
- X * NILIS0 for any UNIX implementation in which the users
- X * address space starts at 0 (and liszt takes advantage
- X * of the fact)
- X * StringTable when the a.out format uses a string table for symbol
- X * names
- X * Vadvise if system has vadvise system call, this is the location
- X * of the vadvise include file.
- X * OS* name of the operating system for the (status features)
- X * list
- X * Pagesize* the size in bytes of a page of memory. Can be specified
- X * as a function to return the value.
- X *
- X * Machine* name of the processor
- X * LongFilenames if this machine has very long filenames
- X * Feature something to be put on the status features list
- X * vms_cfasl for vms, do a cfasl of a native vms object file (i believe)
- X * NewLineBuf if it uses the setlinebuf call to set buffering for stdio
- X * RIndexFcn* function to call to get the location of a given char
- X * from the end of the string.
- X * IndexFcn* function to call to get the location of a given char
- X * machine name (choose one):
- X * GetHostname has the 4.2 gethostname function
- X * os_masscomp [this was mentioned above] use the masscomp version
- X * of gethostname
- X * SiteName a string which is the site name, if it must be hardwired
- X * !this may be altered!
- X * CallBrkdirect if must do a brk with a system call rather than the
- X * C function.
- X * UseSetmask signals are reenabled with sigsetmask rather than
- X * calling 'signal' again (a 4.2 feature)
- X * unisys3botch has a problem in clearing low memory (mysterious flag
- X * which should be better named)
- X * SunCore has suncore
- X * Subxlbotch operands of subxl exchanged [I'm guessing at this, it
- X * was underdocumented in the code]
- X * NoSysTime <sys/time.h> is <time.h>
- X * NoSyscall doesn't have a syscall function
- X * NoAsm doesn't have the function "asm" to insert assembler into the
- X * output of the C compiler (like the cadmus).
- X * AsmOnly This macro is defined in files which are really
- X assembler files and the C pre-processor is being used.
- X (The purpose is to keep typedef's from being passed
- X to the assembler.)
- X * NoGarbColl Turns off garbage collection permanently.
- X (This is done by making sure that Initflag does not
- X get changed in sysat.c
- X *
- X * unchar [default 'unsigned char'] the data type to use for unsigned
- X * character. This is necessary since some C compilers can't
- X * handle 'unsigned char'.
- X * word An integer type (long, int, or short) whose size is the
- X same as that of a pointer so that casts back and forth
- X to (int *) or (char *) will not lose information.
- X * int32 An integer type (long, int, or short) whose size is
- X 32 bits.
- X *
- X * xor [ default uses ^] a macro to xor two quantities. This is
- X * necessary on ibm systems which use the caret for something
- X * else
- X * Incl_ctype [default: defined] if defined then explicitly include
- X * <ctype.h>
- X *
- X * IobName Indicates that a special machine and/or O.S. routine must be
- X * called to determine the locained] has floating point
- X * HasTermcap [default: defined] has interface to termcap
- X * ... stdio flag conversions: this should not be here when
- X * we are done moving stdio
- X * DefLibDir default lisp library directory
- X * NoLowInput Indicates that no attempt should be made to interfere with
- X * low level input routine (read). Otherwise, read is
- X * rewritten in 68k.c
- X * NoLowOutput Indicates that no attempt should be made to interfere with
- X * low level output routine (write). Otherwise, write is
- X * rewritten in 68k.c
- X * Savelisp needs the save/restorelisp feature [apollo]
- X * UseOnlySdotsForBignums
- X * if defined, use only sdots for constructing bignums.
- X * This is for the apollo, and if Savelisp is defined, then
- X * this also MUST be defined. [apollo]
- X * NoDumpLisp this machine cannot support (dumplisp) [apollo]
- X * NoNlist this machine does not have the UNIX function nlist() [apollo]
- X * ReadDir If defined, uses unix system call to read a directory
- X * listing.
- X */
- X
- X/* defaults */
- X
- X#define unchar unsigned char
- X#define xor(a,b) (a) ^ (b)
- X#define Incl_ctype
- X#define GcTime
- X#define HasFloat
- X#define HasTermcap
- X#define XstackSize 16384
- X#define DefLibDir "/usr/lib/lisp"
- X
- X/*
- X** If more machines have weird integer sizes,
- X** these typedefs will have to be moved.
- X*/
- X#ifndef AsmOnly
- X#ifdef Elxsi
- X typedef int int32;
- X typedef int word;
- X#else
- X#ifdef lint
- X typedef int int32;
- X typedef int word;
- X#else
- X typedef long int32;
- X typedef long word;
- X#endif lint
- X#endif Elxsi
- X#endif AsmOnly
- X
- X#ifdef vax_4_1
- X# define m_vax
- X# define OFFSET 0x0
- X# define TTSIZE 6120
- X# define NPINREG
- X# define DefDmpmode 413
- X# define NILIS0
- X# define StringTable
- X# define Vadvise <vadvise.h>
- X# define OS "unix"
- X# define Pagesize 1024
- X# define Machine "vax"
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define SiteName "unknown-site"
- X#define nargsdefined
- X#define ReadDir
- X#endif
- X
- X#ifdef vax_4_1a
- X# define m_vax
- X# define OFFSET 0x0
- X# define TTSIZE 6120
- X# define NPINREG
- X# define DefDmpmode 413
- X# define NILIS0
- X# define StringTable
- X# define Vadvise <vadvise.h>
- X# define OS "unix"
- X# define Pagesize 1024
- X# define Machine "vax"
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define GetHostname
- X#define nargsdefined
- X#define ReadDir
- X#endif
- X
- X#ifdef vax_4_1c
- X# define m_vax
- X# define OFFSET 0x0
- X# define TTSIZE 6120
- X# define NPINREG
- X# define DefDmpmode 413
- X# define NILIS0
- X# define StringTable
- X# define Vadvise <vadvise.h>
- X# define OS "unix"
- X# define Pagesize getpagesize()
- X# define Machine "vax"
- X# define LongFilenames
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define GetHostname
- X#define nargsdefined
- X#define ReadDir
- X#endif
- X
- X#ifdef vax_4_2
- X# define m_vax
- X# define OFFSET 0x0
- X# ifdef HOLE
- X# define TTSIZE 10216
- X# else
- X# define TTSIZE 6120
- X# endif
- X# define NPINREG
- X# define DefDmpmode 413
- X# define NILIS0
- X# define StringTable
- X# define Vadvise <sys/vadvise.h>
- X# define OS "unix"
- X# define Pagesize getpagesize()
- X# define Machine "vax"
- X# define LongFilenames
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define GetHostname
- X# define CallBrkdirect
- X# define UseSetmask
- X#define nargsdefined
- X#define ReadDir
- X#endif
- X
- X#ifdef vax_unix_ts
- X# define m_vax
- X# define OFFSET 0x0
- X# define TTSIZE 6120
- X# define NPINREG
- X# define DefDmpmode 410
- X# define NILIS0
- X# define OS "unix"
- X# define Pagesize 1024
- X# define Machine "vax"
- X# define IndexFcn strchr
- X# define RIndexFcn strrchr
- X# define SiteName "unknown-site"
- X#define nargsdefined
- X#define ReadDir
- X#endif
- X
- X#ifdef vax_eunice_vms
- X# define m_vax
- X# define os_vms
- X# define OFFSET 0x0
- X# define TTSIZE 10216
- X# define NPINREG
- X# define DefDmpmode 413
- X# define NILIS0
- X# define StringTable
- X# define OS "vms"
- X# define Pagesize 512
- X# define Machine "vax"
- X# ifndef EUNICE_UNIX_OBJECT_FILE_CFASL
- X# define vms_cfasl
- X# endif
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define SiteName "unknown-site"
- X#define nargsdefined
- X#define ReadDir
- X#endif
- X
- X#ifdef sun_unisoft
- X# define m_68k
- X# define os_unisoft
- X# define OFFSET 0x40000
- X# define TTSIZE 6120
- X# define DefDmpmode 410
- X# define OS "unix"
- X# define Pagesize 512
- X# define Machine "68k"
- X# define Feature "unisoft"
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define SiteName "unknown-site"
- X# define NoSyscall
- X#define nargsdefined
- X#endif
- X
- X#ifdef dual_unisoft
- X# define m_68k
- X# define os_unisoft
- X# define OFFSET 0x800000
- X# define TTSIZE 6120
- X# define DefDmpmode 410
- X# define OS "unix"
- X# define Pagesize 512
- X# define Machine "68k"
- X# define Feature "unisoft"
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define SiteName "unknown-site"
- X# define NoSyscall
- X#define nargsdefined
- X#endif
- X
- X#ifdef pixel_unisoft
- X# define m_68k
- X# define os_unisoft
- X# define OFFSET 0x20000
- X# define TTSIZE 6120
- X# define DefDmpmode 410
- X# define OS "unix"
- X# define Pagesize 512
- X# define Machine "68k"
- X# define Feature "unisoft"
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define SiteName "unknown-site"
- X# define NoSyscall
- X#endif
- X
- X#ifdef lisa_unisys3
- X# define m_68k
- X# define os_unisoft
- X# define OFFSET 0x20000
- X# define TTSIZE 6120
- X# define unisys3botch 1
- X# define DefDmpmode 410
- X# define OS "unix"
- X# define Pagesize 1024
- X# define Machine "68k"
- X# define IndexFcn strchr
- X# define RIndexFcn strrchr
- X# define SiteName "unknown-site"
- X# define NoSyscall
- X#endif
- X
- X#ifdef sun_4_1c
- X# define m_68k
- X# define os_sun4
- X# define OFFSET 0x8000
- X# define TTSIZE 6120
- X# define DefDmpmode 413
- X# define StringTable
- X# define Vadvise <vadvise.h>
- X# define OS "unix"
- X# define Pagesize getpagesize()
- X# define Machine "68k"
- X# define LongFilenames
- X# define Feature "sun"
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define GetHostname
- X# define SunCore
- X# define Subxlbotch
- X#define nargsdefined
- X#define ReadDir
- X#endif
- X
- X#ifdef sun_4_2beta /* sun release 1.0 */
- X# define m_68k
- X# define os_sun4
- X# define OFFSET 0x8000
- X# define TTSIZE 10216
- X# define SPISFP
- X# define DefDmpmode 413
- X# define StringTable
- X# define Vadvise <sys/vadvise.h>
- X# define OS "unix"
- X# define Pagesize getpagesize()
- X# define Machine "68k"
- X# define LongFilenames
- X# define Feature "sun"
- X# define NewLineBuf
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define GetHostname
- X# define UseSetmask
- X# define SunCore
- X# define Subxlbotch
- X#define nargsdefined
- X#define ReadDir
- X#endif
- X
- X#ifdef sun_4_2 /* sun release 1.1 */
- X# define m_68k
- X# define os_sun4
- X# define OFFSET 0x8000
- X# ifdef BIG
- X# define TTSIZE 10216
- X# else
- X# define TTSIZE 6120
- X# endif BIG
- X# define DefDmpmode 413
- X# define StringTable
- X# define Vadvise <sys/vadvise.h>
- X# define OS "unix"
- X# define Pagesize getpagesize()
- X# define Machine "68k"
- X# define LongFilenames
- X# define Feature "sun"
- X# define NewLineBuf
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define GetHostname
- X# define UseSetmask
- X# define SunCore
- X# define nargsdefined
- X# define ReadDir
- X#endif
- X
- X#ifdef mc500_2_2
- X# define m_68k
- X# define os_masscomp
- X# define growstackbotch
- X# define OFFSET 0x0
- X# define TTSIZE 6120
- X# define DefDmpmode 413
- X# define StringTable
- X/* seems to have disappeared # define Vadvise <sys/vadvise.h> */
- X# define OS "unix"
- X# define Machine "68k"
- X/* # define LongFilenames */
- X# define Feature "masscomp"
- X# define IndexFcn strchr
- X# define RIndexFcn strrchr
- X# define Pagesize 4096
- X# define NoSysTime
- X# define ReadDir
- X#endif
- X
- X#ifdef pegasus
- X# define m_68k
- X# define OFFSET 0
- X# define TTSIZE 6120
- X/* SPISFP isn't quite true, but due to the way in which there is a phantom
- X * spot on the stack, it is probably better that we use it
- X */
- X# define growstackbotch
- X# define SPISFP
- X# undef XstackSize
- X# define XstackSize 22000
- X# define DefDmpmode 413
- X# define OS "uniflex"
- X# define Machine "68k"
- X# define Feature "tek4404"
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define SiteName "fi test machine"
- X# define NoSysTime
- X# define NoSyscall
- X# define NoAsm
- X# undef HasTermcap
- X# undef DefLibDir
- X# define DefLibDir "/lisp/lib"
- X/* stdio conversions */
- X# define _IOREAD _READ
- X# define _IOWRT _WRITE
- X# define _IONBF _UNBUF
- X# define _IOSTRG 0
- X# define _file _fd
- X/* end stdio conversions */
- X# define ReadDir
- X# define NoLowInput
- X#endif
- X
- X#ifdef ibm_cms
- X# define m_ibm
- X# define os_cms
- X# define OFFSET ((int)&nilatom)
- X# define TTSIZE 6120
- X# define SPISFP
- X# define DefDmpmode 0407
- X# define OS "cms"
- X# define Pagesize 512
- X# define Machine "ibm"
- X# define IndexFcn "index"
- X# define RIndexFcn "rindex"
- X# define SiteName "ucb cms"
- X# define NoSyscall
- X/* it is a bug that unsigned char doesn't exist */
- X# undef unchar
- X# define unchar char
- X/* must define xor on ibm system to be the cent sign */
- X# include "ibmxor.h"
- X/* defined in stdio.h on ibm */
- X# undef Incl_ctype
- X# define IobName
- X# undef HasTermcap
- X#endif
- X
- X#ifdef cadmus
- X# define m_68k
- X# define OFFSET 0x600000
- X# define CadmusOsBugs
- X# ifdef CadmusOsBugs
- X# define TTSIZE 8196
- X# else
- X# define TTSIZE 6120
- X# endif CadmusOsBugs
- X# define DefDmpmode 411
- X# define OS "unix"
- X# define Pagesize 1024
- X# define Machine "68k"
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define SiteName "unknown-site"
- X# define NoSyscall
- X# define NoSysTime
- X# define NoAsm
- X# define Subxlbotch
- X# define Feature "cadmus"
- X#endif
- X
- X#ifdef apollo
- X# define m_68k
- X# define Savelisp
- X# define NoDumpLisp
- X# define NoNlist
- X# define UseOnlySdotsForBignums
- X# define SPISFP
- X# define OFFSET ((int) &nilatom)
- X# define TTSIZE 6120
- X# define OS "aegis"
- X# define Pagesize 1024
- X# define Machine "68k"
- X# define IndexFcn index
- X# define RIndexFcn rindex
- X# define SiteName "unknown-site"
- X# define Feature "apollo"
- X# define NoSyscall
- X# define NoSysTime
- X# define NoAsm
- X# define NoLowInput /* to avoid _read, _write */
- X# define NoLowOuput /* to avoid _read, _write */
- X# define NewLineBuf
- X/* stdio conversions */
- X# define _IOREAD _SIRD
- X# define _IOWRT _SIWR
- X# define _IONBF _SIUNB
- X# define _IOSTRG 0
- X# define _file _fd
- X/* things written in asm can't have upper case in routine names */
- X# define Fixzero fixzero
- X# define Ifuncal ifuncal
- X# define Ipushf ipushf
- X# define Lastfix lastfix
- X# define Undeff undeff
- X#endif
- X
- X#ifdef Elxsi
- X/* do not replace "Elxsi" with "elxsi" because elxsi is defined
- X in the C preprosessor */
- X# define SPISFP
- X# define OFFSET 0x800
- X# define Machine "elxsi"
- X# define OS "enix"
- X# define _IOSTRG _IOMYBUF
- X# define NoLowInput /* to avoid _read, _write */
- X# define NoLowOutput
- X# define NoSysTime
- X# define NoGarbColl
- X# define gstart() OFFSET /* ??? */
- X# define Pagesize 1024
- X# define PAGSIZ 1024
- X# define TTSIZE 6120
- X# define DefDmpmode 410
- X# define IndexFcn strchr
- X# define RIndexFcn strrchr
- X# define SiteName "unknown-site"
- X#endif
- X
- X#ifdef m_68k
- X#define SortSymbols
- X#endif
- X
- END_OF_FILE
- if test 16909 -ne `wc -c <'src/franz/config.h'`; then
- echo shar: \"'src/franz/config.h'\" unpacked with wrong size!
- fi
- # end of 'src/franz/config.h'
- fi
- if test -f 'src/man.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/man.c'\"
- else
- echo shar: Extracting \"'src/man.c'\" \(11451 characters\)
- sed "s/^X//" >'src/man.c' <<'END_OF_FILE'
- X/* top level common memory manager */
- X
- X/*
- X
- Xthis is a server process that manages common memory - or at least what
- Xbehaves like common memory. It is actually quite simple. For each object
- Xthat we are keeping track of we allocate a piece of memory via declare().
- XWe write the object with writevalue() and read it with readvalue()
- X
- XInitially, we sit idle waiting for messages. Each message is processed
- Xas follows:
- X
- Xforever {
- X for each message in queue
- X for each component in message
- X declares are created or confirmed
- X reads cause a new message to be built
- X writes cause processes to be tagged for wakeup.
- X acknowledge every message, by sending back a list of variable
- X values that the process is listed as a reader which have been written
- X
- X for each process scheduled for wakeup {
- X and not having an outstanding read in the queue {
- X create a message with all its "read" variables
- X if (message built) send it, delete it
- X }
- X }
- X}
- X
- X*/
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X
- X#include <sys/time.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include "inet.h"
- X
- X#include "cm_constants.h"
- X#include "cm_var.h"
- X#include "cm_sd.h"
- X#include "cm_slot.h"
- X#include "cm_msg.h"
- X#include "cm_man.h"
- X#include "cm_time.h"
- X
- X#include <setjmp.h>
- X#include <signal.h>
- X
- Xstruct process processes[CM_MAXPROCESSES];
- Xstruct variable variables[CM_MAXVARIABLES];
- Xcm_value cm_variable_names = {0,0,0,1};
- X
- Xint connection_socket;
- X
- Xstatic struct msg *cm_imsg;
- Xstruct msg *cm_omsg; /* shared with man_get_slot.c .. ugh! */
- X
- Xstruct slot *nextslot();
- X
- X#define CM_WRITE_TIMEOUT 5 /* after this many seconds, we give */
- X /* up writing to a process, and go */
- X /* on. We will eventually retry. */
- Xstatic int timeout = CM_WRITE_TIMEOUT;
- Xjmp_buf write_context; /* context when we are about to call write() */
- Xvoid sigpipe_handler();
- Xvoid sigalrm_handler();
- X
- Xchar *malloc();
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar **argv;
- X{
- X init(argc,argv);
- X while (TRUE) {
- X process_msg();
- X }
- X}
- X
- Xprocess_msg()
- X{
- X struct slot *s;
- X int clientfd;
- X int slots; /* number of slots in message */
- X
- X int rc;
- X
- X clientfd = man_get_msg(cm_imsg);
- X init_msg(cm_omsg);
- X if (cm_imsg->version == CMM_VERSION) {
- X slots = cm_imsg->slots;
- X s = cm_imsg->data;
- X while (TRUE) {
- X if (s == NULL || slots == 0) break;
- X if (0 > (rc = man_decode_slot(s,clientfd))) {
- X printf("process_msg: error trying to decode slot <%d>...aborting msg\n",rc);
- X break;
- X }
- X s = nextslot(cm_imsg,s);
- X slots--;
- X }
- X } else {
- X char error_message[80];
- X
- X if (cm_imsg->version > CMM_VERSION)
- X sprintf(error_message,"cm library (v%d) is %s than cmm (v%d)",
- X cm_imsg->version,
- X ((cm_imsg->version > CMM_VERSION)?"newer":"older"),
- X CMM_VERSION);
- X put_slot_error(cm_omsg,"version",0,error_message);
- X }
- X
- X
- X /* if a slot produced an explicit message (like an error), send it. */
- X /* otherwise assume he just wants normal variable updates */
- X /* Also, respond immediately to anyone waiting on an immediate
- X /* response. */
- X if ((cm_omsg->slots > 0) || cm_imsg->read_wait) {
- X add_read_vars_to_msg(cm_omsg,clientfd);
- X send_msg_to(cm_omsg,clientfd);
- X processes[clientfd].wakeup = FALSE;
- X }
- X/* why is this necessary, if you figure it out, comment this! */
- X/* else processes[clientfd].wakeup = TRUE;*/
- X wakeup(); /* any processes necessary */
- X}
- X
- Xwakeup()
- X{
- X int i=0;
- X
- X eprintf(3,"processes to wake:\n");
- X for (i=0;i<CM_MAXPROCESSES;i++) { /* step through all processes */
- X if (processes[i].wakeup) {
- X eprintf(3," %s",processes[i].name);
- X init_msg(cm_omsg);
- X add_read_vars_to_msg(cm_omsg,i);
- X if (cm_omsg->slots > 0) send_msg_to(cm_omsg,i);
- X processes[i].wakeup = FALSE;
- X }
- X }
- X eprintf(3,"\n");
- X}
- X
- Xextern char *optarg; /* pointer to start of option argument */
- Xextern int optind; /* index of argv of next argument to be processed */
- X
- X/* initialize the process and variable structures */
- Xinit(argc,argv)
- Xint argc;
- Xchar **argv;
- X{
- X int i;
- X int debug_level = 0;
- X int c;
- X int port = CM_PORT;
- X extern int optind;
- X
- X while (EOF != (c = getopt(argc,argv,"d:p:t:"))) {
- X switch (c) {
- X case 'd':
- X debug_level = atoi(optarg);
- X break;
- X case 'p':
- X port = atoi(optarg);
- X break;
- X case 't': /* timeout */
- X timeout = atoi(optarg);
- X break;
- X }
- X }
- X
- X set_cm_debug_level(debug_level);
- X set_cm_process_name(CM_MANAGER_NAME);
- X
- X eprintf(1,"cmm version %d\n",CMM_VERSION);
- X eprintf(1,"timeout on writes = %d\n",timeout);
- X
- X if (-1 == (connection_socket = initport(PORT_NUMBER(port),SERVER,SOCK_STREAM,
- X (char *)0))) {
- X fprintf(stderr,"failed to initialize connection socket\n");
- X exit(-1);
- X }
- X cm_time_init();
- X
- X if (!(cm_imsg = (struct msg *)malloc(CM_MSGSIZE))) {
- X fprintf(stderr,"init: failed malloc(imsg)\n");
- X exit(-1);
- X }
- X if (!(cm_omsg = (struct msg *)malloc(CM_MSGSIZE))) {
- X fprintf(stderr,"init: failed malloc(omsg)\n");
- X exit(-1);
- X }
- X
- X for (i=0;i<CM_MAXPROCESSES;i++) processes[i].inuse = FALSE;
- X
- X for (i=0;i<CM_MAXVARIABLES;i++) {
- X cm_sd_clear(&variables[i].data);
- X variables[i].readers = 0;
- X variables[i].writers = 0;
- X variables[i].xwriter = 0;
- X variables[i].count = 0;
- X }
- X
- X#if 0
- X /* grab a variable for maintaining the names of all other variables */
- X variables[0].writers = 1;
- X variables[0].xwriter = connection_socket; /* reserved to us */
- X
- X /* stick in the first value */
- X variables[0].count = 1;
- X cm_variable_names.size = cm_variable_name.msize =
- X strlen("cm_variable_names"+1);
- X cm_variable_names.data = new_string("cm_variable_names");
- X#endif
- X
- X signal(SIGPIPE,sigpipe_handler);
- X signal(SIGALRM,sigalrm_handler);
- X}
- X
- X/* if process died while we were writing to it, abort the write() */
- Xvoid sigpipe_handler()
- X{
- X longjmp(write_context,SIGPIPE); /* abort the write() */
- X}
- X
- X/* if process hangs and we write to it enough, eventually we will block */
- X/* abort the write(), when the timer goes off */
- Xvoid sigalrm_handler()
- X{
- X longjmp(write_context,SIGALRM);
- X}
- X
- Xstruct variable *
- Xget_variable(name)
- Xchar *name;
- X{
- X int i;
- X int j;
- X int free_var = -1;
- X
- X for (i=0;i<CM_MAXVARIABLES;i++) {
- X if (!var_inuse(&variables[i])) {
- X free_var = i;
- X } else if (!strcmp(variables[i].name,name)) {
- X return(&variables[i]);
- X }
- X }
- X
- X if (free_var == -1) {
- X /* no old definition and no space for a new one! */
- X /* this is really an exceptional condition, so let's */
- X /* print out some helpful info */
- X
- X fprintf(stderr,"get_variable(%s) failed\n",name);
- X for (i=0;i<CM_MAXVARIABLES;i++) {
- X printf("%d: ",i);
- X if (var_inuse(&variables[i])) {
- X printf("<%s>",variables[i].name);
- X printf(" r=%d w=%d\n inuse=%d",
- X variables[i].readers,
- X variables[i].writers,
- X var_inuse(&variables[i]));
- X } else printf("<not in use>\n");
- X }
- X return(NULL);
- X }
- X
- X
- X strcpy(variables[free_var].name,name);
- X variables[free_var].count = 0;
- X time_now(&variables[free_var].timestamp);
- X variables[free_var].command_association = 0;
- X variables[free_var].xwriter = CM_NULL_PROCESS;
- X for (j=0;j<CM_MAXPROCESSES;j++) {
- X variables[free_var].role[j].reader = FALSE;
- X variables[free_var].role[j].writer = FALSE;
- X variables[free_var].role[j].wakeup = FALSE;
- X variables[free_var].role[j].new = FALSE;
- X }
- X return(&variables[free_var]);
- X}
- X
- Xsend_msg_to(m,to)
- Xstruct msg *m;
- Xint to;
- X{
- X int rc;
- X
- X switch (rc = setjmp(write_context)) {
- X case 0:
- X /* assume write() succeeds */
- X alarm(timeout);
- X sized_write(to,(char *)m,m->size);
- X alarm(0);
- X print_msg(m);
- X break;
- X case SIGPIPE:
- X alarm(0);
- X /* if write() interrupted due to SIGPIPE */
- X eprintf(3,"broken pipe\n");
- X eprintf(3,"detected death of %s on fd %d\n",
- X (processes[to].inuse?
- X processes[to].name:"unknown"),
- X to);
- X kill_client(to);
- X break;
- X case SIGALRM:
- X fprintf(stderr,
- X "process %s is being antisocial on fd %d\n",
- X (processes[to].inuse?
- X processes[to].name:"unknown"),
- X to);
- X break;
- X default:
- X alarm(0);
- X printf("setjmp(write_context) = %d?!\n",rc);
- X abort(); /* should never happen */
- X }
- X}
- X
- X/* The philosophy coded here is that the cmm always responds to a msg
- Xwith the data values that are marked for read and have changed since the
- Xlast time it was read */
- Xadd_read_vars_to_msg(m,pin)
- Xstruct msg *m;
- Xint pin;
- X{
- X struct variable *v;
- X
- X for (v=variables;v<&variables[CM_MAXVARIABLES];v++) {
- X if (!var_inuse(v)) continue;
- X eprintf(5,"is_reader(%s,%s)=%d is_new(%s,%s)=%d\n",
- X processes[pin].name,v->name,is_reader(pin,v),
- X processes[pin].name,v->name,is_new(pin,v));
- X if (is_reader(pin,v) && is_new(pin,v)) {
- X put_slot_read_response(m,v->name,
- X v->count,&v->timestamp,v->command_association,&v->data);
- X unset_new(pin,v);
- X }
- X }
- X}
- X
- Xstatic int clientfds = 0; /* bitmap of sockets to clients */
- X
- Xint /* returns file descriptor of client */
- Xman_get_msg(msg)
- Xstruct msg *msg;
- X{
- X int clientfd;
- X int msg_length = 0;
- X
- X
- X while (msg_length <= 0) {
- X eprintf(3,"known fds = %x\n",clientfds);
- X clientfd = select_server_stream(connection_socket,&clientfds);
- X msg_length = sized_read(clientfd,(char *)msg,CM_MSGSIZE);
- X eprintf(3,"received message from %s. fd = %d length = %d\n",
- X (processes[clientfd].inuse?
- X processes[clientfd].name:"new user"),
- X clientfd,
- X msg_length);
- X print_msg(msg);
- X if (msg_length < 0) {
- X eprintf(3,"detected death of %s on fd %d\n",
- X (processes[clientfd].inuse?
- X processes[clientfd].name:"unknown"),
- X clientfd);
- X kill_client(clientfd);
- X }
- X }
- X
- X if (!processes[clientfd].inuse) {
- X processes[clientfd].inuse = TRUE;
- X processes[clientfd].wakeup = FALSE;
- X strcpy(processes[clientfd].name,msg->name);
- X }
- X eprintf(2,"received msg from %s on fd %d\n",msg->name,clientfd);
- X
- X return(clientfd);
- X}
- X
- X/* delete any info we had about this client */
- Xkill_client(fd)
- Xint fd;
- X{
- X struct variable *v;
- X
- X processes[fd].inuse = FALSE;
- X close(fd);
- X eprintf(3,"known fds = %x (before kill_client)\n",clientfds);
- X/*new*/ clientfds &= ~(1<<fd);
- X eprintf(3,"known fds = %x (after kill_client)\n",clientfds);
- X
- X for (v=variables;v<&variables[CM_MAXVARIABLES];v++) {
- X if (!var_inuse(v)) continue;
- X unset_reader(fd,v);
- X unset_writer(fd,v);
- X unset_wakeup(fd,v);
- X /* note that the above calls change the value of var_inuse */
- X if (var_inuse(v)) continue;
- X /* var had been set, free up any space taken by it */
- X if (v->count) {
- X cm_sd_free(&v->data);
- X v->count = 0;
- X }
- X }
- X}
- X
- X/* flag this variable as having a new value with respect to this process */
- Xset_new(proc,var)
- Xint proc;
- Xstruct variable *var;
- X{
- X var->role[proc].new = TRUE;
- X}
- X
- Xset_reader(proc,var)
- Xint proc;
- Xstruct variable *var;
- X{
- X if (!var->role[proc].reader) {
- X var->role[proc].reader = TRUE;
- X var->readers++;
- X }
- X}
- X
- Xset_nonxwriter(proc,var)
- Xint proc;
- Xstruct variable *var;
- X{
- X if (!var->role[proc].writer) {
- X var->role[proc].writer = TRUE;
- X var->writers++;
- X }
- X}
- X
- Xset_xwriter(proc,var)
- Xint proc;
- Xstruct variable *var;
- X{
- X var->xwriter = proc;
- X set_nonxwriter(proc,var);
- X}
- X
- Xset_wakeup(proc,var)
- Xint proc;
- Xstruct variable *var;
- X{
- X var->role[proc].wakeup = TRUE;
- X}
- X
- Xunset_wakeup(proc,var)
- Xint proc;
- Xstruct variable *var;
- X{
- X var->role[proc].wakeup = FALSE;
- X}
- X
- Xunset_new(proc,var)
- Xint proc;
- Xstruct variable *var;
- X{
- X var->role[proc].new = FALSE;
- X}
- X
- Xunset_reader(proc,var)
- Xint proc;
- Xstruct variable *var;
- X{
- X if (var->role[proc].reader) {
- X var->role[proc].reader = FALSE;
- X var->readers--;
- X }
- X}
- X
- Xunset_writer(proc,var)
- Xint proc;
- Xstruct variable *var;
- X{
- X if (var->role[proc].writer) {
- X if (var->xwriter == proc) var->xwriter = CM_NULL_PROCESS;
- X var->role[proc].writer = FALSE;
- X var->writers--;
- X }
- X}
- X
- Xvar_inuse(var)
- Xstruct variable *var;
- X{
- X return(var->readers || var->writers);
- X}
- END_OF_FILE
- if test 11451 -ne `wc -c <'src/man.c'`; then
- echo shar: \"'src/man.c'\" unpacked with wrong size!
- fi
- # end of 'src/man.c'
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-