[comp.sources.unix] v14i097: Shared memory emulation for 4.2BSD, Part04/04

rsalz@bbn.com (Rich Salz) (05/18/88)

Submitted-by: libes@cme-durer.ARPA (Don Libes)
Posting-number: Volume 14, Issue 97
Archive-name: sharedmem/part04

#! /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 4 (of 4)."
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'doc/usenix/paper.trf' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doc/usenix/paper.trf'\"
else
echo shar: Extracting \"'doc/usenix/paper.trf'\" \(19292 characters\)
sed "s/^X//" >'doc/usenix/paper.trf' <<'END_OF_FILE'
X.TL
XUser-Level Shared Variables (in a Hierarchical Control Environment)
X.AU
XDon Libes
X.AI
XNational Bureau of Standards
XFactory Automation Systems Division
XGaithersburg, MD  20899
X.AB
X.PP
XWe have implemented a shared variable system for 
X.UX
X4.2BSD [Joy]
Xthat emulates a shared or common memory.  
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
XThis shared memory system provides its service
Xtransparently to remote hosts across a local-area network.
X.IP \(bu
XThis system is being used in a real application - an automated
Xfactory.  Shared variables are an appropriate communication paradigm
Xin a real-time environment (in comparison to message passing or pipes).
X.AE
X.PP
X.SH
XBackground
X.PP
XThe National Bureau of Standards has been performing research in the
Xarea of robot control [Albus] for over a decade.  Robot control is
Xtypified by tightly-coupled multiprocessor systems often implemented as
Xmultiple single-board computers residing in a common bus.  These
Xsystems require frequent and fast transfer of small amounts of data.
X.PP
XFor example, a robot arm may require new joint angles 100 times a
Xsecond in order to move smoothly.  These joint angles are very small
Xpieces of data and further, the number of joints and joint angles is
Xconstant, hence they can be stored in "well-known" locations.
X.PP
XTo support this type of application, multiported memory is used
Xso that several
Xdifferent computers can access the same locations.
XIn the robot example, the
Xcontrolling computer and the servo computers each need access to the
Xinformation.  
X.PP
XCommon memory has the further advantage that as new processes are added
Xthat need information already present, extant processes do not have to
Xbe modified to deliver that information.  For example, a process was
Xadded that displays the robot's actions on a graphics monitor.  The
Xdisplay process was added without modification to any other part of the
Xsystem, since it uses the joint angles which are stored in well-known
Xcommon memory locations.  Recently a "safety" process was added to
Xguarantee that the robot never departs its working envelope.  The
Xsafety process also obtains its information from common memory.
X.PP
XIn 1981, work [Furlani] began on an automated factory.
XThis is an extension of
Xthe robot control system in many ways.  It is expected that the
Xfactory model will grow over time, and become richer in the number of
Xprocesses used and the amount of information shared between processes.
XA major difference in the automated factory project
Xis that systems which have to communicate are often in
Xseparate backplanes and use different operating systems.  Common
Xmemory is seen as a consistent communications methodology for this
Xdisparate collection of computers.
X.PP
XToday, as computers grow larger and become more complex, more and
Xmore layers of protocol prevent ready access to common memory.  Indeed,
Xwe find that in most of our computer-to-computer interfaces, common
Xmemory is now simply a way of thinking, rather than an underlying
Ximplementation.  Such is the case with
X.UX
X4.2BSD.
X.PP
XThe following section describes an implementation of the common memory
Xparadigm in the
X.UX
X4.2BSD environment.
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
Xcan note that a value is "stale", 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 between
Xprocesses.  The archetypal example from the automation environment has
Xa supervisor sending the command "hit nail with hammer" to a
Xsubordinate.  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
XThe same problem exists when the supervisor reads the feedback from the
Xsubordinate.  In particular, because there is no synchrony between
Xprocesses, the supervisor has no way of knowing what command the
Xsubordinate is responding to (without handshaking).  Actual code for
Xsuch a sequence would use higher-level routines to read the shared
Xvariable.  For example:
X.PP
X.DS L
X.B
X    struct shared_variable *command_out, *feedback_in;
X    struct shared_variable_value *expected_feedback;
X    .
X    .
X    if (status_equal(command_out, feedback_in, expected_feedback)) . . .
X.R
X.DE
X.PP
XHere, the command to the subordinate is 
X.B command_out .
XThe actual feedback received is 
X.B feedback_in
Xand we are looking for
X.B expected_feedback .
XThe expected feedback is thus compared to the
Xfeedback actually received with respect to the command which generated
Xit.
X.PP
XThese handshaking and synchronization problems are thoroughly discussed
Xin [Libes].
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
Xclients, for example, would not have to loop just waiting for new
Xvalues.  It has turned out to be extremely useful for debugging.
XRather than inserting print statements in existing code and
Xrecompiling, it is possible to create a debug module that simply prints
Xout variables when they change.  It has also been used for a graphics
Xmonitor that continuously displays the state of the entire system.
X.PP
XThe wakeup attribute can be
Xused to force a queuing discipline on a variable.  For
Xexample, a process performing as a resource server may take requests
Xfrom a well-known common memory variable.  As clients write to the
Xvariable, the CMM wakes up the resource server with each new variable
Xvalue.  The resource server typically responds to each variable value in
Xturn; however it can ignore all but the most recent values if it desires.
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 at a well-known location
X("socket") for a request for service.
XAny client can
Xrequest service by writing the variable associated with the socket.
X.PP
XAnother use is to send information to a log file.  In our
Xapplication, we can ask all processes to log their states a given
Xnumber of
Xclock ticks.  By having them all write their states to one variable,
Xa logging process can record all the states of the system through time.
XThis has proven to be invaluable during system testing.
X.PP
X.SH
XII.   4.2BSD Implementation
X.PP
XThe Shared Variables System (SVS) is written in C and uses the 4.2
Xinterprocess communication system [Leffler].
XAn interface exists for Franz Lisp.
X.PP
XThe SVS consists of three layers.  The lowest level simulates a common
Xmemory facility such as is available in System V.  On top of this are
Xthe procedures that transform common memory into common variables.
XThis level provides users with routines allowing access and control of
Xthe common variables.
X.PP
XSpecific to our use of the SVS is a higher level that customizes it for
Xcommunication in a hierarchical control environment.  This level
Xincludes interprocess handshaking.
X.PP
X.SH
XBuilding a server on 4.2
X.PP
X4.2BSD has no common memory facility.  Our system provides one via a
Xserver that stores variables in its own memory space which is private
Xto it.  (See Figure 1) The server runs as a user-level process which
Xneeds no special privileges and can be run from an unrelated user-id.
X.PP
X.DS L
X
X
X
X
X
X
X
X
X
X			Figure 1 goes here
X
X
X
X
X
X
X
X
X
X.DE
X.PP
XCommunications between the common memory server and clients have
Xproperties of both streams and datagrams.  Communication resembles
Xvirtual circuits in that the server and clients pass many messages
Xbetween them in a conversation (like TCP).  These messages are also
Xrecord-oriented (like UDP).  In implementation, UDP was rejected
Xbecause it would have forced us to handle unreliability and
Xfragmentation (datagrams were
Xlimited to 1K which was smaller than the typical message).
X.PP
XIn this case, we chose TCP as the lesser of two evils.  TCP had
Xthe drawback (for us) of removing record boundaries (i.e. the receiver
Xcould not tell where one write ended and the next began).  To handle
Xthis, new versions of read and write were constructed to do the actual
XI/O to the sockets.  These packetized and depacketized the TCP streams
Xback into records.
X.PP
XSince TCP/IP is capable of communicating across the network, clients
Xmay be distributed (figure 2) while accessing the common memory.  However, the
Xsmall number of concurrent TCP connections (viz. the number of open
Xfiles) is a severe limit.  Another system [Mitchell] glues distributed
Xcommon memories together throughout the factory.  This design allows multiple
Xcommon memories to exist but appear to the user as one.  This gluing
Xprocess bypasses the TCP restriction and allows multiple
Xinstances of the 4.2 (as well as others') common memory service to be
Xrun.
X.PP
X.DS L
X
X
X
X
X
X
X
X
X
X                              Figure 2 goes here
X
X
X
X
X
X
X
X
X.DE
X.PP
X.SH
XSimulating common memory on 4.2
X.PP
XThe server's own private memory serves as common memory.  Access to
Xvariables, therefore, is strictly through the valid requests to the CMM
Xserver.   The server accesses variables as requested and maintains
Xextra information such as variable type, owner, etc.
X.PP
XWhenever a client wants to access common memory, it does so by
Xsending a message to the CMM.  Such messages are sent asynchronously
Xbut received synchronously.  In particular, the server is never
Xinterrupted.  
X.PP
XTypically, the server is waiting for service requests.  When a request
Xis received, service is performed.  This service may or may not cause
Xsending of a message in return to the client.  For example, "read"
Xoperations always cause information to be returned from the server
Xwhile "write" operations don't (unless an error is encountered).
X.PP
XIt is up to the client whether it wishes to wait (even after a "read")
Xfor a response from the common memory server.
X.PP
XClient processes keep their own local version of shared variables of
Xinterest until it is convenient for them to synchronize with
Xthe CMM.  By calling 
X.B cm_sync() ,
Xthe user and the common memory server become synchronized.
XAn argument to
X.B cm_sync() 
Xspecifies whether the client waits for a response or not.
X.PP
XWhether the client is waiting or not, an error can occur at the server
Xend, in which case an error message is returned.  For example, a client
Xmay write a value but the variable may be an incompatible type.  When
Xthis happens, a message is sent back to the client.  The client is not
Xinterrupted, but at the next 
X.B cm_sync() 
Xoperation it is notified of the error.
X.PP
XInterestingly, the problem of being able to provide atomic updates to
Xcommon memory vanishes in this system.  Since the server is never
Xinterrupted, client updates functionally prevent all other clients
Xaccess to common memory while their request is being serviced.  This
Xremoves the classic synchronization problem which exists when multiple
Xprocesses are reading and writing real common memory with no
Xsynchronization.  On the other hand, this can cause relatively long
Xwaits for service.
X.PP
XConstruction of higher-level synchronization such as semaphores is
Xeasy.  Potentially stalling manipulations of semaphores and monitors
Xcan call
X.B cm_sync()
Xand then wait for a response from the server to
Xcontinue.  The server acknowledges the client if and only if the client
Xsemaphore action is satisfied.
X.PP
X.SH
XIII.   An application - manufacturing automation
X.PP
XWhile the SVS is a general tool, it is currently being used at the National
XBureau of Standards in the Automated Manufacturing Research Facility
X(AMRF), a testbed for research in the automation of small batch
Xmanufacturing [Simpson].
XThe project is funded by NBS and the Navy Manufacturing
XTechnology Program and significantly supported by industry through
Xdonations or loans of major components and through cooperative research
Xprograms.  The objective of the project is to identify, implement and exercise
Xpotential standard interfaces between existing and future components of
Xsmall-batch manufacturing systems and to provide a laboratory for the
Xdevelopment of factory-floor metrology in an automated environment,
Xdelivering proven measurement techniques and standard reference
Xmaterials to American industry.  Commercially available products are
Xbeing used to construct the facility wherever possible in order to
Xexpedite transfer of research results into the private sector.
X.PP
XTo provide a real testbed for interface standards, the AMRF is
Xintentionally composed of manufacturing and computer equipment from
Xmany vendors, thereby making its construction a major integration
Xeffort.  The types of systems that must be integrated and communicate
Xwith each other include stationary and
Xmobile robots, machine tools, their controllers, and higher-level cell and factory management systems.  Actual computers and operating systems
Xrun the gamut, from micros to mainframes.
X.PP
XProcesses in the AMRF are
Xorganized in a control hierarchy, much like the organization of a
Xconventional factory.  At each level, tasks are broken down into
Xsimpler tasks that can be performed by subordinate processes.  Control
Xis hierarchical.
X.PP
XTo support such control communication, we imagine that processes in
Xthe system communicate along hierarchical channels.  Each process runs
Xasynchronously, continually "sending" commands to subordinate processes
Xand feedback to superior processes.
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
X(figure 3) 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.
X.PP
X.DS L
X
X
X
X
X
X
X
X
X                     Figure 3 goes here
X
X
X
X
X
X
X
X
X.DE
X.PP
X.SH
XSummary
X.PP
XCommon memory is a communications methodology that is easy to use and
Xcan be efficiently implemented.
XIt can use physical common memory or be simulated by other
Xcommunications techniques such as message passing.  In turn, it can be
Xused to implement any other communications techniques.
X.PP
XCommon memory has several important advantages and disadvantages.  The
Xprimary advantage is the ease with which information may be shared.  
XIn our application, we have required this richness of data
Xsharing between processes.
XUsing common memory also has the benefit of being able to add, remove
Xor modify processes without disturbing other processes,
X.I
Xeven if they communicate with each other.
X.R
X.PP
XThe
Xprimary disadvantage is that sharing large amounts of information in
Xthis manner can become hard to keep track of.  Since there is no
Xscoping in the common memory, naming conventions must be
Xfollowed (which in effect, provides scoping).  Common memory is not
Xparticularly apt for all types of communications.  Picking the most
Xappropriate model (pipes, databases, message passing) will invariably
Xlead to a simpler process in the final analysis.  We, of course, use
Xthese other techniques in our application when appropriate.
X.PP
XAt the lowest level of our application, efficient process-to-process
Xcommunication is necessary for real-time behavior.
XThis is
Ximplemented using real common memory with low overhead.  At higher
Xlevels where common memory is simulated and the high-speed demand does
Xnot exist, the methodology extends upwards suitably.
X.PP
XIn the future, we expect to move the ideas of hierarchical control and
Xcommon memory to new applications.  Currently, we are investigating the
Xpotential for control of autonomous aircraft.
X.SH
XReferences
X.XP
XAlbus, J., Barbera, T., Fitzgerald, M.L., "Hierarchical Control for
XSensory Interactive Robots", Proceedings of 31st General Assembly,
XInternational Institution for Production Engineering Research (CIRP),
XToronto, Canada, September, 1981.
X.XP
XFurlani, C., Kent, E., Bloom, H., McLean, C., "The Automated
XManufacturing Research Facility of the National Bureau of Standards",
XProceedings of the Summer Simulation Conference, Vancouver, B.C.,
XCanada, July 1983.
X.XP
XJoy, W., Cooper, E., Fabry, R., Leffler, S., McKusick, K., Mosher, D.,
X"4.2BSD System Interface Overview", Computer Systems Research Group,
XU.C. Berkeley, July, 1983.
X.XP
XLeffler, S., Fabry, R., Joy, W., "4.2BSD Interprocess Communications
XPrimer", Computer Systems Research Group, U.C. Berkeley, July, 1983.
X.XP
XLibes, D., "Handshaking in a Hierarchical Control Environment",
XInternal Memorandum, Center
Xfor Manufacturing Engineering, National Bureau of Standards,
XWashington, DC 20234.
X.XP
XMitchell, M., Barkmeyer, E.,
X"Data Distribution in the NBS Automated Manufacturing Research
XFacility", Center for
XManufacturing Engineering, National Bureau of Standards, Washington, DC
X20234, 1984.
X.XP
XSimpson, J., Hocken, R., Albus, J.,
X"The Automated Manufacturing Research Facility of the National Bureau
Xof Standards", Journal of Manufacturing Systems, Vol. 1, #1.
X.PP
X.SH
XFurther Reading
X.XP
XBloom, H., Furlani, C., Barbera, A., "Emulation as a Design Tool in the
XDevelopment of Real-Time Control Systems", 1984 Winter Simulation
XConference, Dallas, Texas, November 1984.
X.XP
XJohnson, T., Milligan, S., Fortmann, T., Bloom, H., McLean, C.,
XFurlani, C.  "Emulation/Simulation of a Modular Hierarchical Feedback
XSystem", The 21st IEEE Conference on Decision and Control, Orlando, FL,
XDecember 1982.
END_OF_FILE
if test 19292 -ne `wc -c <'doc/usenix/paper.trf'`; then
    echo shar: \"'doc/usenix/paper.trf'\" unpacked with wrong size!
fi
# end of 'doc/usenix/paper.trf'
fi
if test -f 'doc/user.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doc/user.doc'\"
else
echo shar: Extracting \"'doc/user.doc'\" \(26953 characters\)
sed "s/^X//" >'doc/user.doc' <<'END_OF_FILE'
XThe NBS Common Memory System (CMS)
XSept 25, 1987
X
XDon Libes
XNational Bureau of Standards
XMetrology Building, Room A-127
XGaithersburg, MD  20899
X(301) 975-3535
X
XThis system emulates a shared memory system.  (This system is
Xloosely based on the Hierarchical Control System Emulator (HCSE)
Xbuilt by BBN, which provided a shared memory as one of its
Xfacilities.)  User processes can be distributed as well as shared
Xmemory, itself.  A server, the common memory manager (CMM) handles
Xrequests to manipulate shared variables.  This emulator was
Xdesigned for the purposes of providing communication between
Xhierarchically controlled processes.  There is a small amount of
Xfunctions specifically for the purpose of making such communication
Xof such style easier, but the emulator is certainly not restricted
Xby this and thus it also provides communications between processes
Xwith arbitrary relationships.
X
X
XSuperficially, each process that wishes to use a shared variable,
Xdoes so as if it was not shared.  Typically, one process writes
Xinto a variable, while a number of other processes may read the
Xvariable.  (Other scenerios are possible.)  The common memory
Xmanager (CMM) enforces this and other restrictions and also handles
Xany synchronization that may be necessary.  The fact that a
Xvariable is shared is transparent to the user.
X
XThe common memory is implemented as memory private to the CMM,
Xwhich it reads and writes in response to requests by clients.  The
XBBN HCSE used a distributed form of control, depending on each
Xprocess to pass control to the next.  A defect of this was that the
Xunexpected death of a process would halt the emulation when control
Xwas passed to it the next time around.  By centralizing control,
Xthe unexpected death of any user process will not halt the
Xemulation.  In fact, this can be monitored and a new or existing
Xprocess can take over the responsibilities of a deceased process.
X
X
XProcesses
X
XThere is one special process that must always be running when an
Xemulation is in progress.  It is the Common Memory Manager (CMM).
XThere will probably be other auxiliary processes such as
Xfront-ends, debuggers, and editors that are not necessary but will
Xinvariably always be running during any emulation.  This is not the
Xcase now, however.
X
XThe CM manager handles requests from processes to read/write common
Xmemory variables.  Various other requests are possible such as
Xdynamically changing the size, type or writer of a variable.  This
Xlast possibility is very useful, if, say a process agrees to
Xdirectly take over a resource that can be passed around between
Xprocesses.
X
X
XHow to use the Common Memory System
X
XThis system emulates a shared common memory with specific features
Xfor supporting communication between hierarchically controlled
Xprocesses.
X
XThis document describes how to use the current implementation on
Xthe Sun Workstation (running Sun UNIX 1.x, 2.x and 3.x).  It has
Xalso been ported to the Silicon Graphics Iris.  It may be helpful
Xto read the system description and implementation notes to get a
Xbetter idea of how the system works.
X
XLet us get right to the usage details.
X
XProcesses
X
XBefore any other CMS calls, the process should identify itself to
Xthe system:
X
X	int rc = cm_init("HWS","cmm_host",0);	/* C */
X
X	(cm_init "HWS" "cmm_host" 0)		; Lisp
X
XHere, we have declared ourselves as "HWS".  This name need not be
Xdistinct, however when debugging, you will find it helpful if you
Xhave chosen different names for your cm users.
X
XThe second parameter to cm_init() is the host on which the
Xcommon memory manager is running which you wish to use.  Note that
Xthere may be a CMM running on the local machine, while you use one
Xon a remote machine.  The local machine may be designated either by
Xits name or by a null string.
X
XThe third parameter to cm_init() is an integer which
Xindicates the debugging level.  0 indicates no debugging.  Larger
Xvalues request more debugging info.  For example, 2 will give you
Xinformation about messages sent and received.  5 will generate
Xinformation about individual common memory values being
Xmanipulated.  With 10, you will get a veritable flood of garbage
X(that you almost certainly don't want) including things like memory
Xallocation, variable copying, etc.
X
Xcm_init() also performs some necessary initialization of CM
Xclient data structures.  cm_init() returns 0 if successful.
XAnything else is an error.  A common error is that the common
Xmemory manager (cmm) is not running.
X
XBefore a second (or any further calls to) cm_init() call,
Xcm_exit() should be called.  cm_exit() tells the CMM that you have
Xgone away.  It also cleans up various data structures internal to
Xthe cm system.
X
XFor example:
X
X	cm_exit();
X
X	(cm_exit)				; Lisp
X
X
XDeclaring variables for use
X
XAll variables must be declared before use.  cm_declare() is used to
Xdeclare common memory variables.
X
X	cm_variable *date;
X
X	date = cm_declare("date",CM_ROLE_XWRITER);
X
X	(setq date (cm_declare "date" CM_ROLE_WRITER))	; Lisp
X
Xcm_declare() returns an object that can be used when referring to
Xthis variable in the future.  This object can be stored into a
Xvariable declared as type cm_variable.  If cm_declare() returns
XCM_BAD_OBJECT, the declaration has failed (an error message will be
Xprinted out explaining why).  Declarations can fail for a variety
Xof reasons (bad or conflicting arguments, no space left to store
Xvalues, etc).
X
XOnce cm_declare() has returned an object, this object should be
Xused whenever referring to the variable.  In the case of
Xcm_declare, the first argument is almost always a string, while in
Xall other functions, the variable identifier is almost always a
Xcm_variable.
X
XThe second argument of cm_declare() specifies access rights.  The
Xavailable access rights are:
X
X	CM_ROLE_NONXWRITER	or CM_ROLE_NONEXCLUSIVE_WRITER
X	CM_ROLE_XWRITER		or CM_ROLE_EXCLUSIVE_WRITER
X	CM_ROLE_READER
X	CM_ROLE_WAKEUP
X
XThese access rights can be combined by ORing.  For example, the
Xwakeup right is always combined with at least one of the others.
X"wakeup" causes the CMM to wake the process up whenever the
Xvariable is written by someone else.
X
XObviously conflicting combinations should be avoided.  If one
Xprocess has declared a variable CM_ROLE_XWRITER, other processes
Xare prohibited from any kind of write access to that variable.
XThese are the only restrictions on variable access.
X
XCommon memory values are structured in the following way.
X
XThis structure cm_value is used for this.
X
X	typedef struct {		/* common memory value */
X		char *data;
X		unsigned short msize;	/* size of malloc'd space */
X		unsigned short size;	/* size of used space */
X		char mallocable;	/* 1 if space is malloc() */
X	} cm_value;
X
XIf mallocable is 1, CMS will allocate space using malloc whenever the
XCMS passes a value to the user.  Further, if msize is ever smaller
Xthan the incoming value, the pointer will be realloc'd and msize
Xincreased appropriately.
X
XIf you are not prepared to handle objects larger than a given size,
Xset msize yourself, and set mallocable to 0.  Lisp is an example
Xwhere this must be done, as otherwise the common memory may
Xattempt to free a Lisp object, which would be a serious mistake.
X
XThe address of such a structure may be passed to cm_set_value and
Xit's relatives.
X
XA cm_value is declared in Lisp (via c-declare) along with
Xcorresponding access functions.  For example, to declare and set
Xthe various elements of the structure called "foo":
X
X	(setq foo (make-cm_value))		; cm_value foo;
X	(setq data (new-vectori-byte 1000))	; char data[1000];
X	(setf (cm_value->data foo) (ptr data))	; foo.data = data;
X	(setf (cm_value->size foo) 1000)	; foo.size = 1000;
X	(setf (cm_value->msize foo) 1000)	; foo.msize = 1000;
X	(setf (cm_value->mallocable foo) 0)	; foo.mallocable = FALSE;
X
XUser-Defined Types
X
XThe original common memory design was to support user-defined
Xtypes, but experience with other common memory systems have taught
Xus that this is "a bad thing".  There is no reason why the common
Xmemory should know the type of the data that it is storing.
X
XTo provide user-defined structured values, use ASN.1 (X.409).
XThis provides for structured types which are machine independent.
X
X
XReading and Writing Variables
X
XThere are two levels of access into the common memory.  Only the
Xhigher-level will be covered here.  This higher-level incorporates
Xfunctions that are tailored towards communications between
Xprocesses in a hierarchically-controlled manner.
X
XVariables may be read and written with the following calls:
X
X	cm_value *value = {NULL,0,0,1};
X	cm_get_value(variable,value);
X	cm_set_value(variable,value);
X
X	(setq value (make-cm_value))
X	(setf (value->data) 0)
X	(setf (value->msize) 0)
X	(setf (value->size) 0)
X	(setf (value->mallocable) 1)
X	(cm_get_value variable value)
X	(cm_set_value variable value)
X
X
XSeveral additional functions exist for handling handshaking
Xbetween superior and subordinate processes in a control hierarchy.
XSpecifically, variables can be used for command or status.  Status
Xvariables are identified by the system with command value they are
Xassociated with.  For more information, see the technical
Xmemorandum, "Implementing Command-Feedback Variables in a
XHierarchical Environment".
X
XVariables which are command variables should be read and written
Xwith the following routines:
X
X	cm_set_new_command_value(variable,value);
X	cm_get_new_command_value(variable,value);
X
X	(cm_set_new_command_value variable value)
X	(cm_get_new_command_value variable value)
X	
XOne utility routine is available for determining whether a new
Xcommand has been received.  cm_new_command_pending() returns TRUE
Xor FALSE depending on whether a new command has been received.
X
X	maybe = cm_new_command_pending(command_variable);
X
X	(setq maybe (cm_new_command_pending command_variable))
X
XWhen a new command has been received, cm_new_command_pending will
Xreturn TRUE until cm_get_new_command_value() has been called, after
Xwhich it will return FALSE.  cm_get_new_command_value() also
Xreturns TRUE or FALSE, depending upon whether it has detected a new
Xcommand.  (Lisp users can expect t/nil instead of TRUE/FALSE.)
X
X
XStatus variables must be written with the routine,
Xcm_set_status_value().
X
X	cm_set_status_value(command,variable,value);
X
X	(cm_set_status_value command variable value)
X
XStatus (and any other) variables may be read with the routine
Xcm_get_value().
X
XTwo predicates are available that are of use to the superior
Xprocess in determining which command a subordinate process' status
Xis in response to.
X
X	maybe = cm_status_equal(cmd_var,stat_var,s_value);
X	maybe = cm_status_synchronized(cmd_var,stat_var);
X
X	(setq maybe (cm_status_equal cmd_var stat_var s_value))
X	(setq maybe (cm_status_synchronized cmd_var stat_var))
X
Xcm_status_equal() returns TRUE or FALSE, depending on whether or
Xnot the status variable, stat_var, has the value, s_value, and is
Xin response to the command specified by cmd_var.
X
Xcm_status_synchronized() returns TRUE or FALSE, depending on
Xwhether or not the status variable, stat_var, is in response to the
Xcommand specified by cmd_var.  This is very helpful to the superior
Xprocess in finding out whether the subordinate process is
Xresponding the command.
X
XSynchronization
X
XSince the common memory and user processes are actually
Xunsynchronized processes, it is necessary to synchronize them
Xoccasionally.  The idea of calling cm_sync(), is to force all
Xvariables in common to the user and CMM processes to have the same
Xvalue.
X
X	cm_sync(behavior);
X
X	(cm_sync behavior)
X
Xcm_sync() takes one argument that allows several behaviors by the
XCMM.  There are three sets of options.
X
XThe first specifies whether cm_sync() should wait for at least one
Xset of variable updates (or any response from the CMM).  The
Xdefault is CM_WAIT.  To poll and return immediately, use
XCM_NO_WAIT.
X
XThe second option allows one the ability to examine the one set of
Xvariable updates before it has (possibly) been overwritten by an
Ximmediately following set of updates.  This is very useful if you
Xhave a variable from which you expect to be written by multiple
Xprocesses.
X
XSelecting CM_WAIT_AT_MOST_ONCE allows you to read a variables value
Xbefore it is overwritten by yet another value from the CMM.  This
Xis useful, for server processes, which takes requests off a queue.
Xdefault is CM_WAIT_FOR_ALL which simply returns the most recently
Xwritten value.
X
XThe third set of options controls whether the user desires an
Ximmediate reply from the common memory.
X
X	cm_sync(CM_WAIT_READ);
X
XCM_WAIT_READ forces the common memory to respond with the current
Xset of variable values (whether or not they have wakeup flags set
Xon them).  If you expect to poll intermittently, a variable that is
Xbeing regularly set, this is the desirable behavior.
X
XIf the CMS has already sent variable updates to you, CM_WAIT_READ
Xwill get whichever ones are appropriate depending upon the other
Xoptions you have supplied in cm_sync().  For example, specifying
Xboth CM_WAIT_READ and CM_WAIT_FOR_ALL gives an exact simulation of
Xa true common memory.  Note that using CM_WAIT_READ may be slower
Xthan other forms of cm_sync() since you may have to wait for a
Xreply message from the common memory.
X
XTo combine options, bitwise-OR them together.  For example, to poll
Xfor at most one new set of variable values:
X
X	cm_sync(CM_NO_WAIT|CM_WAIT_AT_MOST_ONCE);
X
XHowever, it is expected that most clients will simply want to use:
X
X	cm_sync(CM_WAIT);
X
Xcm_sync returns either 0 (normal completion) or negative numbers
Xdenoting an error (see the cm.h).
X
X
XOther variable information
X--------------------------
X
XVariables are more structured than in the BBN HCSE.  This allows easier
Xcontrol of variables.  For example, handshaking between two levels of the
Xhierarchy is automatically handled by command associations embedded in the
Xvariable structures.  Variables are also tagged with their length,
Xetc...
X
XCommon memory variables have the following attributes:
X
X	/* handshake.h */
X
X	char name[MAXVARIABLENAMELENGTH];
X	unsigned long count;	/* nth definition of this value */
X	unsigned long old_count;/* " " " " " " " " " " " " "when last read */
X	unsigned short size;	/* size in bytes of the uninterpreted data */
X	struct timeval *time_stamp;	/* when last written */
X	command_association command_association; /* command that this variable
X							is associated with */
X	command_association old_command_association; /* " " when last read */
X	cm_value data;		/* uninterpreted data */
X
XVariables also have the following attributes (which are strictly
Xinternal to the CMM).
X
X	char xwriter[PROCESSNAMELENGTH];	/* exclusive writer */
X	struct {
X		unsigned reader : 1;
X		unsigned writer : 1;
X		unsigned wakeup : 1;
X		unsigned new : 1;		/* written since read */
X	} role[PROCESSES];
X
X
XCompiling (or interpreting) CM code
X-------------------------------
X
XTwo libraries are necessary for using common memory.  cmlib.a is
Xthe common memory client code.  This uses a lower-level library,
Xlibstream.a, which provides connection and packet service on top of
XTCP.  Both libraries normally live in /usr/local/lib.
X
XThus, to link common memory programs:
X
X	cc foo.c -lcm -lstream
X
XInclude files live in /usr/local/include/cm.  Normally, it is
Xnecessary only to include /usr/include/sys/time.h and
X/usr/local/include/cm/cm_user.h as follows:
X
X	#include <sys/time.h>
X	#include <cm/cm.h>
X
X.lisp files are in /usr/local/lisp.  There is one file provided to
Xinitialize common memory from lisp, cm_user.lisp.  Thus to use
Xcommon memory, you should execute the following:
X
X	(load 'cm/cm_user.lisp)
X
XThe common memory manager itself, cmm, lives in /usr/local/bin.
X
XBefore any processes are started the CMM should be started up.
XAnyone can do this (i.e.  you do not have to be root or have the
Xsame uid as any other users of the CMM).  Just type:
X
X        /usr/local/bin/cmm
X 
XNormally, nothing else is required, however the cmm can take some
Xarguments to modify the default behavior.
X
X	-d [0-9]
X
XThe argument will cause the cmm to print out debugging information.
XHigher numbers evoke greater amounts of output.  0 means no
Xdebugging.  3 refers to message handling.  6 refers to slot
X(message contents) handling.  9 refers to most buffer/byte/string
Xcoping.
X
X	-t seconds
X
Xblock waiting for up to this time period, if the a client's kernel
Xqueue is full while the cmm is trying to send a message to the
Xclient.  After the timeout expires, the cmm goes on and will retry
Xlater.  This typically implies that the client is hung, but is not
Xalways the case.  The default timeout period is 5 seconds.
X
X	-p port_number
X
XThe initial connection port that the common memory uses may be
Xchanged by specifying the port number.  The default is 1525.  This
Xis useful if you want to have multiple separate common memorys on a
Xsingle computer.
X
X
XThe cmm does not require a controlling terminal to run.  Note, that
Xif the cmm is killed, all the processes using it will terminate if
Xthey are writing at the moment that the cmm is killed.  This is due
Xto a SIGPIPE being sent to each of the clients.  If you do not want
Xthis behavior, you should probably surround your calls to cm_sync
Xwith a setjmp/longjmp alarm, just the way one normally does with
Xblocking writes.  (The common memory manager does this internally
Xto protect itself from the clients dying.  You can look at it in
Xman.c.)  In typical use, however, people do not do this, since the
Xcommon memory never dies of its own accord.
X
XOnce the cmm is running, you can start the user processes.
X(Specifically, the cmm process should be started before the first
Xcm_process_name() is executed.)
X
X
XAdditional Lisp notes
X---------------------
X
XIn Lisp, all functions are identical to their C counterparts.
XCommonsense dictates usage differences.  A small Rosetta stone will
Xbe presented:
X
X	date = cm_declare(......);
X	foo = cm_declare(.....,CM_ROLE_READER);
X	cm_sync(WAIT);
X	cm_set_value(date,"12 Dec...");
X	cm_get_value(foo,foolist);
X
X
X	(setq date (cm_declare 'date CM_ROLE_XWRITER))
X	(setq foo (cm_declare 'foo CM_ROLE_READER))
X
X	(cm_sync WAIT)
X	(cm_set_value date "12 Dec...")
X	(setq foo (cm_get_value foolist))
X
X
XNote that uppercase values denote constants that should be
Xevaluated before use (i.e.  unquoted).  For example, to check if
Xcm_declare() returns without failure the code would look like:
X
X	(cond ((eq CM_BAD_OBJECT (cm_declare ....)) nil)
X	      (t t))
X
X
XPorting code over to the VAX (HCSE)
X
XThe following section is only appropriate to people using the BBN's
XHCSE code on the VAX running VMS.
X
XIt is possible to run the same code on the Sun (Sun CM) and the VAX
X(BBN HCSE) if certain steps are taken.
X
XAn interface library is supported that effectively replaces the
XSun CM user calls with calls into the HCSE library.  This library
Xis currently available in ~libes/cm/src.7v.
X
XCode using the the UNIX CM library with HCSE should add the
Xfollowing parameters to the link command (in a .opt file)
X
X	user1:[libes.cm.src$5n7v]suncmlib/lib,
X	cm_library:cmlib/lib,
X	psect=cm_shrmem,page
X
XVersions of the code compiled for debugging are available by
Xspecifying:
X
X	user1:[libes.cm.src$5n7v]suncmlib_debug/lib,
X	cm_library:cmlib_debug/lib,
X	psect=cm_shrmem,page
X
X
XThere are three restrictions upon use of the HCSE with Sun CM code.
X
XTypes
X
XThe type systems in both the Sun system and the HCSE system are
Xquite different.  The HCSE types are based on Praxis.  Primarily
Xthis means that they have user-definable types.  Secondly, there
Xare no arbitrarily-sized data objects.
X
XTwo extra parameters on the cm_declare statement exist in the HCSE
Xversion of Sun CM to get around this.
X
XThe first is a maximum size.  The second is a pointer to a type
Xstructure.  If the type structure pointer is zero, the size is used
Xto automatically select a type structure.  For more information
Xabout creating type structures, see the HCSE Programmers Manual.
X
XA typical call that would be portable to both the Sun and VAX
Xsystems looks like the following:
X
X	if (!(date = cm_declare("data",CM_ROLE_XWRITER
X#ifdef VAX11C
X		,1000,0
X#endif
X			     ))) {
X		printf("declare of var failed\n");
X		exit(-1);
X	 }
X
XWhen compiled by the DEC C compiler, the additional two parameters
Xwill be included.
X
X
XThe second difference in the UNIX CM system and the HCSE is that
Xthe HCSE does not support queuing of variable updates.  This means
Xthat if one process goes to sleep while a second process writes a
Xvariable several times, if the first process then wakes up, it will
Xsee only the last values written by the second process, not all the
Xintermediate ones.
X
XA different explanation of this phenomena is that there is no
Xdifference between specifying CM_WAIT_AT_MOST_ONCE and
XCM_WAIT_FOR_ALL in cm_sync().
X
X
XThe third difference is that the HCSE does not store command
Xassociations with variables in the cmm itself.  (In fact, they are
Xjust dropped on the floor).  Therefore, routines like
Xcm_status_equal() don't work.
X
XIf you need command associations or their effect (and most people
Xdo), you must do what other HCSE users do.  That is, to stuff in a
Xnumber in front of every variable indicating who many times this
Xvariable has been written.  Then create a new variable, that holds
Xthe old value of the number which you can use to compare it against.
X
XFor more information on this, read:
X
XAMRF Architectural Decision Document: Mailbox Format (2/20/85)
XAMRF Notice 85-1: Command-Status Message Structure (1/8/85)
X
XA package that implements this along with current mailbox types in
Xuse in the AMRF lives in k:~network/mailbox.  An example using
Xthese functions is in the cm source directory in vws.c.  vws.lisp
Xis a lisp version of the same thing.
X
X
XBasic limits of the CM system.
X
XCertain limitations exist in the CMM.  It is possible to change
Xany of these and recompile.  Changable limitations (and their
Xdefaults as the system is distributed are):
X
XCM_MSGSIZE	100000		/* Maximum size of any single set of variable
X				updates between the cmm and a user */
XCM_SLOTSIZE	 20000		/* Maximum size of any single variable */
XCM_PROCESSNAMELENGTH   20	/* Maximum length of the process name */
XCM_VARIABLENAMELENGTH  20	/* Maximum length of any variable name */
XCM_MAXVARIABLES	    50	/* Maximum number of variables local to the cmm */
XCM_MAXPROCESSES	    20	/* Maximum number of processes that can talk to
X				the cmm simultaneously.  Absolute
X				maximum of 32 (or number of user
X				file descriptors) under 4.2BSD. */
XCM_MAXUSERVARIABLES 100 /* Max number of variables local to a user */
X
X
XErrors
X
XMost types of errors are reported at the user program.  Some
Xmessages cannot be reported back to the user, and are reported at
Xthe cmm itself.  Some errors are serious enough that they are
Xreported at both the user and cmm.
X
XUser errors
X
XMost user errors can be fixed when identified.  For example,
Xwriting into a variable declared to be read-only would be a
Xuser-error.
X
XSince user errors indicate a user-programming error, the CMS
Xusually prints out a message indicating the problem.  It also
Xreturns an error code if possible.  It is sometimes not possible to
Xdo this.  For instance, the above example would not be detected
Xuntil after cm_set_value returned.
X
XThe actual message would be printed by cm_sync when it is
Xprocessing incoming messages from the cmm.  Most types of errors
Xare detected by cm_sync.
X
XSystem errors
X
XSystem errors are caused by limitations in the CMS itself, the
Xenvironment it is running in and the user demands upon the system.
XOften, these cannot be avoided.  For example, if the user attempts
Xto send to much data to the common memory at once, the maximum
Xmessage size can be exceeded.
X
XListing of Error Messages
X
Xcm_init:
X	returns E_CM_INIT_FAILED
X	initport(client): Connection refused
X		Problem: cmm is not running.
X
Xcm_sync:
X	failed to send msg to cmm.  cmm disappeared?
X		Problem: cmm died.  Detected while writing to it.
X	cm library (version #) is older/newer than cmm (version #)
X		Problem: cmm is a different version than the
X		libraries your code is compiled with.  This can
X		also be caused by a corrupted message.  The is
X		usually identifiable by wildly different version #s.
X	bad slot encountered...aborting msg
X	user_decode_slot: unknown slot type (#)...msg aborted
X		Problem: corrupted message or internal error in CMS.
X	CMM: error processing variable <name> - error message
X		Problem: cmm detected error "error message" in
X		processing "name".  See below.
X	get_slot_read_response: <name> unknown (sent from cmm)
X		Problem: corrupted message or internal error in CMS
X	too much data for msg!!
X	output msg size = #  slotsize = #
X		Problem: User value is too large for CMS
X		configuration.  Either user error, or message size
X		limit should be increased.
X	cm_sd_free() called on nonmallocable object?
X		Problem: internal error in CMS
X
X*:
X	error: bcopy src/dest is null ptr
X		Problem: internal error or user error.  If user
X		error, check elements of cm_value structures to see
X		that they are consistent.
X
Xcmm:
X	bind() failed
X	initport(server): Address already in use
X	failed to initialize connection socket
X		Problem: another cmm is running, or a process
X		already has the CMM connection socket open.
X	get_variables(name) failed
X		Problem: too many variables in cmm.
X	process <name> is being antisocial on fd #
X		Problem: process has requested wakeup service but
X		is not listening to cmm updates.
X	slot bad
X		Problem: corrupted message or internal error in CMS
X	slot error in <name>  type # - error message
X		Problem: corrupted message or internal error in CMS
X		or user error.  See error message.  This message is
X		sent back to the user.  See below.
X
XError messages generated by the CMM and sent back to the user.
X	version
X		Problem: version mismatch.  See above.
X	bad slot type
X		Problem: corrupted message or internal CMS error.
X	not enough common memory to declare variable
X		Problem: too many variables stored at cmm.
X	cannot get nonexclusive write access
X		Problem: a process has already received exclusive
X		write access to this variable.
X	undeclare of undeclared variable
X		Problem: a nonexistent variable is being undeclared.
X	variable has not been declared
X		Problem: attempt to read/write variable not yet
X		declared.
X	not declared as writer
X		Problem: attempt to write variable declared as
X		read-only.
X	get_slot_write: cm_flat_to_sd() failed!  no space?
X		Problem: cmm ran out of memory trying to read user
X		message.  Indicates lack of system resources or
X		user sent value that was too large.
X	not declared as reader:
X		problem: attempt to read variable declared as
X		write-only.
X
XThere are several places in the CMS where memory is dynamically
Xallocated.  These may fail with an error such as
X
X	func: failed malloc(object,size)
X
Xor
X
X	resized failed! - out of space
X
Xwhere "func" is the CMS function calling malloc, "object" is the
Xobject being malloc'd and size is the size of the object.  
XThese errors typically indicate that either:
X
X1) the user is storing or receiving incredibly lengthy values
X(probably by mistake), or
X
X2) the system is running out of internal space
X
END_OF_FILE
if test 26953 -ne `wc -c <'doc/user.doc'`; then
    echo shar: \"'doc/user.doc'\" unpacked with wrong size!
fi
# end of 'doc/user.doc'
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone
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

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.