USINIT(3P) USINIT(3P)
usinit, usdetach, usadd, _utrace, _uerror - shared arena initialization
#include <ulocks.h>
usptr_t *usinit (const char *filename<b>);
int usadd (usptr_t *u<b>);
void usdetach (usptr_t *u<b>);
extern int _uerror;
extern int _utrace;
usinit is used to initialize a shared arena from which related or
unrelated processes may allocate and share semaphores, locks and memory.
Locks, semaphores and memory can then be allocated using the usptr_t
returned by usinit. More than one call can be made to usinit to create
separate arenas of locks and semaphores. In fact, calls to usinit may be
made on behalf of a process: when sproc(2) is called, an arena containing
the locks and semaphores for libc is created; when m_fork(3P) is called,
an arena is set up to control the spawned tasks. usinit uses a file in
the file system to name the arena. This name can then be used by
unrelated processes to access the arena.
usinit creates a file, filename, and maps it into the caller's space via
mmap(2). The file is mapped using the MAP_AUTOGROW option to mmap(2)
(see usconfig(3P) for ways to alter this behavior). By default the file
is not removed when the last process using it is finished. This behavior
can be modified somewhat via usconfig(3P). File locks (see fcntl(2)) are
used to prevent conflicting accesses to this area during the usinit call.
There is no way to tell the id of the process that actually created the
arena. The file name given to usinit may be an NFS mounted file, however
it is important to understand that NFS does not guarantee write
synchronization across multiple machines - thus if all users of an arena
are running on a single machine and using an NFS mounted file as the
arena, then all will work fine. If multiple users running on different
machines all access the same arena file, the arena will be corrupted.
Gaining access to a particular arena for the purpose of sharing locks,
semaphores, and memory is dependent on how the processes are related and
how the arena was initialized. If the arena was initialized (which is
the default) without the US_SHAREDONLY option to usconfig(3P) then any
process with the appropriate permissions can join the arena at any time
by calling usinit with filename. These processes may be unrelated,
related via fork, related via sproc sharing file descriptors, or related
via sproc not sharing file descriptors.
Page 1
USINIT(3P) USINIT(3P)
If the arena was initialized with the US_SHAREDONLY option to
usconfig(3P) then the file specified by filename is unlinked. This means
that the only processes that can join the arena must somehow already have
a handle for that arena (i.e. the arena must already be mapped into their
address space). Unrelated processes, processes spawned via fork before
the arena was initialized, and process spawned via sproc and not sharing
file descriptors, can never get the appropriate handle. If a process
with the above characteristics calls usinit with filename a NEW arena
will be created that has no relation to any other process's arena.
Processes that have the correct handle are automatically made 'members'
of the arena the first time they use a lock or semaphore. They may
choose to call usadd explicitly so that any potential errors are detected
at initialization time, rather than the first time a lock or semaphore is
used. Previous versions of this manual page suggested calling usinit
rather than usadd. This still works for any arena except one using
/dev/zero. usadd will work for any arena.
Certain attributes of the newly created arena may be set prior to the
call to usinit by usconfig(3P). These include the maximum number of
users that can simultaneously access the arena, the maximum size the
arena can grow to, the access permissions on the arena, the type of
debugging enabled, and where in the caller's address space the arena will
be attached. The overall size will limit how many locks and semaphores
may be allocated and how much space in the arena is left over for the
user to allocate via usmalloc(3P). In addition to the arena header,
basic lock, and semaphore data structures, all history, metering and
debug structures are also allocated via usmalloc(3P) from the arena. The
default size is 64K, and the default number of users is 8.
When called, usinit attempts to determine whether the arena described by
filename is active (i.e. whether any other processes are currently using
it). This determination is made by checking whether any file locks are
currently active on the file. If so, the caller registers its file lock
and merely 'joins' the collection of processes using that arena. If
there are no file locks, the caller re-initializes the entire arena.
Problems can result if a process that did not call usinit is still
accessing the arena (namely a child of a sproc whose parent has died)
when a new process attempts to join. The new process will find no file
locks and re-initialize the arena, thus destroying any state the first
process had. This problem can be solved by having all processes register
with the arena by calling usadd. Previous versions of this manual page
suggested calling usinit rather than usadd. This still works for any
arena except one using /dev/zero. usadd will work for any arena.
As a special case, /dev/zero can be passed as the value for filename.
Since /dev/zero by definition is private to the process that opens it,
this is useful only for share group members that are sharing file
descriptors. The space for /dev/zero comes from the logical swap pool
(see swap(1M)) rather than from the file system. Depending on the system
configuration there may be more space in the logical swap pool than on a
file system. The logical swap pool is also a limited resource and usinit
may fail due to lack of logical swap. It is possible to delay allocation
Page 2
USINIT(3P) USINIT(3P)
of logical swap (much like the MAP_AUTOGROW option delays growth of
files) by using the CONF_AUTORESV option of usconfig(3P).
usinit and the other lock and semaphore routines normally perform their
functions in silence. For a verbose 'trace' of what is being done, the
global flag _utrace may be set to non-zero. In addition, if the
environment variable USTRACE is set, usinit will automatically set
_utrace. The tracing information consists of two types of messages -
trace and error. Error type messages can be enabled independently from
tracing messages by setting the global flag _uerror. In addition, if the
environment variable USERROR is set, usinit will automatically set
_uerror. All messages are printed on stderr. This may aid in debugging
the various error returns.
An arena, once established, must reside at the same virtual address in
each process that attaches to it. This implies that if more than one
process is creating an arena, the creating processes must impose the
appropriate ordering. The following scenario will lead to such an
ordering problem: process A creates arena A_arena, and process B creates
arena B_arena. Then process A attempts to attach (via usinit) to
B_arena. usinit will most probably fail in this case since the virtual
address for both arenas will probably be identical. One way around this
ordering problem is to use usconfig(3P) to manually set the address where
the arena should be attached. It is then only important that all arena
creating processes agree on the addresses for each of the arenas.
Another easy way around this problem is to have all arenas created by one
process.
A process may detach an arena by calling usdetach. This call will unmap
and close all the relevant file descriptors. It does not check for any
outstanding locks, allocated memory, etc. usdetach will not close any
pollable semaphores, this must be done before calling usdetach. For
sproc processes sharing file descriptors, if one member calls usdetach
then the arena is detached for the entire share group. There is no
protection for multiple members of a share group simultaneously calling
usdetach, this should not be done.
If usinit fails, it is a good idea to set the tracing variable _utrace to
1 or set the environment variable USTRACE). This will provide more
descriptive error messages.
usinit or usadd will fail if one or more of the following are true:
EACCES The filename argument could not be opened or created for
read/write.
ENOSPC The file specified by filename could not be grown to the
specified size.
ENOMEM There is not enough space in the arena to allocate the initial
set of required locks and semaphores. The size of the arena
may be manipulated with usconfig(3P).
Page 3
USINIT(3P) USINIT(3P)
EBUSY The caller already has mapped virtual space at the address
requested with the CONF_ATTACHADDR option of usconfig.
EBUSY The caller already has mapped virtual space at the address
required by the arena when attempting to join the arena.
ENXIO One or both of the two semaphore device files, /dev/usema and
/dev/usemaclone, do not exist, or the device is not configured
into the system.
EINVAL This error is returned if the version the currently attaching
process was compiled with is incompatible with the version
compiled into the creator of the arena.
ENOLCK There are no more file locks available because the system
maximum {FLOCK_MAX} [see intro(2)], has been exceeded.
ENOLCK filename is in an NFS-mounted directory, and either the NFS
lock daemon, lockd(1M) is not running (either on the server or
client) or the maximum number of file locks that lockd can
handle has been exceeded.
EAGAIN filename was set to /dev/zero and there isn't enough logical
swap space to map the requested size arena.
Errors may also be the result of a mmap(2) or a fcntl(2) system call.
fcntl(2), mmap(2), sproc(2), acquire_lock(3), barrier(3P), oserror(3C),
uscasinfo(3P), usconfig(3P), usgetinfo(3P), usmalloc(3P), usnewlock(3P),
usnewsema(3P).
Upon successful completion, usinit returns a pointer to a usptr_t
structure. Otherwise, a value of NULL is returned and errno is set to
indicate the error.
Upon successful completion, usadd returns zero. Otherwise a value of
negative one is returned and errno is set to indicate the error.
usinit string compares filename with the names of existing arenas in the
calling process. If it finds a match, it assumes that the arena already
exists and that the caller has already (due to already having called
usinit with the same filename or due to being related to the process that
created the arena) mapped in the arena. This can cause unexpected
results if the application has code along the following lines:
filename = strdup(template);
mktemp(filename);
arena = usinit(filename);
(fork, exec, communicate file name to other process,
Page 4
USINIT(3P) USINIT(3P)
it attaches to arena)
unlink(filename);
The second time this is done, mktemp could come up with the exact same
name file as before (since the first one was unlinked). When usinit
compares the name to the names of already existing and mapped arenas, it
will find a match and NOT create a new arena. Certainly, in this case,
not the desired result.
Currently, it is not possible to create a shared arena that can be used
by programs of differing ABIs. This means that o32, N32, and N64 programs
cannot share an arena. For primitives that can be shared between 32-bit
and 64-bit processes see abilock(3P) and test_and_set(3P).
PPPPaaaaggggeeee 5555 [ Back ]
|