diff -Nru /sys/man/9/0intro /sys/man/9/0intro --- /sys/man/9/0intro Thu Jan 1 00:00:00 1970 +++ /sys/man/9/0intro Sat Jan 5 00:00:00 2013 @@ -0,0 +1,53 @@ +.TH INTRO 9 +.SH NAME +intro \- introduction to kernel functions +.SH DESCRIPTION +This section of the manual +describes the functions publicly available to the authors of +kernel code, particularly device drivers (real and virtual). +This section will eventually be much expanded, but this makes a start. +.PP +The +.SM SYNOPSIS +subsections do not show the header files needed for +the standard kernel declarations. +The primary combinations summarised below: +.IP +.RS +.ta \w'\fL#include 'u +.nf +.B +#include "u.h" +.B +#include "../port/lib.h" +.B +#include "mem.h" +.B +#include "dat.h" +.B +#include "fns.h" +.B +#include "../port/error.h" +.PP +.I "furthermore, added in IP code:" +.br +.B +#include "../ip/ip.h" +.PP +.I "furthermore, in hardware device drivers:" +.br +.B +#include "io.h" +.br +.B +#include "ureg.h" +.PP +.I "furthermore, in network interfaces or ether drivers:" +.B +#include "../port/netif.h" +.fi +.RE +.PP +There might also be specific include files needed by +drivers on particular platforms or to use specialised kernel interfaces. +The easiest method is to check the source of likely-looking drivers nearby. diff -Nru /sys/man/9/NOTICE /sys/man/9/NOTICE --- /sys/man/9/NOTICE Thu Jan 1 00:00:00 1970 +++ /sys/man/9/NOTICE Sat Jan 5 00:00:00 2013 @@ -0,0 +1,2 @@ +Copyright © 1996-2005 Lucent Technologies Inc. +Portions Copyright © 1999-2005 Vita Nuova Limited diff -Nru /sys/man/9/allocb /sys/man/9/allocb --- /sys/man/9/allocb Thu Jan 1 00:00:00 1970 +++ /sys/man/9/allocb Sat Jan 5 00:00:00 2013 @@ -0,0 +1,312 @@ +.TH ALLOCB 9 +.SH NAME +allocb, iallocb, freeb, freeblist, BLEN, blocklen, concatblock, copyblock, trimblock, packblock, padblock, pullblock, pullupblock, adjustblock, checkb \- data block management +.SH SYNOPSIS +.ta \w'\fLBlock* 'u +.B +Block* allocb(int size) +.PP +.B +Block* iallocb(int size) +.PP +.B +void freeb(Block *b) +.PP +.B +void freeblist(Block *b) +.PP +.B +long BLEN(Block *b) +.PP +.B +int blocklen(Block *b) +.PP +.B +Block* concatblock(Block *b) +.PP +.B +Block* copyblock(Block *b, int n) +.PP +.B +Block* trimblock(Block *b, int offset, int n) +.PP +.B +Block* packblock(Block *b) +.PP +.B +Block* padblock(Block *b, int n) +.PP +.B +int pullblock(Block **bph, int n) +.PP +.B +Block* pullupblock(Block *b, int n) +.PP +.B +Block* adjustblock(Block *b, int n) +.PP +.B +void checkb(Block *b, char *msg) +.SH DESCRIPTION +A +.B Block +provides a receptacle for data: +.IP +.EX +.DT +typedef +struct Block +{ + Block* next; + Block* list; + uchar* rp; /* first unconsumed byte */ + uchar* wp; /* first empty byte */ + uchar* lim; /* 1 past the end of the buffer */ + uchar* base; /* start of the buffer */ + void (*free)(Block*); + ulong flag; +} Block; +.EE +.PP +Each +.B Block +has an associated buffer, located at +.BR base , +and accessed via +.B wp +when filling the buffer, or +.B rp +when fetching data from it. +Each pointer should be incremented to reflect the amount of data written or read. +A +.B Block +is empty when +.B rp +reaches +.BR wp . +The pointer +.B lim +bounds the allocated space. +Some operations described below accept lists of +.BR Block s, +which are +chained via their +.B next +pointers, with a null pointer ending the list. +.B Blocks +are usually intended for a +.B Queue +(see +.IR qio (9)), +but can be used independently. +.PP +A +.B Block +and its buffer are normally allocated by one call to +.IR malloc (9) +and aligned on an 8 byte (\fLBY2V\fP) boundary. +Some devices with particular allocation constraints +(eg, requiring certain addresses for DMA) might allocate their own +.B Block +and buffer; +.B free +must then point to a function that can deallocate the specially allocated +.BR Block . +.PP +Many +.B Block +operations cannot be used in interrupt handlers +because they either +.IR sleep (9) +or raise an +.IR error (9). +Of operations that allocate blocks, only +.IR iallocb +is usable. +.PP +.I Allocb +allocates a +.B Block +of at least +.IR size +bytes. +The block +is initially empty: +.B rp +and +.B wp +point to the start of the data. +If it cannot allocate memory, +.I allocb +raises an +.IR error (9); +it cannot be used by an interrupt handler. +.PP +.IR Iallocb +is similar to +.IR allocb +but is intended for use by interrupt handlers, +and returns a null pointer if no memory is available. +It also limits its allocation to a quota allocated at system initialisation to interrupt-time buffering. +.PP +.I Freeb +frees a single +.B Block +(and its buffer). +.PP +.I Freeblist +frees the whole +list of blocks headed by +.IR b . +.PP +.I BLEN +returns the number of unread bytes in a single block +.IR b ; +it is implemented as a macro. +.PP +.I Blocklen +returns the number of bytes of unread data in the whole list of blocks headed by +.IR b . +.PP +.I Concatblock +returns +.I b +if it is not a list, and otherwise +returns a single +.B Block +containing all the data in the list of blocks +.IR b , +which it frees. +.PP +.I Copyblock +by contrast returns a single +.B Block +containing a copy of the first +.I n +bytes of data in the block list +.IR b , +padding with zeroes if the list contained less than +.I n +bytes. +The list +.I b +is unchanged. +.PP +.I Padblock +can pad a single +.B Block +at either end, to reserve space for protocol headers or trailers. +If +.IR n ≥ 0 , +it inserts +.I n +bytes at the start of the block, +setting the read pointer +.B rp +to point to the new space. +If +.IR n < 0 , +it adds +.I n +bytes at the end of the block, +leaving the write pointer +.B wp +pointing at the new space. +In both cases, it allocates a new +.B Block +if necessary, freeing the old, and +it always returns a pointer to the resulting +.BR Block . +.PP +.I Trimblock +trims the list +.I b +to contain no more than +.I n +bytes starting at +.I offset +bytes into the data of the original list. +It returns a new list, freeing unneeded parts of the old. +If no data remains, it returns a null pointer. +.PP +.I Packblock +examines each +.B Block +in the list +.IR b , +reallocating any block in the list that has four times more available space than actual data. +It returns a pointer to the revised list. +.PP +.I Pullblock +discards up to +.I n +bytes from the start of the list headed by +.BI * bph \f1.\f0 +Unneeded blocks are freed. +.I Pullblock +sets +.BI * bph +to point to the new list head +and returns the number of bytes discarded (which might be less than +.IR n ). +It is used by transport protocols to discard ack'd data at +the head of a retransmission queue. +.PP +.I Pullupblock +rearranges the data in the list of blocks +.I b +to ensure that there are at least +.I n +bytes of contiguous data in the first block, +and returns a pointer to the new list head. +It frees any blocks that it empties. +It returns a null pointer if there is not enough data in the list. +.PP +.I Adjustblock +ensures that the block +.I b +has at least +.I n +bytes of data, reallocating or padding with zero if necessary. +It returns a pointer to the new +.BR Block . +(If +.I n +is negative, it frees the block and returns a null pointer.) +.PP +.I Checkb +does some consistency checking of +the state of +.IR b ; +a +.IR panic (9) +results if things look grim. +It is intended for internal use by the queue I/O routines (see +.IR qio (9)) +but could be used elsewhere. +.PP +The only functions that can be called at interrupt level are +.IR iallocb , +.IR freeb , +.IR freeblist , +.IR BLEN , +.IR blocklen , +.IR trimblock +and +.IR pullupblock . +The others allocate memory and can potentially block. +.SH SOURCE +.B /sys/src/9/port/allocb.c +.SH DIAGNOSTICS +Many functions directly or indirectly can raise an +.IR error (9), +and callers must therefore provide for proper error recovery +as described therein to prevent memory leaks and other bugs. +Except for +.IR iallocb , +any functions that allocate new blocks or lists +are unsuitable for use by interrupt handlers. +.IR Iallocb +returns a null pointer when it runs out of memory. +.SH SEE ALSO +.IR qio (9) diff -Nru /sys/man/9/conf /sys/man/9/conf --- /sys/man/9/conf Thu Jan 1 00:00:00 1970 +++ /sys/man/9/conf Sat Jan 5 00:00:00 2013 @@ -0,0 +1,340 @@ +.TH CONF 9 +.SH NAME +conf \- native and hosted kernel configuration file +.SH DESCRIPTION +Plan 9 kernels are built for a given target +.I platform +using platform-specific code in directory +.BI /sys/src/9/ platform +and portable code in +.BR /sys/src/9/port , +.B /sys/src/9/ip +and elsewhere. +Existing +.I platforms +include +.B alphapc +for the DEC Alpha, +.B iPAQ +for the Compaq iPAQ, +.B pc +for the Intel x86, +and +.B ppc +for the IBM/Motorola PowerPC. +Each +.I platform +can have several different kernels with different configurations. +A given configuration is built in the platform's directory using the +.IR mk (1) +command: +.IP +.EX +mk 'CONF=\fIconf\fP' +.EE +.PP +where +.I conf +is a text file that specifies drivers, protocols and other parameters for that +particular kernel: +a parts list. +The result of a successful +.I mk +is +an executable or bootable file with a name determined by the +.IR platform 's +.BR mkfile , +typically +.BI 9 conf. +.PP +A kernel configuration file has several sections of the form +.IP +.EX +.I "label" +.IR " item" " [ " "subitem ..." " ]" +\& ... +.EE +.PP +Each section begins with a +.I label +at the start of a line, which names a configuration +category, followed by +a list of each +.I item +to select from that category, +one line per item, with white space (ie, blank or tab) at the start of the line. +An +.I item +line can optionally list one or more +.I subitems +that must be included in the kernel to support it. +A line that starts with a +.L # +is a comment. +Empty lines are ignored. +.PP +.I Labels +are chosen from the following set, listed in the order +in which they conventionally appear in a configuration file: +.TF etherxx +.TP +.B dev +Device drivers +.TP +.B ip +IP protocols (native kernels only) taken from +.B ../ip +.TP +.B link +Hardware-specific parts of device drivers. +.TP +.B misc +Architecture-specific files; specific VGA and SCSI interfaces +.TP +.B lib +Libraries to link with the kernel +.TP +.B port +C code and declarations to include as-is in the generated configuration file +.TP +.B boot +Configuration for +.IR boot (8) +.TP +.B bootdir +List of files and directories to put in the +.B boot +directory of +.IR root (3). +.PD +.PP +When an +.I item +is listed +under a given +.I label +it causes a corresponding component to be included in the kernel. +The details depend on the +.IR label , +as discussed below. +Each +.I subitem +represents a kernel subcomponent required by the corresponding +.IR item . +Both items and subitems can be either portable (platform-independent) +or platform-specific. +The source file for a given item or subitem +is sought in the platform-directory +(for platform-specific code), and +in directories +.BR ../port +and +.BR ../ip , +under control of the platform's +.BR mkfile +and +.B ../port/portmkfile +(which is included by +.BR mkfile ). +Resulting object files are left in the +.I platform +directory. +.PP +Outside the +.B dev +section, +each item and subitem +.I x +causes the kernel image to include the code compiled from +.IB x .c , +(or +.IB x .s +for assembly-language support), +or +.IB portdir / x .c , +where +.I portdir +is one of the portable directories mentioned above. +In the +.B dev +section, an item +.I x +corresponds instead to the driver source file +.BI dev x .c +in the current (platform-specific) +directory or a portable driver +.IB portdir /dev x .c . +Subitems are handled as in any other section. +Typically they are auxiliary files that are needed by the associated driver. +.PP +For instance, in a native kernel +the portable driver for the +.B draw +device uses platform-specific code from +.BR screen.c . +That can be represented as follows: +.IP +.EX +dev + draw screen +.EE +.PP +Each item +.I x +in the +.B ip +section +corresponds to a protocol implementation compiled from +.BI ../ip/ x .c . +Any subitems +are dealt with in the same way as in the +.B dev +section. +.PP +The +.B link +section provides a way for hardware-specific +parts of drivers to link at runtime to the hardware-invariant part of a device +drivers. +For each item +.IR x , +the kernel will call the function +.IB x link +during its initialisation. +Typically that function makes itself known to the device driver by +calling a function provided by that driver, +passing the address of a interface-specific data structure or linkage table. +For example, +.B ethersmc +is an interface-specific component: +.IP +.EX +link + \fR...\fP + ethersmc +.EE +.PP +and its source file +.B ethersmc.c +provides a function +.B ethersmclink +that +calls +.B addethercard +in the interface-invariant part of the driver, +.BR devether.c : +.IP +.EX +void +ethersmclink(void) +{ + addethercard("smc91cXX", reset); +} +.EE +.PP +The +.B boot +section configures +.IR boot (8), +the first user program run by the kernel. +Each line in the section names a possible boot method (see +.IR boot (8) +for the current list). +The first will be the default. +Also by default, +.B /boot +will run +.B /bin/termrc +from +.IR cpurc (8), +with +.B bootdisk +set to +.BR #S/sdC0/ . +To change the defaults, the line (or lines) containing a +.B boot +label can be given some options: +.RS +.TP +.B "boot cpu" +.br +The kernel is a cpu server: run +.B /bin/cpurc +not +.B /bin/termrc +(see +.IR cpurc (8)). +.TP +.BI "boot cpu boot " disk +Use +.I disk +as the default +.BR bootdisk . +.RE +.PP +The +.B lib +section lists the libraries to include when linking the kernel, +in an order that satisfies any dependencies amongst them. +Each item +.I x +corresponds to +.BI /$objtype/lib x .a , +a target-specific library +produced by compiling the C source code in +.BI /sys/src/lib item, +where +.B objtype +is set in the platform's +.B mkfile +to the target system's object type +(eg, +.BR 386 , +.BR power , +etc). +.PP +An item in the +.B bootdir +section +has one of the forms: +.IP +.EX +.I name +.I "source name" +.EE +.PP +where +.I name +and +.I source +are path names (often absolute path names). +The kernel's initial root file system (see +.IR root (3)) +will contain a file or directory with the given +.IR name . +The contents will come from the file +.I name +(which must exist) unless an explicit +.I source +file is given. +.PP +The +.B port +section usually contains initialisations for kernel-specific values. +The most common one is +.IP +.EX + int cpuserver = \fIn\fP; +.EE +.PP +where +.I n +is non-zero for cpu servers and file servers, and zero otherwise. +.SH FILES +.B /sys/src/9/port/mkdevc +.br +.B /sys/src/9/port/mkdevlist +.br +.B /sys/src/9/port/mkroot +.SH SEE ALSO +.IR mk (1) diff -Nru /sys/man/9/delay /sys/man/9/delay --- /sys/man/9/delay Thu Jan 1 00:00:00 1970 +++ /sys/man/9/delay Sat Jan 5 00:00:00 2013 @@ -0,0 +1,41 @@ +.TH DELAY 9 +.SH NAME +delay, microdelay, addclock0link \- small delays, clock interrupts +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +void delay(int n) +.PP +.B +void microdelay(int n) +.PP +.B +void addclock0link(void(*clockf)(void)) +.SH DESCRIPTION +.I Delay +busy waits for +.I n +milliseconds, forced to be at least one millisecond. +.PP +.I Microdelay +is similar, but busy waits for +.I n +microseconds. +.PP +For delays on the order of clock ticks, +.I tsleep +(see +.IR sleep (9)) +provides a better alternative to the busy waiting of these routines. +.PP +.I Addclock0link +adds +.I clockf +to a list of functions to be executed at each clock interrupt on +the first processor. +.SH SOURCE +.B /sys/src/9/port/portclock.c +.br +.B /sys/src/9/*/clock.c +.SH SEE ALSO +.IR sleep (9) diff -Nru /sys/man/9/devattach /sys/man/9/devattach --- /sys/man/9/devattach Thu Jan 1 00:00:00 1970 +++ /sys/man/9/devattach Sat Jan 5 00:00:00 2013 @@ -0,0 +1,699 @@ +.TH DEVATTACH 9 +.SH NAME +devattach, devclone, devdir, devgen, devwalk, devdirread, devstat, devopen, devbread, devbwrite, devcreate, devremove, devwstat, devreset, devinit, devshutdown, openmode \- common device driver support +.SH SYNOPSIS +.nf +.ta \w'\fLBlock* 'u +10n +.B +typedef int +.B +Devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) +.PP +.B +Chan* devattach(int tc, char *spec) +.PP +.B +Chan* devclone(Chan *c) +.PP +.B +void devdir(Chan *c, Qid qid, char *n, long length, +.B + char *user, long perm, Dir *dp) +.PP +.B +int devgen(Chan *c, char *name, Dirtab *tab, int ntab, +.B + int i, Dir *dp) +.PP +.B +Walkqid* devwalk(Chan *c, Chan *nc, char **name, int nname, +.B + Dirtab *tab, int ntab, Devgen *gen) +.PP +.B +void devstat(Chan *c, uchar *db, int n, Dirtab *tab, +.B + int ntab, Devgen *gen) +.PP +.B +long devdirread(Chan *c, char *d, long n, Dirtab *tab, +.B + int ntab, Devgen *gen) +.PP +.B +Chan* devopen(Chan *c, int omode, Dirtab *tab, +.B + int ntab, Devgen *gen) +.PP +.B +Block* devbread(Chan *c, long n, ulong offset) +.PP +.B +long devbwrite(Chan *c, Block *bp, ulong offset) +.PP +.B +void devcreate(Chan*, char*, int, ulong) +.PP +.B +void devremove(Chan*) +.PP +.B +void devwstat(Chan*, uchar*, int) +.PP +.B +void devreset(void) +.PP +.B +void devinit(void) +.PP +.B +void devshutdown(void) +.PP +.B +int openmode(ulong mode) +.SH DESCRIPTION +Device drivers call these functions to carry out essential tasks and default actions. +They do most of the name space management +for a driver that serves a simple name space +(eg, data and control files), +leaving the driver to concentrate on the device-specific details +of the I/O requests. +More complex drivers also make good use of them at the leaves +of their name space, and to help manage the +.B Chan +structures correctly. +.PP +A device has an associated +.IR type , +represented as a Unicode character (`rune') that identifies the device +inside and outside the kernel. +It appears as the value of the +.B type +field in the +.B Dir +resulting from a +.IR stat (2) +of any file provided by the device. +A device is named outside the kernel using +a path name starting with +.B # +followed by the device character +(eg, +.B c +in +.B #c +for the console). +Any subsequent characters before +the next '/' or end of string is the `device specifier', +interpreted solely by the device itself. +.PP +.I Devattach +returns a new channel representing +the root of the file tree +corresponding to device type +.IR tc , +with device specifier +.IR spec . +It is normally called by a driver's +.I attach +function (see +.IR dev (9)). +The +.B qid +for the new channel is +.BR "(Qid){0,0,QTDIR}" , +suitable for a root directory for many devices, but +a device driver is free to change it (provided the +.B QTDIR +bit remains in the +.BR Qid.type ). +.PP +.I Devclone +returns a new channel that is a copy of +.IR c . +An attempt to clone an open channel causes a +.IR panic (9). +.PP +The +.L Dir +structure is shown below: +.IP +.EX +typedef +struct Dir +{ + /* system-modified data */ + ushort type; /* server type */ + uint dev; /* server subtype */ + /* file data */ + Qid qid; /* unique id from server */ + ulong mode; /* permissions */ + ulong atime; /* last read time */ + ulong mtime; /* last write time */ + vlong length; /* file length */ + char *name; /* last element of path */ + char *uid; /* owner name */ + char *gid; /* group name */ + char *muid; /* last modifier name */ +} Dir; +.EE +.PP +This +.B Dir +structure corresponds directly to the Limbo +.B Dir +adt described in +.IR stat (2). +.PP +Given a channel and assorted other information, +.I devdir +initialises a Dir structure at +.IR dp . +.I Devdir +supplies the following data itself: +.RS +.TF length +.TP +.B atime +last access time (set to current time) +.TP +.B mtime +last modification time (set to kernel creation date) +.TP +.B gid +group name (set to +.IR eve (9)) +.TP +.B length +length in bytes (set to zero, which +is normal for most devices) +.RE +.PD +.PP +Note that +.I devdir +assigns the values of +.I name +and +.I user +directly to fields of +.BI * dp, +and consequently those values must remain valid until the last use of +.BI * dp. +(Sometimes that requires the use of an auxiliary buffer, such as +.BR up->genbuf .) +If channel +.I c +corresponds to a file descriptor on which Styx is served, +.I devdir +sets both the flag bit +.B QTMOUNT +in +.IB dp ->qid.type +and the flag bit +.B DMMOUNT +in +.IB dp ->mode +(see +.I export +in +.IR dial (2) +and +.I mount +in +.IR bind (2)). +.PP +A simple name space can be represented in a driver by an array of +.B Dirtab +structures. +The array is typically static when the names and permissions +are static, but can be dynamically allocated and initialised if required. +The structure of +.B Dirtab +is shown below: +.IP +.EX +typedef +struct Dirtab +{ + char name[KNAMELEN]; + Qid qid; + vlong length; + long perm; +} Dirtab; +.EE +.PP +The name +.RB ` . ' +.I must +appear as the first entry in a +.B Dirtab +if the default +.I devgen +function is used. +On the other hand, the name +.RB ` .. ' +must never appear in a +.B Dirtab +table. +Drivers that support a directory hierarchy must walk up the hierarchy towards +the root when their +.I walk +function receives +.RB ` .. ' +as a file name component. +The name +.RB ` . ' +is never seen by a driver. +.PP +The +.IR devdirread , +.IR devopen , +.IR devstat , +and +.IR devwalk +functions all take a +.I gen +function argument, +of type +.BR Devgen , +which they invoke to retrieve the items in +a +.B Chan +that represents a directory. +.I Gen +takes a channel +.I c +(a directory), +a file +.I name +(which is nil except during +.IR devwalk ), +an array of +.B Dirtab +structures +.I tab +of length +.IR ntab , +and a table index +.IR i . +The functions calling +.I gen +expect it to place the +.IR i 'th +entry in the directory into +.IR \f5*\fPdp . +It should return 1 +if the call was successful, +-1 if +.I i +is beyond the index of the last directory entry, +or 0 if there is no entry at +.IR i , +but there are entries beyond it. +When +.I i +has the special value +.B DEVDOTDOT +then +.I gen +should set +.IR \f5*\fPdp +to reflect the parent of +.IR c ; +if +.I c +is a one-level device directory, then `..' is equivalent to `.'. +Custom implementations of +.I gen +often ignore +.IR devtab , +and instead return their own dynamically generated +set of directory entries from some other source. +Exceptionally, during +.I devwalk +a non-nil +.I name +is provided: it is the name being looked up, and a device-specific +.I gen +can short-circuit the search by returning -1 if the name does not exist, +or filling in +.IR \f5*\fPdp +and returning 1 if it does exist. +.PP +The function +.I devgen +is compatible with +.BR Devgen ; +it returns the +.IR i 'th +entry in +.IR devtab , +and can be used to provide a simple, static +set of directory entries. +.PP +.I Devwalk +walks channel +.I c +to the file in the device named by the path encoded in +.IR name , +which is an array of strings of length +.IR nname . +It provides the interface to +.IR walk (5) +within the kernel, and that specification must be well understood to appreciate +all the nuances of its interface. +Fortunately, in nearly all device drivers, a device's +.I walk +function typically passes its parameters on to +.I devwalk +(adding the device's own +.B Dirtab +array as the the value of +.IR tab ), +and simply returning the result of +.IR devwalk . +.PP +.I Devwalk +walks +.I c +using the given set of names, and if the walk is successful, the +channel +.I nc +will refer to the result of the walk +(specifically, +.IB nc ->qid +is set to the Qid for the file). +If +.I nc +is nil, +.I devwalk +will allocate a new channel itself, that is initially a clone of +.IR c . +As in +.IR walk (5), +.I devwalk +can return a partial result, +represented by +a dynamically allocated value of the following structure: +.IP +.EX +struct Walkqid +{ + Chan *clone; + int nqid; + Qid qid[1]; /* actually nname in length */ +}; +.EE +.PP +The value must be freed after use. +For each element of +.I name , +.I devwalk +passes +the +.I tab +parameter to +.I gen +together with the currently-sought element of +.IR name . +If the first element is not found, +.I devwalk +returns nil; otherwise, it returns a +.B Walkqid +value in which +.B nqid +elements of the array +.B qid +are set to the qids (see +.IR intro (5)) +of each valid element of +.IR name . +If all +.I nname +elements were successfully traversed, then +.B nqid +will have the value +.IR nname , +and +.B clone +will refer to the result of the walk, +which is either +.I nc +if given, or +the new channel allocated by +.IR devwalk . +Otherwise, at least one element succeeded and +.B nqid +is less than +.I nname +and +.B clone +is nil. +On an error or incomplete walk, +the error string is set to the error that stopped the walk (eg, +.B Enonexist +or +.BR Enotdir ). +.PP +.I Devstat +fills the array of bytes +.I db +with data in the format produced by +.IR stat (5) +that describes the file +referenced by channel +.IR c , +which must have a corresponding entry +returned by +.IR gen +(ie, an entry with matching +.BR Qid.path ). +If +.I c +is a communications channel connecting a Styx server to a current mount point, +the +.B DMMOUNT +bit is set in the resulting +.BR Dir.mode , +and +.B QTMOUNT +is set in +.BR Dir.qid.type . +As in +.IR stat (5), +the length of the data written to +.I db +varies; if more than +.I n +bytes are needed, +.I devstat +raises the +.IR error (9) +.BR Ebadarg . +Otherwise, it returns the number of bytes in +.I db +actually used. +.PP +If an entry with the desired qid is not found in the table, but +.I c +corresponds to a directory +(ie, +.B QTDIR +is set in +.IR c\f5->qid.type\fP ), +it is taken to be a +.I stat +of a notional directory containing the files listed in +.IR tab . +.I Dirstat +then builds the corresponding Dir structure: +its +.B Dir.name +is taken from +.IR c\f5->path->elem\fP ; +the length is +.BI DIRLEN*nelem(tab) ; +and +.B Dir.perm +is 0555 (read-execute for all). +.PP +.I Devdirread +calls +.I gen +to obtain successive +.B Dir +structures representing entries in the open directory +.IR c . +These are converted to standard format (see +.I convD2M +in +.IR fcall (2)) +and placed in the buffer +.IR b . +It returns the number of bytes in the result. +At most +.I n +bytes will be returned, in multiples of +.BR DIRLEN . +Because the kernel maintains the current offset in +.IR c , +successive calls to +.I devdirread +return successive directory components. +.PP +.I Devopen +is called to check and complete a request to open channel +.I c +for I/O according to +.IR omode +(the open mode of +.IR open (2)). +It calls +.I gen +to obtain successive directory entries +which it searches +for a Qid matching that of +.IR c , +and ensures that the current user has permission to open +.I c +with the given mode, +.IR omode , +and that the mode itself is valid +(see +.I openmode +below). +Permission is checked against the permission in the +matching entry. +If no matching Qid is found, it is assumed +that the notional parent directory of the files represented in +.I tab +is to be opened. +Such a directory is deemed to have mode +0555, allowing access by any user. +A directory can only be opened for reading +.RB ( OREAD ). +.I Devopen +returns the channel +.I c +on success. +Last, it sets the bit +.B COPEN +in +.B Chan.flag +to mark +.I c +as open. +This convention can always be relied upon by the driver's +.I close +function to tell if an open succeeded. +On the otherhand, +if the open request was unsuccessful, +.I devopen +raises an appropriate +.IR error (9) +and does not return. +.PP +.I Devbread +returns a +.B Block +(see +.IR allocb (9)) +containing up to +.I n +bytes read, +using +.BI "devtab[" c "->type]->read" , +from +.I c +starting at the given +.IR offset . +The read pointer in the returned +.B Block +points to the start of the data; +the write pointer points to the next available byte. +.PP +.I Devbwrite +writes the data in +.B Block +.I bp +to the file +.I c +at the given +.IR offset , +using the write function +.BI "devtab[" c "->type]->write" . +It then frees the block list +.I bp +before +returning the number of bytes written. +.PP +Most built-in devices do not allow +.IR create , +.IR remove +or +.I wstat +on their files. +.IR Devcreate , +.I devremove +and +.I devwstat +are stubs that raise an +.IR error (9), +.BR Eperm . +They can be named directly in a device driver's device +switch (the +.B Dev +structure in +.BR /sys/src/9/port/portdat.h : +see +.IR dev (9)). +.PP +.IR Devreset , +.I devinit +and +.I devshutdown +are also stubs; +they do nothing. +A device driver puts them in its +.B Dev +structure when it need take no action on device reset, initialisation, or shut down. +.PP +.I Openmode +is used by a driver that does not use +.IR devopen , +to check the open mode it receives in its open +routine. +.I Openmode +returns mode +.IR o , +the mode parameter to +.IR open (2) +or +.IR sys-create , +shorn of +.BR OTRUNC +and similar options, +and reduced to one of +.BR OREAD , +.BR OWRITE +or +.BR ORDWR . +In particular, +.B OEXEC +becomes +.B OREAD +within the kernel. +.I Openmode +raises an +.IR error (9) +.B Ebadarg +instead of returning, if +.I o +is an invalid mode (eg, reserved bits set). +.SH SOURCE +.B /sys/src/9/port/dev.c +.SH SEE ALSO +.IR allocb (9), +.IR eve (9), +.IR qio (9) diff -Nru /sys/man/9/dmainit /sys/man/9/dmainit --- /sys/man/9/dmainit Thu Jan 1 00:00:00 1970 +++ /sys/man/9/dmainit Sat Jan 5 00:00:00 2013 @@ -0,0 +1,86 @@ +.TH DMAINIT 9 +.SH NAME +dmainit, dmasetup, dmadone, dmaend, dmacount \- platform-specific DMA support +.SH SYNOPSIS +.ta \w'\fLushort 'u +.B +void dmainit(int chan) +.PP +.B +long dmasetup(int chan, void *va, long len, int isread) +.PP +.B +int dmadone(int chan) +.PP +.B +void dmaend(int chan) +.PP +.B +int dmacount(int chan) +.PP +.SH DESCRIPTION +These functions manage DMA on a bus that uses ISA-style DMA controllers. +They were originally devised for the x86 platform, but the same interface, and similar code, +is used by other platforms that use similar controllers. +They compensate as best they can for the limitations of older DMA implementations +(eg, alignment, boundary and length restrictions). +There are 8 DMA channels: +0 to 3 are byte-oriented; 4 to 7 are word-oriented (16-bit words). +.PP +.I Dmainit +must be called early in a driver's initialisation to prepare +.I chan +for use. +Amongst other things, it allocates a page-sized buffer to help circumvent hardware +restrictions on DMA addressing. +.PP +.I Dmasetup +prepares DMA channel +.IR chan +for a transfer between a device configured to use it +and the virtual address +.IR va . +(The transfer is started by issuing a command to the device.) +If +.I va +lies outside the kernel address space, +the transfer crosses a 64k boundary, +or exceeds the 16 Mbyte limit imposed by some DMA controllers, +the transfer will be split into page-sized transfers using the buffer previously allocated by +.IR dmainit . +If +.I isread +is true (non-zero), data is to be transferred from +.I chan +to +.IR va ; +if false, data is transferred from +.I va +to +.IR chan . +In all cases, +.I dmasetup +returns the number of bytes to be transferred. +That value (rather than +.IR len ) +must be given to the device in the read or write request that starts the transfer. +.PP +.I Dmadone +returns true (non-zero) if +.I chan +is idle. +.PP +.I Dmaend +must be called at the end of every DMA operation. +It disables +.IR chan , +preventing further access to the previously associated memory and, +if a low-memory buffer was required for input, transfers its contents +to the appropriate part of the target buffer. +.PP +.I Dmacount +returns the number of bytes that were last transferred by channel +.IR chan . +The count is always even for word-oriented DMA channels. +.SH SOURCE +.B /sys/src/9/pc/dma.c diff -Nru /sys/man/9/error /sys/man/9/error --- /sys/man/9/error Thu Jan 1 00:00:00 1970 +++ /sys/man/9/error Sat Jan 5 00:00:00 2013 @@ -0,0 +1,168 @@ +.TH ERROR 9 +.SH NAME +error, nexterror, poperror, waserror \- error handling functions +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +void error(char*) +.PP +.B +void nexterror(void) +.PP +.B +void poperror(void) +.PP +.B +int waserror(void) +.SH DESCRIPTION +The kernel handles error conditions using non-local gotos, +similar to +.IR setjmp (2), +but using a stack of error labels to implement nested exception handling. +This simplifies many of the internal interfaces by eliminating the need +for returning and checking error codes at every level of the call stack, +at the cost of requiring kernel routines to adhere to a strict discipline. +.PP +Each process has in its defining kernel +.B Proc +structure a stack of labels, +.B NERR +(currently 64) elements deep. +A kernel function that must perform a clean up or recovery action on an error +makes a stylised call to +.IR waserror , +.IR nexterror +and +.IR poperror : +.IP +.EX +.DT +if(waserror()){ + /* recovery action */ + nexterror(); +} +/* normal action */ +poperror(); +.EE +.PP +When called in the normal course of events, +.I waserror +registers an error handling block by pushing its label onto the stack, +and returns zero. +The return value of +.I waserror +should be tested as shown above. +If non-zero (true), the calling function should perform the needed +error recovery, ended by a call to +.I nexterror +to transfer control to the next location on the error stack. +Typical recovery actions include deallocating memory, unlocking resources, and +resetting state variables. +.PP +Within the recovery block, +after handling an error condition, there must normally +be a call to +.I nexterror +to transfer control to any error recovery lower down in the stack. +The main exception is in the outermost function in a process, +which must not call +.I nexterror +(there being nothing further on the stack), but calls +.I pexit +(see +.IR kproc (9)) +instead, +to terminate the process. +.PP +When the need to recover a particular resource has passed, +a function that has called +.I waserror +must +remove the corresponding label from the stack by calling +.IR poperror . +This +must +be done before returning from the function; otherwise, a subsequent call to +.I error +will return to an obsolete activation record, with unpredictable but unpleasant consequences. +.PP +.I Error +copies the given error message, which is limited to +.B ERRMAX +bytes, into the +.B Proc.error +of the current process, +enables interrupts by calling +.I spllo +.RI ( native +only), +and finally calls +.I nexterror +to start invoking the recovery procedures currently stacked by +.IR waserror . +The file +.B /sys/src/9/port/error.h +offer a wide selection of predefined error messages, suitable for almost any occasion. +The message set by the most recent call to +.I error +can be obtained within the kernel by examining +.B up->error +and in an application, by using the +.L %r +directive of +.IR print (2). +.PP +A complex function can have nested error handlers. +A +.I waserror +block will follow the acquisition of a resource, releasing it +on error before calling +.I nexterror, +and a +.I poperror +will precede its release in the normal case. +For example: +.IP +.EX +.DT +void +outer(Thing *t) +{ + qlock(t); + if(waserror()){ /* A */ + qunlock(t); + nexterror(); + } + m = mallocz(READSTR, 0); + if(m == nil) + error(Enomem); + if(waserror()){ /* B */ + free(m); + nexterror(); /* invokes A */ + } + inner(t); + poperror(); /* pops B */ + free(m); + poperror(); /* pops A */ + qunlock(t); +} +.sp 1v +void +inner(Thing *t) +{ + if(t->bad) + error(Egreg); /* error() call returns to B */ + t->valid++; +} +.EE +.SH SOURCE +.B /sys/src/9/port/proc.c +.SH CAVEATS +The description above has many instances of +.IR should , +.IR will , +.I must +and +.IR "must not" . +.SH SEE ALSO +.IR panic (9) diff -Nru /sys/man/9/eve /sys/man/9/eve --- /sys/man/9/eve Thu Jan 1 00:00:00 1970 +++ /sys/man/9/eve Sat Jan 5 00:00:00 2013 @@ -0,0 +1,46 @@ +.TH EVE 9 +.SH NAME +eve, iseve \- privileged user +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +char eve[NAMELEN] = "bootes"; +.PP +.B +int iseve(void) +.SH DESCRIPTION +.I Eve +is a null-terminated string containing the name of the owner of +the Plan 9 system (sometimes called the `host owner', +see +.IR cons (3)). +The identity is set on a terminal to the name of the user who logs in. +It is set on a CPU server to the +.I authid +obtained either from NVRAM or by a console prompt. +The initial process created by system initialisation is given the +.I eve +identity. +.PP +.I Iseve +returns true if the current user is +.IR eve . +Several drivers use +.I iseve +to check the caller's identity +before granting permission to perform certain actions. +For example, the console driver allows only the user +.I eve +to write a new identity into the +.B /dev/user +file. +The privileges are strictly local and do not extend into the network +(in particular, to file servers—even ones running on the local machine). +.SH SOURCE +.B /sys/src/9/port/auth.c +.SH SEE ALSO +.IR auth (2), +.IR cap (3), +.IR cons (3), +.IR authsrv (6), +.IR auth (8) diff -Nru /sys/man/9/inb /sys/man/9/inb --- /sys/man/9/inb Thu Jan 1 00:00:00 1970 +++ /sys/man/9/inb Sat Jan 5 00:00:00 2013 @@ -0,0 +1,83 @@ +.TH INB 9 +.SH NAME +inb, ins, inl, outb, outs, outl, insb, inss, insl, outsb, outss, outsl \- programmed I/O +.SH SYNOPSIS +.ta \w'\fLushort 'u +.B +int inb(int port) +.PP +.B +ushort ins(int port) +.PP +.B +ulong inl(int port) +.PP +.B +void outb(int port, int value) +.PP +.B +void outs(int port, ushort value) +.PP +.B +void outl(int port, ulong value) +.PP +.B +void insb(int port, void *address, int count) +.PP +.B +void inss(int port, void *address, int count) +.PP +.B +void insl(int port, void *address, int count) +.PP +.B +void outsb(int port, void *address, int count) +.PP +.B +void outss(int port, void *address, int count) +.PP +.B +void outsl(int port, void *address, int count) +.SH DESCRIPTION +The +.I x86 +implementation provides functions to allow kernel code +written in C to access the I/O address space. +On several other architectures such as the PowerPC and Strongarm, +the platform-dependent code provides similar functions to access +devices with an I/O space interface, even when that is memory mapped, to encourage portability of device drivers. +.PP +.IR Inb , +.I ins +and +.I inl +apply the corresponding hardware instruction to fetch the next byte, short or long +from the I/O +.IR port . +.IR Outb , +.I outs +and +.I outl +output a +.I value +to the I/O +.IR port . +.PP +The remaining functions transfer +.I count +bytes, shorts, or longs using programmed I/O between a memory +.I address +and +.IR port . +Functions +.BI ins x +copy values into memory; functions +.BI outs x +copy values from memory. +The +.I count +is in elements, not bytes. +.SH SOURCE +.B /sys/src/9/pc/l.s +.SH SEE ALSO +.IR dma (9) diff -Nru /sys/man/9/intrenable /sys/man/9/intrenable --- /sys/man/9/intrenable Thu Jan 1 00:00:00 1970 +++ /sys/man/9/intrenable Sat Jan 5 00:00:00 2013 @@ -0,0 +1,106 @@ +.TH INTRENABLE 9 +.SH NAME +intrenable, intrdisable \- enable (disable) an interrupt handler +.SH SYNOPSIS +.ta \w'\fLvoid* 'u +.B +void intrenable(int v, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) +.PP +.B +void intrdisable(int v, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) +.SH DESCRIPTION +.I Intrenable +registers +.I f +to be called by the kernel's interrupt controller driver each time +an interrupt denoted by +.I v +occurs, and unmasks the corresponding interrupt in the interrupt controller. +The encoding of +.I v +is platform-dependent; it is often an interrupt vector number, but +can be more complex. +.I Tbdf +is a platform-dependent value that might further qualify +.IR v . +It might for instance +denote the type of bus, bus instance, device number and function +(following the PCI device indexing scheme), hence its name, +but can have platform-dependent meaning. +.I Name +is a string that should uniquely identify the corresponding device (eg, \f5"uart0"\fP); +again it is usually platform-dependent. +.I Intrenable +supports sharing of interrupt levels when the hardware does. +.PP +Almost invariably +.I f +is a function defined in a device driver to carry out the device-specific work associated with a given interrupt. +The pointer +.I a +is passed to +.IR f ; +typically it points to the driver's data for a given device or controller. +It also passes +.I f +a +.B Ureg* +value that +contains the registers saved by the interrupt handler (the +contents are platform specific; +see the platform's include file +.BR "ureg.h" ). +.PP +.I F +is invoked by underlying code in the kernel that is invoked directly from the hardware vectors. +It is therefore not running in any process (see +.IR kproc (9); +indeed, on many platforms +the current process pointer +.RB ( up ) +will be nil. +There are many restrictions on kernel functions running outside a process, but a fundamental one is that +they must not +.IR sleep (9), +although they often call +.B wakeup +to signal the occurrence of an event associated with the interrupt. +.IR Qio (9) +and other manual pages note which functions are safe for +.I f +to call. +.PP +The interrupt controller driver does whatever is +required to acknowledge or dismiss the interrupt signal in the interrupt controller, +before calling +.IR f , +for edge-triggered interrupts, +and after calling +.I f +for level-triggered ones. +.I F +is responsible for deal with the cause of the interrupt in the device, including any +acknowledgement required in the device, before it returns. +.PP +.I Intrdisable +removes any registration previously made by +.I intrenable +with matching parameters, and if no other +interrupt is active on +.IR v , +it masks the interrupt in the controller. +Device drivers that are not dynamically configured tend to call +.I intrenable +during reset or initialisation (see +.IR dev (9)), +but can call it at any appropriate time, and +instead of calling +.I intrdisable +they can simply enable or disable interrupts in the device as required. +.SH SOURCE +.B /sys/src/9/*/trap.c +.SH SEE ALSO +.IR malloc (9), +.IR qio (9), +.IR sleep (9), +.IR splhi (9) diff -Nru /sys/man/9/kbdputc /sys/man/9/kbdputc --- /sys/man/9/kbdputc Thu Jan 1 00:00:00 1970 +++ /sys/man/9/kbdputc Sat Jan 5 00:00:00 2013 @@ -0,0 +1,52 @@ +.TH KBDPUTC 9 +.SH NAME +kbdputc, kbdq \- keyboard interface to \fIcons\fP(3) +.SH SYNOPSIS +.ta \w'\f5extern\ \ \f1'u +.B +.B +void kbdputc(Queue *q, int c) +.PP +.B +extern Queue *kbdq; +.SH DESCRIPTION +This is the internal interface between +.IR cons (3) +and the platform-dependent keyboard driver. +Before calling any of these functions, +the global variable +.B kbdq +must be initialised; +.IR cons (3) +does not initialise it. +This is usually done during system initialisation by the keyboard driver's +.I kbdinit +or +.I kbdenable +function , +as follows: +.IP +.EX +kbdq = qopen(4*1024, 0, 0, 0); +qnoblock(kbdq, 1); +.EE +.PP +.I Kbdputc +puts a Unicode character +.I c +(ie, a `rune') +on the given +.IR q , +as a sequence of bytes in UTF-8 encoding +(see +.IR utf (6)). +It is up to the platform's keyboard driver to map a physical keyboard character, +or a combination of them (for instance, following +.IR keyboard (6)) +to a given Unicode character. +.SH SOURCE +.B /sys/src/9/*/kbd*.c +.SH SEE ALSO +.IR cons (3), +.IR utf (6), +.IR qio (9) diff -Nru /sys/man/9/kproc /sys/man/9/kproc --- /sys/man/9/kproc Thu Jan 1 00:00:00 1970 +++ /sys/man/9/kproc Sat Jan 5 00:00:00 2013 @@ -0,0 +1,131 @@ +.TH KPROC 9 +.SH NAME +kproc, pexit, postnote \- kernel process creation, termination and interrupt +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +void kproc(char *name, void (*func)(void*), void *arg) +.PP +.B +void pexit(char *note, int freemem) +.PP +.B +void postnote(Proc *p, int dolock, char *n, int flag) +.SH DESCRIPTION +.I Kproc +creates a new kernel process +to run the function +.IR func , +which is invoked as +.BR "(*func)(arg)" . +The string +.I name +is copied into the +.B text +field of the +.B Proc +structure of the new process; this value is the name of the kproc in +the output of +.IR ps (1). +The process is made runnable; it +will run when selected by the scheduler +.IR sched (9). +The process is created with base and current priorities set to +.BR PriKproc . +It shares the kernel process group and thus name space. +.PP +A kernel process terminates only when it calls +.IR pexit , +thereby terminating itself. +There is no mechanism for one process to force the termination of another, +although it can send a software interrupt using +.IR postnote . +.I Note +is a null string on normal termination, or +the cause of +If +.I freemem +is non-zero, +any memory allocated by the process is discarded; +it should normally be non-zero for any process created +by +.IR kproc . +Use the following to terminate a kernel process normally: +.IP +.EX +pexit("", 1); +.EE +.PP +to terminate a kernel process normally. +.PP +.I Postnote +sends a software interrupt to process +.IR p , +causing it, if necessary, to wake from +.IR sleep (9) +or break out of a +.IR rendezvous (2), +with an +.IR error (9) +`interrupted'. +Up to +.B NNOTE +notes can be pending at once (currently 5); +if more than that arrive, the process is forced +out of +.I sleep +and +.IR rendezvous , +but the message itself is discarded. +.I Postnote +returns non-zero iff the note has been +delivered successfully. +If +.I dolock +is non-zero, +.I postnote +synchronises delivery of the note with the debugger +and other operations of +.IR proc (3). +.I Flag +is zero, or one of the following +.TP +.B NDebug +Print the note message on the user's standard error. +Furthermore, suspend the process in a +.B Broken +state, preserving its memory, for later debugging. +.TP +.B NExit +Deliver the note quietly. +.TP +.B NUser +The note comes from another process, not the system. +.PP +The kernel uses +.I postnote +to signal processes that commit grave faults, +and to implement the note and kill functions of +.IR proc (3). +A device driver should use +.I postnote +only to tell a service process, +previously started by the driver using +.I kproc , +that it should stop; +the note will cause that process to raise an +.IR error (9). +For example, a process started to read packets from a network device could +be stopped as follows when the interface is unbound: +.IP +.EX +postnote(readp, 1, "unbind", 0); +.EE +.PP +where +.I readp +points to the appropriate +.BR Proc . +The text of the message is typically irrelevant. +.SH SOURCE +.B /sys/src/9/port/proc.c diff -Nru /sys/man/9/lib /sys/man/9/lib --- /sys/man/9/lib Thu Jan 1 00:00:00 1970 +++ /sys/man/9/lib Sat Jan 5 00:00:00 2013 @@ -0,0 +1,161 @@ +.TH LIB 9 +.SH NAME +lib \- C library functions used by the kernel +.SH SYNOPSIS +.B +#include "../port/lib.h" +.SH DESCRIPTION +A small collection of functions from the normal Plan 9 C +library is used in the kernel. +Only a subset is made available by declarations in +.BR lib.h , +which must be included instead of the usual +.BR . +Here is a list of the manual pages, and the functions from them declared +by +.B lib.h +for kernel use: +.IR +.TP +.IR abs (2) +.br +.I abs +.TP +.IR atof (2) +.br +.IR atoi , +.IR strtol , +.IR strtoul , +.IR strtoll , +and +.I strtoull +.TP +.IR cleanname (2) +.br +.I cleanname +.TP +.IR encode (2) +.IR dec64 +and +.I encodefmt +.TP +.IR fmtinstall (2) +.br +.BR Fmt , +.IR fmtinstall , +.IR fmtprint +and +.IR fmtstrcpy +.TP +.IR getbe (2) +.IR getbe , +.IR putbe , +.IR getle , +and +.I putle +.TP +.IR getcallerpc (2) +.br +.I getcallerpc +.TP +.IR getfields (2) +.br +.I getfields +and +.I tokenize +(see also +.IR parsecmd (9)) +.TP +.IR quote (2) +.br +for +.IR quotefmtinstall +.TP +.IR print (2) +.br +.IR print , +.IR seprint , +.IR snprint , +.IR sprint , +.IR vseprint +and +.IR vsnprint , +.TP +.IR memory (2) +.br +.IR memccpy , +.IR memchr , +.IR memcmp , +.IR memmove +and +.IR memset +.TP +.IR rune (2) +.br +.IR chartorune , +.IR runetochar , +.IR runelen , +.IR utflen +and +.IR utfrune +.TP +.IR open (2) +.br +values +.BR OCEXEC , +.BR OEXCL , +.BR OEXEC , +.BR ORCLOSE , +.BR ORDWR , +.BR OREAD , +.BR OTRUNC +and +.BR OWRITE , +.TP +.IR stat (2) +.br +data structures +.BR Dir +and +.BR Qid , +and values +.B DMDIR +etc. +and +.B QTDIR +etc. +.TP +.IR strcat (2) +.br +.IR strcat , +.IR strchr , +.IR strcmp , +.IR strcpy , +.IR strecpy , +.IR strlen , +.IR strncat , +.IR strncmp , +.IR strncpy , +.IR strrchr +and +.IR strstr +.TP +.IR wait (2) +.br +data structure +.B Waitmsg +.PP +.B lib.h +also defines +.B ERRMAX +(the limit in bytes for error strings) +and +.B KNAMELEN +(fixed-length limit in bytes for device driver file names) +.PP +A few other libraries such as +.IR memdraw (2) +and +.IR mp (2) +are called by specialised kernel components and drivers but they use +the normal include file for each library. diff -Nru /sys/man/9/lock /sys/man/9/lock --- /sys/man/9/lock Thu Jan 1 00:00:00 1970 +++ /sys/man/9/lock Sat Jan 5 00:00:00 2013 @@ -0,0 +1,106 @@ +.TH LOCK 9 +.SH NAME +lock, canlock, ilock, iunlock, unlock \- spin locks +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +void lock(Lock *l) +.PP +.B +int canlock(Lock *l) +.PP +.B +void unlock(Lock *l) +.PP +.B +void ilock(Lock *l) +.PP +.B +void iunlock(Lock *l) +.SH DESCRIPTION +These primitives control access to shared +resources using spin locks. +They in turn are used to build higher-level synchronisation mechanisms +such as those described in +.IR sleep (9), +.IR qlock (9) +and +.IR qio (9). +They should be used only to protect short critical sections +that update shared data structures. +.PP +.I Lock +loops repeatedly attempting acquire the spin lock +.I l +until it succeeds. +.I Lock +should not be used to lock a structure shared with an interrupt handler +unless interrupts are disabled by +.IR splhi (9) +before attempting the lock; +it is better to use +.IR ilock , +below. +.PP +.I Canlock +is non-blocking. +Only one attempt is made for the lock. +It returns non-zero if the lock was successfully acquired; 0 otherwise. +.PP +.I Unlock +releases the lock +.IR l . +A lock must be unlocked only by the locking process. +.PP +When called by a process, the functions above temporarily boost its priority +to the highest priority, +.BR PriLock ; +its original priority is restored at the end of the critical section by +.IR unlock . +On a uniprocessor, if +.I l +is unavailable, +.I lock +can reschedule unless interrupts are disabled before entering +.I lock +or there is no current process (eg, when executing the scheduler). +.PP +.I Ilock +disables interrupts before attempting to acquire the lock. +It should be used to lock a resource shared between a process and an interrupt handler. +On a uniprocessor, disabling interrupts is sufficient to exclude an interrupt handler +from the critical section, +and on a multiprocessor the spin lock excludes an interrupt handler running on another processor. +.I Ilock +never reschedules the caller, nor must a caller allow itself to be rescheduled +(eg, by calling +.IR sleep (9)) +before releasing the lock. +.PP +.I Iunlock +releases a lock previously got by +.IR ilock . +.SH SOURCE +.B /sys/src/9/port/taslock.c +.br +.B /sys/src/9/*/l.s +.SH SEE ALSO +.IR qlock (9) +.SH DIAGNOSTICS +The lock functions +guard against the possibility of never acquiring the lock by capping the number of lock attempts. +If the limit is reached, a message of +the following form is written on the console: +.IP +.EX +lock loop on \fIlock-address\fP key \fIkey-value\fP pc \fIcaller-pc\fP held by pc \fIlock-pc\fP +.EE +.PP +Most lock loops represent deadlocks caused by failing to unlock a resource, +attempting to lock (eg, by recursive call) a resource already held by the process, +inconsistent locking and unlocking of nested resources, using a spin-lock +to guard code that reschedules, using +.I lock +not +.I ilock +to interlock with an interrupt routine, and similar blunders. diff -Nru /sys/man/9/malloc /sys/man/9/malloc --- /sys/man/9/malloc Thu Jan 1 00:00:00 1970 +++ /sys/man/9/malloc Sat Jan 5 00:00:00 2013 @@ -0,0 +1,193 @@ +.TH MALLOC 9 +.SH NAME +malloc, mallocz, smalloc, realloc, calloc, free, msize, setmalloctag, setrealloctag, getmalloctag, getrealloctag, malloctopoolblock \- kernel memory allocator +.SH SYNOPSIS +.ta \w'\fLvoid* 'u +.B +void* malloc(ulong size) +.PP +.B +void* mallocalign(ulong size, ulong align, long offset, ulong span) +.PP +.B +void* mallocz(ulong size, int clr) +.PP +.B +void* smalloc(ulong size) +.PP +.B +void* realloc(void *p, ulong size) +.PP +.B +void* calloc(ulong n, ulong szelem) +.PP +.B +void free(void *ptr) +.PP +.B +ulong msize(void *ptr) +.PP +.B +void setmalloctag(void *ptr, ulong tag) +.PP +.B +ulong getmalloctag(void *ptr) +.PP +.B +void setrealloctag(void *ptr, ulong tag) +.PP +.B +ulong getrealloctag(void *ptr) +.PP +.B +void* malloctopoolblock(void*) +.PP +.SH DESCRIPTION +These are kernel versions of the functions in +.IR malloc (2). +They allocate memory from the +.B mainmem +memory pool, +which is managed by +the allocator +.IR pool (2), +which in turn replenishes the pool as required by calling +.IR xalloc (9). +All but +.I smalloc +(which calls +.IR sleep (9)) +may safely be called by interrupt handlers. +.PP +.I Malloc +returns a pointer to a block of at least +.I size +bytes, initialised to zero. +The block is suitably aligned for storage of any type of object. +The call +.B malloc(0) +returns a valid pointer rather than null. +.I Mallocz +is similar, but only clears the memory if +.I clr +is non-zero. +.PP +.I Smalloc +returns a pointer to a block of +.I size +bytes, initialised to zero. +If the memory is not immediately available, +.I smalloc +retries every 100 milliseconds until the memory is acquired. +.PP +.I Mallocalign +allocates a block of at least +.I n +bytes of memory respecting alignment contraints. +If +.I align +is non-zero, +the returned pointer is aligned to be equal to +.I offset +modulo +.IR align . +If +.I span +is non-zero, +the +.I n +byte block allocated will not span a +.IR span -byte +boundary. +.PP +.I Realloc +changes the size of the block pointed to by +.I p +to +.I size +bytes, +if possible without moving the data, +and returns a pointer to the block. +The contents are unchanged up to the lesser of old and new sizes, +and any new space allocated is initialised to zero. +.I Realloc +takes on special meanings when one or both arguments are zero: +.TP +.B "realloc(0,\ size) +means +.LR malloc(size) ; +returns a pointer to the newly-allocated memory +.TP +.B "realloc(ptr,\ 0) +means +.LR free(ptr) ; +returns null +.TP +.B "realloc(0,\ 0) +no-op; returns null +.PD +.PP +.I Calloc +returns a pointer to a block of memory of at least +.I "n*szelem" +bytes, initialised to zero. +New code should use +.I mallocz +instead. +.PP +The argument to +.I free +is a pointer to a block of memory allocated by one of the routines above, which +is returned to the allocation pool, or a null pointer, which is ignored. +.PP +When a block is allocated, sometimes there is some extra unused space at the end. +.I Msize +grows the block to encompass this unused space and returns the new number +of bytes that may be used. +.PP +The memory allocator maintains two word-sized fields +associated with each block, the ``malloc tag'' and the ``realloc tag''. +By convention, the malloc tag is the PC that allocated the block, +and the realloc tag the PC that last reallocated the block. +These may be set or examined with +.IR setmalloctag , +.IR getmalloctag , +.IR setrealloctag , +and +.IR getrealloctag . +When allocating blocks directly with +.I malloc +and +.IR realloc , +these tags will be set properly. +If a custom allocator wrapper is used, +the allocator wrapper can set the tags +itself (usually by passing the result of +.IR getcallerpc (2) +to +.IR setmalloctag ) +to provide more useful information about +the source of allocation. +.PP +.I Malloctopoolblock +takes the address of a block returned by +.I malloc +and returns the address of the corresponding +block allocated by the +.IR pool (2) +routines. +.SH SOURCE +.B /sys/src/9/port/alloc.c +.SH DIAGNOSTICS +All functions except +.I smalloc +return a null pointer if space is unavailable. +If the allocated blocks have no malloc or realloc tags, +.I getmalloctag +and +.I getrealloctag +return +.BR ~0 . +.SH SEE ALSO +.IR pool (2), +.IR xalloc (9) diff -Nru /sys/man/9/newchan /sys/man/9/newchan --- /sys/man/9/newchan Thu Jan 1 00:00:00 1970 +++ /sys/man/9/newchan Sat Jan 5 00:00:00 2013 @@ -0,0 +1,225 @@ +.TH NEWCHAN 9 +.SH NAME +newchan, chanfree, cclose, eqqid, eqchan, isdir, fdtochan, namec \- channel operations +.SH SYNOPSIS +.ta \w'\fLChan* 'u +.B +Chan* newchan(void) +.PP +.B +void chanfree(Chan *c) +.PP +.B +int eqqid(Qid a, Qid b) +.PP +.B +int eqchan(Chan *a, Chan *b, int pathonly) +.PP +.B +void isdir(Chan *c) +.PP +.B +Chan* fdtochan(Fgrp *f, int fd, int mode, int chkmnt, int iref) +.PP +.B +Chan* namec(char *pathname, int amode, int omode, ulong perm) +.PP +.B +void cclose(Chan *c) +.SH DESCRIPTION +A value of type +.B Chan +represents a kernel channel for I/O and name space operations. +It has the following public structure: +.IP +.EX +typedef struct Chan{ + ushort type; /* driver name */ + ulong dev; /* instance number */ + ushort mode; /* open mode */ + ushort flag; /* COPEN set once opened */ + ulong offset; /* current file offset */ + Qid qid; /* unique id (path, vers) */ + Path* path; /* name by which it was accessed */ +.EE +.PP +.I Newchan +returns a pointer to a newly allocated channel (sleeping if necessary until memory is available). +Device drivers do not normally call +.IR newchan +directly, but instead allocate channels using either +.IR devattach , +when a process attaches to the device's root, +or +.IR devclone , +when an existing channel is cloned; +see +.IR devattach (9). +.PP +.I Chanfree +frees the channel structure +.I c +for reuse. +.PP +.I Eqqid +returns 1 if +.B Qid +values +.I a +and +.I b +are equal +(ie, +both their +.B path +and +.B vers +members are equal); +it returns 0 otherwise. +.PP +.I Eqchan +returns 1 if +.I a +and +.I b +have the same +.BR qid , +.BR type +and +.BR dev +members +(ie, they represent the same file); +it returns 0 otherwise. +If +.I pathonly +is non-zero, the comparison of the two +.B qid +members compares only their +.B path +values, +ignoring the version field +.BR vers . +.PP +.I Isdir +checks that a given channel +.I c +is a directory. +If so, it returns; +otherwise, it generates an +.IR error (9), +.BR Enotdir . +.PP +The +.B Fgrp +structure represents an array of open files, each +represented by a +.BR Chan , +indexed by integer file descriptors. +A given +.B Fgrp +can be shared between processes. +.PP +.I Fdtochan +returns a pointer to the +.B Chan +corresponding to file descriptor +.I fd +in file descriptor group +.I f +(almost invariably +.BR up->fgrp , +the file descriptor group for the current process). +If +.I mode +is a valid mode for +.IR open (2), +typically +.BR OREAD , +.B OWRITE +or +.BR ORDWR , +it must correspond to the mode with which +.I fd +was originally opened; if +.I mode +is +.BR -1 , +no check is made. +If +.I chkmnt +is non-zero, +.I c +must not be a channel in use by the mount driver +.IR mnt (3). +On successful return, if +.I iref +is non-zero, the channel's reference count has been incremented. +.I Fdtochan +calls +.IR error (9) +if it detects invalid uses, in particular an invalid file descriptor +.IR fd . +.PP +.I Namec +looks up a +.I pathname +in the current name space and returns a channel. +.I Amode +determines the mode of look up, and must be one of the constants below: +.TF Aaccess +.PD +.TP +.B Aaccess +Access file for information, as in the stat command or call. +.TP +.B Atodir +Access file as directory (the +.B QTDIR +bit of its +.B qid.type +must be set). +.TP +.B Aopen +Access for I/O. +.TP +.B Amount +Access directory to be mounted upon. +.TP +.B Acreate +File is to be created. +.PP +If +.I amode +is +.B Aopen +or +.BR Acreate , +.I omode +should be a mode suitable for +.IR open (2); +if +.BR Acreate , +.I perm +should be valid file permissions. +In all other cases, +.I omode +and +.I perm +can be zero. +.PP +.I Cclose +decrements the reference count on +.IR c ; +if no further references remain, it +calls the corresponding device's +.B Dev.close +to close the channel, and frees +.IR c . +.SH SOURCE +.B /sys/src/9/port/chan.c +.SH DIAGNOSTICS +Most functions call +.IR error (9) +on any sort of error. +.SH SEE ALSO +.IR ref (9) diff -Nru /sys/man/9/panic /sys/man/9/panic --- /sys/man/9/panic Thu Jan 1 00:00:00 1970 +++ /sys/man/9/panic Sat Jan 5 00:00:00 2013 @@ -0,0 +1,25 @@ +.TH PANIC 9 +.SH NAME +panic \- abandon hope +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +void panic(char *fmt, ...) +.SH DESCRIPTION +.I Panic +writes a message to the console and +causes the system to give up the ghost. +It enables interrupts, dumps the kernel stack, +and halts the current processor; +if more than one, others will gradually come to a halt. +Depending on configuration settings, the platform-dependent +.I exit +might reboot the system. +The format +.I fmt +and associated arguments are the same as those for +.IR print (9). +.I Panic +adds a prefix +.L "panic: " +and a trailing newline. diff -Nru /sys/man/9/parsecmd /sys/man/9/parsecmd --- /sys/man/9/parsecmd Thu Jan 1 00:00:00 1970 +++ /sys/man/9/parsecmd Sat Jan 5 00:00:00 2013 @@ -0,0 +1,107 @@ +.TH PARSECMD 9 +.SH NAME +parsecmd, cmderror, lookupcmd \- parse device commands +.SH SYNOPSIS +.ta \w'\fLCmdbuf* 'u +.B +Cmdbuf* parsecmd(char *a, int n) +.PP +.B +void cmderror(Cmdbuf *cb, char *s) +.PP +.B +Cmdtab* lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) +.SH DESCRIPTION +.I Parsecmd +is an interface to +.I tokenize +(see +.IR getfields (2)), +that safely parses a command, with blank-separated fields, as might be +written to a device's +.B ctl +file. +The buffer +.I a +and count +.I n +can be those passed to the driver's +.I write +function. +.I Parsecmd +converts the byte array (which might not be null-terminated) to a null-terminated string, +trimming any trailing new line, +before invoking +.I tokenize +to break the string into arguments, interpreting blank and tab as field separators +when they are not quoted +(in the style of +.IR rc (1)). +It returns a pointer to a dynamically-allocated +.B Cmdbuf +structure, +which holds a copy of the string as +modified by +.IR parsefields , +and the resulting fields; it is defined as follows: +.IP +.EX +.ta 6n +\w'char* 'u +typedef +struct Cmdbuf +{ + char buf[128]; + char *f[16]; + int nf; +} Cmdbuf; +.EE +.PP +The array +.B f +holds the field pointers; +.B nf +gives the number of fields. +.B Cmdbuf +is allocated by +.I smalloc +(see +.IR malloc (9)), +and the caller is responsible for freeing it using +.IR free . +.I Cmderror +prepends the given format with the original command, +then calls +.IR error (9). +.PP +Command strings may be turned into a (typically enumerated) +integer with +.IR lookupcmd . +The catchall +.L * +matches any text. Unrecognized commands, or commands +given an unacceptable number of arguments generate a +call to +.IR error . +The definition is as follows +.IP +.EX +.ta 6n +\w'char* 'u +struct Cmdtab +{ + int index; + char *cmd; + int narg; +}; +.EE +.PP +The integer +.B index +is the number returned on command match. +The string +.B cmd +is the command name, and +.B narg +is 0 (indicating a varadic function) or the +number of arguments. +.SH SOURCE +.B /sys/src/9/port/parse.c diff -Nru /sys/man/9/qio /sys/man/9/qio --- /sys/man/9/qio Thu Jan 1 00:00:00 1970 +++ /sys/man/9/qio Sat Jan 5 00:00:00 2013 @@ -0,0 +1,480 @@ +.TH QIO 9 +.SH NAME +qio: qget, qdiscard, qconsume, qpass, qproduce, qcopy, qopen, qbread, qread, qbwrite, qwrite, qiwrite, qfree, qclose, qhangup, qreopen, qlen, qwindow, qcanread, qsetlimit, qnoblock, qflush, qfull \- queued I/O for devices +.SH SYNOPSIS +.ta \w'\fLQueue* 'u +.B +Queue* qopen(int limit,int msg, void (*kick)(void*),void *arg) +.PP +.B +void qhangup(Queue *q, char *reason) +.PP +.B +void qclose(Queue *q) +.PP +.B +void qreopen(Queue *q) +.PP +.B +void qfree(Queue *q) +.PP +.B +long qbwrite(Queue *q, Block *b) +.PP +.B +long qwrite(Queue *q, void *buf, int len) +.PP +.B +int qpass(Queue *q, Block *b) +.PP +.B +int qpassnolim(Queue *q, Block *b) +.PP +.B +int qproduce(Queue *q, void *buf, int len) +.PP +.B +int qiwrite(Queue *q, void *buf, int len) +.PP +.B +Block* qbread(Queue *q, int len) +.PP +.B +long qread(Queue *q, void *buf, int len) +.PP +.B +Block* qcopy(Queue *q, int len, ulong offset) +.PP +.B +Block* qget(Queue *q) +.PP +.B +int qconsume(Queue *q, void *buf, int len) +.PP +.B +int qdiscard(Queue *q, int len) +.PP +.B +void qflush(Queue *q) +.PP +.B +int qlen(Queue *q) +.PP +.B +int qwindow(Queue *q) +.PP +.B +int qcanread(Queue *q) +.PP +.B +void qsetlimit(Queue *q, int limit) +.PP +.B +void qnoblock(Queue *q, int nonblock) +.PP +.B +int qfull(Queue *q) +.SH DESCRIPTION +This suite of functions provides serial data buffering for device drivers. +Data is stored in a +.B Queue +structure as a sequence of variable-sized +.BR Blocks ; +see +.IR allocb (9). +.PP +.I Qopen +initialises and returns a pointer to a new +.BR Queue , +configuring it according to the following parameters: +.TF limit +.PD +.TP +.I limit +Set the queue limit (high water mark) in bytes. +.TP +.I msg +Set message mode if non-zero; otherwise, stream mode (discussed below). +.TP +.I kick +Optional flow-control function called by +.I qbread +to restart writers, and by +.I qbwrite +(also +.IR qiwrite ) +to restart readers. +.TP +.I arg +Argument to pass to +.I kick +.PP +.I Qhangup +marks +.I q +as `hung up' +for the given +.IR reason +.RB ( Ehungup +by default). +Subsequent attempts to write to the queue raise an +.IR error (9). +.I Qhangup +does not flush the queue: subsequent read requests are +handled normally until the queue empties. +.I Qread +and the other functions then return their conventional values +for a hungup stream: 0, -1 or a null pointer, depending on the function. +After a few such attempts by any process, an +.IR error (9) +is raised (typically +.BR Ehungup ) +on each subsequent read. +.PP +If queued data is left unread, and not flushed by +.I qflush +or +.IR qclose , +the data will again be readable following a subsequent +.IR qreopen . +.PP +.I Qclose +also marks a given +.I q +as `hung up', +but removes and frees any queued data Blocks. +.I Qclose +ignores calls when +.I q +is null. +.PP +.I Qreopen +makes a closed or hung up queue available for use again. +The queue's data limit is reset to the +.I limit +value given when the queue was first created by +.IR qopen , +cancelling the effect of any previous call to +.IR qsetlimit . +.PP +.I Qfree +closes +.I q +with +.I qclose +and frees it. +The caller must ensure that no references remain; +these functions do not keep a reference count. +.SS "Flow control" +The queue I/O routines provide a flow control mechanism to coordinate producers and consumers. +Each queue has a limit on the number of bytes queued, its `high water mark', +initially set when the queue is created, but adjustable by +.IR qsetlimit , +below. +The low water mark is not set explicitly: +it is always half the current queue limit. +When the high water mark is exceeded, writes normally block until a reader drains the +queue below its low water mark; the writer is then allowed to proceed. +Conversely, readers normally block when the queue is empty, until a writer +arrives with data, or the queue is closed. +.PP +A queue can be given a +.I kick +function when the queue is created by +.IR qopen . +The function is invoked by +.IR qread +and +.IR qbread , +to prod an output routine when the queue falls below the low-water mark, and by +.IR qwrite , +.IR qbwrite +and +.IR qiwrite , +to notify a reader that a queue is no longer empty. +Because +.I kick +is called from the reading (or writing) process, or an interrupt handler, it +must not block. +.PP +Interrupt handlers must not +.IR sleep (9), +and are therefore restricted to using only the non-blocking functions described below. +.SS "Stream mode and message mode" +In stream mode, +no read will return more than one +block +of data, but +a read can split a block that contains more data than requested, leaving the remainder +in a new block at the front of the Queue. +Writes of more than the maximum +.B Block +size (currently 128k bytes) +are split into as many Blocks as required, each written separately to the queue, +in order, but with possible flow-control between them. +The queue is locked meanwhile, however, so that data from other writers is not intermingled. +.PP +In message mode, by contrast, a read will return at most +one block's worth of data, but the remainder of a partially-read block will be discarded, +not returned to the queue. +If a write count exceeds the maximum +.B Block +size, the excess data is discarded: +at most a single block can be queued. +.PP +The mode of the queue should be taken into account in the descriptions below +of the following functions: +.IR qwrite , +.IR qiwrite , +.IR qbread +and +.IR qconsume . +No other functions are aware of the distinction. +.SS "Write operations (flow controlled)" +.I Qwrite +copies +.I len +bytes of data from +.I buf +into one or more +.B Blocks +which it places on the +.IR q . +.I Qwrite +always returns +.IR len . +It can implement message mode. +.PP +.I Qbwrite +places the single Block +.I b +on the tail of +.IR q , +waking any sleeping reader. +If the queue is full, the +writing process blocks until a reader +has reduced the queued data to +the low-water mark; +if the queue is non-blocking +(see +.I qnoblock +below), +the data is discarded without notice. +.I Qbwrite +normally returns +.IR len , +but raises an +.IR error (9) +if the queue is closed (see +.I qhangup +and +.IR qclose ). +The block +.I b +is always freed. +Note that +.I b +can be empty (zero-length), to punctuate the data in a queue. +.I Qbwrite +cannot handle a list of Blocks; +.I qpass +must be used instead. +.SS Non-blocking writes +.PP +.I Qproduce +returns -1immediately if +.I q +is full. +Otherwise, it queues +.I len +bytes of data from +.I buf +in a single +.B Block +on +.I q +and returns the number of bytes written. +.PP +.I Qpass +attempts to place the list of Blocks headed by +.I b +on +.IR q , +returning the number of bytes written if successful. +If +.I q +was full, it +frees the Block list +.I b +and returns -1. +.PP +.I Qpassnolim +puts the Block list +.I b +on +.I q +regardless of flow control; it returns the number of bytes in the list +.IR b . +.PP +.I Qiwrite +is a variant of +.I qwrite +used exclusively by the kernel print function, +to allow printing by interrupt handlers; +.I qiwrite +could be used with care by other routines, but +.IR qproduce +is preferable. +.I Qiwrite +writes the +.I len +bytes of data at +.I buf +into the +.I q +without regard to flow control; +the writer never blocks. +The queue is assumed to be open. +.I Qiwrite +always returns +.IR len . +It can implement message mode. +.SS "Read operations (flow controlled)" +.I Qbread +blocks until data arrives on +.IR q , +then +returns the first +.BR Block ; +it limits the data returned +to +.I len +bytes (in the manner depending on the mode of +.IR q ). +It returns a null pointer if the queue has hung up. +.PP +.I Qread +reads a Block of up to +.I len +bytes from +.I q +using +.IR qbread , +and copies the data in the Block into +.IR buf , +then frees the Block and returns +the number of bytes read. +.I Qread +returns 0 on end of file or error (hangup). +It can implement message mode. +.PP +.I Qcopy +returns a Block with a copy of data from the queue (the data remains on the queue). +The copy begins +.I offset +bytes into the queue's data and proceeds until +.I len +bytes have been copied or no more data remains. +The Block's read and write pointers delimit the data copied into it. +.I Qcopy +can be used by a reliable transport protocol to copy a packet for transmission, +leaving the data queued for possible retransmission, if unacknowledged. +.SS Non-blocking reads +.PP +.I Qconsume +returns -1 immediately if +.I q +is empty. +Otherwise, it +copies up to +.I len +bytes from the first +.B Block +on the queue into +.IR buf , +returning the number of bytes copied. +It can implement message mode. +.PP +.I Qget +returns a null pointer immediately if +.I q +is empty or closed. +Otherwise, it +returns the first +.B Block +on the queue. +.SS "Discard and flush" +.I Qdiscard +removes the first +.I len +data bytes from +.IR q ; +it returns the number of bytes actually discarded, in case +the queue is shorter than +.IR len . +If the queue drains below the low-water mark, +.I qdiscard +wakes any sleeping writers. +Since it does not block, +.I qdiscard +can safely be called from interrupt handlers. +It is useful in transport protocol drivers to remove data from the queue +once acknowledged. +.PP +.I Qflush +discards all data waiting on +.IR q , +waking any waiting writer. +.SS "Queue status" +The following functions return a Queue's status. +Note that between a call to one of these functions and another operation, +the state can change if a driver allows concurrent access by +either another process or an interrupt handler. +.PP +.I Qlen +returns the number of bytes queued on +.IR q . +.PP +.I Qwindow +returns the number of bytes that can be written before reaching the queue's high-water mark. +A return of 0 means that a write operation will certainly block; +a non-zero return gives no guarantees (see +.IR qfull , +below). +.PP +.I Qcanread +returns 1 if any data queued is queued. A subsequent read operation will not block. +.PP +.I Qfull +returns non-zero if +.I q +is flow-controlled and a write would block or a non-blocking write would return an error. +(Note that the implementation allows +.I qwindow +to return non-zero yet +.I qfull +to return true.) +.SS "Queue control" +.I Qsetlimit +sets the high water mark for the queue to +.IR limit . +Note that +.I qopen +saves the initial queue limit. +If the queue is closed and reopened (by +.IR qreopen ) +that initial limit is restored. +.PP +.I Qnoblock +sets or resets non-blocking mode. +If +.I nonblock +is non-zero, +the queue becomes non-blocking, and +data written to a queue beyond its high water mark is discarded +by calls that would otherwise block. +.SH SOURCE +.B /sys/src/9/port/qio.c +.SH SEE ALSO +.IR allocb (9), +.IR ref (9) diff -Nru /sys/man/9/qlock /sys/man/9/qlock --- /sys/man/9/qlock Thu Jan 1 00:00:00 1970 +++ /sys/man/9/qlock Sat Jan 5 00:00:00 2013 @@ -0,0 +1,105 @@ +.TH QLOCK 9 +.SH NAME +qlock, qunlock, canqlock, rlock, runlock, wlock, wunlock \- serial synchronisation +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +void qlock(QLock *l) +.PP +.B +void qunlock(QLock *l) +.PP +.B +int canqlock(QLock *l) +.PP +.B +void rlock(RWlock *l) +.PP +.B +void runlock(RWlock *l) +.PP +.B +int canrlock(RWlock *l) +.PP +.B +void wlock(RWlock *l) +.PP +.B +void wunlock(RWlock *l) +.SH DESCRIPTION +The primitive locking functions described in +.IR lock (9) +guarantee mutual exclusion, but they implement spin locks, +and should not be used if the process might +.IR sleep (9) +within a critical section. +The following functions serialise access to a resource by forming an orderly +queue of processes. +.PP +Each resource to be controlled is given an associated +.B QLock +structure; it is usually most straightforward to put the +.B QLock +in the structure that represents the resource. +It must be initialised to zero before use +(as guaranteed for global variables and for structures allocated by +.IR malloc ). +.PP +On return from +.IR qlock , +the process has acquired the lock +.IR l , +and can assume exclusive access to the associated resource. +If the lock is not immediately available, the requesting process is placed on a +FIFO queue of processes that have requested the lock. +Processes on this list are blocked in the +.L Queueing +state. +.PP +.I Qunlock +unlocks +.I l +and schedules the first process queued for it (if any). +.PP +.I Canqlock +is a non-blocking form of +.IR qlock . +It tries to obtain the lock +.I l +and returns true if successful, and 0 otherwise; +it always returns immediately. +.PP +.B RWlock +is a form of lock for resources that have distinct readers and writers. +It allows concurrent readers but gives each writer exclusive access. +A caller announces its read or write intentions by choice of lock (and unlock) function; +the system assumes the caller will not modify a structure accessed under read lock. +.PP +.I Rlock +acquires +.I l +for reading. +The holder can read but agrees not to modify the resource. +There may be several concurrent readers. +.I Canrlock +is non-blocking: it returns non-zero if it successfully acquired the lock immediately, +and 0 if the resource was unavailable. +.PP +.I Runlock +returns a read lock; +the last reader out enables the first writer waiting (if any). +.PP +.I Wlock +acquires a write lock. +The holder of such a lock may assume exclusive access to the resource, +and is allowed to modify it. +.PP +.I Wunlock +returns a write lock. +The next pending process, whether reader or writer, is scheduled. +.SH SOURCE +.B /sys/src/9/port/qlock.c +.br +.SH SEE ALSO +.IR lock (9), +.IR splhi (9) diff -Nru /sys/man/9/readnum /sys/man/9/readnum --- /sys/man/9/readnum Thu Jan 1 00:00:00 1970 +++ /sys/man/9/readnum Sat Jan 5 00:00:00 2013 @@ -0,0 +1,58 @@ +.TH READNUM 9 +.SH NAME +readnum, readstr \- return values from read from device +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.B +int readstr(ulong off, char *buf, ulong n, char *str) +.PP +.B +int readnum(ulong off, char *buf, ulong n, ulong val, int size) +.SH DESCRIPTION +.I Readstr +and +.I readnum +simplify the return of strings and numbers from device +.I read +routines, +because they deal with any buffering and boundary cases. +Several parameters to the read call are often handed on directly +to these functions: +the file offset, as +.IR off ; +the address of the user's buffer, as +.IR buf ; +and the number of bytes requested, as +.IR n . +Both functions return the number of bytes they have stored in +.IR buf , +and which can often be returned directly from the device read routine. +.PP +.I Readstr +satisfies a read by copying data into +.I buf +from the NUL-terminated string in +.IR str . +The data transferred is selected and limited by +.IR off , +.I n +and the length of +.IR str . +.PP +.I Readnum +converts the unsigned integer +.I val +to a decimal representation in +.IR buf . +The value is right-justified in a field of +.IR size "-1" +places and is followed by a blank. +.I Size +can be the global constant +.L NUMSIZE +for 32-bit integers; +the largest +.I size +allowed is 64 bytes. +.SH SOURCE +.B /sys/src/9/port/devcons.c diff -Nru /sys/man/9/ref /sys/man/9/ref --- /sys/man/9/ref Thu Jan 1 00:00:00 1970 +++ /sys/man/9/ref Sat Jan 5 00:00:00 2013 @@ -0,0 +1,59 @@ +.TH REF 9 +.SH NAME +Ref, incref, decref \- reference counts +.SH SYNOPSIS +.ta \w'\fLchar* 'u +.PP +.B +int incref(Ref *r) +.PP +.B +int decref(Ref *r) +.SH DESCRIPTION +A +.B Ref +structure holds a reference count for a data structure: +.IP +.EX +typedef struct +struct Ref +{ + Lock; + long ref; +} Ref; +.EE +.PP +The reference count proper is found in +.BR ref ; +the +.B Lock +prevents concurrent updates +(see +.IR lock (9)). +.PP +.I Incref +atomically increments the reference count +.IR r , +and returns the new count. +.PP +.I Decref +atomically decrements the reference count +.IR r , +and returns the new count. +.SH EXAMPLES +Release a structure containing a +.B Ref +on last use. +.IP +.EX +if(decref(s) == 0) + free(s); +.EE +.SH SOURCE +.B /sys/src/9/port/chan.c +.SH DIAGNOSTICS +.I Decref +will +.IR panic (9) +if the count goes negative, +revealing a reference counting bug. diff -Nru /sys/man/9/seconds /sys/man/9/seconds --- /sys/man/9/seconds Thu Jan 1 00:00:00 1970 +++ /sys/man/9/seconds Sat Jan 5 00:00:00 2013 @@ -0,0 +1,93 @@ +.TH SECONDS 9 +.SH NAME +seconds, ticks, fastticks, HZ, MS2HZ, MS2TK, TK2MS, TK2SEC \- kernel times and time conversions +.SH SYNOPSIS +.ta \w'\fL#define 'u +.B +long seconds(void) +.PP +.B +m->ticks +.br +MACHP(0)->ticks +.PP +.B +vlong fastticks(uvlong *hz) +.PP +.EX +#define HZ ... +#define MS2HZ(t) ... +#define TK2SEC(t) ... +#define TK2MS(t) ... +#define MS2TK(m) ... +.EE +.SH DESCRIPTION +.I Seconds +returns the system's idea of the current time as the number of seconds +since the start of the epoch +(00:00:00 GMT, January 1, 1970). +.PP +The +.B ticks +field of the +.B Mach +structure pointed to by +.B m +returns the number of system-dependent clock ticks on the +given processor since system boot. +On a multiprocessor, +.B MACHP(0) +is sometimes used to provide a reference time, since the tick value +might vary slightly across processors. +.PP +.I Fastticks +returns the number of ticks since boot as measured by the +fastest clock provided by the platform. +The frequency of the clock, in ticks per second, +is returned through +.IR hz , +unless it is nil. +.PP +The system clock frequencies are platform-dependent. +Several symbolic constants and macro functions are defined by +the file +.B mem.h +to convert between different time units: +.TF TK2SEC(t) +.PD +.TP +.B HZ +The number of clock ticks per second. +.TP +.B MS2HZ +Milliseconds per clock tick. +.TP +.BI TK2SEC( t ) +Convert +.I t +clock ticks to seconds and return the result (truncating not rounding). +.TP +.BI TK2MS( t ) +Convert +.I t +clock ticks to milliseconds and return the result. +.TP +.BI MS2TK( m ) +Convert +.I m +milliseconds to clock ticks and return the result (truncating). +.PP +The functions are often used to calculate delays for timing functions, +for instance: +.IP +.EX +if(atactlrwait(dp->cp, DHmagic, 0, MS2TK(100))){ + ... +} +.EE +.SH SOURCE +.B /sys/src/9/*/mem.h +.br +.B /sys/src/9/*/clock.c +.br +.B /sys/src/9/port/tod.c diff -Nru /sys/man/9/sleep /sys/man/9/sleep --- /sys/man/9/sleep Thu Jan 1 00:00:00 1970 +++ /sys/man/9/sleep Sat Jan 5 00:00:00 2013 @@ -0,0 +1,123 @@ +.TH SLEEP 9 +.SH NAME +sleep, wakeup, tsleep, return0 \- process synchronisation +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +void sleep(Rendez *r, int (*f)(void*), void *arg) +.PP +.B +void wakeup(Rendez *r) +.PP +.B +void tsleep(Rendez *r, int (*f)(void*), void *arg, int ms) +.PP +.B +int return0(void *arg) +.PP +.SH DESCRIPTION +A process running in the kernel can use these functions to +synchronise with an interrupt handler or another kernel process. +In particular, they are used by device drivers to wait for an event to be signalled on +receipt of an interrupt. +(In practice, they are most often used indirectly, through +.IR qio (9) +for instance.) +.PP +The caller of +.I sleep +and a caller of +.I wakeup +share a +.B Rendez +structure, to provide a rendezvous point between them +to synchronise on an event. +.I Sleep +uses a condition function +.I f +that returns true if the event has occurred. +.PP +.I Sleep +evaluates +.IB f ( arg ). +If true, the event has happened and +.I sleep +returns immediately. +Otherwise, +.I sleep +blocks on the event variable +.IR r , +awaiting +.IR wakeup . +.PP +.I Wakeup +is called by either a process or an interrupt handler to wake any process +sleeping at +.IR r , +signifying that the corresponding condition is true (the event has occurred). +It has no effect if there is no sleeping process. +.PP +.I Tsleep +is similar to +.IR sleep , +except that if the condition +.IB f ( arg ) +is false and the caller does sleep, +and nothing else wakes it within +.I ms +millliseconds, +the system will wake it. +.IR Tsleep 's +caller must check its environment to decide whether timeout or the event +occurred. +The timing provided by +.I tsleep +is imprecise, but adequate in practice for the normal use of protecting against +lost interrupts and otherwise unresponsive devices or software. +.PP +.I Return0 +ignores its arguments and returns zero. It is commonly used as +the predicate +.I f +in a call to +.I tsleep +to obtain a time delay, using a +.B Rendez +variable +.B sleep +in the +.B Proc +structure, for example: +.IP +.B tsleep(&up->sleep, return0, nil, 10); +.PP +Both +.I sleep +and +.I tsleep +can be interrupted by +.IR swiproc +(see +.IR kproc (9)), +causing a non-local goto through a call to +.IR error (9). +.SH SOURCE +.B /sys/src/9/port/proc.c +.SH DIAGNOSTICS +There can be at most one process waiting on a +.BR Rendez , +and if two processes collide, the system will +.IR panic (9) +.RB (`` "double sleep" ''). +Access to a +.B Rendez +must therefore be serialised by some other mechanism, usually +.IR qlock (9). +.SH SEE ALSO +.IR lock (9), +.IR qlock (9), +.IR delay (9) +.br +``Process Sleep and Wakeup on a Shared-memory Multiprocessor'', +in +.I "Plan 9 Programmer's Manual: Volume 2". diff -Nru /sys/man/9/splhi /sys/man/9/splhi --- /sys/man/9/splhi Thu Jan 1 00:00:00 1970 +++ /sys/man/9/splhi Sat Jan 5 00:00:00 2013 @@ -0,0 +1,57 @@ +.TH SPLHI 9 +.SH NAME +splhi, spllo, splx, islo \- enable and disable interrupts +.SH SYNOPSIS +.ta \w'\fLvoid 'u +.B +int spllo(void) +.PP +.B +int splhi(void) +.PP +.B +void splx(int x) +.PP +.B +int islo(void) +.SH DESCRIPTION +These primitives enable and disable maskable interrupts on the current +processor. +Generally, device drivers should use +.I ilock +(see +.IR lock (9)), +.IR sleep (9), +or the functions in +.IR qio (9) +to control interaction between processes and interrupt handlers. +Those routines (but not these) provide correct synchronisation on multiprocessors. +.PP +.I Spllo +enables interrupts and returns a flag representing the previous interrupt enable state. +It must not normally be called from interrupt level. +.PP +.I Splhi +disables all maskable interrupts and returns the previous interrupt enable state. +The period during which interrupts are disabled had best be short, +or real-time applications will suffer. +.PP +.I Splx +restores the interrupt enable state +state to +.IR x , +which must be a value returned +by a previous call to +.I splhi +or +.IR spllo . +.PP +.I Islo +returns true (non-zero) if interrupts are currently enabled, and 0 otherwise. +.SH SOURCE +.B /sys/src/9/*/l.s +.SH SEE ALSO +.IR lock (9), +.IR qio (9), +.IR sleep (9), +.IR intrenable (9) diff -Nru /sys/man/9/uartp8250 /sys/man/9/uartp8250 --- /sys/man/9/uartp8250 Thu Jan 1 00:00:00 1970 +++ /sys/man/9/uartp8250 Sat Jan 5 00:00:00 2013 @@ -0,0 +1,77 @@ +.TH UARTP8250 9 +.SH NAME +uartp8250 \- portable 8250-style uarts +.SH SYNOPSIS +.EX +#include "../port/uartp8250.h" + +typedef struct Ctlr Ctlr; +struct Ctlr { + void *reg; + uint (*get)(void*, int); + void (*set)(void*, int, uint); + int (*itr)(Uart*, int); + + int irq; + int tbdf; + int iena; + + uchar sticky[8]; + + Lock; + int hasfifo; + int checkfifo; + int fena; +}; +.EE +.PP +.ta \w'\fLPhysUart 'u +.PP +.B +PhysUart p8250physuart; +.PP +.B +void i8250interrupt(Ureg*, void*); +.SH DESCRIPTION +P8250 provides a portable interface for 8250-style uarts. +All necessary functions are provided except for +.BR get , +.BR set , +and +.BR itr . +These functions get or set an 8250 register or enable +or disable the interrupt, respectively. Since the +.B PhysUart +structure is required for device discovery, a dummy +version needs to be provided +.IP +.EX +PhysUart myphysuart = { + .name = "myuart", + .pnp = mypnp, +}; +.EE +.PP +On entry of the pnp function, the +.B PhysUart +can be filled out: +.EX + memmove(&myphysuart, &p8250physuart, sizeof(PhysUart)); + myphysuart.name = "myuart"; + myphysuart.pnp = mypnp; +.EE +.PP +as can the +.B Ctlr +structure, which is assigned to +.BR "uart->regs" . +.SH SOURCE +.B /sys/src/9/port/uartp8250.h +.br +.B /sys/src/9/port/uartp8250.c +.SH "SEE ALSO" +.IR uart (3). +.SH BUGS +The +.B PhysUart +is uncomfortable to use for device discovery. diff -Nru /sys/man/9/xalloc /sys/man/9/xalloc --- /sys/man/9/xalloc Thu Jan 1 00:00:00 1970 +++ /sys/man/9/xalloc Sat Jan 5 00:00:00 2013 @@ -0,0 +1,72 @@ +.TH XALLOC 9 +.SH NAME +xalloc, xspanalloc, xfree \- basic memory management +.SH SYNOPSIS +.ta \w'\fLvoid* 'u +.B +void* xalloc(ulong size) +.PP +.B +void* xspanalloc(ulong size, int align, ulong span) +.PP +.B +void xfree(void *p) +.SH DESCRIPTION +.I Xalloc +and +.I xfree +are primitives used by higher-level memory allocators in the kernel, +such as +.IR malloc (9). +They are not intended for use directly by most kernel routines. +The main exceptions are routines that permanently allocate large structures, +or need the special alignment properties guaranteed by +.IR xspanalloc . +.PP +.I Xalloc +returns a pointer to a range of size bytes of memory. The memory will be zero filled and aligned on a 8 byte +.RB ( BY2V ) +address. If the memory is not available, +.B xalloc +returns a null pointer. +.PP +.I Xspanalloc +allocates memory given alignment and spanning constraints. +The block returned will contain +.I size +bytes, aligned on a boundary that is +.BI "0 mod" " align," +in such a way that the memory in the block does not +span an address that is +.BI "0 mod" " span." +.I Xspanalloc +is intended for use +allocating hardware data structures (eg, page tables) or I/O buffers +that must satisfy specific alignment restrictions. +If +.I xspanalloc +cannot allocate memory to satisfy the given constraints, it will +.IR panic (9). +The technique it uses can sometimes cause memory to be wasted. +Consequently, +.I xspanalloc +should be used sparingly. +.PP +.I Xfree +frees the block of memory at +.IR p , +which must be an address previously returned by +.I xalloc +(not +.IR xspanalloc ). +.SS Allocation status +Some memory allocation statistics are written to the console in response to +the debugging sequence +.LR "control-T control-T x" . +The output includes the total free space, the number of free holes, +and a summary of active holes. +Each line shows `address top size'. +.SH SOURCE +.B /sys/src/9/port/xalloc.c +.SH SEE ALSO +.IR malloc (9)