[gnu.gcc.bug] perprocess variable proposal

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