%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%									%
%	Copyright (C) 1992, 1993, 1994 Michael K. Johnson,		%
%	johnsonm@SunSITE.unc.edu					%
%									%
%	This file is freely copyable, but you must preserve this	%
%	copyright notice on all copies, it must only be distributed	%
%	as part of the Linux Kernel Hackers' Guide, and its use is	%
%	is subject to the conditions expressed in the copyright for	%
%	the whole guide, in the file prelim/copyright.tex		%
%									%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\section{Supporting Functions}\label{sec-dev-funcs}

Here is a list of many of the most common supporting functions
available to the device driver writer.  If you find other supporting
functions that are useful, please point them out to me.  I know this
is not a complete list, but I hope it is a helpful one.

\begin{dispitems}
\item[{\tt add\_request()}]\begin{verbatim}
static void add_request(struct blk_dev_struct *dev,
                        struct request * req)\end{verbatim}

This is a static function in ll\_rw\_block.c, and cannot be called by
other code.  However, an understanding of this function, as well as an
understanding of {\tt ll\_rw\_block()}, may help you understand the
strategy routine.

If the device that the request is for has an empty request queue, the
request is put on the queue and the strategy routine is called.
Otherwise, the proper place in the queue is chosen and the request is
inserted in the queue, maintaining proper order by insertion sort.

Proper order (the elevator algorithm) is defined as:
\begin{description}
\item[a.] Reads come before writes.
\item[b.] Lower minor numbers come before higher minor numbers.
\item[c.] Lower block numbers come before higher block numbers.
\end{description}
The elevator algorithm is implemented by the macro {\tt IN\_ORDER()},
which is defined in drivers/block/blk.h

{\bf Defined in:} drivers/block/ll\_rw\_block.c\\
{\bf See also:} {\tt make\_request()}, {\tt ll\_rw\_block()}.





\item [{\tt add\_timer()}]
{\tt void add\_timer(struct timer\_list * timer)}

{\tt \#include <linux/timer.h>}

Installs the timer structures in the list {\tt timer} in the timer
list.

The {\tt timer\_list} structure is defined by:
\begin{screen}\begin{verbatim}
struct timer_list {
        struct timer_list *next;
        struct timer_list *prev;
        unsigned long expires;
        unsigned long data;
        void (*function)(unsigned long);
};
\end{verbatim}\end{screen}

In order to call {\tt add\_timer()}, you need to allocate a {\tt
timer\_list} structure, and then call {\tt init\_timer()}, passing it a pointer
to your {\tt timer\_list}.  It will nullify the {\tt next} and {\tt
prev} elements, which is the correct initialization.  If necessary,
you can allocate multiple {\tt timer\_list} structures, and link them
into a list.  Do make sure that you properly initialize all the unused
pointers to {\tt NULL}, or the timer code may get very confused.

For each struct in your list, you set three variables:

\begin{dispitems}
\item [{\tt expires}] The number of jiffies (100ths of a second in
Linux/86) after which to time out.
\item [{\tt function}] Kernel-space function to run after timeout has occured.
\item [{\tt data}] Passed as the argument to {\tt function} when {\tt
function} is called.
\end{dispitems}

Having created this list, you give a pointer to the first (usually the
only) element of the list as the argument to {\tt add\_timer()}.
Having passed that pointer, keep a copy of the pointer handy, because
you will need to use it to modify the elements of the list (to set a
new timeout when you need a function called again, to change the
function to be called, or to change the data that is passed to the
function) and to delete the timer, if necessary.

{\bf Note:} This is {\em not} process-specific.  Therefore, if you
want to wake a certain process at a timeout, you will have to use
the sleep and wake primitives.  The functions that you install through
this mechanism will run in the same context that interrupt handlers
run in.

{\bf Defined in:} kernel/sched.c\\
{\bf See also:} {\tt timer\_table} in include/linux/timer.h, {\tt
init\_timer()}, {\tt del\_timer()}.





\item [{\tt cli()}]
{\tt \#define cli() \_\_asm\_\_ \_\_volatile\_\_ ("cli"::)}

{\tt \#include <asm/system.h>}

Prevents interrupts from being acknowledged.  {\tt cli} stands for
``CLear Interrupt enable''.

{\bf See also:} {\tt sti()}






\item [{\tt del\_timer}]
{\tt void del\_timer(struct timer\_list * timer)}

{\tt \#include <linux/timer.h>}

Deletes the timer structures in the list {\tt timer} in the timer
list.

The timer list that you delete must be the address of a timer
list you have earlier installed with {\tt add\_timer()}.  Once you
have called {\tt del\_timer()} to delete the timer from the kernel
timer list, you may deallocate the memory used in the {\tt
timer\_list} structures, as it is no longer referenced by the kernel
timer list.

{\bf Defined in:} kernel/sched.c\\
{\bf See also:} {\tt timer\_table} in include/linux/timer.h, {\tt
init\_timer()}, {\tt add\_timer()}.





\item[{\tt end\_request()}]
{\tt static void end\_request(int uptodate)}\\

{\tt \#include "blk.h"}

Called when a request has been satisfied or aborted.  Takes one
argument:
\begin{dispitems}
\item [{\tt uptodate}]
If not equal to 0, means that the request has been satisfied.\\
If equal to 0, means that the request has not been satisfied.
\end{dispitems}

If the request was satisfied ({\tt uptodate != 0}), {\tt
end\_request()} maintains the request list, unlocks the buffer, and
may arrange for the scheduler to be run at the next convenient time
({\tt need\_resched = 1}; this is implicit in {\tt wake\_up()}, and is
not explicitly part of {\tt end\_request()}), before waking up all
processes sleeping on the {\tt wait\_for\_request} event, which is
slept on in {\tt make\_request()}, {\tt ll\_rw\_page()}, and {\tt
ll\_rw\_swap\_file()}.

{\bf Note:} This function is a static function, defined in
drivers/block/blk.h for every non-SCSI device that includes blk.h.
(SCSI devices do this differently; the high-level SCSI code itself
provides this functionality to the low-level device-specific SCSI
device drivers.)
It includes several defines dependent on static device information,
such as the device number.  This is marginally faster than a more
generic normal C function.

{\bf Defined in:} kernel/blk\_drv/blk.h\\
{\bf See also:} {\tt ll\_rw\_block()}, {\tt add\_request()}, {\tt
make\_request()}.







\item [{\tt free\_irq()}]
{\tt void free\_irq(unsigned int irq)}

{\tt \#include <linux/sched.h>}

Frees an irq previously aquired with {\tt request\_irq()} or {\tt
irqaction()}.  Takes one argument:
\begin{dispitems}
\item [{\tt irq}] interrupt level to free.
\end{dispitems}

{\bf Defined in:} kernel/irq.c\\
{\bf See also:} {\tt request\_irq()}, {\tt irqaction()}.







\item [{\tt get\_user*()}]
{\tt inline unsigned char get\_user\_byte(const char * addr)}\\
{\tt inline unsigned short get\_user\_word(const short * addr)}\\
{\tt inline unsigned long get\_user\_long(const int *addr)}

{\tt \#include <asm/segment.h>}

Allows a driver to access data in user space, which is in a different
segment than the kernel.

\blackdiamond {\bf Note:} these functions may cause implicit I/O, if
the memory being accessed has been swapped out, and therefore
pre-emption may occur at this point.  Do not include these functions
in critical sections of your code even if the critical sections are
protected by {\tt cli()}/{\tt sti()} pairs, because that implicit I/O
will violate the integrity of your {\tt cli()}/{\tt sti()} pair.  If
you need to get at user-space memory, copy it to kernel-space memory
{\em before} you enter your critical section.

These functions take one argument:
\begin{dispitems}
\item [{\tt addr}] Address to get data from.
\end{dispitems}
\begin{dispitems}
\item [{\bf Returns:}] Data at that offset in user space.
\end{dispitems}

{\bf Defined in:} include/asm/segment.h\\
{\bf See also:} {\tt memcpy\_*fs()}, {\tt put\_user*()}, {\tt cli()},
{\tt sti()}.





\item [{\tt inb(), inb\_p()}]
{\tt inline unsigned int inb(unsigned short port)}\\
{\tt inline unsigned int inb\_p(unsigned short port)}

{\tt \#include <asm/io.h>}

Reads a byte from a port.  {\tt inb()} goes as fast as it can, while
{\tt inb\_p()} pauses before returning.  Some devices are happier if
you don't read from them as fast as possible.  Both functions take one
argument:
\begin{dispitems}
\item [{\tt port}] Port to read byte from.
\end{dispitems}
\begin{dispitems}
\item [{\bf Returns:}] The byte is returned in the low byte of the
32-bit integer, and the 3 high bytes are unused, and may be garbage.
\end{dispitems}

{\bf Defined in:} include/asm/io.h\\
{\bf See also:} {\tt outb()}, {\tt outb\_p()}.





\item [{\tt init\_timer()}]

Inline function for initializing {\tt timer\_list} structures for use
with {\tt add\_timer()}.

{\bf Defined in:} include/linux/timer.h\\
{\bf See also:} {\tt add\_timer()}.





\item [{\tt irqaction()}]
{\tt int irqaction(unsigned int irq, struct sigaction *new)}

{\tt \#include <linux/sched.h>}

Hardware interrupts are really a lot like signals.  Therefore, it
makes sense to be able to register an interrupt like a signal.  The
{\tt sa\_restorer()} field of the {\tt struct sigaction} is not used,
but otherwise it is the same.  The int argument to the {\tt
sa.handler()} function may mean different things, depending on whether
or not the IRQ is installed with the {\tt SA\_INTERRUPT} flag.  If it
is not installed with the {\tt SA\_INTERRUPT} flag, then the argument
passed to the handler is a pointer to a register structure, and if it
is installed with the {\tt SA\_INTERRUPT} flag, then the argument
passed is the number of the IRQ.  For an example of handler set to use
the {\tt SA\_INTERRUPT} flag, look at how {\tt rs\_interrupt()} is
installed in \dots/kernel/chr\_drv/serial.c

The {\tt SA\_INTERRUPT} flag is used to determine whether or not the
interrupt should be a ``fast'' interrupt.  Normally, upon return from the
interrupt, {\tt need\_resched}, a global flag, is checked.  If it is
set ($\not= 0$), then {\tt schedule()} is run, which may schedule
another process to run.  They are also run with all other interrupts
still enabled.  However, by setting the {\tt sigaction} structure
member {\tt sa\_flags} to {\tt SA\_INTERRUPT}, ``fast'' interrupts are
chosen, which leave out some processing, and very specifically do not
call {\tt schedule()}.

{\tt irqaction()} takes two arguments:
\begin{dispitems}
\item [{\tt irq}] The number of the IRQ the driver wishes to acquire.
\item [{\tt new}] A pointer to a sigaction struct.
\item [{\bf Returns:}] {\tt -EBUSY} if the interrupt has already been
acquired,\\
{\tt -EINVAL} if {\tt sa.handler()} is NULL,\\
0 on success.
\end{dispitems}

{\bf Defined in:} kernel/irq.c\\
{\bf See also:} {\tt request\_irq(), free\_irq()}






\item[{\tt IS\_*(inode)}]
{\tt IS\_RDONLY(inode) ((inode)->i\_flags \& MS\_RDONLY)}\\
{\tt IS\_NOSUID(inode) ((inode)->i\_flags \& MS\_NOSUID)}\\
{\tt IS\_NODEV(inode) ((inode)->i\_flags \& MS\_NODEV)}\\
{\tt IS\_NOEXEC(inode) ((inode)->i\_flags \& MS\_NOEXEC)}\\
{\tt IS\_SYNC(inode) ((inode)->i\_flags \& MS\_SYNC)}

{\tt \#include <linux/fs.h>}

These five test to see if the inode is on a filesystem mounted the
corresponding flag.







\item [{\tt kfree*()}]
{\tt \#define kfree(x) kfree\_s((x), 0)}\\
{\tt void kfree\_s(void * obj, int size)}

{\tt \#include <linux/malloc.h>}

Free memory previously allocated with {\tt kmalloc()}.  There are two
possible arguments:
\begin{dispitems}
\item [{\tt obj}] Pointer to kernel memory to free.
\item [{\tt size}] To speed this up, if you know the size, use {\tt
kfree\_s()} and provide the correct size.  This way, the kernel memory
allocator knows which bucket cache the object belongs to, and doesn't
have to search all of the buckets.  (For more details on this
terminology, read mm/kmalloc.c.)
\end{dispitems}

{\bf Defined in:} mm/kmalloc.c, include/linux/malloc.h\\
{\bf See also:} {\tt kmalloc()}.





\item [{\tt kmalloc()}]
{\tt void * kmalloc(unsigned int len, int priority)}

{\tt \#include <linux/kernel.h>}

{\tt kmalloc()} used to be limited to 4096 bytes.  It is now limited
to 131056 bytes ($(32*4096)-16$).  Buckets, which used to be all exact
powers of 2, are now a power of 2 minus some small number, except for
numbers less than or equal to 128.  For more details, see the
implementation in mm/kmalloc.c.

{\tt kmalloc()} takes two arguments:
\begin{dispitems}
\item [{\tt len}] Length of memory to allocate.  If the maximum is
exceeded, kmalloc will log an error message of ``{\tt kmalloc of too large
a block (\%d bytes).}'' and return {\tt NULL}.
\item [{\tt priority}] {\tt GFP\_KERNEL} or {\tt GFP\_ATOMIC}.  If {\tt
GFP\_KERNEL} is chosen, {\tt kmalloc()} may sleep, allowing
pre-emption to occur.  This is the normal
way of calling {\tt kmalloc()}.  However, there are cases where it is
better to return immediately if no pages are available, without
attempting to sleep to find one.  One of the places in which this is
true is in the swapping code, because it could cause race conditions,
and another in the networking code, where things can happen at much
faster speed that things could be handled by swapping to disk to make
space for giving the networking code more memory.  The most important
reason for using {\tt GFP\_ATOMIC} is if it is being called from an
interrupt, when you cannot sleep, and cannot receive other interrupts.

\item [{\bf Returns:}] {\tt NULL} on failure.\\
Pointer to allocated memory on success.
\end{dispitems}

{\bf Defined in:} mm/kmalloc.c\\
{\bf See also:} {\tt kfree()}





\item[{\tt ll\_rw\_block()}]
{\tt void ll\_rw\_block(int rw, int nr, struct buffer\_head *bh[])}

{\tt \#include <linux/fs.h>}

No device driver will ever call this code: it is called only through
the buffer cache.  However, an understanding of this function may help
you understand the function of the strategy routine.

After sanity checking, if there are no pending requests on the
device's request queue, {\tt ll\_rw\_block()} ``plugs'' the queue so
that the requests don't go out until all the requests are in the
queue, sorted by the elevator algorithm.  {\tt make\_request()} is
then called for each request.  If the queue had to be plugged, then
the strategy routine for that device is not active, and it is called,
{\bf with interrupts disabled.  It is the responsibility of the
strategy routine to re-enable interrupts.}

{\bf Defined in:} devices/block/ll\_rw\_block.c\\
{\bf See also:} {\tt make\_request()}, {\tt add\_request()}.







\item [{\tt MAJOR()}]
{\tt \#define MAJOR(a) (((unsigned)(a))>>8)}

{\tt \#include <linux/fs.h>}

This takes a 16 bit device number and gives the associated major
number by shifting off the minor number.

{\bf See also:} {\tt MINOR()}.







\item[{\tt make\_request()}]
{\tt static void make\_request(int major, int rw, struct buffer\_head *bh)}

This is a static function in ll\_rw\_block.c, and cannot be called by
other code.  However, an understanding of this function, as well as an
understanding of {\tt ll\_rw\_block()}, may help you understand the
strategy routine.

{\tt make\_request()} first checks to see if the request is readahead
or writeahead and the buffer is locked.  If so, it simply ignores the
request and returns.  Otherwise, it locks the buffer and, except for
SCSI devices, checks to make sure that write requests don't fill the
queue, as read requests should take precedence.

If no spaces are available in the queue, and the request is neither
readahead nor writeahead, {\tt make\_request()} sleeps on the event
{\tt wait\_for\_request}, and tries again when woken.  When a space in
the queue is found, the request information is filled in and {\tt
add\_request()} is called to actually add the request to the queue.

{\bf Defined in:} devices/block/ll\_rw\_block.c\\
{\bf See also:} {\tt add\_request()}, {\tt ll\_rw\_block()}.







\item [{\tt MINOR()}]
{\tt \#define MINOR(a) ((a)\&0xff)}

{\tt \#include <linux/fs.h>}

This takes a 16 bit device number and gives the associated minor
number by masking off the major number.

{\bf See also:} {\tt MAJOR()}.





\item [{\tt memcpy\_*fs()}]\begin{verbatim}
inline void memcpy_tofs(void * to, const void * from,
                        unsigned long n)
inline void memcpy_fromfs(void * to, const void * from,
                          unsigned long n)\end{verbatim}

{\tt \#include <asm/segment.h>}

Copies memory between user space and kernel space in chunks larger
than one byte, word, or long.  Be very careful to get the order of the
arguments right!

\blackdiamond {\bf Note:} these functions may cause implicit I/O, if
the memory being accessed has been swapped out, and therefore
pre-emption may occur at this point.  Do not include these functions
in critical sections of your code, even if the critical sections are
protected by {\tt cli()}/{\tt sti()} pairs, because implicit I/O will
violate the {\tt cli()} protection.  If you need to get at user-space
memory, copy it to kernel-space memory {\em before} you enter your
critical section.

These functions take three arguments:
\begin{dispitems}
\item [{\tt to}] Address to copy data to.
\item [{\tt from}] Address to copy data from.
\item [{\tt n}] Number of bytes to copy.
\end{dispitems}

{\bf Defined in:} include/asm/segment.h\\
{\bf See also:} {\tt get\_user*()}, {\tt put\_user*()}, {\tt cli()},
{\tt sti()}.






\item [{\tt outb(), outb\_p()}]
{\tt inline void outb(char value, unsigned short port)}\\
{\tt inline void outb\_p(char value, unsigned short port)}

{\tt \#include <asm/io.h>}

Writes a byte to a port.  {\tt outb()} goes as fast as it can, while
{\tt outb\_p()} pauses before returning.  Some devices are happier if
you don't write to them as fast as possible.  Both functions take two
arguments:
\begin{dispitems}
\item [{\tt value}] The byte to write.
\item [{\tt port}] Port to write byte to.
\end{dispitems}

{\bf Defined in:} include/asm/io.h\\
{\bf See also:} {\tt inb()}, {\tt inb\_p()}.







\item[{\tt printk()}]
{\tt int printk(const char* fmt, ...)}

{\tt \#include <linux/kernel.h>}

{\tt printk()} is a version of {\tt printf()} for the kernel, with
some restrictions.  It cannot handle floats, and has a few other
limitations, which are documented in kernel/vsprintf.c.  It
takes a variable number of arguments:
\begin{dispitems}
\item [{\tt fmt}] Format string, {\tt printf()} style.
\item [{\tt ...}] The rest of the arguments, {\tt printf()} style.
\end{dispitems}
\begin{dispitems}
\item [{\bf Returns:}] Number of bytes written.

{\bf Note:} \blackdiamond {\tt printk()} may cause implicit I/O, if
the memory being accessed has been swapped out, and therefore
pre-emption may occur at this point.  Also, {\tt printk()} will set
the interrupt enable flag, so {\bf never use it in code protected by
{\tt cli()}.}  Because it causes I/O, it is not safe to use in
protected code anyway, even it if didn't set the interrupt enable flag.

\end{dispitems}

{\bf Defined in:} kernel/printk.c.





\item [{\tt put\_user*()}]
{\tt inline void put\_user\_byte(char val, char *addr)}\\
{\tt inline void put\_user\_word(short val, short *addr)}\\
{\tt inline void put\_user\_long(unsigned long val, unsigned long *addr)}

{\tt \#include <asm/segment.h>}

Allows a driver to write data in user space, which is in a different
segment than the kernel.  When entering the kernel through a system
call, a selector for the current user space segment is put in the fs
segment register, thus the names.

\blackdiamond {\bf Note:} these functions may cause implicit I/O, if
the memory being accessed has been swapped out, and therefore
pre-emption may occur at this point.  Do not include these functions
in critical sections of your code even if the critical sections are
protected by {\tt cli()}/{\tt sti()} pairs, because that implicit I/O
will violate the integrity of your {\tt cli()}/{\tt sti()} pair.  If
you need to get at user-space memory, copy it to kernel-space memory
{\em before} you enter your critical section.

These functions take two arguments:
\begin{dispitems}
\item [{\tt val}] Value to write
\item [{\tt addr}] Address to write data to.
\end{dispitems}

{\bf Defined in:} asm/segment.h\\
{\bf See also:} {\tt memcpy\_*fs()}, {\tt get\_user*()}, {\tt cli()},
{\tt sti()}.






\item [{\tt register\_*dev()}]
\begin{verbatim}
int register_chrdev(unsigned int major, const char *name,
                    struct file_operations *fops)
int register_blkdev(unsigned int major, const char *name,
                    struct file_operations *fops)
\end{verbatim}

{\tt \#include <linux/fs.h>}\\
{\tt \#include <linux/errno.h>}

Registers a device with the kernel, letting the kernel check to make
sure that no other driver has already grabbed the same major number.
Takes three arguments:
\begin{dispitems}
\item [{\tt major}] Major number of device being registered.
\item [{\tt name}] Unique string identifying driver.  Used in the
output for the /proc/devices file.
\item [{\tt fops}] Pointer to a {\tt file\_operations} structure for
that device.  This must {\bf not} be {\tt NULL}, or the kernel will
panic later.
\end{dispitems}
\begin{dispitems}
\item [{\bf Returns:}] {\tt -EINVAL} if major is $\ge$ {\tt MAX\_CHRDEV} or
{\tt MAX\_BLKDEV} (defined in {\tt <linux/fs.h>}), for character or
block devices, respectively.\\
{\tt -EBUSY} if major device number has already been allocated.\\
0 on success.
\end{dispitems}

{\bf Defined in:} fs/devices.c\\
{\bf See also:} {\tt unregister\_*dev()}






\item [{\tt request\_irq()}]
\begin{verbatim}
int request_irq(unsigned int irq, void (*handler)(int),
                unsigned long flags, const char *device)
\end{verbatim}
{\tt \#include <linux/sched.h>}\\
{\tt \#include <linux/errno.h>}

Request an IRQ from the kernel, and install an IRQ interrupt handler
if successful.  Takes four arguments:
\begin{dispitems}
\item [{\tt irq}] The IRQ being requested.
\item [{\tt handler}] The handler to be called when the IRQ occurs.
The argument to the handler function will be the number of the IRQ
that it was invoked to handle.
\item [{\tt flags}] Set to {\tt SA\_INTERRUPT} to request a ``fast''
interrupt or 0 to request a normal, ``slow'' one. 
\item [{\tt device}] A string containing the name of the device
driver, {\sl device}.
\end{dispitems}
\begin{dispitems}
\item [{\bf Returns:}] {\tt -EINVAL} if {\tt irq} $>$ 15 or {\tt
handler} $=$ {\tt NULL}.\\
{\tt -EBUSY} if {\tt irq} is already allocated.\\
0 on success.
\end{dispitems}

If you need more functionality in your interrupt handling, use the
{\tt irqaction()} function.  This uses most of the capabilities of the
{\tt sigaction} structure to provide interrupt services similar to to
the signal services provided by {\tt sigaction()} to user-level
programs.

{\bf Defined in:} kernel/irq.c\\
{\bf See also:} {\tt free\_irq()}, {\tt irqaction()}.





\item [{\tt select\_wait()}]
\begin{verbatim}
inline void select_wait(struct wait_queue **wait_address,
                        select_table *p)\end{verbatim}

{\tt \#include <linux/sched.h>}

Add a process to the proper {\tt select\_wait} queue.  This function
takes two arguments:
\begin{dispitems}
\item [{\tt wait\_address}] Address of a {\tt wait\_queue} pointer to
add to the circular list of waits.
\item [{\tt p}] If {\tt p} is {\tt NULL}, {\tt select\_wait} does
nothing, otherwise the current process is put to sleep.  This should
be the {\tt select\_table *wait} variable that was passed to your {\tt
select()} function.
\end{dispitems}

{\bf Defined in:} linux/sched.h\\
{\bf See also:} {\tt *sleep\_on(), wake\_up*()}






\item[{\tt *sleep\_on()}]
{\tt void sleep\_on(struct wait\_queue ** p)}\\
{\tt void interruptible\_sleep\_on(struct wait\_queue ** p)}

{\tt \#include <linux/sched.h>}

Sleep on an event, putting a {\tt wait\_queue} entry in the list so
that the process can be woken on that event.  {\tt sleep\_on()} goes
into an uninteruptible sleep:  The only way the process can run is to
be woken by {\tt wake\_up()}.  {\tt interruptible\_sleep\_on()} goes
into an interruptible sleep that can be woken by signals and process
timeouts will cause the process to wake up.  A call to {\tt
wake\_up\_interruptible()} is necessary to wake up the process and
allow it to continue running where it left off.  Both take one
argument:
\begin{dispitems}
\item [{\tt p}] Pointer to a proper {\tt wait\_queue} structure
that records the information needed to wake the process.
\end{dispitems}

{\bf Defined in:} kernel/sched.c\\
{\bf See also:} {\tt select\_wait()}, {\tt wake\_up*()}.





\item [{\tt sti()}]
{\tt \#define sti() \_\_asm\_\_ \_\_volatile\_\_ ("sti"::)}

{\tt \#include <asm/system.h>}

Allows interrupts to be acknowledged.  {\tt sti} stands for
``SeT Interrupt enable''.

{\bf Defined in:} asm/system.h\\
{\bf See also:} {\tt cli()}.





\item[{\tt sys\_get*()}]
{\tt int sys\_getpid(void)}\\
{\tt int sys\_getuid(void)}\\
{\tt int sys\_getgid(void)}\\
{\tt int sys\_geteuid(void)}\\
{\tt int sys\_getegid(void)}\\
{\tt int sys\_getppid(void)}\\
{\tt int sys\_getpgrp(void)}

These system calls may be used to get the information described in the
table below, or the information can be extracted directly from the
process table, like this:\\
{\tt {\sl foo} = current->{\sl pid};}\\
\begin{tabular}{|r|l|}\hline
 {\tt pid} & Process ID\\\hline
 {\tt uid} & User ID\\\hline
 {\tt gid} & Group ID\\\hline
{\tt euid} & Effective user ID\\\hline
{\tt egid} & Effective group ID\\\hline
{\tt ppid} & Process ID of process' parent process\\\hline
{\tt pgid} & Group ID of process' parent process\\\hline
\end{tabular}

The system calls should not be used because they are slower {\em and}
take more space.  Because of this, they are no longer exported as
symbols throughout the whole kernel.

{\bf Defined in:} kernel/sched.c\\







\item [{\tt unregister\_*dev()}]
\begin{verbatim}
int unregister_chrdev(unsigned int major, const char *name)
int unregister_blkdev(unsigned int major, const char *name)
\end{verbatim}

{\tt \#include <linux/fs.h>}\\
{\tt \#include <linux/errno.h>}

Removes the registration for a device device with the kernel, letting
the kernel give the major number to some other device.
Takes two arguments:
\begin{dispitems}
\item [{\tt major}] Major number of device being registered.
Must be the same number given to {\tt register\_*dev()}.
\item [{\tt name}] Unique string identifying driver.
Must be the same number given to {\tt register\_*dev()}.
\end{dispitems}
\begin{dispitems}
\item [{\bf Returns:}] {\tt -EINVAL} if major is $\ge$ {\tt MAX\_CHRDEV} or
{\tt MAX\_BLKDEV} (defined in {\tt <linux/fs.h>}), for character or
block devices, respectively, or if there have not been file operations
registered for major device {\tt major}, or if {\tt name} is not the
same name that the device was registered with.\\
0 on success.
\end{dispitems}

{\bf Defined in:} fs/devices.c\\
{\bf See also:} {\tt register\_*dev()}






\item [{\tt wake\_up*()}]
{\tt void wake\_up(struct wait\_queue ** p)}\\
{\tt void wake\_up\_interruptible(struct wait\_queue ** p)}

{\tt \#include <linux/sched.h>}

Wakes up a process that has been put to sleep by the matching {\tt
*sleep\_on()} function.  {\tt wake\_up()} can be used to wake up tasks
in a queue where the tasks may be in a {\tt TASK\_INTERRUPTIBLE} or
{\tt TASK\_UNINTERRUPTIBLE} state, while {\tt
wake\_up\_interruptible()} will only wake up tasks in a {\tt
TASK\_INTERRUPTIBLE} state, and will be insignificantly faster than
{\tt wake\_up()} on queues that have only interruptible tasks.  These
take one argument:
\begin{dispitems}
\item [{\tt q}] Pointer to the {\tt wait\_queue} structure of the
process to be woken.
\end{dispitems}

Note that {\tt wake\_up()} does not switch tasks, it only makes
processes that are woken up runnable, so that the next time {\tt
schedule()} is called, they will be candidates to run.

{\bf Defined in:} kernel/sched.c\\
{\bf See also:} {\tt select\_wait()}, {\tt *sleep\_on()}

\end{dispitems}
