|
|
coherent
vv_sslleeeepp() -- Accessible Kernel Routine
#iinncclluuddee <ssyyss/sscchheedd.hh>
vvooiidd
vv_sslleeeepp(_e, _c_v, _i_v, _s_v, _s_t_r)
cchhaarr *_e;
iinntt _c_v, _i_v, _s_v;
cchhaarr *_s_t_r;
vv_sslleeeepp() suspends processing of a process until event _e has completed. _e
normally represents a data item's address in the static kernel data space.
_s_t_r is a human readable event name displayed by command ppss. _c_v is the
scheduling value set to obtain the CPU as soon as the process awakes. _i_v
is the swap value obtained to keep the process in memory for the duration
of the sleep. _s_v is the swap value that allows the process to be swapped
in if it has been swapped out. The following table gives the manifest
constants to use with _c_v, _i_v, and _s_v for normal processing tasks, as set in
the header file <ssyyss/sscchheedd.hh>:
Child Process CCVVCCHHIILLDD IIVVCCHHIILLDD SSVVCCHHIILLDD
Swapper CCVVSSWWAAPP IIVVSSWWAAPP SSVVSSWWAAPP
Wait for Block I/O to Complete CCVVBBLLKKIIOO IIVVBBLLKKIIOOSSVVBBLLKKIIOO
Wait for Gate to Open CCVVGGAATTEE IIVVGGAATTEE SSVVGGAATTEE
Terminal Output CCVVTTTTOOUUTT IIVVTTTTOOUUTT SSVVTTTTOOUUTT
Wait for Free clists CCVVCCLLIISSTT IIVVCCLLIISSTT SSVVCCLLIISSTT
Process Trace CCVVPPTTSSEETT IIVVPPTTSSEETT SSVVPPTTSSEETT
Process Trace Stop CCVVPPTTRREETT IIVVPPTTRREETT SSVVPPTTRREETT
Waiting for a Pipe CCVVPPIIPPEE IIVVPPIIPPEE SSVVPPIIPPEE
Terminal Input CCVVTTTTIINN IIVVTTTTIINN SSVVTTTTIINN
Pause CCVVPPAAUUSSEE IIVVPPAAUUSSEE SSVVPPAAUUSSEE
Wait CCVVWWAAIITT IIVVWWAAIITT SSVVWWAAIITT
If _c_v is less than _C_V_N_O_S_I_G, then signals may abort the process without
returning from the sleep.
Please note the following caveats when using vv_sslleeeepp(). Disobeying these
rules can jeopardize the health of your system.
First, your driver can vv_sslleeeepp() while it waits for some condition to be
satisfied. However, the vv_sslleeeepp() may return prematurely; therefore, you
must place the call to vv_sslleeeepp() within a loop and check for the initial
condition to still be valid. Normally, a sleep is performed in the
following manner:
set interrupt priority to keep out the gremlins
while (work is not yet completed)
v_sleep( &some_variable_in_the_kernel_data_area, ... )
restore interrupt mask
The interrupt routine will, in turn, call wwaakkeeuupp() or defer wakeup for
later background processing if time is not an issue. This will cause the
aforementioned code to return from the call to vv_sslleeeepp().
As you can see, there is an inherent race condition between the wwhhiillee and
vv_sslleeeepp(). If the work is serviced while the driver is vv_sslleeeepp()ing, the
wwhhiillee loop will work correctly. However, should the last interrupt happen
after the wwhhiillee but before the vv_sslleeeepp(), the driver will deadlock -- it
will, in effect, be waiting for Godot.
vv_sslleeeepp() returns for various reasons, but you cannot always depend on it
to return for reasons other than a process calling wwaakkeeuupp() on the variable
that your driver fell asleep on. So, if your driver is waiting for
something to happen based upon an interrupt, be sure to bracket the call to
vv_sslleeeepp() with calls to the kernel routines sspphhii() and ssppll().
_S_e_e _A_l_s_o
aacccceessssiibbllee kkeerrnneell rroouuttiinneess, sspphhii(), ssppll(), wwaakkeeuupp()
_N_o_t_e_s
Please note the following warnings:
-> Do not call vv_sslleeeepp(), either directly or indirectly, from the block
routine of a driver.
-> Do not call vv_sslleeeepp(), either directly or indirectly, from with an
interrupt handler. When the interrupt occurs, the driver does not
know which process was running at the time, so it does not whose _u
_a_r_e_a it will be sleeping on. Thus, calling vv_sslleeeepp() from within an
interrupt handler will deadlock your driver.
-> Calling vv_sslleeeepp() from the load routine of a driver linked to the
kernel will cause a panic.
-> Always check for signals while sleeping. Failure to do so will result
in user processes which cannot be terminated due to an uncooperative
device driver. For example, the following code fragment can be used
in a blocking driver _x_xooppeenn() routine to allow the user to break out
of a sleep by hitting the interrupt character on the keyboard.
if (SELF->p_ssig && nondsig()) { /* received a signal? */
u.u_error = EINTR; /* indicate that we were interrupted */
return; /* return to user process */
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.