Copyright (c) 1993 Xerox Corporation. All rights reserved. TODO: - sigsetjmp nyi - the PCR_IO_gfdLim and PCR_IOGblUFSImpl_openFileMax stuff in PCR_IOGblUFSImpl_Setup needs to become OS dependent?! - There is no fcntl/ioctl implementation in PCR_IOGblUFSImpl.c!!! - What is the organization for optional things? e.g. sockets? seems like the simplest thing is to make the header file break if not defined(PCR_NO_HOSTDEP_ERR). A special subdir hostdep behaves like ansi and posix, has includes that may or may not be implemented. - Emulation for non-blocking I/O ????? - think about which signals cannot be caught and by whom? - There is no implementation of advisory record locking yet. - the typical cc include file mechanism picks up the wrong file when host include files include what should be other host include files. Often a PCR include file will be used, instead. - need a way to start pcr that displays help for its supported switches SIGNAL STUFF TODO: fix default handler to do sanity checks - Does the PCR implementation get to use the string compare procs under their usual names? This is probably safe in most implementations, but I do have a bit of exposure here. What is it? - Threads (preemptive prio sched) dyload (commit/abort), GC (conservative, useful for C). - Thread-safe ANSI C library. - POSIX.1 compliant ANSI C programs run as threads. This implies a certain amount of state -- working directory, (some) file descriptors, local data for some C library procedures, etc. -- must be kept per-thread. - Source-level POSIX.1 implementation, client code must be compiled with special PCR header files. - Renaming => must include files for all POSIX symbols referenced or things break. Use dyloading to develop code. PCR_ERes and PCR_GetErrno() The model of signal interaction res = PCR_Foo(...,PCR_sigset_t *sigMask, PCR_MSecs wakeup) interpretation of the sigMask and wakeup parameters Externally generated signals caught by high-priority thread that redistributes them as required. Naming conventions for PCR identifiers, files, ... Startup - main is in a client routine *not* compiled with symbol translation turned on in the pcr headers? What is the client entitled to do? - PCR_BaseArgs used to split/interpret args List of Public Interfaces with brief explanation of each ... ansi, base, cmd, config, dbg, emu, il, mm, sig, th, vd Base Startup, some other utilities that pertain to the entire PCR world. Optional(?) utilities for parsing Unix-like command lines. Cmd Optional. No setup. Implementation of a simple command interpreter for use with dyload, etc. Config Not directly used by clients. Configuration stuff for porting between architectures and operating systems. Dbg I don't know what to do about this one. It is a trivial interface, but if there's going to be a Cirio-like thing, there will have to be something like this institutionalized. Emu Not directly used by clients. Implementations of PCR emulations of POSIX, ANSI, and hostdep stuff. Exec Uses a process forked at pcr startup to exec other host applications. Starting pcr with the -noexec option prevents the server process from being forked (and of course, suppresses the ability to do the exec operations). IL Incremental loader. (Can this be made optional?) Discussion of loader lock; symbol binding; commit/abort. ??? discussion somewhere of how to write a file reader ??? IO Input/Output. Here we need to explain the difference between local and global descriptors. Ugh. MM Allocation / memory management. Same interface whether or not the GC is included. Without a GC, PCR itself leaks memory a bit. Sig Some signal IDs and types, plus the interface used to catch externally generated signals. Th Threads stuff. Note ThCtl and ThUWProt. (Here's something that depends on setjmp.h!) Per-thread signals are here. VD Not directly used by clients. Virtual dirty bits, used by GC. Introduction This is PPCR, (POSIX Portable Common Runtime), a completely new implementation of the Xerox Portable Common Runtime described in [???]. Unlike the original, it is intended (and believed) to be lightweight and portable enough for use by mere mortals. PPCR consists of: A lightweight threads package with preemptive priority scheduler. Threads behave sensibly with respect to I/O and blocking (emulated) system calls -- the thread invoking the operation may block, but other threads continue to run. A dynamic object code (re-)loading facility, with client access to runtime symbol tables. A conservative (hence non-copying), mostly-parallel (hence nearly real-time) garbage collector based on the work described in [xx], [yy], [zz]. We routinely use this collector on hand-written C code as well as on the C code produced by our Cedar compiler. Miscellaneous other creature comforts. The "POSIX" refers to refers to POSIX.1 (IEEE Std 1003.1-1990 [??]), not (yet) the IEEE Realtime Extensions [??] or PThreads [??] efforts. PPCR relates to POSIX.1 in two ways: As a client: PPCR should be easily portable to any (32-bit, byte- addressed) system providing POSIX.1 and a very minimal set of extensions. PPCR is written in ANSI C, assuming the Multiple External Definitions extension defined in Section F.5.11 of the ANSI C definition [??], and assuming reasonably long case- sensitive external symbols. It is compatible with version 2.1 the gnu C compiler. As an implementation: PPCR provides a nearly exact ANSI C POSIX.1 environment for each thread independently. That is, multiple POSIX.1 compliant (ANSI) C programs can run without source changes as separate threads in the same PPCR world, without interfering with one another. In particular, PPCR includes (nearly) complete thread-safe POSIX.1 emulation and ANSI C libraries. To make this work, PPCR maintains considerable state (e.g. the current working directory, (some) file descriptors, local data for certain library procedures) on a per-thread basis. Note that POSIX.1 is a source code standard, not an object code standard. PPCR provides its own set of {ANSI,POSIX} header files. Code to be run inside PPCR must be compiled using these files; otherwise it will not work and is likely to crash PPCR. Organization Organization PPCR consists of a number of components, some of which are optional or host-dependent. Each component occupies a separate subdirectory of the distribution directory. Naming conventions To make up (in part) for the lack of qualified names in C and Unix, PPCR adheres to a strict set of naming conventions for files and global variables: Every (file or variable) name within PPCR begins with the 4-character sequence "PCR_". Consequently, client programs should avoid such names. (Already this means PPCR is not quite POSIX compliant, but we believe the number of programs that will break because of this name space restriction is acceptably small). The next few letters of a file name usually identify the component (subdirectory) containing the file. For example, PCR_Th.h is in the th (threads) component, while PCR_IOLcl.h is in the io component. A C identifier with file or global scope will usually begin with an indication of its declaring (header or implementation) file, followed by an underscore. For example, the procedure PCR_IOGbl_FPathConf is declared in io/PCR_IOGbl.h, and defined in io/PCR_IOGblImpl.c; while the static variable PCR_IOGblUFSImpl_methods is both declared and defined in io/PCR_IOGblUFSImpl.c. Usually an initial uppercase letter indicates a type or procedure name (so an initial lowercase letter indicates a variable or constant name). For example, PCR_Th_Fork is a procedure, PCR_Th_CV is a type, and PCR_Th_CV_null is a constant of that type. An important departure from this convention is names that are part of the ANSI or POSIX.1 standards. These are renamed by prepending "PCR_" with no other change. For example, the PPCR fcntl.h header file renames open to PCR_open (using #define). The ansi directory This contains PPCR versions of all the standard ANSI header files. In most cases these files use the C preprocessor to rename symbols (e.g. strtok becomes PCR_strtok) unless the preprocessor variable PCR_NO_RENAME is set. This trick allows PPCR to be both a client and an implementation of the ANSI library, enabling thread-safe versions of many procedures to be implemented in terms of their host-provided (possibly thread-unsafe) versions. The posix directory This contains PPCR versions of all the standard POSIX.1 header files. In most cases these #include the corresponding header files of the host OS and do preprocessor tricks to rename symbols (e.g. open becomes PCR_open) unless the preprocessor variable PCR_NO_RENAME is set. This trick enables PPCR to be both a client and an implementation of the POSIX.1 interface, as described above for the ANSI library. The hostdep directory This directory contains PPCR header files for features that are not ANSI or POSIX mandated, and are host-dependent or may be unimplemented on some hosts. The hostansi directory This is a symbolic link to the directory containing the ANSI include files provided with the host OS. The hostposix directory This is a symbolic link to the directory containing the POSIX.1 include files provided with the host OS. The threads directory This is a major component of PPCR. It includes several public or semi-public interfaces: PCR_Th.h Types and operations for dealing with threads monitor locks and conditions timeouts asynchronous signals are defined here. PCR_ThUWProt.h PCR_ThDynEnv.h ??? Two different interfaces that support unwinding of stacks. They don't (yet) know about one another. PCR_ThDynEnv.h supports a general dynamic environment, including other data in addition to just unwind protection. PCR_ThUWProt.h interacts correctly with calls to setjmp()/longjmp(). PCR_ThCtl.h An interface to allow threads to exercise control over other threads. This is primarily for use by the garbage collector, but other clients can use it as well. PCR_ThData.h An interface to support arbitrary per-thread data. This makes special provision for the PPCR builtin ANSI/POSIX emulations; other clients need to cooperate, at least to the extent of knowing about one another's index values. ??? Possibly this should be fixed ??? The base subdirectory This directory contains the PPCR startup procedure and some utilities that pertain to the entire PPCR world. PCR_Base.h Procedures to start and terminate the entire PPCR world. PCR_BaseArgs.h Procedures that enable client threads to access command-line arguments supplied to PPCR. The config directory This directory contains OS and architecture configuration information, plus some ubiquitous datatypes and their associated operations. PCR_Arch.h Identification and description of the host architecture: word size, big-endian or little-endian, etc. PCR_OS.h Identification of the host OS, plus description of those areas where PPCR's use of it deviates from strict POSIX compliance. PCR_StdDefs.h This file is included indirectly by nearly every PPCR header file. It cointains two important definitions: PCR_Any, an arithmetic type capable of containing either a void * or a long without information loss. Defining this as a union type would have undesirable consequences (e.g. with respect to parameter passing) on some systems PCR_ERes, the result type of most PPCR "system calls." By convention, a nonnegative value is success of some kind, while a negative value is an error code. Arguably this file is mislocated, and it may move in the future. The dbg directory ??? I have no idea about this ??? The emu directory This directory contains implementations of PPCR's ANSI and POSIX.1 emulations. There is a complete ANSI C library, including compatible thread-safe and thread-unsafe versions of stdio. There are emulations of all required POSIX.1 calls. Both the ANSI and POSIX emulations are basically clients of the rest of PPCR, and it can be built without including them. Per-thread state required for these emulations is maintained using the th/PCR_ThData.h package. Installation / Portability ??? what makefile, sed, ld, cc ??? C external symbol / common resolution rules Include file lookup rules ??? If you don't have a -I... you're in trouble. If nested includes behave differently you're in trouble.