Sophie

Sophie

distrib > Mandriva > 8.2 > i586 > media > contrib > by-pkgid > 211238da6d926d1ca4390483bb29f586 > files > 63

coda-doc-5.2.0-4mdk.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
 <TITLE> RPC2 User Guide and Reference Manual: Chapter(The Basic LWP Package)</TITLE>
 <LINK HREF="rpc2_manual-9.html" REL=next>
 <LINK HREF="rpc2_manual-7.html" REL=previous>
 <LINK HREF="rpc2_manual.html#toc8" REL=contents>
</HEAD>
<BODY>
<A HREF="rpc2_manual-9.html">Next</A>
<A HREF="rpc2_manual-7.html">Previous</A>
<A HREF="rpc2_manual.html#toc8">Contents</A>
<HR>
<H2><A NAME="s8">8. Chapter(The Basic LWP Package)</A></H2>

<P>
<A NAME="LWPReference"></A> <P>The LWP package implements primitive functions providing basic
facilities that enable procedures written in C, to proceed in an
unsynchronized fashion.  These separate threads of control may
effectively progress in parallel, and more or less independently of
each other.  This facility is meant to be general purpose with a heavy
emphasis on simplicity.  Interprocess communication facilities can be
built on top of this basic mechanism, and, in fact, many different IPC
mechanisms could be implemented.  The RPC2 remote procedure call
package (also described in this manual) is one such IPC mechanism.
<P>
<P>The LWP package makes the following key design choices:
<UL>
<LI>The package should be small and fast;
</LI>
<LI>All processes are assumed to be trustworthy -- processes are not protected
from each others actions;
</LI>
<LI>There is no time slicing or preemption -- the processor must be yielded
explicitly.</LI>
</UL>
<P>In order to set up the environment needed by the lightweight process
support, a one-time invocation of the LWP_Init function must
precede the use of the facilities described here.  The initialization
function carves an initial process out of the currently executing C
procedure.  The process id of this initial process is returned as the
result of the LWP_Init function.  For symmetry a
LWP_TerminateProcessSupport function may be used explicitly to
release any storage allocated by its initial counterpart.  If used, it
must be issued from the process created by the LWP_Init function. 
<P>
<P>Upon completion of any of the lightweight process
functions, an integer value is returned to indicate whether any error
conditions were encountered.
<P>
<P>Macros, typedefs, and manifest constants for error codes needed by the
lightweight process mechanism reside in the file <CODE>&lt;lwp.h&gt;</CODE> (shown
in Appendix 
<@@ref>lwp.h)XXX</A>.
A process is identified by an object of type PROCESS, which is
defined in the include file. 
<P>
<P>The process model supported by the operations described here
is based on a non-preemptive priority dispatching scheme. (A priority is an integer in the range [0..LWP_MAX_PRIORITY],
where 0 is the lowest priority.)
Once a given lightweight process is selected and dispatched, it
remains in control until it voluntarily relinquishes its claim
on the CPU.
Relinquishment may be either explicit (LWP_DispatchProcess) or
implicit (through the use of certain other LWP operations).
In general, all LWP operations that may cause a
higher priority process to become ready for dispatching,
preempt the process requesting the service.
When this occurs, the priority dispatching mechanism takes over and
dispatches the highest priority process automatically.  Services in this
category (where the scheduler is guaranteed to be invoked in the absence of
errors) are
<P>
<UL>
<LI>LWP_CreateProcess</LI>
<LI>LWP_WaitProcess</LI>
<LI>LWP_MwaitProcess</LI>
<LI>LWP_SignalProcess</LI>
<LI>LWP_DispatchProcess</LI>
<LI>LWP_DestroyProcess</LI>
</UL>
<P>The following services are guaranteed not to cause preemption (and so may be issued with no fear of losing control to another
lightweight process):
<UL>
<LI>LWP_Init</LI>
<LI>LWP_NoYieldSignal</LI>
<LI>LWP_CurrentProcess</LI>
<LI>LWP_StackUsed</LI>
<LI>LWP_NewRock</LI>
<LI>LWP_GetRock</LI>
</UL>
<P>The symbol LWP_NORMAL_PRIORITY provides a good default value to
use for process priorities.
<P>
<H2><A NAME="ss8.1">8.1 A word about initialization</A>
</H2>

<P>The LWP, IOMGR, Fast Time, and RPC2 packages have routines that
perform global initialization for the package.  Each of these routines
may be called more than once, and only the parameters from the first
invocation will be used.  In addition, each routine calls any of the
others that it needs for proper operation.
<P>The result is that if you only use one package directly, you need only
call the initialization routine for that package.  You may call the
initialization routines for other packages anyway in order to set the
initialization parameters yourself.  If you wish to initialize all of
these packages yourself, you must call the initialization routines in
this order: Fast Time, LWP, IOMGR, RPC2.  The RPC2 package does not
call the LWP packages initialization routine.  You must call
LWP_Init explicitly before calling RPC2_Init.
<P>In contrast, the Preemption package initialization routine may be
called multiple times to change the value of the preemption time
slice.
<P>The Lock and Timer packages have initialization routines that initialize
objects instead of global data.  The only restriction on the order of the
initialization calls to these packages is that calls to TM_Init must
follow your call to FT_Init, if you have one.
<P>
<P>
<H2><A NAME="ss8.2">8.2 A Simple Example</A>
</H2>

<P>
<P>
<BLOCKQUOTE><CODE>
<PRE>

#include &lt;lwp.h&gt;

static read_process (id)
    int *id;
{
    LWP_DispatchProcess ();             /* Just relinquish control for now */

    for (;;) {
        /* Wait until there is something in the queue */
        while (empty(q)) LWP_WaitProcess (q);
        /* Process queue entry */
        LWP_DispatchProcess ();
   }
}

static write_process ()
{
    . . .

    /* Loop &amp; write data to queue */
    for (mesg=messages; *mesg!=0; mesg++) {
        insert (q, *mesg);
        LWP_SignalProcess (q);
    }
}

main (argc, argv)
   int argc; char **argv;
{
    PROCESS *id;

    LWP_Init (LWP_VERSION, 0, &amp;id);
    /* Now create readers */
    for (i=0; i &lt; nreaders; i++)
        LWP_CreateProcess (read_process, STACK_SIZE, 0, i, "Reader", &amp;readers[i]);
    LWP_CreateProcess (write_process, STACK_SIZE, 1, 0, "Writer", &amp;writer);
    /* Wait for processes to terminate */
    LWP_WaitProcess (&amp;done);
    for (i=nreaders-1; i&gt;=0; i--) LWP_DestroyProcess (readers[i]);
}
@end(program)
main (argc, argv)
   int argc; char **argv;
{
    PROCESS *id;

    LWP_Init (LWP_VERSION, 0, &amp;id);
    /* Now create readers */
    for (i=0; i&lt; nreaders; i++)
        LWP_CreateProcess (read_process, STACK_SIZE, 0, i, "Reader", &amp;readers[i]);
    LWP_CreateProcess (write_process, STACK_SIZE, 1, 0, "Writer", &amp;writer);
    /* Wait for processes to terminate */
    LWP_WaitProcess (&amp;done);
    for (i=nreaders-1; i&gt;=0; i--) LWP_DestroyProcess (readers[i]);
}
</PRE>
</CODE></BLOCKQUOTE>
<P>
<H2><A NAME="ss8.3">8.3 LWP Runtime Calls</A>
</H2>

<P>
<H3>LWP_Init -- <EM> Initialize LWP support and start initial process</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int LWP_Init(</EM><B>in</B> char *VersionId&gt;, @w&lt;<B>in</B> int priority&gt;, @w&lt;<B>out</B> PROCESS *pid&gt;)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>VersionId</B><DD><P>Set this to the constant LWP_VERSION.  The current value of this string  constant must be identical to the value at the time the client runtime system was compiled.
<DT><B>priority</B><DD><P>Priority at which initial process is to run.
<DT><B>pid</B><DD><P>The process id of the initial process will be returned in this parameter.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>All went well
<DT><B>LWP_EBADPRI</B><DD><P>Illegal priority specified (&lt; 0 or too large)
</DL>
<H3>Description:</H3>

<P>Initializes the LWP package.  In addition, this routine turns the current thread of control into the initial process with the specified priority.  The process id
of this initial process will be returned in parameter pid. This routine must be
called to ensure proper initialization of the LWP routines.  This routine will
not cause the scheduler to be invoked.
)
<P>
<H3>LWP_TerminateProcessSupport -- Terminate process support and clean up  </H3>

<H3>Call:</H3>

<P><EM>int LWP_TerminateProcessSupport()</EM>
<H3>Parameters:</H3>

<P><EM>none.</EM>
<H3>Completion Codes:</H3>

<P><EM>N/A</EM>
<H3>Description:</H3>

<P>This routine will terminate the LWP process support and clean
up by freeing any auxiliary storage used.  This routine must be
called from within the procedure and process that invoked
LWP_Init.  After
LWP_TerminateProcessSupport has been called,
LWP_Init may be called again to resume
LWP process support.
)
<P>
<H3>LWP_CreateProcess -- Create and start a light-weight process</H3>

<P>
<H3>Call:</H3>

<P><EM>int LWP_CreateProcess(</EM><B>in</B> int (*ep) (),<B>in</B> int stacksize,<B>in</B> int priority, <B>in</B> char *parm <B>in</B> char *name, <B>out</B> PROCESS *pid)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>ep</B><DD><P>This is the address of the code that is to execute the function
of this process.  This parameter should be the address
of a C routine with a single parameter.,
<DT><B>stacksize</B><DD><P>This is the size (in bytes) to make the stack for the
newly-created process.  The stack cannot be shrunk or expanded,
it is fixed for the life of the process.,
<DT><B>priority</B><DD><P>This is the priority to assign to the new process.,
<DT><B>parm</B><DD><P>This is the single argument that will be passed to the new
process.  Note that this argument is a pointer and, in general,
will be used to pass the address of a structure containing
further "parameters".,
<DT><B>name</B><DD><P>This is an ASCII string that will be used for debugging purposes
to identify the process.  The name may be a maximum of 32
characters.,
<DT><B>pid</B><DD><P>The process id of the new process will be returned in this
parameter,
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>Process created successfully,
<DT><B>LWP_ENOMEM</B><DD><P>Not enough free space to create process,
<DT><B>LWP_EBADPRI</B><DD><P>Illegal priority specified (&lt; 0 or too large),
<DT><B>LWP_EINIT</B><DD><P>LWP_Init has not been called
</DL>

This routine is used to create and mark as runnable a new light-weight
process.  This routine will cause the scheduler to be called.
Note that the new process will begin execution before this call
returns only if the priority of the new process is greater than
or equal to the priority of the creating process.
)
<P>
<H3>LWP_DestroyProcess -- Destroy a light-weight process</H3>

<P>
<H3>Call:</H3>

<P><EM> int LWP_DestroyProcess(</EM><B>in</B> PROCESS pid)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>pid</B><DD><P>The process id of the process to be destroyed.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>Process destroyed successfully
<DT><B>LWP_EINIT</B><DD><P>LWP_Init has not been called
</DL>
<H3>Description:</H3>

<P>This routine will destroy the specified process.  The
specified process will be terminated immediately and its
internal storage will be freed.  A process is allowed to
destroy itself (of course, it will only get to see the return
code if the destroy fails).  Note a process may also destroy
itself by executing a <B>return</B> from the C routine.  This routine
calls the scheduler.
<P>
<H3>LWP_WaitProcess -- Wait for event</H3>

<P>
<H3>Call:</H3>

<P><EM>int LWP_WaitProcess(</EM><B>in</B> char *event)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>event</B><DD><P>The event to wait for.  This can be any memory address.  But, 0 is an
illegal event.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>The event has occurred
<DT><B>LWP_EINIT</B><DD><P>LWP_Init has not been
called
<DT><B>LWP_EBADEVENT</B><DD><P>The specified event was illegal (0)
</DL>
<H3>Description:</H3>

<P>This routine will put the calling process to sleep until
another process does a call of LWP_SignalProcess or LWP_NoYieldSignal with the
specified event.  Note that signals of events are not queued:
if a signal occurs and no process is woken up, the signal is
lost.  This routine invokes the scheduler. 
)
<P>
<H3>LWP_MwaitProcess -- Wait for a specified number of a group of signals  </H3>

<H3>Call:</H3>

<P><EM>int LWP_MwaitProcess(</EM><B>in</B> int wcount, <B>in</B> char *evlist)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>wcount</B><DD><P>Is the number of events that must be signaled to wake up this
process
<DT><B>evlist</B><DD><P>This a null-terminated list of events (remember that 0 is not a
legal event).  There may be at most LWP_MAX_EVENTS events
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>The specified number of appropriate
signals has occurred
<DT><B>LWP_EBADCOUNT</B><DD><P>There are too few events (0)
or wcount &gt; the number of events in evlist
<DT><B>LWP_EINIT</B><DD><P>LWP_Init has not been
called
</DL>
<H3>Description:</H3>

<P>This routine allows a process to wait for wcount signals of
any of the signals in evlist.  Any number of signals of a
particular event is only counted once.  The scheduler will be
invoked.
)
<P>
<H3>LWP_SignalProcess -- Signal an event</H3>

<P>
<H3>Call:</H3>

<P><EM>int LWP_SignalProcess(</EM><B>in</B> char *event)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>event</B><DD><P>The event to be signaled.  An event is any memory address
except 0
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>The signal was a success (a process was
waiting for it)
<DT><B>LWP_EBADEVENT</B><DD><P>The specified event was illegal (0),
<DT><B>LWP_EINIT</B><DD><P>LWP_Init was not
called,
<DT><B>LWP_ENOWAIT</B><DD><P>No process was waiting for this signal,
</DL>
<H3>Description:</H3>

<P>This routine causes event to be signaled.  This will mark all
processes waiting for only this event as runnable.  The
scheduler will be invoked.  Signals are not queued: if no
process is waiting for this event, the signal will be lost and
LWP_ENOWAIT will be returned.
)
<P>
<H3>What call is thore for. </H3>

<P>
<P>
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>event</B><DD><P>The event to be signaled.  An event is any memory address
except 0,
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>The signal was a success (a process was
waiting for it),
<DT><B>LWP_EBADEVENT</B><DD><P>The specified event was illegal (0),
<DT><B>LWP_EINIT</B><DD><P>LWP_Init was not
called,
</DL>
<H3>Description:</H3>

<P>Text=`This routine causes event to be signaled.  This will mark all
processes waiting for only this event as runnable.  This call
is identical to LWP_SignalProcess except that the scheduler
will not be invoked -- control will remain with the signalling process.
Signals are not queued: if no process is waiting for this event, the signal
will be lost and LWP_ENOWAIT will be returned.
)
<P>
<H3>LWP_XXXFIXME  </H3>

<H3>Parameters:</H3>

<P>Well??
<P>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>All went well,
<DT><B>LWP_EINIT</B><DD><P>LWP_Init has not been
called,
</DL>
<H3>Description:</H3>

<P>Text=`This routine is a voluntary yield to the LWP scheduler.
<P>
<H3>LWP_CurrentProcess -- Get the current process id  </H3>

<H3>Call:</H3>

<P><EM>int LWP_CurrentProcess(</EM><B>out</B> PROCESS *pid)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>pid,</B><DD><P>The current process id will be returned in this parameter
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>The current process id has been returned,
<DT><B>LWP_EINIT</B><DD><P>LWP_Init has not been
called,
</DL>
<H3>Description:</H3>

<P>Text=`This routine will place the current process id in the
parameter pid.
)
<P>
<H3>LWP_StackUsed -- Get information about stack usage for a process  </H3>

<H3>Call:</H3>

<P><EM>int LWP_StackUsed(</EM><B>in</B> PROCESS pid<B>out</B> int *max<B>out</B> int *used)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>pid</B><DD><P>The target process
<DT><B>max</B><DD><P>Max stack size given at process creation time
<DT><B>used</B><DD><P>Stack used so far
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>No problem,
<DT><B>LWP_NO_STACK</B><DD><P>Stack counting was not enabled for this
process.,
</DL>
<H3>Description:</H3>

<P>Text=`This routine returns the amount of stack space allocated to
the process and the amount actually used by the process so
far.  It works by initializing the stack to a special pattern
at process creation time and checking to see how much of the
pattern is still there when <B>LWP_StackUsed</B> is called.
The stack of the process is only initialized to the special
pattern if the global variable <B>lwp_stackUseEnabled</B> is
true when the process is created.  This variable is initially
true.  If <B>lwp_stackUseEnabled</B> was false at the time the
process was created, then <B>*used</B> will be set to zero
and the routine will return <B>LWP_NO_STACK</B>.
)
<P>
<H3>LWP_NewRock -- Find a rock under which private information can be hidden  </H3>

<H3><EM>int LWP_NewRock(</EM><B>in</B> int Tag <B>in</B> char *Value)  </H3>

<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Tag</B><DD><P>A unique integer identifying this rock.
<DT><B>Value</B><DD><P>A value (usually a pointer to some data structure) to be associated with the current LWP and identified by Tag.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>No problem.
<DT><B>LWP_EBADROCK</B><DD><P>Rock called Tag already exists for this LWP.
<DT><B>LWP_ENOROCKS</B><DD><P>All rocks are in use.
</DL>
<H3>Description:</H3>

<P>Text=`The rock is exactly what its name implies: a place to squirrel away application-specific
information associated with an LWP.  The Tag is any unique integer.
Users of the LWP package must coordinate their choice of Tag values.
Note that you cannot change the value associated with Tag.  To obtain
a mutable data structure use one level of indirection.
)
<P>
<H3>LWP_GetRock -- Obtain information hidden under a rock  </H3>

<H3>Call:</H3>

<P><EM>int LWP_GetRock(</EM><B>in</B> int Tag, <B>out</B> char **Value)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Tag</B><DD><P>Rock under which to look.,
<DT><B>Value</B><DD><P>The current value (usually a pointer to some data structure) hidden under this rock.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>LWP_SUCCESS</B><DD><P>Value has been filled.,
<DT><B>LWP_EBADROCK</B><DD><P>Specified rock does not exist.,
</DL>
<H3>Description:</H3>

<P>Text=`Recovers information hidden by a LWP_NewRock call.
<P>
<HR>
<A HREF="rpc2_manual-9.html">Next</A>
<A HREF="rpc2_manual-7.html">Previous</A>
<A HREF="rpc2_manual.html#toc8">Contents</A>
</BODY>
</HTML>