server_block(2) CX/UX server_block(2)
NAME
serverblock, serverwake1, serverwakevec - client/server
thread coordination
SYNOPSIS
#include <sys/types.h>
#include <sys/time.h>
#include <sys/threadsynch.h>
int serverblock (options, r, timeout)
int options;
struct reschedvar *r;
struct timeval *timeout;
int serverwake1 (server, r)
tidt server;
struct reschedvar *r;
int serverwakevec (servers, nservers, r)
tidt *servers;
int nservers;
struct reschedvar *r;
DESCRIPTION
serverblock blocks the calling thread if no wake-up has
occurred since the last return from serverblock. If a
wake-up has occurred, serverblock returns immediately.
Options must be zero.
If r is not NULL, serverblock decrements the number of
locks in the rescheduling variable.
If timeout is not NULL, it specifies the maximum length of
time the caller will be blocked.
The caller should be prepared for premature returns; that
is, it should re-test the condition that originally caused
it to block. Upon return there is no guarantee that the
condition blocking the caller has changed.
Serverwake1 wakes thread server if it is blocked in
serverblock. If server is not blocked in serverblock, the
wake-up will be applied to the next call to serverblock.
If r is not NULL, serverwake1 decrements the number of
locks in the rescheduling variable.
The real or effective user ID of the caller must match the
real or effective user ID of server, unless the effective
user ID of the caller is super-user.
Page 1 CX/UX Programmer's Reference Manual
server_block(2) CX/UX server_block(2)
Serverwakevec serves the same purpose as serverwake1,
except that a vector of threads may be specified rather than
one thread.
EXAMPLES
Suppose that producer and consumer threads exchange data
through a mailbox in shared memory. When the mailbox is
empty, consumers block until data arrives. When producers
deposit new data, they wake the waiting consumers.
In the pseudo-code that follows, let
01 struct mailbox {
02 struct spinmutex mx; /* serializes access to mailbox */
03 queueof consumers; /* waiting consumers */
04 queueof data; /* the data, type varies */
05 };
represent a mailbox in shared memory, rv represent a
rescheduling variable, and spin_acquire and spin_release
represent primitives that lock and unlock spinlocks and
rescheduling variables (see spintrylock(2)). Consumers
extract data from the mailbox as follows.
11 void
12 consume (box, data)
13 struct mailbox *box;
14 anyt *data;
15 {
16 spinacquire (&box->mx, &rv);
17 while (box->data == empty) {
18 enqueue (box->consumers, rv.rvtid);
19 spinunlock (&box->mx);
20 serverblock (0, &rv, 0);
21 spinacquire (&box->mx, &rv);
22 }
23 *data = dequeue (box->data);
24 spinrelease (&box->mx, &rv);
25 }
The mailbox is a shared data structure requiring serializa-
tion. Consumer threads lock the mailbox to test for the
presence of and ultimately to extract the data. When they
wait, consumers unlock the mailbox to allow producers to
deposit new data. Consumers re-check the mailbox when they
awaken because there is no guarantee that the mailbox will
contain data.
Producers store data into the mailbox as follows. This
example assumes that at most one consumer can benefit from
the arrival of the new data, so producers wake one rather
than all consumers.
Page 2 CX/UX Programmer's Reference Manual
server_block(2) CX/UX server_block(2)
31 void
32 produce (box, data)
33 struct mailbox *box;
34 anyt data;
35 {
36 spinacquire (&box->mx, &rv);
37 enqueue (box->data, data);
38 if (box->consumers == empty)
39 spinrelease (&box->mx, &rv);
40 else {
41 tidt tid = dequeue (box->consumers);
42 spinunlock (&box->mx);
43 serverwake1 (tid, &rv);
44 }
45 }
Producers signal the arrival of new data only when there is
a waiting consumer, and do so AFTER they unlock the mailbox.
The first act of a newly awakened consumer is to lock the
mailbox. If a producer were to awaken a consumer before it
unlocked the mailbox, the consumer may run only to find the
mailbox locked. Furthermore, spinlocks should only be held
for short periods of time. Unlocking the mailbox after the
call to serverwake1 would lengthen its hold time tremen-
dously. Also note that rescheduling remains disabled until
the call to serverwake1 in order to prevent unnecessary
context switching.
RETURN VALUE
Upon successful completion 0 is returned. Otherwise, -1 is
returned and errno is set to indicate the error.
ERRORS
These routines will fail if any of the following are true:
[EFAULT] A bad address was specified for one of the
arguments.
[EINVAL] Options was non-zero.
[EINVAL] The timeout was invalid.
[EINVAL] The rescheduling variable specified in r was
not the caller's rescheduling variable.
[EINVAL] The number of rescheduling locks in r was
less than or equal to 0.
[ESRCH] No thread could be found with the specified
ID.
[EPERM] The user ID of the calling thread was not
Page 3 CX/UX Programmer's Reference Manual
server_block(2) CX/UX server_block(2)
super-user, and its real or effective user ID
did not match the real or effective user ID
of the target thread.
[EINTR] The system call was interrupted by a signal.
[ETIME] The system call timed out.
SEE ALSO
CX/UX Programmer's Guide.
gettid(2), reschedcntl(2), spintrylock(2),
clientblock(2).
Page 4 CX/UX Programmer's Reference Manual