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.