sc.h File Reference

#include <stdio.h>

Go to the source code of this file.

Defines

#define mytrace
#define instrCnt
#define _BEGIN   do {
 Begin/end a macro.
#define _END   } while (0)
#define _idMax   8*sizeof(threadvector)
 Number of threads.
#define clearPC(id)
#define initPC(p, label)
#define setPC(id, label)
#define _declState
 Dispatcher.
#define _BEGIN_SWITCH
#define _END_SWITCH
#define _
#define _break
#define _SC_LABEL(label)   label
#define _goto_init(label)   goto label
#define _goto(label)   goto label
#define _goto_disp(label)   goto label
#define _deref(label)   *label
#define _ref(label)   &&label
#define _setStateInit
#define _while(cond)   while (cond)
#define selectCid_()   selectCid()
#define dispatch_init()   selectCid_(); _goto_init(_deref(_pc[_cid]))
#define dispatch()   selectCid_(); _goto_disp(_deref(_pc[_cid]))
#define u2b(u)   (1 << u)
 Encoding of signal/thread 'u' (some non-negative int) in bitvector.
#define enable(id)
 Thread enabling/disabling.
#define enableInit(id)
#define disable(id)   enabled &= ~u2b(id)
#define disableSet(idset)   enabled &= ~idset
#define isEnabled(id)   (enabled & u2b(id))
#define isEnabledNotOnly(id)   (enabled != u2b(id))
#define isEnabledNoneOf(idset)   ((enabled & idset) == 0)
#define activate(id)   active |= u2b(id)
 Thread (de-)activation.
#define deactivate(id)   active &= ~u2b(id)
#define deactivateSet(idset)   active &= ~idset
#define isActive(id)   (active & u2b(id))
#define _TickEnd   0
#define TICKSTART(isIni, p)
 Start a tick (an instant). 'p' denotes the main thread.
#define TICKEND
 Complete a tick.
#define dispatch_   _goto(_L_dispatch)
#define dispatch_init_   _goto_init(_L_dispatch)
#define mergedDispatch
#define _CONCAT_helper(a, b)   a ## b
 Construct a label, of the form "_L'line in source file'".
#define _CONCAT(a, b)   _CONCAT_helper(a, b)
#define __LABEL__   _CONCAT(_L, __LINE__)
#define __LABELL__   _CONCAT(_LL, __LINE__)
#define PAUSE
 Pause a thread, resume at subsequent statement.
#define PAUSEG(label)
 Shorthand for 'PAUSE; GOTO(label)'.
#define PAUSEG_(label)
 Helper function (if/else-unsafe).
#define HALT
 Shorthand for 'label: PAUSE; GOTO(label)'.
#define SUSPEND(cond)
 Suspend current thread if 'cond' is true.
#define SUSPENDG(label)
 Suspend current thread, goto 'label'.
#define TRANS(label)
 Transition to 'label', kill descendant threads (implements abortion).
#define ABORT
 Abort (terminate) descendant threads.
#define ABORT_
 Helper function (if/else-unsafe).
#define TERM
 Terminate a thread.
#define TERM_   _goto(_L_TERM)
 Helper function (if/else-unsafe).
#define FORK(label, p)
 Spawn a thread at 'label', with priority 'p'.
#define FORK_(label, p)
 Helper function (if/else-unsafe).
#define FORKE(label)
 Denote parent thread, starting at 'label'.
#define FORKE_(label)
 Helper function (if/else-unsafe).
#define JOINELSE(elselabel)
 Join completed child threads.
#define JOINELSEG(thenlabel, elselabel)
 Shorthand for 'JOINELSE(elselabel); GOTO(thenlabel)'.
#define JOINELSEG_(thenlabel, elselabel)
 Helper function (if/else-unsafe).
#define JOIN
 Shorthand for 'elselabel: JOINELSE(elselabel)'. Join completed child threads.
#define PRIO(p)
 Set priority of a thread.
#define PRIOG(p, label)
 Shorthand for 'PRIO(p); GOTO(label)'.
#define PRIO_(p)
 Helper function (if/else-unsafe).
#define PRIOG_(p, label)
 Helper function (if/else-unsafe).
#define PPAUSEG(p, label)
 Efficient shorthand for 'PRIO(p); PAUSE; GOTO(label)'.
#define PPAUSEG_(p, label)
 Helper function (if/else-unsafe).
#define PPAUSE(p)
 Efficient shorthand for 'PRIO(p); PAUSE'.
#define JPPAUSEG(p, thenlabel, elselabel)
 Efficient shorthand for 'JOINELSE(label); GOTO thenlabel; label: PRIO(p); PAUSE; GOTO(elselabel)'.
#define JPPAUSEG_(p, thenlabel, elselabel)
 Helper function (if/else-unsafe).
#define JPPAUSE(p, elselabel)
 Shorthand for 'JOINELSE(label); GOTO thenlabel; label: PRIO(p); PAUSE; GOTO(elselabel); thenlabel:'.
#define SIGNAL(s)
 Initialize a local signal (handles reincarnation).
#define EMIT(s)
 Emission of a pure signal 's'.
#define SUSTAIN(s)
 Sustain a pure signal 's'.
#define PRESENT(s)
 Test for presence of signal 's'.
#define PRESENTELSE(s, label)
 Test for presence of signal 's'.
#define PRESENTEMIT(s, t)
 If signal 's' is present, emit 't'.
#define AWAITI(s)
 Await (immediately) signal 's'.
#define AWAIT(s)
 Await (non-immediately) signal 's'.
#define _declindex
#define _setValInit
#define EMITINT(s, val)
 Emission of a valued signal 's', type integer.
#define EMITINTMUL(s, val)
 Emission of a valued signal 's', type integer, combined with * .
#define VAL(s)
 Retrieve value of signal 's'.
#define VALREG(s, reg)
 Retrieve value of signal 's' into 'reg'.
#define _setPreInit
#define setPre
#define freezePre
#define freezePreClear
#define PRESENTPRE(s)
 Test for presence of signal in previous tick.
#define PRESENTPREELSE(s, label)
 Test for presence of signal in previous tick.
#define VALPRE(s)
 Retrieve previous value of signal 's'.
#define VALPREREG(s, reg)
 Retrieve previous value of signal 's' into 'reg'.
#define GOTO(label)
 Just a goto that also gets counted as instruction.
#define ISAT(id, statelabel, label)
 Test whether an Exit Action has to be performed.
#define CALL(label)
 Call a function at 'label'.
#define RET
 Return from a function call.
#define ISATCALL(id, statelabel, label)
 Conditionally call a function.
#define instrCntIncr   tickInstrCnt++;
 Instruction counting/Tracing.
#define instrCntIncrc   tickInstrCnt++,
#define instrCntDecr   tickInstrCnt--;
#define trace0(f)   printf(f);
 If tracing is turned on, print trace string.
#define trace1(f, a)   printf(f, a);
#define trace2(f, a, b)   printf(f, a, b);
#define trace3(f, a, b, c)   printf(f, a, b, c);
#define trace4(f, a, b, c, d)   printf(f, a, b, c, d);
#define trace5(f, a, b, c, d, e)   printf(f, a, b, c, d, e);
#define trace6(f, a, b, c, d, e, g)   printf(f, a, b, c, d, e, g);
#define trace7(f, a, b, c, d, e, g, h)   printf(f, a, b, c, d, e, g, h);
#define trace8(f, a, b, c, d, e, g, h, i)   printf(f, a, b, c, d, e, g, h, i);
#define trace0c(f)   printf(f),
#define trace1c(f, a)   printf(f, a),
#define trace2c(f, a, b)   printf(f, a, b),
#define trace3c(f, a, b, c)   printf(f, a, b, c),
#define elsetrace   else {
#define elsetraceend   }
#define traceThread(s)
 Count instruction (optionally), print trace string prefix (optionally).
#define traceThreadc(s)
#define trace0t(s, f)   traceThread(s) trace0(f)
 Print trace prefix + suffix.
#define trace1t(s, f, a)   traceThread(s) trace1(f, a)
#define trace2t(s, f, a, b)   traceThread(s) trace2(f, a, b)
#define trace3t(s, f, a, b, c)   traceThread(s) trace3(f, a, b, c)
#define trace4t(s, f, a, b, c, d)   traceThread(s) trace4(f, a, b, c, d)
#define trace5t(s, f, a, b, c, d, e)   traceThread(s) trace5(f, a, b, c, d, e)
#define trace6t(s, f, a, b, c, d, e, f1)   traceThread(s) trace6(f, a, b, c, d, e, f1)
#define trace7t(s, f, a, b, c, d, e, f1, g)   traceThread(s) trace7(f, a, b, c, d, e, f1, g)
#define trace8t(s, f, a, b, c, d, e, f1, g, h)   traceThread(s) trace7(f, a, b, c, d, e, f1, g, h)
#define trace0tc(s, f)   traceThreadc(s) trace0c(f)
#define trace1tc(s, f, a)   traceThreadc(s) trace1c(f, a)
#define trace2tc(s, f, a, b)   traceThreadc(s) trace2c(f, a, b)
#define trace3tc(s, f, a, b, c)   traceThreadc(s) trace3c(f, a, b, c)

Typedefs

typedef void * labeltype
 Computed goto - a la gcc.
typedef unsigned int bitvector
 32 bits on IA32
typedef bitvector signalvector
 32 signals on IA32
typedef int threadtype
 Thread id/priority.
typedef bitvector threadvector
 32 threads on IA32

Functions

void getInputs ()
 Initialize signals to inputs for one tick.
int checkOutputs (signalvector *tickOutputs)
 Set reference outputs and check valued signals, if there are any.
void printVal (int id)
 Print value of a signal, if it has one.
int tick (int isInit)
 Compute one tick.
void selectCid ()
 Functions defined in sc.c.

Variables

signalvector signals
 Bit mask for signals.
threadvector enabled
 Bit mask for enabled threads.
threadvector active
 Bit mask for active threads.
int runCnt
 Counts program runs.
int tickCnt
 Counts program ticks.
int tickInstrCnt
 Instructions in one tick.
threadtype _cid
 Id of current thread.
labeltype _pc [_idMax]
 Pseudo program counters.
threadvector _descs [_idMax]
 Descendants of thread.
threadtype _parent [_idMax]
 Parent of thread.
labeltype _returnAddress
 For function calls (eg Exit Actions).
char * statePrev [_idMax]
 State where thread resumed previous tick.
char * state [_idMax]
 State where thread resumed current tick.
int runMax
 # of runs to execute
int tickMax
 # of ticks to execute
const char * s2signame []
 Names of signals.


Detailed Description

Definition of SyncChart C macros.

See README.txt for general information. See LICENSE.txt for licensing information. For further information, see http://www.informatik.uni-kiel.de/rtsys/sc/ .

Author:
Reinhard v. Hanxleden, rvh@informatik.uni-kiel.de

Define Documentation

#define _BEGIN   do {

Begin/end a macro.

To make macros then/else safe (ie, to allow using it in a then-branch, followed by a semicolon and an else, without resulting in an isolated else), enclose it in a "do ... while (0)".

However, when using switch logic, this additional while loop nullifies the "break" used in _goto, hence we unfortunately have to turn it off then; a Java-style labeled break statement would help here. This may require adding some braces in the source code, eg "if (...) then { PAUSE; } else ..." instead of just "if (...) then PAUSE; else ...".

#define _CONCAT_helper ( a,
 )     a ## b

Construct a label, of the form "_L'line in source file'".

Origindally contributed by Nicolas Berthier (nicolas.berthier@imag.fr)

To avoid label clashes, one must

  • not generate multiple labels at the same line (this could be, eg, "PAUSE; PAUSE" in one line)
  • not include another files within a function (this appears unlikely anyway)

Note that goto labels have function scope, hence it is ok to have identical labels in different files, as long as they belong to different functions.

Note also that the ## preprocessing macro, which concatenates strings, prevents macro expansion of it arguments. Thus the construction using _CONCAT and _CONCAT_helper.

#define _declState

Dispatcher.

When using switch-case logic, embed the tick function into a switch statement, in turn embedded in an infinite while loop.

#define ABORT

Value:

_BEGIN                                                  \
    ABORT_;                                                             \
    trace2t("ABORT:", "disables 0%o, enabled = 0%o\n",                  \
            _descs[_cid], enabled)                                      \
  _END
Abort (terminate) descendant threads.

#define ABORT_

Value:

disableSet(_descs[_cid]);                                               \
    deactivateSet(_descs[_cid])
Helper function (if/else-unsafe).

#define AWAIT (  ) 

Value:

_BEGIN                                                  \
    trace0t("AWAIT:", "initial pause\n")                                \
    _goto(__LABELL__);                                                  \
_SC_LABEL(__LABEL__): if (!(signals & u2b(s))) {                        \
      trace2t("AWAIT:", "determines %s/%d as absent, waits\n",          \
            s2signame[s], s)                                            \
        _SC_LABEL(__LABELL__): PAUSEG_(__LABEL__);                      \
    }                                                                   \
    trace2t("AWAIT:", "determines %s/%d as present, proceeds\n", s2signame[s], s) \
  _END
Await (non-immediately) signal 's'.

Pause; Then, IF 's' is present, THEN proceed to next instruction, ELSE pause.

Shorthand for 'PAUSE; AWAITI(s)', or, alternatively: 'elselabel: PAUSE; PRESENT(s, elselabel)'.

#define AWAITI (  ) 

Value:

_BEGIN                                          \
  _SC_LABEL(__LABEL__): if (!(signals & u2b(s))) {                      \
      trace2t("AWAITI:", "determines %s/%d as absent, waits\n",         \
            s2signame[s], s)                                            \
      PAUSEG_(__LABEL__);                                               \
    }                                                                   \
    trace2t("AWAITI:", "determines %s/%d as present, proceeds\n", s2signame[s], s) \
  _END
Await (immediately) signal 's'.

IF 's' is present, THEN proceed to next instruction, ELSE pause.

Shorthand for 'GOTO(label); elselabel: PAUSE; label: PRESENT(s, elselabel)'.

#define CALL ( label   ) 

Value:

_BEGIN                                          \
    trace1t("CALL:", "calls %s\n", #label)                              \
      _returnAddress = _ref(__LABEL__);                                 \
    _goto(label);                                                       \
  _SC_LABEL(__LABEL__): (void) 0;                                       \
  _END
Call a function at 'label'.

Use this if an Exit Action _must_ be performed.

#define clearPC ( id   ) 

Value:

statePrev[id] = "<init>";                                               \
  state[id] = "<init>"

#define dispatch_   _goto(_L_dispatch)

If inlineDispatch is defined, call dispatcher at each operator that needs it. Otherwise, create shared code block for TERM/PAUSE/dispatch.

This can be included by TICKEND

#define EMIT (  ) 

Value:

_BEGIN                                                  \
    trace2t("EMIT:", "emits %s/%d\n", s2signame[s], s)                  \
    signals |= u2b(s);                                                  \
  _END
Emission of a pure signal 's'.

#define EMITINT ( s,
val   ) 

Value:

_BEGIN                                          \
    valSigInt[s] = val;                                                 \
    trace3t("EMITInt:", "emits %s/%d, value %d\n",                      \
            s2signame[s], s, val)                                       \
    signals |= u2b(s);                                                  \
  _END
Emission of a valued signal 's', type integer.

#define EMITINTMUL ( s,
val   ) 

Value:

_BEGIN                                  \
    valSigIntMult[s] *= val;                                            \
    trace4t("EMITInt*:", "emits %s/%d, value %d, result %d\n",          \
            s2signame[s], s, val, valSigIntMult[s])                     \
    signals |= u2b(s);                                                  \
  _END
Emission of a valued signal 's', type integer, combined with * .

#define enable ( id   ) 

Value:

enabled |= u2b(id);                             \
  active  |= u2b(id)
Thread enabling/disabling.

#define enableInit ( id   ) 

Value:

#define FORK ( label,
 ) 

Value:

_BEGIN                                          \
    FORK_(label, p);                                                    \
    trace3t("FORK:", "forks %d/%s, active = 0%o\n", p, #label, active)  \
  _END
Spawn a thread at 'label', with priority 'p'.

#define FORK_ ( label,
 ) 

Value:

initPC(p, label);                                                       \
  _parent[p] = _cid;                                                    \
  _forkdescs |= u2b(p);                                                 \
  enable(p)
Helper function (if/else-unsafe).

#define FORKE ( label   ) 

Value:

_BEGIN                                          \
    trace0t("FORKE:", "\n")                                             \
    FORKE_(label);                                                      \
  _END
Denote parent thread, starting at 'label'.

Must also calculate descendants. Descendants are used

  • to check for termination (with JOIN)
  • to be disabled upon abortion (with TRANS)

#define FORKE_ ( label   ) 

Value:

setPC(_cid, label);                                                     \
  _descs[_cid] = _forkdescs;                                            \
  _forkdescs = 0;                                                       \
  _pid = _cid;                                                          \
  while ((_ppid = _parent[_pid]) != _TickEnd)   {                       \
    _descs[_ppid] |= _descs[_pid];                                      \
    _pid = _ppid;                                                       \
  }                                                                     \
  dispatch_
Helper function (if/else-unsafe).

#define GOTO ( label   ) 

Value:

_BEGIN                                  \
    trace1t("GOTO:", "transfer to %s\n",        #label)         \
    instrCntIncr                                                \
       _goto(label);                                            \
  _END
Just a goto that also gets counted as instruction.

#define HALT

Value:

_BEGIN                                                  \
  _SC_LABEL(__LABEL__): trace1t("HALT:", "pauses, active = 0%o\n", active)      \
    PAUSEG_(__LABEL__);                                                 \
  _END
Shorthand for 'label: PAUSE; GOTO(label)'.

#define initPC ( p,
label   ) 

Value:

_pc[p] = _ref(label);                                                   \
  statePrev[p] = "<init>";                                              \
  state[p] = #label

#define instrCntIncr   tickInstrCnt++;

Instruction counting/Tracing.

Increment/decrement SC instruction counter.

Decrement is needed in some places to avoid duplicate counting.

#define ISAT ( id,
statelabel,
label   ) 

Value:

{                                       \
  if (isEnabled(id) && (_pc[id] == _ref(statelabel))) {                 \
    trace1t("ISAT:", "_is_ at %s\n", #statelabel)                       \
  } else {                                                              \
    trace2t("ISAT:", "is _not_ at %s, transfer to %s\n",                \
            #statelabel, #label)                                        \
      _goto(label);                                                     \
  }}
Test whether an Exit Action has to be performed.

IF thread 'id' is active and at state 'statelabel', THEN proceed to next instruction, ELSE jump to 'label'

#define ISATCALL ( id,
statelabel,
label   ) 

Value:

_BEGIN                          \
    if (isEnabled(id) && (_pc[id] == _ref(statelabel))) {               \
      trace1t("ISATCALL:", "calls %s\n", #label)                        \
      _returnAddress = _ref(__LABEL__);                                 \
      _goto(label);                                                     \
    }                                                                   \
    trace1t("ISATCALL:", "does _not_ call %s\n", #label)                \
    _SC_LABEL(__LABEL__): (void) 0;                                     \
  _END
Conditionally call a function.

IF thread 'id' is active and at state 'statelabel', THEN call function at 'label'; Return to 'retlabel' Use this if an Exit Action _may_ have to be performed Shorthand for ISAT(id, statelabel, retlabel); CALL(label, retlabel);

#define JOIN

Value:

_BEGIN                                                  \
  _SC_LABEL(__LABEL__):  JOINELSEG_(__LABELL__, __LABEL__);             \
_SC_LABEL(__LABELL__): (void) 0;                                        \
  _END
Shorthand for 'elselabel: JOINELSE(elselabel)'. Join completed child threads.

IF all descendants have terminated, THEN proceed, ELSE pause, resume at JOIN.

#define JOINELSE ( elselabel   ) 

Value:

_BEGIN                                  \
  JOINELSEG_(__LABEL__, elselabel);                                     \
_SC_LABEL(__LABEL__): (void) 0;                                         \
  _END
Join completed child threads.

IF all descendants have terminated, THEN proceed after JOINELSE, ELSE pause, resume at 'elselabel'.

Semantically, this is the primitive Join-operator, from which the others can be derived; hence JOINELSE appears first, and the other operators are considered shorthands.

In terms of implementation, the operators are built from JOINELSEG, which semantically corresponds to JOINELSE + GOTO.

#define JOINELSEG ( thenlabel,
elselabel   ) 

Value:

_BEGIN                          \
    JOINELSEG_(thenlabel, elselabel);                                   \
  _END
Shorthand for 'JOINELSE(elselabel); GOTO(thenlabel)'.

IF all descendants have terminated, THEN jump to 'thenlabel', ELSE pause, resume at 'elselabel'

#define JOINELSEG_ ( thenlabel,
elselabel   ) 

Value:

if (isEnabledNoneOf(_descs[_cid])) {                                    \
    trace1t("JOINELSEG:", "joins, transfers to %s\n", #thenlabel)       \
    _goto(thenlabel);                                                   \
  }                                                                     \
  trace1t("JOINELSEG:", "does not join, pauses at %s\n", #elselabel)    \
  instrCntDecr                                                          \
  PAUSEG_(elselabel)
Helper function (if/else-unsafe).

#define JPPAUSE ( p,
elselabel   ) 

Value:

_BEGIN                                  \
    trace2t("JPPAUSE:", "%s, prio = %d\n",                              \
            isEnabledNoneOf(_descs[_cid]) ? "joins" : "does not join", p) \
    JPPAUSEG_(p, __LABEL__, elselabel);                                 \
_SC_LABEL(__LABEL__): (void) 0;                                         \
  _END
Shorthand for 'JOINELSE(label); GOTO thenlabel; label: PRIO(p); PAUSE; GOTO(elselabel); thenlabel:'.

IF all descendants have terminated, THEN proceed, ELSE set priority, pause, and continue at 'elselabel'.

This shorthand avoids the context switch immediately before the PAUSE.

#define JPPAUSEG ( p,
thenlabel,
elselabel   ) 

Value:

_BEGIN                  \
    trace2t("JPPAUSEG:", "%s, prio = %d\n",                             \
            isEnabledNoneOf(_descs[_cid]) ? "joins" : "does not join", p) \
    JPPAUSEG_(p, thenlabel, elselabel);                                 \
  _END
Efficient shorthand for 'JOINELSE(label); GOTO thenlabel; label: PRIO(p); PAUSE; GOTO(elselabel)'.

IF all descendants have terminated, THEN jump to 'thenlabel', ELSE set priority, pause, and continue at 'elselabel'.

This shorthand avoids the context switch immediately before the PAUSE.

#define JPPAUSEG_ ( p,
thenlabel,
elselabel   ) 

Value:

if (isEnabledNoneOf(_descs[_cid]))                                      \
    _goto(thenlabel);                                                   \
  instrCntDecr                                                          \
  PPAUSEG_(p, elselabel)
Helper function (if/else-unsafe).

#define mergedDispatch

Value:

_SC_LABEL(_L_TERM):   disable(_cid);                                    \
_SC_LABEL(_L_PAUSEG):   deactivate(_cid);                               \
_SC_LABEL(_L_dispatch): dispatch();

#define mytrace

Check whether externflags has been defined (eg from gcc command line). If so, suppress tracing and instruction counting. This then results in compact macro-expanded source code and executable.

#define PAUSE

Value:

_BEGIN                                                          \
    trace1t("PAUSE:", "pauses, active = 0%o\n", active)                 \
    PAUSEG_(__LABEL__); _SC_LABEL(__LABEL__): (void) 0;                 \
  _END
Pause a thread, resume at subsequent statement.

Semantically, this is the primitive operator. In terms of implementation, it is built with PAUSEG.

#define PAUSEG ( label   ) 

Value:

_BEGIN                                          \
    trace1t("PAUSEG:", "pauses, active = 0%o\n", active)                \
    PAUSEG_(label);                                                     \
  _END
Shorthand for 'PAUSE; GOTO(label)'.

Pause a thread, resume at 'label'.

#define PAUSEG_ ( label   ) 

Value:

setPC(_cid, label);                                                     \
    _goto(_L_PAUSEG)
Helper function (if/else-unsafe).

#define PPAUSE (  ) 

Value:

_BEGIN                                          \
    trace1t("PPAUSE:", "sets prio to %d, pauses\n", p)                  \
    PPAUSEG_(__LABEL__);                                                \
_SC_LABEL(__LABEL__): (void) 0;                                         \
  _END
Efficient shorthand for 'PRIO(p); PAUSE'.

Set a priority, then pause (this sets "prionext").

This shorthand avoids the context switch immediately before the PAUSE.

#define PPAUSEG ( p,
label   ) 

Value:

_BEGIN                                          \
    trace2t("PPAUSEG:", "sets prio to %d, pauses, resumes at %s\n", p, #label)       \
    PPAUSEG_(p, label);                                                 \
  _END
Efficient shorthand for 'PRIO(p); PAUSE; GOTO(label)'.

Set a priority, then pause (this sets "prionext"), resume at 'label'.

This shorthand avoids the context switch immediately before the PAUSE.

#define PPAUSEG_ ( p,
label   ) 

Value:

PRIO_(p);                                               \
  instrCntDecr                                          \
  PAUSEG_(label)
Helper function (if/else-unsafe).

#define PRESENT (  ) 

Value:

(trace3tc("PRESENT:", "determines %s/%d as %s\n",                       \
           s2signame[s], s, (signals & u2b(s)) ? "present" : "absent")  \
   (signals & u2b(s)))
Test for presence of signal 's'.

IF 's' is present, THEN return 1, ELSE return 0.

#define PRESENTELSE ( s,
label   ) 

Value:

_BEGIN                                  \
    if (!(signals & u2b(s))) {                                          \
      trace3t("PRESENTELSE:", "determines %s/%d as absent, transfers to %s\n", \
              s2signame[s], s, #label)                                  \
      _goto(label);                                                     \
    }                                                                   \
    trace2t("PRESENTELSE:", "determines %s/%d as present\n", s2signame[s], s) \
    _END
Test for presence of signal 's'.

IF 's' is present, THEN proceed to next instruction, ELSE jump to 'label'

#define PRESENTEMIT ( s,
 ) 

Value:

_BEGIN                                  \
    if (signals & u2b(s)) {                                             \
      trace4t("PRESENTEMIT:", "determines %s/%d as present, emits %s/%d\n", \
              s2signame[s], s, s2signame[t], t)                         \
      signals |= u2b(t);                                                \
    }                                                                   \
    elsetrace                                                           \
      trace2t("PRESENTEMIT:", "determines %s/%d as absent\n", s2signame[s], s) \
    elsetraceend                                                        \
    _END
If signal 's' is present, emit 't'.

Shorthand for 'PRESENTELSE(s, label); EMIT(t); label:'

#define PRESENTPRE (  ) 

Value:

(trace3tc("PRESENTPRE:", "determines %s/%d as %s\n",                    \
           s2signame[s], s, (sigsPre & u2b(s)) ? "present" : "absent")  \
   (sigsPre & u2b(s)))
Test for presence of signal in previous tick.

IF 's' was present in previous tick, THEN return 1, ELSE return 0.

#define PRESENTPREELSE ( s,
label   ) 

Value:

_BEGIN                                  \
    if (!(sigsPre & u2b(s))) {                                          \
      trace3t("PRESENTPRE:", "determines previous %s/%d as absent, transfers to %s\n", \
              s2signame[s], s, #label)                                  \
      _goto(label);                                                     \
    }                                                                   \
    trace2t("PRESENTPRE:", "determines previous %s/%d as present\n",    \
            s2signame[s], s)                                            \
  _END
Test for presence of signal in previous tick.

IF 's' was present in previous tick, THEN proceed to next instruction, ELSE jump to 'label'

#define PRIO (  ) 

Value:

_BEGIN                                                  \
    trace1t("PRIO:", "set to priority %d\n", p)                         \
    PRIOG_(p, __LABEL__);                                               \
_SC_LABEL(__LABEL__): (void) 0;                                         \
  _END
Set priority of a thread.

Semantically, this is the primitive operator. In terms of implementation, PRIOG is the basic operator.

#define PRIO_ (  ) 

Value:

deactivate(_cid);                                                       \
  disable(_cid);                                                        \
  _descs[p] = _descs[_cid];                                             \
  _pid = _cid;                                                          \
  while ((_ppid = _parent[_pid]) != _TickEnd)   {                       \
    _descs[_ppid] &= ~u2b(_cid);                                        \
    _descs[_ppid] |= u2b(p);                                            \
    _pid = _ppid;                                                       \
  }                                                                     \
  _cid = p;                                                             \
  enable(_cid);
Helper function (if/else-unsafe).

#define PRIOG ( p,
label   ) 

Value:

_BEGIN                                          \
    trace2t("PRIOG:", "set to priority %d, goto %s\n", p, #label)       \
    PRIOG_(p, label);                                                   \
  _END
Shorthand for 'PRIO(p); GOTO(label)'.

#define PRIOG_ ( p,
label   ) 

Value:

PRIO_(p);                                                               \
  setPC(_cid, label);                                                   \
  dispatch_
Helper function (if/else-unsafe).

#define RET

Value:

_BEGIN                                                  \
    trace0t("RET:", "returns\n")                                        \
      _goto(_deref(_returnAddress));                                    \
  _END
Return from a function call.

#define setPC ( id,
label   ) 

Value:

_pc[id] = _ref(label);                                          \
  statePrev[id] = state[id];                                            \
  state[id] = #label

#define SIGNAL (  ) 

Value:

_BEGIN                                          \
    trace2t("SIGNAL:", "initializes %s/%d\n", s2signame[s], s)          \
    signals &= ~u2b(s);                                                 \
  _END
Initialize a local signal (handles reincarnation).

#define SUSPEND ( cond   ) 

Value:

_BEGIN                                          \
  _SC_LABEL(__LABEL__): if (cond) {                                     \
    trace1t("SUSPEND:", "suspends itself and descendants 0%o\n", _descs[_cid]) \
    active &= ~_descs[_cid];                                            \
    freezePre                                                           \
    instrCntDecr                                                        \
    PAUSEG_(__LABEL__);                                                 \
  }                                                                     \
 _END
Suspend current thread if 'cond' is true.

Note: suspension is implemented by deactivating the current thread as well as its descendants. This exploits that the PCs of the descendants must reside at tick boundaries.

#define SUSPENDG ( label   ) 

Value:

_BEGIN                                          \
    trace1t("SUSPENDGOT:", "suspends itself and descendants 0%o\n", _descs[_cid]) \
    active &= ~_descs[_cid];                                            \
    freezePre                                                           \
    instrCntDecr                                                        \
    PAUSEG_(label);                                                     \
  _END
Suspend current thread, goto 'label'.

Note: suspension is implemented by deactivating the current thread as well as its descendants. This exploits that the PCs of the descendants must reside at tick boundaries.

#define SUSTAIN (  ) 

Value:

_BEGIN                                          \
  _SC_LABEL(__LABEL__): trace2t("SUSTAIN:", "emits %s/%d\n", s2signame[s], s)   \
    EMIT(s); PAUSEG_(__LABEL__);                                        \
  _END
Sustain a pure signal 's'.

#define TERM

Value:

_BEGIN                                          \
    trace1t("TERM:", "terminates, enabled = 0%o\n", enabled)    \
    TERM_;                                                      \
  _END
Terminate a thread.

#define TICKEND

Value:

_SC_LABEL(_L_TICKEND): setPre                           \
  return isEnabledNotOnly(_TickEnd);                    \
  mergedDispatch                                        \
  _END_SWITCH
Complete a tick.

Return 0 iff computation has terminated

#define TICKSTART ( isIni,
 ) 

Value:

static threadtype _pid, _ppid;                  \
  static threadvector _forkdescs = 0;                   \
  _declindex                                            \
  _declState                                            \
  freezePreClear                                        \
  if (isIni) {                                          \
    tickCnt = 0;                                        \
    initPC(_TickEnd, _L_TICKEND);                       \
    enableInit(_TickEnd);                               \
    _cid = p;                                           \
    _parent[_cid] = _TickEnd;                           \
    clearPC(_cid);                                      \
    enable(_cid);                                       \
    _setStateInit                                       \
    _setPreInit                                         \
    _setValInit                                         \
      } else {                                          \
    active = enabled;                                   \
    dispatch_init_;                                     \
  }                                                     \
  _BEGIN_SWITCH
Start a tick (an instant). 'p' denotes the main thread.

IF this is the initial tick ('isIni' is set), THEN initialize things and continue with following instruction, ELSE call dispatcher to resume where we left off.

This also initializes the _TickEnd thread. Note that _parent[_TickEnd] is undefined. Note also that _descs[_TickEnd] does not matter, as that thread should never perform an ABORT (TRANS) or JOIN.

#define trace0t ( s,
 )     traceThread(s) trace0(f)

Print trace prefix + suffix.

s is string denoting instruction (eg, "PAUSE:") f is format string for trace suffix a, b, ... are arguments for format string

#define traceThread (  ) 

Value:

instrCntIncr                                                            \
  trace3("%-9s %d/%s ", s, _cid, state[_cid])
Count instruction (optionally), print trace string prefix (optionally).

Trace string prefix takes a string s (typically denoting the instruction) and identifies the executing thread, both by name and thread id.

#define traceThreadc (  ) 

Value:

instrCntIncrc                                                           \
  trace3c("%-9s %d/%s ", s, _cid, state[_cid])

#define TRANS ( label   ) 

Value:

_BEGIN                                          \
    ABORT_;                                                             \
    trace3t("TRANS:", "disables 0%o, transfers to %s, enabled = 0%o\n", \
            _descs[_cid], #label, enabled)                              \
    _goto(label);                                                       \
  _END
Transition to 'label', kill descendant threads (implements abortion).

Shorthand for 'ABORT; GOTO(label)'.

#define u2b (  )     (1 << u)

Encoding of signal/thread 'u' (some non-negative int) in bitvector.

This implementation is fast and simple, BUT limits the max thread ID and max signal ID to the word width of the machine (eg 32).

#define VAL (  ) 

Value:

(                                                       \
    trace3tc("VAL:", "determines value of %s/%d as %d\n",               \
            s2signame[s], s, valSigInt[s])                              \
    valSigInt[s])
Retrieve value of signal 's'.

#define VALPRE (  ) 

Value:

(                                               \
    trace3tc("VALPRE:", "determines value of %s/%d as %d\n",    \
            s2signame[s], s, valSigIntPre[s])                   \
    valSigIntPre[s])
Retrieve previous value of signal 's'.

#define VALPREREG ( s,
reg   ) 

Value:

_BEGIN                          \
    trace3t("VALPREREG:", "determines value of %s/%d as %d\n",  \
            s2signame[s], s, valSigIntPre[s])                   \
    reg = valSigIntPre[s];                                      \
  _END
Retrieve previous value of signal 's' into 'reg'.

#define VALREG ( s,
reg   ) 

Value:

_BEGIN                                          \
    trace3t("VALREG:", "determines value of %s/%d as %d\n",             \
            s2signame[s], s, valSigInt[s])                              \
    reg = valSigInt[s];                                                 \
  _END
Retrieve value of signal 's' into 'reg'.


Function Documentation

void selectCid (  ) 

Functions defined in sc.c.

Functions defined in sc.c.

Uses obvious algorithm, run time linear in position of highest bit. Note that there are also alternatives that run logarithmic to bit vector size. See eg http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog . Which is actually faster depends on application.

int tick ( int  isInit  ) 

Compute one tick.

Returns 1 if some thread is still active in current tick.


Generated on Tue Nov 10 18:19:48 2009 for SC by  doxygen 1.5.7.1