spl_request(3C) spl_request(3C)
NAME
spl_map, spl_request, spl_unmap, spl_request_macro - system
interrupt priority level controls
SYNOPSIS
#include <sys/types.h>
#include <ml/spl.h>
caddr_t spl_map (addr)
caddr_t addr;
int spl_unmap (addr)
caddr_t addr;
void spl_request (value, addr)
u_int value;
caddr_t addr;
spl_request_macro (value, addr, pv)
u_int val;
caddr_t addr;
u_int pv;
DESCRIPTION
The system interrupt priority level, ipl, may be modified
from user-level, by using this set of spl library routines.
This is accomplished by binding the physical address of the
system interrupt priority register into the address space of
the process, and then writing directly to this hardware
register from the process's address space.
By raising a cpu's ipl from the normal user-level value of
zero, a process may hold out certain interrupts. For exam-
ple, by raising the ipl to SPL4, a process holds out all VME
level 4 interrupts, which would prevent level 4 VME devices
from interrupting the process's cpu.
The spl_map() routine binds the physical address of the ipl
register into the address space of the process and returns
the resulting virtual address of the interrupt priority
register. This is accomplished by creating a shared memory
region. The addr parameter is a virtual address where the
caller wishes the shared memory region to be attached. If
addr is zero, the system will pick the virtual address. If
addr is not zero, then spl_map() will attempt to attach the
shared memory region at the specified address, automatically
rounding the addr value to a SHMLBA boundary.
Certain library routines, such as those contained in a
user-level device driver, may make spl_map() calls in addi-
tion to spl_map() calls made by the non-library code portion
Page 1 CX/UX Programmer's Reference Manual
spl_request(3C) spl_request(3C)
of the program. Therefore, if a process makes more than one
call to spl_map() before making a spl_umap() call, an
attempt will be made to use the previously bound spl shared
memory region. In this case, spl_map() will simply incre-
ment an internal reference count and return the previously
bound virtual address. However, if an addr parameter is
specified on an additional spl_map() call and the address
does not match the previously bound spl region's address, an
error wil be returned.
The spl_request() routine sets the ipl to the specified
interrupt priority level. The value parameter should be an
ipl value that is defined in the <ml/spl.h> include file.
The addr parameter should be the virtual address value that
was returned from a previous spl_map() call. spl_request()
returns the previous ipl value; that is, the value of the
ipl register before it was modified to the caller's speci-
fied value.
The spl_request_macro() macro is provided as a faster method
for modifying the ipl register. The value and addr parame-
ters should contain the same information as the
spl_request() routine. The pv parameter should be an u_int
variable where the previous ipl value will be returned.
(The pv parameter should always be supplied.) This macro is
only available to C language programs and is not available
to Fortran or Ada programs.
The spl_unmap() routine is provided to detach the shared
memory region from the process. The addr parameter is the
virtual address returned from the previous spl_map() routine
call. (The spl shared memory region will be automatically
detached when a process terminates, or issues one of the
exec(2) system service calls.)
If the process has made multiple calls to spl_map() before
calling spl_unmap(), the spl region will not actually be
detached until the corresonding number of spl_unmap() calls
have been made.
NOTES
These routines would normally be used to coordinate shared
data accesses between user-level processes and user-level
interrupt routine(s). (See iconnect(2) for more information
on user-level interrupt routines). By raising the ipl up to
or higher than the interrupt priority level of the user-
level interrupt routine's external interrupt, the user-level
proces may then be assured that it may execute on it's cpu
without being interrupted by its corresponding user-level
interrupt routine process.
Page 2 CX/UX Programmer's Reference Manual
spl_request(3C) spl_request(3C)
On multiprocessor systems, an additional user-level spin
lock should be used, to provide synchronization to shared
data among multiple cpus. The spin_init(2),
spin_trylock(2), spin_islock(2), spin_unlock(2) set of ser-
vices are recommended for this purpose. See this man page
for more information on using these services.
For example, on a multiprocessor system, a user-level pro-
cess that shares data with a user-level interrupt process
that needs to synchronize its access to this data would do
so by:
Raising ipl to the appropriate level.
Locking the user defined spin lock.
Accessing or modifying the shared data.
Unlocking the user defined spin lock.
Lowering ipl to zero.
The corresponding user-level interrupt routine process would
access this same data by:
Locking the user defined spin lock
Accessing or modifying the shared data.
Unlocking the user defined spin lock.
RESTRICTIONS
A process must be super-user, or must have the ACC_SHMBIND
access vector bit set in order to use the spl_map() routine.
During the time that a process has raised ipl until it has
lowered ipl back to zero, the process should not:
Make any system service calls.
Reference any memory location that will result in a
system page fault. It is highly recommended that the
process lock down its entire address space if it
intends to use the spl_request() routine.
Set any debugger breakpoints, or single-step in any
section of code where ipl has been set above zero.
It is recommended that a process not raise ipl above zero
for any length of time.
Page 3 CX/UX Programmer's Reference Manual
spl_request(3C) spl_request(3C)
WARNINGS
A user-level process (not a user-level interrupt routine
process) that raises ipl should ALWAYS reset the ipl back to
zero.
If a user-level interrupt routine temporarily raises ipl, it
should not set the ipl back to zero, but it should restore
the ipl value back to what it was when it entered the user-
level interrupt routine. This should be the value that was
returned on the initial spl_request() call. See iconnect(2)
for more information on user-level interrupt routines.
RETURN VALUE
For spl_map() routine calls, upon successful completion, the
virtual address of the ipl register is returned. For
spl_unmap() routine calls, upon successful completion, a
value of zero is returned. Otherwise, for both of these
calls, a value of -1 is returned and errno is set to indi-
cate the error.
The spl_request() routine returns no error status.
ERRORS
If any of the following conditions is detected, spl_map()
will return -1 and set errno to the following value:
[EACCES] The caller is not super-user, or does not
have the ACC_SHMBIND access vector bit set
(if access vectors are configured).
[EINVAL] The addr parameter is not a valid shared
memory segment value.
[EBUSY] The process has previously called spl_map(),
and the current addr parameter that was
specified does not match the previous bind
address. The proces must first call
spl_unmap() before binding the spl shared
memory region to a new virtual address.
[EMFILE] The number of shared memory segments attached
to the calling process would exceed the
system-imposed limit.
[ENOSPC] The spl shared memory identifier is to be
created, but the system-imposed limit on the
maximum number of allowed system-wide shared
memory identifiers would be exceeded.
If the following condition is detected, spl_unmap() will
return -1 and set errno to the following value:
Page 4 CX/UX Programmer's Reference Manual
spl_request(3C) spl_request(3C)
[EINVAL] The specified addr parameter was not a valid
segment start address of the ipl shared
memory segment.
SEE ALSO
iconnect(2), eti_map(3C), spin_init(2)
Page 5 CX/UX Programmer's Reference Manual