Museum

Home

Lab Overview

Retrotechnology Articles

⇒ Online Manual

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

gettid(2)

spin_trylock(2)

server_block(2)

client_block(2)

assert(3X)

resched_cntl(2)  —  CX/UX

NAME

resched_cntl, resched_nlocks, resched_lock, resched_unlock − rescheduling control

SYNOPSIS

#include <sys/types.h>
#include <sys/time.h>
#include <sys/thread_synch.h>

int resched_cntl (cmd, arg)
int cmd;
char ∗arg;

int resched_nlocks (r)
struct resched_var ∗r;

void resched_lock (r)
struct resched_var ∗r;

void resched_unlock (r)
struct resched_var ∗r;

DESCRIPTION

Multi-thread, real-time applications frequently wish to defer CPU rescheduling for brief periods of time.  For example, to use busy-wait mutual exclusion effectively (see spin_trylock(2)), spinlock hold times should be small and predictable.  CPU rescheduling is a source of unpredictability.  A thread would like to make itself immune to rescheduling when it acquires a spinlock, and vulnerable again when it releases the lock.  A system call could raise the caller’s priority to the highest in the system, but the overhead of doing so is prohibitive.  The primitives described here provide low overhead control of CPU rescheduling and signal delivery. 

A "rescheduling variable" is a data structure,

struct resched_var {
pid_t rv_pid;
tid_t rv_tid;
...
};

defined in <sys/thread_synch.h>, that controls a single thread’s vulnerability to rescheduling.  It is allocated on a per-thread basis by the application, not by the kernel.  The resched_cntl system call informs the kernel of the location of the variable, and the kernel examines the variable before making rescheduling decisions.  Direct manipulation of the variable from user mode with the resched_lock and resched_unlock macros disables and re-enables rescheduling.  For convenience, a rescheduling variable also contains the owning thread’s thread ID and process ID. 

The resched_cntl system call performs different functions depending on the value of cmd:

­RESCHED_SET_VARIABLE This command informs the kernel of the location of the caller’s rescheduling variable.  If arg is not NULL, the struct resched_var it points to is initialized and locked into physical memory.  If arg is NULL, the caller is disassociated from any existing variable, and the appropriate pages are unlocked.  No two threads should use the same rescheduling variable.  After a fork(2), the child process does NOT inherit a rescheduling variable from its parent.  Use of this command requires ACC_SETPRI privilege, unless the caller is the super-user. 

­RESCHED_GET_VARIABLE This command returns the location of the caller’s rescheduling variable.  Arg must point to a rescheduling variable pointer.  The pointer referenced by arg is set to NULL if the caller has no rescheduling variable, and is set to the location of the rescheduling variable otherwise. 

­RESCHED_SET_LIMIT This command is a debugging tool.  If arg is not NULL, it points to a struct timeval specifying the maximum length of time the caller expects to defer rescheduling.  The SIGRESCHED signal is sent to the caller when this limit is exceeded.  The signal’s default action is to terminate the thread, but it may also be ignored or caught.  If arg is NULL any previous limit is forgotten. 

­RESCHED_SERVE This command is used by resched_unlock to service pending signals and context switches.  Applications should not need to use this command directly.  Arg must be 0. 

­RESCHED_YIELD This command causes the calling process to relinquish control of the CPU to other equal-priority processes.  If there are no other processes of equal priority, the calling process retains control of the CPU.  Arg must be 0. 

The resched_nlocks macro returns the number of rescheduling locks currently in effect. 

The resched_lock macro increments the number of rescheduling locks held by the calling thread.  As long as the thread does not enter the kernel, quantum expirations, preemptions, and some signal deliveries are deferred until all rescheduling locks are released.  However, if the thread generates an exception (e.g., a page fault) or makes a system call, it may receive signals or otherwise context switch regardless of the number of rescheduling locks it holds.  The following signals represent error conditions and are NOT affected by rescheduling locks: SIGILL, SIGTRAP, SIGFPE, SIGKILL, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGXCPU, SIGXFSZ, and SIGRESCHED. 

The resched_unlock macro decrements the number of rescheduling locks held by the calling thread.  If there are no outstanding locks after the decrement, and a context switch or signal are pending, they are serviced immediately.  No checks are made to prevent the number of rescheduling locks from becoming negative, which will happen if more resched_unlock requests are made than resched_lock requests.  Applications concerned about this possibility should use resched_nlocks to make the appropriate assertions. 

EXAMPLES

A rescheduling variable may be declared as a global variable.  After initialization with resched_cntl, resched_lock and resched_unlock disable and re-enable rescheduling. 

01 struct resched_var rv;
02
03 void
04 main ()
05 {
06resched_cntl (RESCHED_SET_VARIABLE, &rv);
07
08resched_lock (&rv);
09
10/∗ non-preemptible code ∗/
11...
12
13assert (resched_nlocks (&rv) > 0);
14resched_unlock (&rv);
15 }

The assertion in line 13 may be a useful debugging tool. 

RETURN VALUE

Resched_lock and resched_unlock do not return values.  Resched_nlocks returns the number of rescheduling locks currently in effect.  Upon successful completion of resched_cntl, 0 is returned.  Otherwise, a value of −1 is returned and errno is set to indicate the error. 

ERRORS

resched_cntl will fail if any of the following are true:

­[EINVAL] Cmd was not one of the values documented above. 

­[EINVAL] An attempt was made to establish a rescheduling variable when one already existed. 

­[EINVAL] An attempt was made to remove a rescheduling variable when none existed. 

­[EINVAL] The struct timeval pointed to by arg was invalid. 

­[EFAULT] Arg contains an invalid address. 

SEE ALSO

CX/UX Programmer’s Guide. 
gettid(2), spin_trylock(2), server_block(2), client_block(2), assert(3X). 

CX/UX Programmer’s Reference Manual

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026