\section{Global Variables and Utility functions}
\label{globalvars}

Different vendors are not consistent about how they treat global and static
variables.  Most vendors write C compilers in which global variables are
shared among all the processors in the node.  A few vendors write C
compilers where each processor has its own copy of the global variables.
In theory, it would also be possible to design the compiler so that
each thread has its own copy of the global variables.

The lack of consistency across vendors, makes it very hard to write a
portable program.  The fact that most vendors make the globals shared
is inconvenient as well, usually, you don't want your globals to be
shared.  For these reasons, we added ``pseudoglobals'' to \converse{}.
These act much like C global and static variables, except that you have
explicit control over the degree of sharing.

\subsection{\converse{} PseudoGlobals}

Three classes of pseudoglobal variables are supported: node-private,
process-private, and thread-private variables.

\begin{description}
\item[Node-private global variables] are specific to a node. They are
     shared among all the processes within the node.
\item[Process-private global variables]  are specific to a process. They are
     shared among all the threads within the process.
\item[Thread-private global variables] are specific to a thread. They are 
     truely private.
\end{description}

There are five macros for each class. These macros are for
declaration, static declaration, extern declaration, initialization,
and access. The declaration, static and extern specifications have the
same meaning as in C. In order to support portability, however, the
global variables must be installed properly, by using the
initialization macros.  For example, if the underlying machine is a
simulator for the machine model supported by \converse{}, then the
thread-private variables must be turned into arrays of variables.
Initialize and Access macros hide these details from the user.  It is
possible to use global variables without these macros, as supported by
the underlying machine, but at the expense of portability.

Macros for node-private variables:

\function{CsvDeclare(type,variable)}
\function{CsvStaticDeclare(type,variable)}
\function{CsvExtern(type,variable)}
\function{CsvInitialize(type,variable)}
\function{CsvAccess(variable)}

\index{CsvDeclare}
\index{CsvStaticDeclare}
\index{CsvExtern}
\index{CsvInitialize}
\index{CsvAccess}

Macros for process-private variables:

\function{CpvDeclare(type,variable)}
\function{CpvStaticDeclare(type,variable)}
\function{CpvExtern(type,variable)}
\function{CpvInitialize(type,variable)}
\function{CpvAccess(variable)}

\index{CpvDeclare}
\index{CpvStaticDeclare}
\index{CpvExtern}
\index{CpvInitialize}
\index{CpvAccess}

Macros for thread-private variables:

\function{CtvDeclare(type,variable)}
\function{CtvStaticDeclare(type,variable)}
\function{CtvExtern(type,variable)}
\function{CtvInitialize(type,variable)}
\function{CtvAccess(variable)}

\index{CtvDeclare}
\index{CtvStaticDeclare}
\index{CtvExtern}
\index{CtvInitialize}
\index{CtvAccess}


A sample code to illustrate the usage of the macros is provided
in Figure~\ref{fig:cpv}.
There are a few rules that the user must pay attention to: The
{\tt type} and {\tt variable} fields of the macros must be a single
word. Therefore, structures or pointer types can be used by defining
new types with the {\tt typedef}. In the sample code, for example,
a {\tt struct point} type is redefined with a {\tt typedef} as {\tt Point}
in order to use it in the macros. Similarly,  the access macros contain
only the name of the global variable. Any indexing or member access
must be outside of the macro as shown in the sample code 
(function {\tt func1}). Finally, all the global variables must be
installed before they are used. One way to do this systematically is
to provide a module-init function for each file (in the sample code - 
{\tt ModuleInit()}. The module-init functions of each file, then, can be 
called at the beginning of execution to complete the installations of 
all global variables.

\begin{figure}
\begin{alltt}
File: Module1.c

    typedef struct point
    \{
         float x,y;
    \} Point;


    CpvDeclare(int, a);
    CpvDeclare(Point, p);

    void ModuleInit()
    \{
         CpvInitialize(int, a)
         CpvInitialize(Point, p);

         CpvAccess(a) = 0;
    \}

    int func1() 
    \{
         CpvAccess(p).x = 0;
         CpvAccess(p).y = CpvAccess(p).x + 1;
    \}
\end{alltt}
\caption{An example code for global variable usage}
\label{fig:cpv}
\end{figure}

\subsection{Utility Functions}
\label{utility}

To further simplify programming with global variables on shared memory
machines, \converse{} provides the following functions and/or
macros. \note{These functions are defined on machines other than
shared-memory machines also, and have the effect of only one processor
per node and only one thread per processor.}

\function{int CmiMyNode()}
\index{CmiMyNode}
\desc{Returns the node number to which the calling processor belongs.}

\function{int CmiNumNodes()}
\index{CmiNumNodes}
\desc{Returns number of nodes in the system. Note that this is not the
same as \param{CmiNumPes()}.}

\function{int CmiMyRank()}
\index{CmiMyRank}
\desc{Returns the rank of the calling processor within a shared memory node.}

\function{int CmiNodeFirst(int node)}
\index{CmiNodeFirst}
\desc{Returns the processor number of the lowest ranked processor on node
\param{node}}

\function{int CmiNodeSize(int node)}
\index{CmiNodeSize}
\desc{Returns the number of processors that belong to the node \param{node}.}

\function{int CmiNodeOf(int pe)}
\index{CmiNodeOf}
\desc{Returns the node number to which processor \param{pe} belongs. Indeed,
\param{CmiMyNode()} is a utility macro that is aliased to 
\param{CmiNodeOf(CmiMyPe())}.}

\function{int CmiRankOf(int pe)}
\index{CmiRankOf}
\desc{Returns the rank of processor \param{pe} in the node to which it belongs.}

\subsection{Node-level Locks and other Synchronization Mechanisms}
\label{nodelocks}

\function{void CmiNodeBarrier()}
\index{CmiNodeBarrier}
\desc{Provide barrier synchronization at the node level, i.e. all the 
processors belonging to the node participate in this barrier.}

\function{typedef McDependentType CmiNodeLock}
\index{CmiNodeLock}
\desc{This is the type for all the node-level locks in \converse{}.}

\function{CmiNodeLock CmiCreateLock(void)}
\index{CmiCreateLock}
\desc{Creates, initializes and returns a new lock. Initially the
lock is unlocked.}

\function{void CmiLock(CmiNodeLock lock)}
\index{CmiLock}
\desc{Locks \param{lock}. If the \param{lock} has been locked by other
processor, waits for \param{lock} to be unlocked.}

\function{void CmiUnlock(CmiNodeLock lock)}
\index{CmiUnlock}
\desc{Unlocks \param{lock}. Processors waiting for the \param{lock} can
then compete for acquiring \param{lock}.}

\function{int CmiTryLock(CmiNodeLock lock)}
\index{CmiTryLock}
\desc{Tries to lock \param{lock}. If it succeeds in locking, it returns
0. If any other processor has already acquired the lock, it returns 1.}

\function{voi CmiDestroyLock(CmiNodeLock lock)}
\index{CmiDestroyLock}
\desc{Frees any memory associated with \param{lock}. It is an error to
perform any operations with \param{lock} after a call to this function.}

\zap{
\function{void *CmiSvAlloc(int size)}
\index{CmiSvAlloc}
\desc{Allocates a block of memory of \param{size} bytes from the heap in node's 
local memory and returns pointer to the start of this block. \note{On 
machines other than shared-memory machines, this is equivalent to 
\param{CmiAlloc}.}}
}
