ham@Neon.Stanford.EDU (Peter R. Ham) (09/14/89)
Proposed: Perprocess Variable Extension to C The goal of this extension is to provide global variables that are private to a single thread in a multi-threaded, shared memory program. In this discussion, process is synonymous with thread. This extension assumes multi-threaded, shared memory, and single address space programs. In this scheme, global variables in the source code may have one of the following to mutually exclusive attributes: "shared" or "perprocess". Every thread with a program posesses its own private copy of the programs set of perprocess variables. Only one copy of shared variables exist per program. All threads within a program have equal and unsynchronized access to these shared variables. At process creation, child processes inherit the values of their parent's perprocess variables. During program initialization, the root thread's perprocess variables may be intialized with constant values specified in the program text or left uninitialized just as shared variables may be. Global variables are "perprocess" by default. If global variables are to be shared among threads, then they are declared "shared". This ensures that only variables that the programmer explicity intends to be shared are shared, eliminating unintended race conditions and side effects by other processes. Caveats: Note that the address of a perpocess variable is not a compile time value. Thus, the following program fragment: int foo; int *bar = &foo; Is illegal because the address of foo is dependent on the current process. The following code is legal: shared int foo; int *bar foo; since the addresses of shared variables are known at compile time. Note: Spinlock variables should always be shared. Implementation: At Stanford's Distributed Systems Group, we have implemented perprocess variables for both the vax and m68k architectures running under the V Distributed System. The V systems supports multiple threads and shared memory communication between them. A register is reserved to point to a processes perprocess area. All perprocess variables are references off of this register. The use of this register is transparent to the C programmer. This implementation is based on the GNU compilation system. Changes were required in the compiler, assembler, linker, and related programs. The BSD-style GNU object format was extended to support two additional segments: the initialized and uninitialized perprocess segments of the program's root thread. The V System program loader was modified to accept the new object format. With the increasing popularity of threads, this extension should become increasingly useful. Other work: Apparently, Sequent and Encore systems have similar support for "private" and "shared" variables. The difference between this approach and the Sequent one is that Sequents environment is not a shared memory (threads) one by default. Instead, address spaces must be explicitly shared. In the V System, the operating system kernel itself is unaware of perprocess versus shared variables, but supports threads and shared memory. I don't know what the GNU OS will be like, but if it is like Mach, then both of these models can be supported, but object format changes will have to be made. Since the storage models of C and C++ are essentially the same. C++ could be similarly extended with "shared" and "perprocess" variables. It would be nice for people with multiple processing interests in gcc to coordinate their efforts. I would love to have my stuff integrated into gcc proper. Currently, my changes are #ifdef in my copy of the source code. I'd love to get my stuff into gcc proper, but didn't think that it was applicable. My design and implementation may not be what you want exactly, but I'm definitely willing to comprimise to get the general concept into the Gnu compilation system. Please comment. Peter -- Peter Ham PO Box 3430 (h)(415) 324-9645 MS Computer Science Student Stanford, CA ham@polya.stanford.edu Stanford University 94309 (o)(415) 723-2067
crowl@cs.rochester.edu (Lawrence Crowl) (09/14/89)
In article <HAM.89Sep13105654@Neon.Stanford.EDU> ham@Neon.Stanford.EDU (Peter R. Ham) writes: > >Proposed: Perprocess Variable Extension to C > >The goal of this extension is to provide global variables that are private to >a single thread in a multi-threaded, shared memory program. In this >discussion, process is synonymous with thread. This extension assumes >multi-threaded, shared memory, and single address space programs. In this >scheme, global variables in the source code may have one of the following to >mutually exclusive attributes: "shared" or "perprocess". C does not have a notion of thread or of process. To add the concept of a 'perprocess', you must impose a model of 'process'. You also assume a rather specific uniform-memory-access architecture. I use a non-uniform-memory-access archtecture in which *where* the data lives is every bit as important as whether or not it is shared. I believe it is premature to impose a process model on C. Therefore, 'perprocess' variables are too specific and premature. >Global variables are "perprocess" by default. If global variables are to be >shared among threads, then they are declared "shared". ... Note that the >address of a perpocess variable is not a compile time value. Thus, the >following program fragment: > > int foo; int *bar = &foo; > >Is illegal because the address of foo is dependent on the current process. This is inconsistent with the current definition of C. I must be able to run current single-thread programs without modification. >A register is reserved to point to a processes perprocess area. All >perprocess variables are references off of this register. The use of this >register is transparent to the C programmer. We can achieve near this effect through use of the GNU global register variable facility. Define all 'perprocess' variables as members of a structure type. And then set the global register variable to point to the current process's 'perprocess' variables. For example, struct perprocess { ... } ; register struct perprocess *my_process asm ( "a5" ) ; In contrast to the proposed 'perprocess' variables, using a global register variable: - does not require modification of the GNU compilation system - does not presume a model of processes - does not presume an architecture - does require explicit structure access - does require explicit structure initialization (as opposed to the inheritance proposed) In summary, the mechanisms are in place to get near the semantics you want, with a little extra programmer effort. To do better requires making assumptions in C about the machine architecture and process model that I believe are premature for *C*. So, I believe the 'perprocess' proposal should not be adopted. -- Lawrence Crowl 716-275-9499 University of Rochester crowl@cs.rochester.edu Computer Science Department ...!{allegra,decvax,rutgers}!rochester!crowl Rochester, New York, 14627