/* 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 */ /* * ThreadsBackdoor.h * * Demers, December 14, 1990 2:14:47 pm PST * Boehm, August 19, 1991 4:48:47 pm PDT */ #ifndef _XR_THREADS_BACKDOOR_ #define _XR_THREADS_BACKDOOR_ 1 #ifndef _XR_THREADS_ #include "Threads.h" #endif #ifndef _TIME_ #include #endif /* * Configuration constants */ extern char XR_threadsVersion[]; /* table sizes */ #define XR_MAX_VPS 4 extern unsigned XR_maxVPs; #define XR_MAX_SLAVEIOPS 3 extern unsigned XR_maxSlaveIOPs; #define XR_MAX_STDIOPS 5 extern unsigned XR_maxStdIOPs; #define XR_MAX_STRIOPS 3 extern unsigned XR_maxStrIOPs; #define XR_MAX_IOPS (XR_MAX_SLAVEIOPS+XR_MAX_STDIOPS+XR_MAX_STRIOPS) extern unsigned XR_maxIOPs; #define XR_MAX_SYS_MEM (512*1024) #define XR_DEFAULT_SYS_MEM (128*1024) extern unsigned XR_maxSysMem; /* From ThreadsSharedMem.h: */ extern char * XR_SetShmType(/* char * shmType */); extern char * XR_GetShmType(); extern char * XR_SetShmArg(/* char * shmArg */); extern char * XR_GetShmArg(); #define XR_MAX_IOPE_CLIENT_DATA 12 #define XR_MAX_SA_CLIENT_DATA 8 #define XR_MAX_THREADS 250 extern unsigned XR_maxThreads; typedef struct XR_ThreadStackGroupRep { int tsg_numThreads; int tsg_stackBytes; } *XR_ThreadStackGroup; #define XR_MAX_THREAD_STACK_GROUPS 8 extern int XR_maxThreadStackGroups; extern struct XR_ThreadStackGroupRep XR_threadStackGroups[XR_MAX_THREAD_STACK_GROUPS]; #ifdef sparc # define XR_WARMSTACKSPACE (8*1024) # define XR_OFLOHANDLERSTACKSPACE (8*1024) # define XR_MIN_THREAD_STACK_BYTES \ ((16*1024)+XR_WARMSTACKSPACE+XR_OFLOHANDLERSTACKSPACE) # define XR_MAX_THREAD_STACK_BYTES ((4*1024)*1024) /* sanity check */ # define XR_THREAD_STACK_BYTES (64*1024) /* default */ #else error define stack parameters for architecture ??? #endif /* sparc */ extern int XR_threadStackBytes; extern int XR_argc; /* PCR command line argc */ extern char **XR_argv; /* PCR command line argv */ #define XR_DEFAULT_DBX_SCRIPT_NAME "XRDBXInner" extern int XR_SetDBXScriptName(/* char *name */); extern char *(XR_GetDBXScriptName()); #define XR_DEFAULT_TMP_DIRECTORY "/tmp/" extern int XR_SetTmpDirectory(/* char *dirName */); extern char *(XR_GetTmpDirectory()); extern int XR_SetPCRFileName(/* char *pcrFileName */); extern char *(XR_GetPCRFileName()); extern int XR_verbosity; /* signed, default is 0 */ #define XR_SWAP_FILE_NAME_SIZE 256 /* ??? */ extern char XR_swapFileName[XR_SWAP_FILE_NAME_SIZE]; /* ??? */ /* * Well-known address of system area */ #define XR_SA struct XR_SARep * extern XR_SA XR_sysArea; /* * Time */ extern void XR_SetBootTime (); /* Initialize boot time for later use. Called once at the beginning of time. */ /* * Debugger State */ typedef int XR_DBStat; # define XR_DBSTAT_STOP ((XR_DBStat)(-2)) # define XR_DBSTAT_RUN0 ((XR_DBStat)(-1)) # define XR_DBSTAT_RUN ((XR_DBStat)(0)) # define XR_DBSTAT_EXAMINE(pid) ((XR_DBStat)(pid)) /* External debugger sets sv_dbStat, waits for processors */ /* to copy it to vpe_dbStat. */ /* * Semaphore groups (for inter-processor communication) * * System V dependent */ typedef struct XR_SGRep { int sg_semid; /* Unix semaphore id */ int sg_numSems; /* number of semaphores in group */ } * XR_SG; extern void XR_InitSG (/* sg, count */); /* XR_SG sg; int count; Initialize semaphore group to contain `count' semaphores. */ extern void XR_PSem (/* sg, index, count */); /* XR_SG sg; int index; int count; P operation, decrementing `index'th semaphore of `sg' by `count'. Retries if interrupted by Unix signal. */ extern void XR_VSem (/* sg, index, count */); /* XR_SG sg; int index; int count; V operation, incrementing `index'th semaphore of `sg' by `count'. */ /* * VProcessor orders */ #define XR_MAX_VPO_ARGS 4 typedef struct XR_VPOrderRep { void (*vpo_proc)(/* order */); /* proc to execute, NIL okay */ bool vpo_stop; /* TRUE ==> stop VProcessors */ unsigned vpo_args[XR_MAX_VPO_ARGS]; /* argument buffer */ } * XR_VPOrder; /* * VProcessor descriptor Entry */ typedef struct XR_VPERep { unsigned vpe_index; /* index of this vpe in table */ unsigned vpe_pid; /* UNIX pid, non-0 => vprocessor running */ XR_Pri vpe_pri; /* pri of current process, for sched */ bool vpe_doSwitch; /* switch request from e.g. int handler */ XR_Ticks vpe_ticksSinceBoot;/* per-VP ticks value, see ThreadsTime.c */ unsigned vpe_orderNum; /* most recently executed order */ XR_DBStat vpe_dbStat; /* most recent sv_dbstat value read */ XR_Pointer vpe_rusage; /* --> description of resource use */ } * XR_VPE; extern XR_VPE XR_vpe; /* per-processor, non-NIL if this is a vp */ /* * IOProcessor orders -- see ThreadsOrders.c */ #define XR_MAX_IOPO_ARGS 6 #define XR_MAX_IOPO_RESULTS 2 typedef struct XR_IOPOrderRep { struct XR_IOPOrderRep * iopo_next; int iopo_done; /* iop completion code */ struct XR_CVRep iopo_cv; /* notify when order done */ void (*iopo_cancel)(/* order */); /* proc to cancel request */ void (*iopo_proc)(/* order */); /* proc to execute */ unsigned iopo_args[XR_MAX_IOPO_ARGS]; /* argument buffer */ unsigned iopo_results[XR_MAX_IOPO_RESULTS]; /* result buffer */ } * XR_IOPOrder; extern void XR_InitIOPOrder (/* iopo */); /* XR_IOPOrder iopo; */ /* * IOProcessor descriptor entry */ typedef unsigned XR_IOPEFlags; # define XR_IOP_FLAGS_STARTED 0x1 typedef struct XR_IOPERep { unsigned iope_index; /* index of this iope in table */ unsigned iope_pid; /* UNIX pid, 0 if IOPE not in use */ unsigned iope_kind; /* unique value identifies kind of iop */ /* (currently the run proc address) */ XR_IOPEFlags iope_flags; /* flag values -- kind-specific */ bool (*iope_workerProc)(); /* worker proc -- kind-specific */ struct XR_VPOrderRep iope_vpOrderBuf; /* buffer for issuing vp order */ struct XR_MLRep iope_orderLock; /* lock for vp issuing order to me */ struct XR_CVRep iope_orderAccepted; /* vp issuing order waits on this */ XR_IOPOrder iope_order; /* next order for me to execute */ unsigned iope_clientData[XR_MAX_IOPE_CLIENT_DATA]; } * XR_IOPE; extern XR_IOPE XR_iope; /* per-processor, non-NIL if this is an iop */ /* * Issue VP Orders ... * to be called by iop, NOT process */ extern void XR_IssueVPOrder (/* order, proc, stop */); /* XR_VPOrder order; void (*iopo_proc)( (* order *) ); bool stop; Assume caller has stored into order->vpo_args[]. Caller (iop) becomes sa_vpOrderMaster (if it isn't already). Every vprocessor executes `order'. Caller waits for this to complete. If stop == TRUE, all vp's stop after executing order, and caller remains sa_vpOrderMaster on return. If stop == FALSE, vp's continue after executing the order, and caller is no longer sa_vpOrderMaster on return. */ /* * Issue IOP Orders ... */ typedef int XR_IOPOResult; # define XR_IOPO_RESULT_OK ((XR_IOPOResult)(0)) # define XR_IOPO_RESULT_ABORTED ((XR_IOPOResult)(-1)) # define XR_IOPO_RESULT_TIMEDOUT ((XR_IOPOResult)(-2)) extern XR_IOPOResult XR_IssueIOPOrder (/* iop, order, proc, cancel, abortable, timeout */); /* XR_IOPE iop; XR_IOPOrder order; void (*proc)( (* order *) ); void (*cancel)( (* order *) ); bool abortable; XR_Ticks timeout; Assumes order->iopo_args[] has been filled, and caller has exclusive access to `order'. Acquires iop->iope_orderLock and stores order in iop->iope_order, unless the calling thread has previously eexcuted an XR_AcquireIOPOrderLocks. Notifies the IOProcessor that there's an order (using kill()). The IOProcessor then executes `order'. It is the (joint) responsibility of `order' and the IOProcessor to make sure that naked notifies of iop->iope_orderAccepted and order->iopo_cv will occur at the appropriate times. Waits on iop->iope_orderAccepted then releases iop->iope_orderLock. Waits on order->iopo_cv. This wait may time out or be aborted, in which case the `cancel' order (if non-NIL) is issued to the same IOProcessor that was supposed to execute the original order. Returns XR_IOPOResult indicating what happened. The value of order->iopo_done is significant even if the result is ABORTED or TIMEDOUT. The IOProcessor is free to modify order->iopo_next and order->iopo_results until it notifies order->iopo_cv. The IOProcessor must complete a `cancel' order before notifying iop->iope_orderAccepted; after that the caller is free to deallocate the XR_IOPOrder structure. */ extern XR_IOPOResult XR_IssueIOPOrders (/* XR_IOPOrder order, void (*remoteProc)(XR_IOPOrder order), void (*localProc)(XR_IOPOrder order, XR_IOPE iope) */); /* Acquire all locks and issue order to all IOPs simultaneously, unless they have already been acquired. Invoke the localProc on the issuing VP once for each IOP, just before the order is issued to that iop. The order cannot timeout or be aborted. Since multiple IOPs execute the orders, multiple results are produced. The "most interesting" results are stored in order->iopo_results[...]: when an IOP returns a result (iopo->iopo_results[...]), if( (order->iopo_result[0] == 0) -- prob. no saved result yet -- || (((int)(iopo_results[0])) < 0) -- error from this IOP -- ) order->iopo_results[*] = iopo->iopo_results[*]; IssueIOPOrders may be called only from a VP. */ XR_Thread XR_IssueingIOP0Order (); /* Return the running thread currently giving orders to iop0. Non-NIL is a hint that other vp's on the same processor might want to yield. */ extern void XR_AcquireIOPOrderLocks(); /* Require all IOP order locks, in expectation of issuing an order in the future. This is required only when it would be unsafe to acquire the lock at the time the order is issued, e.g. because the garbage collector has stopped the world. */ extern void XR_ReleaseIOPOrderLocks(); /* Release all IOP order locks. Required if, and to be used only if, they were previously acquired with XR_AcquireIOPOrderLocks(). */ extern void XR_NotifyIOPODone(/* XR_IOPOrder iopo */); /* To be called by an IOP on completion of an order. */ /* * Initial process create / destroy */ extern unsigned XR_Root (/* mp */); /* XR_MesaProc mp; Provided by client. The system starts up by forking XR_MakeMesaProc( XR_Root ) */ /* * System Area * * There's only one of these, in shared space. * It is defined to be the first thing in segment 0, * mapped to a well-known virtual memory address XR_sysArea. */ typedef struct XR_SARep { /* "metaLock" -- locks system process & timeout queues */ struct XR_PSLRep sa_metaLock; /* thread queues */ struct XR_CVRep sa_threadAvail; /* NOTIFYed just before thread freed */ /* 1 sec timeout => waiter awakens */ struct XR_TQRep sa_preFreeTQ; /* free threads not by stacksize */ struct XR_TQRep sa_freeTQ[XR_MAX_THREAD_STACK_GROUPS]; /* free threads, by stacksize */ struct XR_TQRep sa_readyTQ[XR_PRI_LAST+1]; /* ready threads, by priority */ /* scheduling control */ struct XR_MLRep sa_mlSchedCtl; /* lock for sched ctl mutex */ XR_Thread sa_schedCtlMaster; /* master for sched ctl */ struct XR_CVRep sa_cvSchedCtl; /* NOTIFied when master = NIL */ /* time, processes awaiting timeout */ struct XR_PSLRep sa_ticksSinceBootLock; struct timeval sa_bootTime; /* when system was booted */ unsigned sa_ticksSinceBoot; /* cached ticks since boot */ int sa_ticksSinceBootDeficit; /* prevent clock running backwards */ bool sa_doTimeouts; /* hint */ int sa_nTimeouts; /* number threads in timeout heap */ /* stdin */ unsigned sa_ttinRecvd; /* unix SIGTTIN from stdin */ /* "tele"-debugger stuff */ unsigned sa_dbpid; /* UNIX pid of debugger */ XR_Pointer sa_dbData; /* debugger private data */ XR_DBStat sa_dbStat; /* state-change cmd from debugger */ XR_Thread sa_examinee; /* thread being examined */ /* VProcessor, IOProcessor configuration */ unsigned sa_numVP; /* number of VProcessors */ unsigned sa_pgrpVP; /* UNIX vprocessor process group */ unsigned sa_numIOP; /* number of IOProcessors */ struct XR_MLRep sa_mlIOP; /* for allocating IOPs */ /* Issuing VP Orders */ unsigned sa_vpOrderNum; /* seq number of sa_vpOrder */ XR_VPOrder sa_vpOrder; /* order to execute */ struct XR_SGRep sa_vpOrderSem; /* sem group for vp order processing */ # define XR_VP_ORDER_SEM_LOCK 0 /* lock sa_vpOrder */ # define XR_VP_ORDER_SEM_WAIT 1 /* wait for vp's to finish order */ # define XR_VP_ORDER_SEM_LAST 1 XR_IOPE sa_vpOrderMaster; /* iop issuing orders */ /* memory map */ unsigned sa_heapNum; /* heap map generation number */ struct XR_SegRep sa_heapSeg; /* the system heap */ XR_Pointer sa_heapLimit; /* it can't grow beyond here */ struct XR_SegRep sa_sharedDataSeg; #ifdef XXXX struct XR_SegRep sa_sharedCommonSeg; struct XR_SegRep sa_sharedBSSSeg; #endif /* statistics, debugging, ... */ int *sa_stats; /* -> stats buffer */ struct XR_MLRep sa_mlRUsage; /* lock on vpe_rusage entries */ /* termination */ struct XR_PSLRep sa_terminating; /* held => terminating */ int sa_terminationStatus; /* status for exiting processes */ bool sa_suspendOnPanic; /* suspend or terminate? */ char * sa_panicMsg; /* system panic message */ /* buffer space */ XR_Thread sa_timeouts[XR_MAX_THREADS+1]; struct XR_VPERep sa_vpe[XR_MAX_VPS]; struct XR_IOPERep sa_iope[XR_MAX_IOPS]; struct XR_ThreadRep sa_threadPool[XR_MAX_THREADS]; XR_Pointer sa_clientData[XR_MAX_SA_CLIENT_DATA]; #undef XR_SA } * XR_SA; /* * enumerate all active threads */ extern bool XR_ApplyToActiveThreadStacks (/* bool (*proc)(void *stackp, void *stacklimit, void *clientData), void *clientData */); /* Apply proc to stacks of all active threads. Return TRUE if enumeration finishes. Abort enumeration and return FALSE if proc ever returns FALSE. This is reliable only if called from IOP with VProcessors stopped! */ #endif _XR_THREADS_BACKDOOR_