occam-pi powered

Valid CSS!

Valid XHTML 1.1!

Last modified 3rd May 2005
This document is maintained by Fred Barnes
Department of Computer Science, University of Kent.

The occam-pi C interface

This page documents the C interface (CIF) for the KRoC occam-pi system. This allows processes written in C to run alongside and communicate with occam-pi processes, using an extended version of the CCSP/MESH API, based on the original INMOS C API.

[ C processes | process control | communication | mobiles | time | priority | low-level process control | occam-pi features | miscellaneous | external calls | index ]

C Processes

The C interface for the KRoC occam-pi system attempts to follow the existing INMOS C API, so existing (and probably quite old) C applications can be ported with relative ease. Applications which previously used CCSP should also be portable with minimum effort. The existing C API has been extended to cover the new features of occam-pi (e.g. mobile data, channels, processes and barriers).

Starting a C process from occam requires an externally called allocation routine, that returns a Process * to occam as an INT. The process is then run (from occam) using a small stub routine, cifccsp.startprocess (INT addr), that returns only when the C process terminates/returns. The various CIF example programs ("cif/examples/" in the KRoC distribution) do allocation this way, in some cases cleaning up afterwards (if the C process is expected to terminate). For example:


    #INCLUDE "cifccsp.inc"

    #PRAGMA EXTERNAL "PROC C.example.init (CHAN BYTE kyb?, scr!, err!, RESULT INT addr) = 0"
    #PRAGMA EXTERNAL "PROC C.example.cleanup (INT addr) = 0"

    PROC example (CHAN BYTE kyb?, scr!, err!)
      INT addr:
      SEQ
        C.example.init (kyb?, scr!, err!, addr)
        cifccsp.startprocess (addr)
        C.example.cleanup (addr)
    :
		

The two external calls are declared starting "C.", indicating that these are ordinary external C calls -- i.e. those functions execute in the stack of the KRoC run-time system and must not call any CIF functions that require a process context. A typical implementation of the above C functions could be:


    #include "cifccsp.h"

    /* actual functions */

    static void real_example_init (Channel *kyb, Channel *scr, Channel *err, Process **pptr)
    {
        *pptr = ProcAlloc (demo_process, 65536, 3, kyb, scr, err);
        return;
    }

    static void real_example_cleanup (Process **pptr)
    {
        ProcAllocClean (*pptr);
        *pptr = NULL;
        return;
    }

    /* interface glue */

    void _example_init (int *ws) {
        real_example_init ((Channel *)(ws[0]), (Channel *)(ws[1]), (Channel *)(ws[2]),
                           (Process **)(ws[3]));
    }

    void _example_cleanup (int *ws) {
        real_example_cleanup ((Process **)(ws[0]));
    }
		

The other required function is the actual "demo_process" process. Unlike the C functions above, this runs in a process context. I.e. it has its own stack (65536 bytes) and may communicate on the 3 channels passed to it. A simple hello-world process could be implemented using:


    static void demo_process (Process *me, Channel *kyb, Channel *scr, Channel *err)
    {
        static char *message = "hello, C world!\n";
        char *ch;

        for (ch = message; *ch != '\0'; ch++) {
            ChanOutChar (scr, *ch);
        }
    }
		

This simple process only uses ChanOutChar(); the various other CIF examples are more extensive, covering: building and running process networks; communication with parallel occam-pi processes; external C calls; blocking system-calls; time and timeouts; mobile channel-type parameters, communication and shared-end handling; plus a variety of others. To compile the above C fragment, a command similar to the following should be used, assuming the above C code is in a "demo.c" file:


    bash$ gcc -O2 -Wall -fomit-frame-pointer -fno-defer-pop -c -o demo.o demo.c
		

The corresponding occam-pi code (e.g. in "mydemo.occ") would then be compiled with:


    bash$ kroc mydemo.occ demo.o -lcif
		

The following sections describe the API for C processes, grouped by functionality. In most cases, these "functions" are pre-processor macros that translate to C function calls or inline assembler, defined in the "cifccsp.h" file.

Process Control

These functions provide mechanisms to allocate, free and run processes. The functions ProcAlloc(), ProcInit(), ProcParam(), ProcAllocClean() and ProcInitClean() may be called from outside of a CIF process context.

Communication

These functions provide mechanisms to allocate, free and communicate over channels. Because occam-pi channels only consist of a single word, declarations of Channels may be made outright, instead of declaring a pointer and using ChanAlloc()/ChanAllocClean().

Mobiles

These functions provide for mobile communication. KRoC supports various types of static and dynamic mobile; dynamic mobiles are allocated and free'd using the dynamic memory allocation instructions DMemAlloc() and DMemFree(), described below. Dynamic mobile communication and assignment is strictly one-way in the implementation: processes that output a dynamic mobile must consider it undefined afterwards (unless the mobile is shared and the reference-count adjusted appropriately); processes that input dynamic mobiles should ensure any previously held dynamic mobile is free'd appropriately. The various mobile types currently supported by KRoC are:

  1. Static mobiles: fixed-size mobiles (typically MOBILE RECORD structures), that are always allocated. Communication and assignment in the same memory-space are implemented by pointer-swapping. The ChanMIn()/ChanMOut() functions are used for static mobile communication.

  2. Dynamic mobile arrays: run-time sized mobiles (e.g. MOBILE []BYTE arrays). In memory, the dimension counts follow the data pointer at increasing addresses. 1-dimensional arrays are communicated using ChanMIn64() and ChanMOut64(). Arrays of higher dimensions are communicated using ChanMInN() and ChanMOutN().

  3. Dynamic mobile channel-types: a bundle of channel-words with a reference-count, optional type description and hook fields, and optional client-end and server-end semaphores (for handling shared ends). Communication of these is done using the ChanMInN() and ChanMOutN() functions with a word-count of 1. The semaphore operations are described below.

  4. Dynamic mobile barriers: the occam-pi MOBILE BARRIER type, used for process synchronisation. These are always shared in occam-pi, C code can choose to output and keep (incrementing the reference-count), or output and lose (not touching the reference-count). Mobile barriers are comunicated using the ChanMInN() and ChanMOutN() functions with a word-count of 1. The C structure MBarrier is defined by CIF, reflecting the structure of the corresponding occam-pi type. Barrier-specific functions are described below.

  5. Dynamic mobile processes: occam-pi mobile process variables. Communication of these is done using the ChanMInN() and ChanMOutN() functions with a word-count of 1. The C interface does not yet support creation, activation or suspension of mobile processes -- they may only be communicated through it currently.

The communication functions are:

Time

The following functions are provided for handling time in CIF. These follow the occam-pi representation of time, a signed 32-bit integer that counts in micro-seconds (giving a range of approximately 35 minutes in the past or future). The CIF header file "cifccsp.h" defines a Time type, unless the pre-processor define "CIF_NO_TIMEDEF" is defined -- necessary when combining CIF with code that defines a Time type for itself, that must not be used with CIF time-related functions if a different type. Careful separation of code between source files can overcome such issues.

Process Priority

The following functions deal with process priority in occam-pi. The current run-time supports 32 levels of priority, 0 being the highest (and default priority), and 31 the lowest. Process priority scheduling is strict, in that a higher priority process will always run before a lower priority process. However, event priority where used (PRI ALT in occam-pi, and the default behaviour of ProcAlt()) overrides process priority. CIF provides additional ProcProcPriAlt() functions (described here) which are aware of process priority, giving it precedence over event priority.

Low-Level Process Control

These functions provide for low-level process control, i.e. starting and stopping processes, and run-queue manipulation. General code should not need to use these, but they are provided for completeness and are required for certain things.

occam-pi Features

These functions provide access to a range of occam-pi specific language/run-time features.

Miscellaneous

These are functions that do not fit neatly into the above categories.

External Calls

Four macros are provided to handle external (blocking and non-blocking) C calls in CIF. When POSIX threads are enabled, external C calls to certain library functions must be wrapped by the EXTERNAL_CALL/EXTERNAL_CALLN macro. This ensures that the call executes within a genuine POSIX thread stack, otherwise certain functions will fail. External calls, both blocking and non-blocking, may not use process-context dependant CIF calls. In the case where POSIX threads are not enabled, the EXTERNAL_CALL/EXTERNAL_CALLN macros do nothing. Note that if the return value of an external call is required (and POSIX threads are enabled), suitable glue-code will be required to capture it.

Index of Functions

The following table gives an alphabetised index of the above CIF functions/macros.

BLOCKING_CALLexternal blocking C call.
BLOCKING_CALLNexternal blocking C call.
ChanAllocallocates a channel.
ChanAllocCleanfrees a channel.
ChanIngeneric channel input.
ChanInCharbyte channel input.
ChanInIntinteger channel input.
ChanInitinitialises a channel
ChanMInstatic mobile input.
ChanMIn6464-bit dynamic mobile input.
ChanMInNgeneric dynamic mobile input.
ChanMOutstatic mobile output.
ChanMOut6464-bit dynamic mobile output.
ChanMOutNgeneric dynamic mobile output.
ChanOutgeneric channel output.
ChanOutCharbyte channel output.
ChanOutIntinteger channel output.
ChanXAbleextended input enable.
ChanXEndextended input end.
ChanXInextended input.
ChanXMInextended static mobile input.
ChanXMIn64extended 64-bit dynamic mobile input.
ChanXMInNextended generic dynamic mobile input.
CTSemClaimclaims a channel-type semaphore.
CTSemInitinitialises channel-type semaphore.
CTSemReelasereleases a channel-type semaphore.
DMemAllocdynamic memory allocation.
DMemFreedynamic memory release.
EXTERNAL_CALLexternal C function call.
EXTERNAL_CALLNexternal C function call.
GetPriget process priority.
MBarrierAllocallocates a mobile barrier.
MBarrierAllocCleanfrees a mobile barrier.
MBarrierEnrollenrolls processes on a mobile barrier.
MBarrierInitinitialises a mobile barrier.
MBarrierResignresigns processes from a mobile barrier.
MBarrierSyncsynchronises on a mobile barrier.
ProcAfterdelay process.
ProcAllocallocates and initialises a new process.
ProcAllocCleanfrees a process.
ProcAltalternation.
ProcAltListalternation.
ProcForkspawns a new concurrent process.
ProcInitallocates and initialises a new process with a specified stack.
ProcInitCleanfrees a process.
ProcParruns processes in parallel.
ProcParamsets parameters of a process.
ProcParListruns processes in parallel.
ProcPriParruns processes in parallel at specified priority levels.
ProcPriParListruns processes in parallel at specified priority levels.
ProcPriRunscheduled a process at a specific priority.
ProcProcPriAltprocess prioritised alternative.
ProcProcPriAltListprocess prioritised alternative.
ProcRunschedules a process.
ProcStopdeschedules a process.
ProcTimereads the current time.
ProcTimeAfterwait until specified time.
ProcTimeMinussubtracts time values.
ProcTimePlusadds time values.
Reschedulereschedules process.
SaveLload run-queue pointers.
SavePriload run-queue poitners for a specific priority.
SetErrgenerate a trappable run-time error.
SetPriset process priority.
StLBstore run-queue back-pointer.
StLFstore run-queue front-pointer.
StPriBstore run-queue back-pointer for a specific priority.
StPriFstore run-queue front-pointer for a specific priority.

Copyright © 2005, Fred Barnes, Department of Computer Science, University of Kent.