server_block(2) CX/UX server_block(2)
NAME
server_block, server_wake1, server_wakevec - client/server
thread coordination
SYNOPSIS
#include <sys/types.h>
#include <sys/time.h>
#include <sys/thread_synch.h>
int server_block (options, r, timeout)
int options;
struct resched_var *r;
struct timeval *timeout;
int server_wake1 (server, r)
tid_t server;
struct resched_var *r;
int server_wakevec (servers, nservers, r)
tid_t *servers;
int nservers;
struct resched_var *r;
DESCRIPTION
server_block blocks the calling thread if no wake-up has
occurred since the last return from server_block. If a
wake-up has occurred, server_block returns immediately.
Options must be zero.
If r is not NULL, server_block 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.
Server_wake1 wakes thread server if it is blocked in
server_block. If server is not blocked in server_block, the
wake-up will be applied to the next call to server_block.
If r is not NULL, server_wake1 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)
Server_wakevec serves the same purpose as server_wake1,
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 spin_mutex mx; /* serializes access to mailbox */
03 queue_of consumers; /* waiting consumers */
04 queue_of 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 spin_trylock(2)). Consumers
extract data from the mailbox as follows.
11 void
12 consume (box, data)
13 struct mailbox *box;
14 any_t *data;
15 {
16 spin_acquire (&box->mx, &rv);
17 while (box->data == empty) {
18 enqueue (box->consumers, rv.rv_tid);
19 spin_unlock (&box->mx);
20 server_block (0, &rv, 0);
21 spin_acquire (&box->mx, &rv);
22 }
23 *data = dequeue (box->data);
24 spin_release (&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 any_t data;
35 {
36 spin_acquire (&box->mx, &rv);
37 enqueue (box->data, data);
38 if (box->consumers == empty)
39 spin_release (&box->mx, &rv);
40 else {
41 tid_t tid = dequeue (box->consumers);
42 spin_unlock (&box->mx);
43 server_wake1 (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 server_wake1 would lengthen its hold time tremen-
dously. Also note that rescheduling remains disabled until
the call to server_wake1 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), resched_cntl(2), spin_trylock(2),
client_block(2).
Page 4 CX/UX Programmer's Reference Manual