/* begincopyright Copyright (c) 1988 Xerox Corporation. All rights reserved. Use and copying of this software and preparation of derivative works based upon this software are permitted. Any distribution of this software or derivative works must comply with all applicable United States export control laws. This software is made available AS IS, and Xerox Corporation makes no warranty about the software, its performance or its conformity to any specification. Any person obtaining a copy of this software is requested to send their name and post office or electronic mail address to: PCR Coordinator Xerox PARC 3333 Coyote Hill Rd. Palo Alto, CA 94304 endcopyright */ /* * UIOPrivate.h * * * Private definitions for Unix I/O interface * for Xerox Runtime threads package. * * Suitable for AT&T streams. * * Demers, July 30, 1990 9:53:32 am PDT * Boehm, May 14, 1990 2:51:23 pm PDT */ #ifndef ←XR←UIO←PRIVATE← #define ←XR←UIO←PRIVATE← 1 #ifndef ←XR←THREADS←BACKDOOR← # include "ThreadsBackdoor.h" #endif #ifndef ←XR←UIO← # include "UIO.h" #endif /* * The following controls whether STREAMS support is compiled in. * On some systems we may have to fudge the streams header files * if STREAMS is false. */ #define STREAMS 1 /* * The following controls a hack in ThreadsUIO.c/USysCalls.c to allow strings * declared in data or bss segments to be passed to IOPs in a packaged * threads configuration. It doesn't hurt anything in other configurations. * * NOTE: in 2←12 and later versions this is NEVER needed. */ #define XR←COPY←FOR←PACKAGED←THREADS 0 /* * Queue of events (Unix signals) passed back to PCR threads ... */ #define XR←UIO←EVENT←QUEUE←SIZE 8 /* * Max descriptors per IOP. * Each kind of UIO IOP may implement fewer than this ... */ #define XR←MAX←FDS←PER←IOP 256 #if !defined(POLLIN) # include <poll.h> #endif #if STREAMS # if !defined(I←STR) # include <stropts.h> # endif #endif #if XR←COPY←FOR←PACKAGED←THREADS extern char * XR←UIOFixStringArg(); #else # define XR←UIOFixStringArg(x) (x) #endif /* * Wait Kinds -- set of descriptor events to wait for * * Taken from System V <poll.h> */ typedef unsigned XR←UIOWaitKinds; /* POLLIN -- normal input POLLPRI -- priority input POLLOUT -- output POLLERR -- error return POLLHUP -- stream disappeared POLLNVAL -- descriptor not a stream */ /* * State of FDE * * It's okay to `OR' XR←FDE←STATE←BUSY into any other state. */ typedef unsigned XR←FDEState; # define XR←FDE←STATE←FREE ((XR←FDEState)(0)) # define XR←FDE←STATE←BUSY ((XR←FDEState)(1)) # define XR←FDE←STATE←OPEN ((XR←FDEState)(2)) /* * Data structures for virtual file descriptor entries (FDE's) * and physical file descriptor cache entries (FDC's) */ #define XR←FDC struct XR←FDCRep * #define XR←FDE struct XR←FDERep * typedef struct XR←FDERep { int fde←index; unsigned fde←gen; /* generation number */ int fde←opCnt; /* # ops in progress */ XR←FDEState fde←state; XR←IOPE fde←owner; /* IOP that owns descriptor */ int fde←ownerIndex; /* owner's descriptor index */ XR←FDKind fde←fdKind; /* kind of associated descriptors */ /* (same as kind of IOP) */ XR←UIOBlocking fde←getBlocking; /* input blocking behavior */ XR←UIOBlocking fde←putBlocking; /* output blocking behavior */ XR←Ticks fde←getTimeout; /* input timeout */ XR←Ticks fde←putTimeout; /* output timeout */ bool fde←inputPri; /* poll input => pri */ XR←FDC fde←fdc; /* -> cached fdc or NIL */ struct XR←CVRep fde←avail; /* wait here e.g. for FDC */ #undef XR←FDE } * XR←FDE; typedef struct XR←FDCRep { int fdc←index; /* index in cache */ unsigned fdc←whenUsed; /* for LRU */ bool fdc←valid; /* Unix descriptor exists */ XR←FDE fdc←fde; /* associated fde or NIL */ #undef XR←FDC } * XR←FDC; /* * UIO IOP working directory maintenance */ typedef struct XR←UIOWDBufRep { int wdb←maxLen; int wdb←len; char wdb←data[ /*maxLen+1*/ 4]; } * XR←UIOWDBuf; #define XR←UIOWDBufBytes(len) ( sizeof(struct XR←UIOWDBufRep) + (len) - 3 ) extern char * XR←UIOFixPathForIOP(/* char *path, XR←IOPE iope */); /* (to be called only from a thread) Return (possibly new, heap-allocated) full pathname for path. As side-effect, if iope is not NIL, ensure that the IOP's wdBuf is big enough to hold (the directory prefix of) the full path name. */ extern int XR←UIOIOPChDirForPaths(/* char *fullPath, char *fullPath2 */); /* (fullPath2 may be NIL) (to be called only from IOP) Change IOP's unix working directory to appropriate (common) prefix of fullPath (and fullPath2 if it's not NIL). Store working directory in IOP's WD slot, to be accessed by XR←GetUIOIOPEWD(iope). Return length of common prefix (which is now IOP's working directory) on success, or (-errno) on failure. */ /* * * UIO system data structure * */ typedef struct XR←UIOAreaRep { /* monitor locks */ struct XR←MLRep uioa←ml; struct XR←MLRep uioa←wdML; /* PCR working directory cache */ XR←UIOWDBuf uioa←pcrWD; /* IOPs */ XR←IOPE uioa←iope; int uioa←numIOPE; # define XR←UIOIOPELimit \ (&(XR←uioArea->uioa←iope[XR←uioArea->uioa←numIOPE])) /* FDEs */ XR←FDE uioa←fde; int uioa←numFDE; # define XR←UIOFDELimit \ (&(XR←uioArea->uioa←fde[XR←uioArea->uioa←numFDE])) /* FDCs */ XR←FDC uioa←fdc; int uioa←numFDC; # define XR←UIOFDCLimit \ (&(XR←uioArea->uioa←fdc[XR←uioArea->uioa←numFDC])) /* cv for spinning to wait for free fdc (rare!) */ struct XR←CVRep uioa←spinCV; /* op count (for LRU) */ unsigned uioa←opCnt; /* misc data for sys calls */ XR←IOPOrder uioa←spawnWaitList; bool uioa←spawnChildDied; struct XR←VPOrderRep uioa←profVPOrderBuf; } * XR←UIOArea; extern XR←UIOArea XR←uioArea; /* readonly, shared */ /* * IOPE client data fields * * (uioFreeSlots is protected by uioArea monitor lock uioa←ml) * (IOPEWDBuf is protected by uioArea monitor lock uioa←wdML) */ #define iope←uioFDKind iope←clientData[0] #define iope←uioFDEBase iope←clientData[1] #define iope←uioFreeSlots iope←clientData[2] #define XR←GetUIOIOPEWD(iope) \ ((XR←UIOWDBuf)((iope)->iope←clientData[3])) #define XR←SetUIOIOPEWD(iope, wdb) \ (iope)->iope←clientData[3] = ((unsigned)(wdb)) #define XR←GetUIOIOPEWDBuf(iope) \ ((XR←UIOWDBuf)((iope)->iope←clientData[4])) #define XR←SetUIOIOPEWDBuf(iope, wdb) \ (iope)->iope←clientData[4] = ((unsigned)(wdb)) /* * * Per-IOP data structure for wait-until-ready requests * */ typedef struct XR←WaitReadyDataRep { struct pollfd wrd←pollfd; } * XR←WaitReadyData; # define wrd←fd wrd←pollfd.fd # define wrd←events wrd←pollfd.events # define wrd←revents wrd←pollfd.revents #define XR←waitReadyData ((XR←WaitReadyData)(XR←iope->iope←clientData[5])) #define XR←GetWaitReadyData(iope) \ ((XR←WaitReadyData)((iope)->iope←clientData[5])) #define XR←SetWaitReadyData(iope, d) \ (iope)->iope←clientData[5] = ((unsigned)(d)) #define XR←numWaitReadyData (XR←iope->iope←clientData[6]) #define XR←GetNumWaitReadyData(iope) \ ((iope)->iope←clientData[6]) #define XR←SetNumWaitReadyData(iope,x) \ (iope)->iope←clientData[6] = ((unsigned)(x)) typedef struct XR←WaitReadyHeaderRep { unsigned wrh←index; XR←WaitReadyData wrh←wrd; /* ref to WaitReadyDataRep or NIL */ XR←IOPOrder wrh←orders; /* list of wait ready orders for this FDE */ } * XR←WaitReadyHeader; #define XR←waitReadyHeaders ((XR←WaitReadyHeader)(XR←iope->iope←clientData[7])) #define XR←GetWaitReadyHeaders(iope) \ ((XR←WaitReadyHeader)((iope)->iope←clientData[7])) #define XR←SetWaitReadyHeaders(iope,h) \ (iope)->iope←clientData[7] = ((unsigned)(h)) /* * Asynchronous events */ typedef struct XR←UIOEventQueueRep { unsigned uioeq←wNum; unsigned uioeq←rNum; int uioeq←eventID[XR←UIO←EVENT←QUEUE←SIZE] } *XR←UIOEventQueue; #define XR←uioEventQueue ((XR←UIOEventQueue)(XR←iope->iope←clientData[8])) #define XR←GetUIOEventQueue(iope) \ ((XR←UIOEventQueue)((iope)->iope←clientData[8])) #define XR←SetUIOEventQueue(iope,q) \ (iope)->iope←clientData[8] = ((unsigned)(q)) extern void XR←UIONotifyEventAvail(); /* Notify any waiting thread of an asynchronous event in IOP. */ /* * * Descriptor Utilities * */ #define XR←IOP←POLL←TIMEOUT←MSEC 2000 /* internal timeout */ extern int XR←UIOPollStd( /* XR←waitReadyData fds, int nfds, unsigned timeout, unsigned *flagp */ ); /* Like a System V poll call, but on standard descriptors. The timeout is specified in msec. As late as possible, test *flagp and if it is nonzero, return (-1) with errno set to EINTR. Ideally this should be atomic! Normal result is number of descriptors that tested ready. */ extern bool XR←UIOPollStream( /* XR←waitReadyData fds, int nfds, unsigned timeout, unsigned *flagp */ /* Assumed to be called only from IOP, or with stack arguments. */ ); /* Like XR←UIOPollStd. */ /* * IOP order proc utilities */ extern int XR←UIOIOPFixDescriptor (/* fde, d */); /* XR←FDE fde; int d; XR←FDKind kind; Assume d is the result of a Unix system call to create a descriptor -- open, socket, ... (thus d could be -1). Insist that d be of right kind for fde, else return (-ENOSTR). Set `d' to be non-blocking, move it to the descriptor slot corresponding to `fde'. Return the new descriptor (guaranteed to be the slot corresponding to `fde', which may be different from the original value of d), or -errno on failure. On error returns, the descriptor `d' has been closed. */ extern int XR←UIOIOPSetNonBlockingStd(/*int d*/); /* Set Unix (standard) descriptor d to non-blocking. Return d on success, or (-errno) on failure. */ extern int XR←UIOIOPSetNonBlockingStream(/*int d*/); /* Set Unix (streams) descriptor d to non-blocking. Return d on success, or (-errno) on failure. */ extern void XR←UIONotifyIOPODone(/* iopo */); /* XR←IOPOrder iopo; Set iopo←done and do a naked notify of iopo←cv, with some error checking. This is the approved way to notify the waiting thread that an IOP order has been completed. */ extern unsigned XR←UIOComputeLengthForSingleIOSysCall(/* char *b, unsigned maxlen */); /* Compute length for a single I/O call, to limit amount of time spent uninterruptably blocked in system call. */ /* * * VP Orders * */ /* --- */ #define vpo←fdc vpo←args[0] extern void XR←RecvDescriptorVPOrderProc (/* vpo */); /* XR←VPOrder vpo; Receive descriptor. Argument in vpo←fdc tells where it belongs. */ extern void XR←FlushDescriptorVPOrderProc (/* vpo */); /* XR←VPOrder vpo; Flush cached descriptor. Argument in vpo←fdc tells which one. */ /* --- */ #define vpo←profBuf vpo←args[0] #define vpo←profBufSize vpo←args[1] #define vpo←profOffset vpo←args[2] #define vpo←profScale vpo←args[3] extern void XR←ProfilVPOrderProc (/* vpo */); /* XR←VPOrder vpo; Execute profil system call. */ /* --- */ #define vpo←mma vpo←args[0] extern void XR←MMapVPOrderProc (/* vpo */); /* XR←VPOrder vpo; Execute mmap system call in vp. */ extern void XR←MUnmapVPOrderProc (/* vpo */); /* XR←VPOrder vpo; Execute munmap system call in vp. */ extern void XR←MProtectVPOrderProc (/* vpo */); /* XR←VPOrder vpo; Execute mprotect system call in vp. */ /* --- */ #define vpo←sha vpo←args[0] extern void XR←ShmAtVPOrderProc (/* vpo */); /* XR←VPOrder vpo; Execute shmat system call. */ extern void XR←ShmDtVPOrderProc (/* vpo */); /* XR←VPOrder vpo; Execute shmdt system call. */ /* * * IOPOrders * */ /* * args shared by many procs */ #define iopo←fdc iopo←args[0] #define iopo←fde iopo←args[1] /* --- */ #define iopo←oName iopo←args[2] #define iopo←oFlags iopo←args[3] #define iopo←oMode iopo←args[4] extern void XR←OpenIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Open a named file. Args in iopo←fde, iopo←oName, iopo←oFlags, iopo←oMode. Result in iopo←results[0] is (fde←ownerIndex) or (-errno). */ /* --- */ extern void XR←CloseIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Close a descriptor. Arg in iopo←fde and fde←fdc (cache entry to flush by issuing VPOrder, may be NIL). Result in iopo←results[0] is 0 or (-errno). */ /* --- */ extern void XR←SendDescriptorIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Send a descriptor to the VP caches. Arguments in iopo←fde (=> which descriptor) and iopo←fdc (which cache entry to store into). Assumed never to fail (panic if it does). */ /* --- */ #define iopo←wrHow iopo←args[2] extern void XR←WaitReadyIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Args in iopo←fde and iopo←wrHow. Wait for descriptor to be ready as specified by wrHow. Result in iopo←results[0] is 0 or (-errno). */ extern void XR←WaitReadyIOPCancelProc (/* iopo */); /* XR←IOPOrder iopo; Cancel previously issued WaitReady order in iopo. */ /* --- */ #define iopo←sAf iopo←args[2] #define iopo←sType iopo←args[3] #define iopo←sProtocol iopo←args[4] extern void XR←SocketIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Execute socket call. Result in iopo←results[0] is (fde←ownerIndex) or (-errno) */ /* --- */ #define iopo←accNewFDE iopo←args[2] #define iopo←accAddr iopo←args[3] #define iopo←accAddrLen iopo←args[4] extern void XR←AcceptIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Execute accept call. Result in iopo←results[0] is (new fde←ownerIndex) or (-errno) */ /* --- */ #define iopo←profBuf iopo←args[0] #define iopo←profBufSize iopo←args[1] #define iopo←profOffset iopo←args[2] #define iopo←profScale iopo←args[3] extern void XR←ProfilIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Order all VProcessors to execute profile call. */ /* --- */ #define iopo←mma iopo←args[0] extern void XR←MMapIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Recv descriptor and do mmap call on IOP. If this is IOP 0, send mmap order to all the vprocessors. */ extern void XR←MUnmapIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Do munmap call on IOP. If this is IOP 0, send munmap order to all the vprocessors. */ /* --- */ #define iopo←sha iopo←args[0] extern void XR←ShmAtIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Do a shmat call on the IOP. If this is IOP 0, send a shmat order to all the vprocessors. */ extern void XR←ShmDtIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Do a shmdt call on the IOP. If this is IOP 0, send a shmdt order to all the vprocessors. */ /* --- */ #define iopo←spawnCmd iopo←args[0] #define iopo←spawnWD iopo←args[1] #define iopo←spawnStdin iopo←args[2] #define iopo←spawnStdout iopo←args[3] #define iopo←spawnStderr iopo←args[4] #define iopo←spawnPID iopo←args[5] extern void XR←SpawnIOPOrderProc (/* iopo */); /* XR←IOPOrder iopo; Spawn child. The IOPOrder is linked into a global list, not set done until child terminates. Result in iopo->iopo←results[0] is termination status of child, or (-errno) if fork was unsuccessful. N.B. This is abortable, and has no cancel proc; iopo must be dynamically allocated. */ /* --- */ #define iopo←accessPath iopo←args[0] #define iopo←accessMode iopo←args[1] extern void XR←AccessIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = access(path, mode) (or -errno on failure) */ /* --- */ #define iopo←chmodPath iopo←args[0] #define iopo←chmodMode iopo←args[1] extern void XR←ChModIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = chmod(path, mode) (or -errno on failure) */ /* --- */ #define iopo←linkName1 iopo←args[0] #define iopo←linkName2 iopo←args[1] extern void XR←LinkIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = link(name1, name2) (or -errno on failure) */ /* --- */ #define iopo←mkdirPath iopo←args[0] #define iopo←mkdirMode iopo←args[1] extern void XR←MkDirIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = mkdir(path, mode) (or -errno on failure) */ /* --- */ #define iopo←mknodName iopo←args[0] #define iopo←mknodMode iopo←args[1] #define iopo←mknodDev iopo←args[2] extern void XR←MkNodIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = mknod(path, mode, dev) (or -errno on failure) */ /* --- */ #define iopo←readlinkPath iopo←args[0] #define iopo←readlinkBuf iopo←args[1] #define iopo←readlinkBufsiz iopo←args[2] extern void XR←ReadLinkIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = readlink(path, mode, dev) (or -errno on failure) */ /* --- */ #define iopo←renameFrom iopo←args[0] #define iopo←renameTo iopo←args[1] extern void XR←RenameIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = rename(from, to) (or -errno on failure) */ /* --- */ #define iopo←rmdirName iopo←args[0] extern void XR←RmDirIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = rmdir(name) (or -errno on failure) */ /* --- */ #define iopo←statPath iopo←args[0] #define iopo←statBuf iopo←args[1] extern void XR←StatIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = stat(path, buf) (or -errno on failure) */ /* --- */ #define iopo←lstatPath iopo←args[0] #define iopo←lstatBuf iopo←args[1] extern void XR←LStatIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = lstat(path, buf) (or -errno on failure) */ /* --- */ #define iopo←statfsPath iopo←args[0] #define iopo←statfsBuf iopo←args[1] extern void XR←StatFSIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = statfs(path, buf) (or -errno on failure) */ /* --- */ #define iopo←symlinkName1 iopo←args[0] #define iopo←symlinkName2 iopo←args[1] extern void XR←SymLinkIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = symlink(name1, name2) (or -errno on failure) */ /* --- */ #define iopo←truncatePath iopo←args[0] #define iopo←truncateLength iopo←args[1] extern void XR←TruncateIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = truncate(path, length) (or -errno on failure) */ /* --- */ #define iopo←unlinkPath iopo←args[0] extern void XR←UnlinkIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = truncate(path, length) (or -errno on failure) */ /* --- */ #define iopo←utimesFile iopo←args[0] #define iopo←utimesTVP iopo←args[1] extern void XR←UTimesIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = stat(file, tvp) (or -errno on failure) */ /* --- */ #define iopo←eventSigNum iopo←args[0] #define iopo←eventInteresting iopo←args[1] extern void XR←RegisterInterestIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = 0 after doing appropriate sigvec calls (or -errno on failure) */ /* --- */ #define iopo←fcntlCmd iopo←args[2] #define iopo←fcntlArg iopo←args[3] extern void XR←FCntlIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = 0 after doing appropriate fcntl call (or -errno on failure) */ /* --- */ #define iopo←ioctlRequest iopo←args[2] #define iopo←ioctlArgp iopo←args[3] extern void XR←IOCtlIOPOrderProc (/* XR←IOPOrder iopo */); /* iopo->iopo←results[0] = 0 after doing appropriate ioctl call (or -errno on failure) */ /* * Utilities run by threads */ extern int XR←MProtect4(/* addr, len, prot, include←iops*/); /* XR←Pointer addr; unsigned len; int prot; bool include←iops; A version of MProtect that allows heap addresses, does no checking on on addr, and allows caller to specify whether or not IOPs are included. */ typedef unsigned long XR←FDEWhichIOP; /* how choose iop for descriptor */ #define XR←FDE←WHICH←IOP←FIRST 0 #define XR←FDE←WHICH←IOP←MOSTFREE 1 #define XR←FDE←WHICH←IOP←LEASTFREE 2 #define XR←FDE←WHICH←IOP←LAST 2 #define XR←FDE←WHICH←IOP←FROM←IOPE(iope) \ ((XR←FDEWhichIOP)(iope)) #define XR←FDE←WHICH←IOP←IS←IOPE(which) \ ((which) > XR←FDE←WHICH←IOP←LAST) #define XR←IOPE←FROM←WHICH←IOP(which) \ ((XR←IOPE)(which)) extern XR←FDE XR←AllocateFDE (/* fdKind, which */); /* XR←FDKind fdKind; XR←FDEWhichIOP which; Allocate an unused fde according to strategy which. Caller is assumed to hold uioArea monitor lock. On success, return the fde in BUSY (but not OPEN) state. On failure, set errno and return NIL. */ extern void XR←FreeFDE (/* fde */); /* XR←FDE fde; Free an fde. Caller is assumed to hold the fde exclusively, and to hold uioArea monitor lock. */ #define XR←IncFDEOpCnt(fde) \ (fde)->fde←opCnt += 1 #define XR←DecFDEOpCnt(fde) \ if( --((fde)->fde←opCnt) == 0 ) XR←Broadcast(&((fde)->fde←avail)) #define XR←FDCUsed(fdc) \ (fdc)->fdc←whenUsed = (++(XR←uioArea->uioa←opCnt)) /* Mark an FDC as used (for LRU). */ extern XR←FDC XR←AllocateFDC (/* fde */); /* XR←FDE fde; Allocate an fdc: - one that's not assigned to an fde, if possible ... - failing that, "steal" LRU FDC assigned to an unlocked fde ... - failing either of those, return NIL. Set fde->fde←fdc and fdc->fdc←fde pointers. Set fdc->fdc←valid = FALSE. Caller is assumed to hold uioArea monitor lock. */ extern void XR←FreeFDC(/* fdc */); /* XR←FDC fdc; Free an fdc. This updates the associated fde, if any, and sets fdc←valid = FALSE. Caller is assumed to hold the uioArea ml. */ extern XR←FDE XR←UIODoWithFDELocked(/* fildes, proc, x1, x2, x3 */); /* XR←Fildes fildes; int ( *proc)(* fde, x1, x2, x3 *); unsigned x1, x2, x3; Generic routine for UIO FDE parameter setting. The `proc' gets called with the FDE corresponding to `fildes' and arguments x1, x2, x3. If successful, proc should return a non-negative value; on error, it should set errno and return a negative value. If `proc' returns a non-negative value, then the FDE is returned from DoWithFDE; otherwise NIL is returned (with an error code in errno). Certain error conditions (EBADF ...) may cause DoWithFDE to set errno and return without calling proc. All this is done with the monitor lock held, so `proc' shouldn't block or do anything else that acquires the lock. */ #define XR←FDE←LOCKED←WORKER(name) \ int name (fde, x1, x2, x3) \ XR←FDE fde; \ unsigned x1, x2, x3; extern XR←FDE XR←UIODoWithNewFDE(/* fdKind, which, proc, x1, x2, x3 */); /* XR←FDKind fdKind; XR←FDEWhichIOP which; int ( *proc)(* fde, x1, x2, x3 *); unsigned x1, x2, x3; Generic routine for FDE creation. For fdKind, which interpretation see XR←AllocateFDE. The `proc' gets called with (newly-allocated) FDE (in state BUSY) and arguments x1, x2, x3. If successful, proc should return a non-negative value; on error, it should set errno and return a negative value. If `proc' returns a non-negative value, then the new FDE is returned from DoWithNewFDE in state OPEN; otherwise, the FDE is deallocated and DoWithNewFDE returns NIL (with an error code in errno). Certain error conditions (EMFILE ...) may cause DoWithNewFDE to set errno and return without calling proc. */ extern XR←FDE XR←UIODoWithOldAndNewFDE(/* fildes, proc, x1, x2 */); /* XR←IOPE iope; int ( *proc)(* fde, fdeNew, x1, x2 *); unsigned x1, x2; Generic routine for UIO with both and old and a newly-allocated FDE (e.g. accept, ...). The newly-allocated FDE comes from the same iop as the old one. The `proc' gets called with FDE's and arguments x1, x2. If successful, proc should return a non-negative value; on error, it should set errno and return a negative value. If `proc' returns a non-negative value, then the new FDE is returned from DoWithNewFDE; otherwise, the FDE is deallocated and DoWithNewFDE returns NIL (with an error code in errno). Certain error conditions (EMFILE ...) may cause DoWithNewFDE to set errno and return without calling proc. */ typedef struct XR←UIOWaitReadyProcRep { int (*wrp←proc)(/* XR←UIOWaitReadyProc self, XR←FDE fde */); XR←UIOWaitKinds wrp←how; XR←Ticks wrp←timeout; } * XR←UIOWaitReadyProc; /* Type of `waitReadyProc' parameter to UIODoWithFDEAndFDC, below. Called by (waitReadyProc->wrp←proc)(waitReadyProc, fde); Waits for fde to be ready (w/ appropriate direction, timeout, ...) Returns 0 on success, and (-1) with errno set on failure. */ extern int XR←UIODoWithFDEAndFDC(/* fildes, waitReadyProc, proc, x1, x2 */); /* XR←Fildes fildes; XR←UIOWaitReadyProc waitReadyProc; int (*proc)(XR←FDE fde, XR←FDC fdc, unsigned x1, unsigned x2); unsigned x1, x2; Generic routine for UIO with an FDE and an associated FDC. How to deal with EWOULDBLOCK is specified by `waitReadyProc'. The `proc' gets called with (locked) fde and fdc as arguments, together with the two client data values `x1' and `x2'. Ordinarily, the result of calling proc is returned from UIODoWithFDEAndFDC. If successful, `proc' should return a non-negative value; on error, it should set errno and return a negative value. Certain error conditions (EBADF, XR←EABORTED, ...) cause UIODoWithFDEAndFDC to set errno and return -1 without calling proc. */ #define XR←FDE←FDC←WORKER(name) \ int name (fde, fdc, x1, x2) \ XR←FDE fde; \ XR←FDC fdc; \ unsigned x1, x2; extern struct XR←UIOWaitReadyProcRep XR←UIOIn0WaitReadyProc; /* waitProc for first try on input (POLLIN) operations */ extern struct XR←UIOWaitReadyProcRep XR←UIOIn1WaitReadyProc; /* waitProc for later tries on input (POLLIN) operations */ extern struct XR←UIOWaitReadyProcRep XR←UIOOut0WaitReadyProc; extern struct XR←UIOWaitReadyProcRep XR←UIOOut1WaitReadyProc; extern struct XR←UIOWaitReadyProcRep XR←UIOPri0WaitReadyProc; extern struct XR←UIOWaitReadyProcRep XR←UIOInPri0WaitReadyProc; extern struct XR←UIOWaitReadyProcRep XR←UIOInOut0WaitReadyProc; extern struct XR←UIOWaitReadyProcRep XR←UIOPriOut0WaitReadyProc; extern struct XR←UIOWaitReadyProcRep XR←UIOInPriOut0WaitReadyProc; extern int XR←UIODoWithFDERefreshFDC(/* fildes, proc, x1, x2 */); /* XR←Fildes fildes; int (*proc)(XR←FDE fde, unsigned x1, unsigned x2); unsigned x1, x2; Generic routine for UIO with an FDE when the operation performed by proc would invalidate a cached FDC. How to deal with EWOULDBLOCK is specified by `waitReadyProc'. The `proc' gets called with (locked) fde as argument, together with the two client data values `x1' and `x2'. Ordinarily, the result of calling proc is returned. If successful, `proc' should return a non-negative value; on error, it should set errno and return a negative value. Certain error conditions (EBADF, XR←EABORTED, ...) cause UIODoWithFDERefreshFDC to set errno and return -1 without calling proc. */ #define XR←FDE←REFRESH←WORKER(name) \ int name (fde, x1, x2) \ XR←FDE fde; \ unsigned x1, x2; /* * For spawned (Unix) processes ... */ extern void XR←IOPSpawnChildDied(); /* Call on IOP that does spawns to reap children that have exited. */ #endif ←XR←UIO←PRIVATE←