/*{{{ Header*/ /****************************************************************************** * File name : Occam2c.h * Owner : OyT * Module Description : SPOC header file * Document name(s) : * Main project name : RIFT/GL-100 (800620UN) * Sub project name : DSP CPU S.W (800821UN) * * Copyright Autronica AS 1996-97 * 7005 TRONDHEIM, NORWAY * * Ver. yy-mm-dd Author Approved Description * ---- -------- ------ -------- ---------------------------------------------- * 0.01 See banner above * 1.24 20Aug98 OyT lint-ed * 1.24 02Dec98 OyT GLKDSP=1044: SETERR involves no lineNo and fileName ******************************************************************************/ /*}}} */ /*{{{ includes*/ #include <stdlib.h> #include <string.h> #include <time.h> #include <limits.h> #include <setjmp.h> #include <math.h> #define inline /*}}} */ /*{{{ Teig*/ /* * I have not modified any control structure in here, only layout, in the * process of trying to understand. * "ReadTimer" has been modified so that all timing is "low priority" * Also, some LINT errors have been fixed. * All #define etc in CheckPrimitiveSizes removed * BYTE is char instead of unsigned char * #define MOSTNEGINT16 ((INT16)0xFFFF8000) , was 0x8000 * MSG_MALLOC is new, plus seterr * MSG_TIMER is new * BREAKPOINT_F and BREAKPOINT_M * ChanOut4_InterruptEvent (17Apr98) * PC-lint done (Aug98) * SETERR_MLF is new, it has replaced several "seterr(m,l,f)" */ #define USE_RANGE_FUNCTIONS_NO_LINEFILE /*}}} */ /*{{{ SPOC 1.3*/ // SPOC 1.3: // #define BITS_PER_CHAR (8) // #define NaN (1./0.-1./0.) // #define Inf (1./0.) /*}}} */ /*{{{ DO_BREAK*/ // GLKDSP=1044.4: #define BREAK_ now defined: For lint, to remove the bulk of "control flows into case/default" (warning 616) #ifdef DO_BREAK // For lint, to remove the bulk of "control flows into case/default" (warning 616) #define BREAK_ break /*lint -save +fce -e309 : Continue on error, filter #error */ #error DO_BREAK filters some PC-lint warnings 616, undef to create functional code! It's ok for run-time make, DO_BREAK is not defined in "mak"-files. /*lint -restore */ #else // Resolves into single ';' (=null statemennt) #define BREAK_ #endif /*}}} */ /*{{{ NO_BREAKPOINT_C and BREAKPOINT_F*/ #if (defined NO_BREAKPOINT_C) // Observe that ExceptionHandler calls Breakpoint directly, so it cannet be removed! #define BREAKPOINT_F(b) #else #define BREAKPOINT_F(b) Breakpoint(b) #endif /*}}} */ /*{{{ architectures and operating systems*/ #define TRANSPUTER 0 #define PC 1 #define VAX 2 #define SUN3 3 #define SUN4 4 #define LITTLE 0 #define BIG 1 #define NONE 0 #define DOS 1 #define VMS 2 #define SUNOS 3 /*}}} */ /*{{{ endianness*/ #define LITTLE_AND_LITTLE /*}}} */ /*{{{ maths support*/ #define NaN ((float)0x7f800010) #define Inf ((float)0x7f800000) // DSP: 0x7f7fffff (?) /*}}} */ /*{{{ jmp_buf*/ extern jmp_buf STOPP_env; // In <setjmp.h>, was originally in SPOC // For lint: // Info 718: _setjmp undeclared, assumed to return int // Info 746: call to _setjmp() not made in the presence of a prototype // --- Global Wrap-up // Warning 628: no argument information provided for function _setjmp() // This did not quiet lint, we still had to do "-esym(526,_setjmp)" in occam2c.lnt extern int setjmp (jmp_buf); // In <rts.src>, inserted by Teig. This quiets Texas compiler! /*}}} */ /*{{{ typedef tFuncPtr, CHAN, tTask, bool, tTimer*/ typedef const void *(*tFuncPtr)(); typedef struct Task tTask; /* "struct Task" defined in fold below */ #define NoTask (tTask *)0 typedef struct { tTask *Task; void *Data; } CHAN; #define false 0 // Better for lint, will avoid all lint 731's: #define true (1) // was: true (!false) #define SETSCOPE(S) typedef long tTimer; #define AFTER(a,b) ((a-b)>0) /*}}} */ /*{{{ task states and priorities*/ //efine NUM_PRIORITY_LEVELS 2 #define NUM_PRIORITY_LEVELS 3 // When DINT1 needed to be served fast typedef enum { HighPriority = 0, LowPriority = 1 } tTaskPri; typedef enum { OUT_p = 1, IN_p = 2, EXEC_p = 3, WAIT_p = 4, ALTING_p = 5, TALTING_p = 6, TWAIT_p = 7, TSOCK_p = 8 } tTaskMode; typedef enum { NotAlting_p = -1, Enabling_p = -2, Waiting_p = -3, Ready_p = -4, TReady_p = -5 } tAltMode; typedef enum { TimeNotSet_p = -2, TimeSet_p = -3 } tTimerMode; /*}}} */ /*{{{ struct Task*/ struct Task { tTask *Next; /* Linked List of Active Tasks */ tTask *Parent; /* Parent Task */ tFuncPtr Func; /* Current Function being executed by this task */ void *FP; /* Frame Pointer for this task */ tTaskMode state; int Children; /* Active Children Count */ char *name; /* Task Name */ union { struct { long len; /* Comms */ void *data; /* Comms */ // char buff[4]; /* Comms */ // lint: Not referenced (768) } io; struct { tTimerMode TimerMode; /* Timer Alternation */ tTimer time; } timer; } comms; tAltMode AltMode; /* Alternation */ int TaskId; /* Number identifying task, for debugging */ int TaskPriority; }; /*}}} */ /*{{{ scheduling queues*/ extern tTask *QFP[NUM_PRIORITY_LEVELS]; extern tTask *QBP[NUM_PRIORITY_LEVELS]; extern tTask *QTM; extern tTask *CURTASK; extern tTimer TIMER; /*}}} */ /*{{{ MSG*/ // bits 8..3: // \x20 See ULL_CALC_SETERR_A in "Survive.h" static char* MSG_EXRAM_ERR = "\x28 EXRAM error"; static char* MSG_STACK_OVERFLOW = "\x30 Stack overflow"; //atic char* MSG_FLASHDRV = \x38 Defined in "FlashDrv.c" static char* MSG_I0_CODE_CKSUM_ERR = "\x40 "; // Vacant static char* MSG_I1_CODE_CKSUM_ERR = "\x48 "; // vacant static char* MSG_I01_CODE_CKSUM_ERR = "\x50 I01 Err"; static char* MSG_ALBUM_ERR = "\x58 Album error"; // static char* MSG_NULL = "\x98"; static char* MSG_MALLOC = "\xa0 Malloc failed in main"; static char* MSG_TIMER = "\xa8 Timer interrupt failed"; static char* MSG_EFROL = "\xb0 ERROR FLAG raised on line %d of file %s"; static char* MSG_TA = "\xb8 Terminating application"; static char* MSG_INT = "\xc0 Interrupt processing failed"; static char* MSG_SP = "\xc8 STOPPing process %s"; static char* MSG_IF = "\xd0 All IF branches failed"; static char* MSG_CASE = "\xd8 No CASE option matched"; static char* MSG_CASEIN = "\xe0 Input tag does not match CASE options"; static char* MSG_STOP = "\xe8 Executed STOP process"; static char* MSG_PRI = "\xf0 Invalid priority level"; static char* MSG_IP = "\xf8 Invalid Instruction Pointer"; /*}}} */ /*{{{ runtime error handling*/ #if (defined STOPP_ON_ERROR) #define SETERR_PROCEED longjmp (STOPP_env,0); #elif (defined CONTINUE_ON_ERROR) #define SETERR_PROCEED #else // TERMINATE_ON_ERROR = GLK-100 #define SETERR_PROCEED exit(1) #endif // A copy of these lines are in "Seterr2c.h": // GLKDSP=1044: seterr_ is new, SETERR() redefined: #define SETERR(M) /*lint -save -function(exit,seterr_) */ seterr_ (M) /*lint -restore*/ //efine SETERR(M) /*lint -save -function(exit,seterr) */ seterr (M,__LINE__,__FILE__) /*lint -restore*/ #define SETERR_MLF(M,L,F) /*lint -save -function(exit,seterr) */ seterr (M,L,F) /*lint -restore*/ // lint: Warning 644: var_name may not have been initialized in state-macines static void seterr (char *Message, int LineNo, char *FileName); extern void seterr_ (char *Message); /*}}} */ /*{{{ primitive types*/ /*{{{ values*/ #undef INT #undef INT16 #undef INT32 #undef INT64 #undef BYTE #undef REAL32 #undef REAL64 #undef BOOL #undef TEMPVAL // New definition 18Aug98 to satisfy lint better: // I still had to swith lint 737 off, so maybe we could just keep the old ones? #define INT int #define INT32 int #define INT16 int // Was: // #define INT long int // #define INT32 long int // #define INT16 short int //#define BYTE unsigned char // Original #define BYTE char // Teig: Helps for debugger, arrays; but not single-bytes #define REAL32 float #define BOOL char typedef union { BOOL VBOOL; INT VINT; INT32 VINT32; INT16 VINT16; BYTE VBYTE; REAL32 VREAL32; } TEMPVAL; #define MOSTPOSINT16 ((INT16)0x7FFF) #define MOSTNEGINT16 ((INT16)0xFFFF8000) // Teig #define MOSTPOSINT32 ((INT32)0x7FFFFFFF) #define MOSTNEGINT32 ((INT32)0x80000000) /*}}} */ /*{{{ casting down primitives*/ //GLKDSP=1044.3: FailConvert(void), was FailConvert (int V,int L, char *F) //static void inline FailConvert (int V,int L, char *F) static void inline FailConvert(void) { // was s e t e r r(MSG_NULL,L,F); SETERR(MSG_NULL); } #ifdef CHECK_CONVERSIONS // #define downtoINT16(v) ((((v)<MOSTNEGINT16)||((v)>MOSTPOSINT16)) ? (FailConvert((v),__LINE__,__FILE__),((INT16)(v))):((INT16)(v))) // #define downtoBYTE(v) ((((v)<0)||((v)>255)) ? (FailConvert((v),__LINE__,__FILE__),((BYTE)(v))):((BYTE)(v))) // #define downtoBOOL(v) ((((v)<0)||((v)>1)) ? (FailConvert((v),__LINE__,__FILE__),((BOOL)(v))):((BOOL)(v))) //GLKDSP=1044.3: New downtoINT16, downtoBYTE, downtoBOOL #define downtoINT16(v) ((((v)<MOSTNEGINT16)||((v)>MOSTPOSINT16)) ? (FailConvert(), ((INT16)(v))) : ((INT16)(v))) #define downtoBYTE(v) ((((v)<0)||((v)>255)) ? (FailConvert(), ((BYTE)(v))) : ((BYTE)(v))) #define downtoBOOL(v) ((((v)<0)||((v)>1)) ? (FailConvert(), ((BOOL)(v))) : ((BOOL)(v))) #define downtoINT32(v) ((INT32)(v)) #define downtoREAL32(v) ((REAL32)(v)) #else #define downtoINT32(v) ((INT32)(v)) #define downtoINT16(v) ((INT16)(v)) #define downtoBYTE(v) ((BYTE)(v)) #define downtoBOOL(v) ((BOOL)(v)) #define downtoREAL32(v) ((REAL32)(v)) #endif /*}}} */ /*{{{ fixed word size integer conversions*/ #define INT32INT32(v) (v) #define INT32INT16(v) ((INT32) (v)) #define INT32BYTE(v) ((INT32) (v)) #define INT32BOOL(v) ((INT32) ((v)?1:0)) #define INT16INT32(v) downtoINT16(v) #define BYTEINT32(v) downtoBYTE(v) #define BOOLINT32(v) downtoBOOL(v) #define INT16INT16(v) (v) #define INT16BYTE(v) ((INT16) (v)) #define INT16BOOL(v) ((INT16) ((v)?1:0)) #define BYTEINT16(v) downtoBYTE(v) #define BOOLINT16(v) downtoBOOL(v) #define BYTEBYTE(v) (v) #define BYTEBOOL(v) ((BYTE) ((v)?1:0)) #define BOOLBYTE(v) downtoBOOL(v) #define BOOLBOOL(v) (v) /*}}} */ /*{{{ REAL32 conversions*/ #define INT32REAL32TRUNC(v) downtoINT32(v) #define REAL32INT32TRUNC(v) ((REAL32) (v)) #define INT32REAL32ROUND(v) downtoINT32((v)+0.5) #define REAL32INT32ROUND(v) ((REAL32) (v)) #define INT16REAL32TRUNC(v) downtoINT16(v) #define REAL32INT16TRUNC(v) ((REAL32) (v)) #define INT16REAL32ROUND(v) downtoINT16((v)+0.5) #define REAL32INT16ROUND(v) ((REAL32) (v)) #define BYTEREAL32TRUNC(v) downtoBYTE(v) #define REAL32BYTETRUNC(v) ((REAL32) (v)) #define BYTEREAL32ROUND(v) downtoBYTE((v)+0.5) #define REAL32BYTEROUND(v) ((REAL32) (v)) #define BOOLREAL32TRUNC(v) downtoBOOL(v) #define REAL32BOOLTRUNC(v) ((REAL32) (v)) #define BOOLREAL32ROUND(v) downtoBOOL((v)+0.5) #define REAL32BOOLROUND(v) ((REAL32) (v)) #define REAL32REAL32(v) (v) #define REAL32REAL32ROUND(v) (v) #define REAL32REAL32TRUNC(v) (v) /*}}} */ /*{{{ conversions involving INT*/ #if (BYTES_PER_WORD==4) #define MOSTPOSINT MOSTPOSINT32 #define MOSTNEGINT MOSTNEGINT32 #define INT16INT(v) INT16INT32(v) #define INT32INT(v) INT32INT32(v) #define INTINT(v) INT32INT(v) #define INTINT16(v) INT32INT16(v) #define INTINT32(v) INT32INT32(v) #define INTBOOL(v) INT32BOOL(v) #define INTBYTE(v) INT32BYTE(v) #define BYTEINT(v) BYTEINT32(v) #define BOOLINT(v) BOOLINT32(v) #define INTREAL32TRUNC(v) INT32REAL32TRUNC(v) #define REAL32INTTRUNC(v) REAL32INT32TRUNC(v) #define INTREAL32ROUND(v) INT32REAL32ROUND(v) #define REAL32INTROUND(v) REAL32INT32ROUND(v) #elif (BYTES_PER_WORD==2) #define MOSTPOSINT MOSTPOSINT16 #define MOSTNEGINT MOSTNEGINT16 #define INT16INT(v) INT16INT16(v) #define INT32INT(v) INT32INT16(v) #define INTINT(v) INT16INT16(v) #define INTINT16(v) INT16INT16(v) #define INTINT32(v) INT16INT32(v) #define INTBOOL(v) INT16BOOL(v) #define INTBYTE(v) INT16BYTE(v) #define BYTEINT(v) BYTEINT16(v) #define INTREAL32TRUNC(v) INT16REAL32TRUNC(v) #define REAL32INTTRUNC(v) REAL32INT16TRUNC(v) #define INTREAL32ROUND(v) INT16REAL32ROUND(v) #define REAL32INTROUND(v) REAL32INT16ROUND(v) #else #error Compilation Error- Unsupported word length #endif /*}}} */ /*}}} */ /*{{{ SPOC 1.3*/ // Teig: This turned up in the COMPLEX32 RECORD example: #define USER INT #define SIZEUSER(s) (sizeof(INT)*s) /*}}} */ /*{{{ CheckPrimitiveSizes*/ static void inline CheckPrimitiveSizes(void) { char *failedtype=NULL; // All these tests evaluate to false, so the code is optimized away: // Not needed: we already filter with 774 in occam2c.lnt: /* lint -save -e774 Boolean within 'if' always evaluates to False*/ if (4 * sizeof(INT) != BYTES_PER_WORD) failedtype="INT"; if (4 * sizeof(INT32) != 4 ) failedtype="INT32"; if (2 * sizeof(INT16) != 2 ) failedtype="INT16"; if ( sizeof(BOOL) != 1 ) failedtype="BOOL"; if ( sizeof(BYTE) != 1 ) failedtype="BYTE"; if (4 * sizeof(REAL32) != 4 ) failedtype="REAL32"; /* lint -restore */ if (failedtype != NULL) { // exit(1); SETERR(MSG_NULL); // Internal Error - C primitive type used is not of expected size } } /*}}} */ /*{{{ frame header*/ typedef struct { void *ReturnFP; tFuncPtr ReturnFunc; int IP; TEMPVAL Temp; // int Scope; // lint: Not referenced (768) char *ProcName; } tHeader; /*}}} */ /*{{{ scheduling / communication primitives*/ #define INPUT(c,m,s,l) {FP->_Header.IP = l; if (ChanIn (c,m,s)) return;} BREAK_ #define INPUT1(c,m,l) {FP->_Header.IP = l; if (ChanIn1 (c,m)) return;} BREAK_ #define INPUT2(c,m,l) {FP->_Header.IP = l; if (ChanIn2 (c,m)) return;} BREAK_ #define INPUT4(c,m,l) {FP->_Header.IP = l; if (ChanIn4 (c,m)) return;} BREAK_ #define INPUT8(c,m,l) INPUT(c,m,8,l) #define OUTPUT(c,m,s,l) {FP->_Header.IP = l; if (ChanOut (c,m,s)) return;} BREAK_ #define OUTPUT1(c,m,l) {FP->_Header.IP = l; if (ChanOut1(c,m)) return;} BREAK_ #define OUTPUT2(c,m,l) {FP->_Header.IP = l; if (ChanOut2(c,m)) return;} BREAK_ #define OUTPUT4(c,m,l) {FP->_Header.IP = l; if (ChanOut4(c,m)) return;} BREAK_ #define OUTPUT8(c,m,l) OUTPUT(c,m,8,l) #define OUTPUT4_InScheduler(c,m,l) {FP->_Header.IP = l; ChanOut4(c,m);} // (Teig) No return statement #define ALT() { AltStart(); } #define ENBC(f,c) { if (f) EnableChannel(c); } #define ENBS(f) { if (f) EnableSkip(); } #define ENBT(f,t) { if (f) EnableTimer(t); } #define ALTWT(l) { FP->_Header.IP = l; if (AltWait()) return; } BREAK_ #define DISC(l,f,c) ( (f) ? DisableChannel(l,c) : (false) ) #define DISS(l,f) ( (f) ? DisableSkip(l) : (false) ) #define DIST(l,f,t) ( (f) ? DisableTimer(l,t) : (false) ) #define DELAY(t,l) { FP->_Header.IP = l; WaitOnTimer(t); return; } BREAK_ #define ALTEND() { FP->_Header.IP = AltFinish(); break; } BREAK_ #ifdef FASTGOTOS #define CASE(x) case x: label_ ## x #define GOTO(x) goto label_ ## x; BREAK_ #else #define CASE(x) case x #define GOTO(x) {FP->_Header.IP = x; break;} #endif #define STARTP(t,f,s,n,p) {(s)->Chain = FP; (s)->_Header.IP = 0; Start_Process(t,(tFuncPtr)f,s,n,p);} #define PLACED_STARTP(proc,t,f,s,n) {(s)->Chain = FP; (s)->_Header.IP = 0; Start_Placed(t,(tFuncPtr)f,s,n,proc); } #define ENDP() {End_Process(); return; } BREAK_ #define WAITP(l) {FP->_Header.IP = l; DeSchedule(WAIT_p); return; } BREAK_ #define INITCH(c) {(c)->Task = NoTask; (c)->Data = NULL; } #define CALL(p,s,l,n) {(s)->_Header.ReturnFunc=CURTASK->Func;\ (s)->_Header.ReturnFP=FP;\ FP->_Header.IP = l;\ (s)->_Header.ProcName = n;\ CURTASK->Func=(tFuncPtr)p;\ CURTASK->FP=(void *)s;\ IDENTIFYCALL(n);\ (s)->_Header.IP = 0;\ return;\ } BREAK_ #define RETURN() {CURTASK->Func=FP->_Header.ReturnFunc;\ CURTASK->FP = FP->_Header.ReturnFP;\ return;\ } BREAK_ #define WAITSOCKET(s) { CURTASK->Func=FP->_Header.ReturnFunc;\ CURTASK->FP = FP->_Header.ReturnFP;\ WaitSocket(s); return; } /*}}} */ /*{{{ scheduling / communication routines*/ /*{{{ DeSchedule*/ static void inline DeSchedule(register tTaskMode state) { register tTask *task = CURTASK; task->state = state; QFP[task->TaskPriority] = CURTASK->Next; if (QFP[task->TaskPriority] == NoTask) { QBP[task->TaskPriority] = NoTask; } } /*}}} */ /*{{{ ReSchedule*/ static void inline ReSchedule(register tTask *task) { if (task->state == TWAIT_p || task->state == TALTING_p) { tTask *prev = NoTask; tTask *this = QTM; while(this != NoTask && this != task) { prev = this; this = this->Next; } if (prev != NoTask) prev->Next = task->Next; else QTM = task->Next; } task->Next = NoTask; if (QFP[task->TaskPriority] != NoTask) QBP[task->TaskPriority]->Next = task; else QFP[task->TaskPriority] = task; task->state = EXEC_p; QBP[task->TaskPriority] = task; } /*}}} */ /*{{{ End_Process*/ static void inline End_Process (void) { register tTask *task = CURTASK; QFP[task->TaskPriority] = task->Next; if (QFP[task->TaskPriority] == NoTask) QBP[task->TaskPriority] = NoTask; task->Next = NoTask; if (task->Parent) { if (--(task->Parent->Children) == 0) ReSchedule(task->Parent); } } /*}}} */ /*{{{ ChanIn*/ static int inline ChanIn (register CHAN *chan,register void *data,register long len) { register tTask *task = chan->Task; if (task != NoTask) { if (len > 0) memcpy(data,task->comms.io.data,(size_t)len); chan->Task = NoTask; ReSchedule(task); return 0; } chan->Task = CURTASK; CURTASK->comms.io.data = data; CURTASK->comms.io.len = len; DeSchedule(IN_p); return 1; } /*}}} */ /*{{{ ChanIn1*/ static int inline ChanIn1(register CHAN *chan,register void *data) { register tTask *task = chan->Task; if (task != NoTask) { *((BYTE *)data) = *((BYTE *)task->comms.io.data); chan->Task = NoTask; ReSchedule(task); return 0; } chan->Task = CURTASK; CURTASK->comms.io.data = data; CURTASK->comms.io.len = 1; DeSchedule(IN_p); return 1; } /*}}} */ /*{{{ ChanIn2*/ static int inline ChanIn2(register CHAN *chan,register void *data) { register tTask *task = chan->Task; if (task != NoTask) { *((INT16 *)data) = *((INT16 *)task->comms.io.data); chan->Task = NoTask; ReSchedule(task); return 0; } chan->Task = CURTASK; CURTASK->comms.io.data = data; CURTASK->comms.io.len = 2; DeSchedule(IN_p); return 1; } /*}}} */ /*{{{ ChanIn4*/ static int inline ChanIn4(register CHAN *chan,register void *data) { register tTask *task = chan->Task; if (task != NoTask) { *((INT32 *)data) = *((INT32 *)task->comms.io.data); chan->Task = NoTask; ReSchedule(task); return 0; } chan->Task = CURTASK; CURTASK->comms.io.data = data; CURTASK->comms.io.len = 4; DeSchedule(IN_p); return 1; } /*}}} */ /*{{{ ChanOut*/ static int inline ChanOut (register CHAN *chan,register void *data,register long len) { register tTask *task = chan->Task; if (task != NoTask) { tAltMode mode = task->AltMode; if (mode == NotAlting_p) { if (len>0) memcpy(task->comms.io.data,data,(size_t)len); chan->Task = NoTask; ReSchedule(task); return 0; } else if (mode == Waiting_p) { ReSchedule(task); } } chan->Task = CURTASK; CURTASK->comms.io.data = data; CURTASK->comms.io.len = len; DeSchedule(OUT_p); return 1; } /*}}} */ /*{{{ ChanOut1*/ static int inline ChanOut1 (register CHAN *chan,register void *data) { register tTask *task = chan->Task; if (task != NoTask) { tAltMode mode = task->AltMode; if (mode == NotAlting_p) { *((BYTE *)task->comms.io.data) = *((BYTE *)data); chan->Task = NoTask; ReSchedule(task); return 0; } else if (mode == Waiting_p) { task->AltMode = Ready_p; ReSchedule(task); } } chan->Task = CURTASK; CURTASK->comms.io.data = data; CURTASK->comms.io.len = 1; DeSchedule(OUT_p); return 1; } /*}}} */ /*{{{ ChanOut2*/ static int inline ChanOut2 (register CHAN *chan,register void *data) { register tTask *task = chan->Task; if (task != NoTask) { tAltMode mode = task->AltMode; if (mode == NotAlting_p) { *((INT16 *)task->comms.io.data) = *((INT16 *)data); chan->Task = NoTask; ReSchedule(task); return 0; } else if (mode == Waiting_p) { task->AltMode = Ready_p; ReSchedule(task); } } chan->Task = CURTASK; CURTASK->comms.io.data = data; CURTASK->comms.io.len = 2; DeSchedule(OUT_p); return 1; } /*}}} */ /*{{{ ChanOut4*/ static int inline ChanOut4 (register CHAN *chan,register void *data) { register tTask *task = chan->Task; if (task != NoTask) { tAltMode mode = task->AltMode; if (mode == NotAlting_p) { *((INT32 *)task->comms.io.data) = *((INT32 *)data); chan->Task = NoTask; ReSchedule(task); return 0; } else if (mode == Waiting_p) { task->AltMode = Ready_p; ReSchedule(task); } } chan->Task = CURTASK; CURTASK->comms.io.data = data; CURTASK->comms.io.len = 4; DeSchedule(OUT_p); return 1; } /*}}} */ /*{{{ ChanOut4_InterruptEvent Teig*/ static int inline ChanOut4_InterruptEvent (register CHAN *chan, register void *data, register tTask *sender) { register tTask *task = chan->Task; int return_value = 0; // Default is not success! if (task != NoTask) { tAltMode mode = task->AltMode; if (mode == NotAlting_p) { // return 0; // Not success! (Default value used) } else if (mode == Waiting_p) { task->AltMode = Ready_p; ReSchedule(task); // Receiving task // Receiving end takes data from this sending end: chan->Task = sender; sender->comms.io.data = data; sender->comms.io.len = 4; return_value = 1; // Success! } } else { // return 0; // Not success! (Default value used) } return return_value; } /*}}} */ /*{{{ TimerWait*/ static void inline TimerWait(tTimer when) { tTask *prev = NoTask; tTask *tq = QTM; CURTASK->comms.timer.time = when; while(tq != NoTask && !AFTER(tq->comms.timer.time,when)) { prev = tq; tq = tq->Next; } if (prev == NoTask) { CURTASK->Next = QTM; QTM=CURTASK; } else { CURTASK->Next = prev->Next; prev->Next = CURTASK; } } /*}}} */ /*{{{ AltStart*/ static void inline AltStart (void) { #ifdef CHECK_INTERNALS if (CURTASK->AltMode != NotAlting_p) { // exit(1); SETERR(MSG_NULL); } #endif CURTASK->AltMode = Enabling_p; CURTASK->comms.timer.TimerMode = TimeNotSet_p; } /*}}} */ /*{{{ EnableChannel*/ static void inline EnableChannel (register CHAN *chan) { if (chan->Task != CURTASK) { if (chan->Task != NoTask) { CURTASK->AltMode = Ready_p; } else { chan->Task = CURTASK; } } } /*}}} */ /*{{{ EnableSkip*/ static void inline EnableSkip (void) { CURTASK->AltMode = Ready_p; } /*}}} */ /*{{{ EnableTimer*/ static void inline EnableTimer (register long t) { if (CURTASK->comms.timer.TimerMode == TimeNotSet_p) { CURTASK->comms.timer.TimerMode = TimeSet_p; CURTASK->comms.timer.time = t; } else { if (AFTER(CURTASK->comms.timer.time,t)) { CURTASK->comms.timer.time = t; } } } /*}}} */ /*{{{ AltWait*/ static int inline AltWait (void) { if ((CURTASK->comms.timer.TimerMode == TimeSet_p) && AFTER(TIMER,CURTASK->comms.timer.time)) { CURTASK->AltMode = TReady_p; } if (CURTASK->AltMode == Enabling_p) { CURTASK->AltMode = Waiting_p; if (CURTASK->comms.timer.TimerMode == TimeSet_p) { DeSchedule(TALTING_p); TimerWait(CURTASK->comms.timer.time); } else DeSchedule(ALTING_p); return 1; } return 0; } /*}}} */ /*{{{ DisableChannel*/ static BOOL inline DisableChannel (register int label, register CHAN *chan) { if (chan->Task != NoTask) { if (chan->Task == CURTASK) { chan->Task = NoTask; } else { if (CURTASK->AltMode < ((tAltMode)0)) { CURTASK->AltMode = (tAltMode) label; return(true); } } } return(false); } /*}}} */ /*{{{ DisableSkip*/ static BOOL inline DisableSkip (register int label) { if (CURTASK->AltMode < ((tAltMode)0)) { CURTASK->AltMode = (tAltMode) label; return(true); } return(false); } /*}}} */ /*{{{ DisableTimer*/ static BOOL inline DisableTimer (register int label, register long t) { if (CURTASK->AltMode == TReady_p && CURTASK->comms.timer.time == t) { CURTASK->AltMode = (tAltMode) label; return(true); } return(false); } /*}}} */ /*{{{ AltFinish*/ static int inline AltFinish (void) { tAltMode mode = CURTASK->AltMode; #ifdef CHECK_INTERNALS if (mode < 0) { // exit(1); SETERR(MSG_NULL); } else #endif CURTASK->AltMode = NotAlting_p; return (int) mode; } /*}}} */ /*{{{ WaitOnTimer*/ static void WaitOnTimer(tTimer when) { DeSchedule(TWAIT_p); TimerWait(when); } /*}}} */ /*{{{ ReadTimer*/ static tTimer inline ReadTimer(void) { // New scheme: return TIMER; // Since we have only one timer interrupt, why not have // only one universal time? // Original scheme: // register tTask *task = CURTASK; // return (task->TaskPriority==0) ? TIMER<<6 : TIMER; // This is the only place where TIMER is shifted. // The scheme above makes high-pri task time slow } /*}}} */ /*{{{ WaitSocket*/ extern void WaitSocket (int socket); /*}}} */ /*{{{ Start_Process*/ extern void Start_Process(register tTask *task, register tFuncPtr Func, register void *FP, register char *name,int Pri); /*}}} */ /*{{{ Start_Placed*/ extern void Start_Placed(register tTask *task, register tFuncPtr Func, register void *FP, register char *name,int Processor); /*}}} */ /*}}} */ /*{{{ heap management*/ // Not used, let's remove them // static char *MSG_HEAP = "Error- Out of heap storage\n"; // If used with GLK-100, // see "MSG" above for how first char should be used // static inline void *ALLOCVEC(int s) // { // void *vec = malloc((unsigned int) s); /* lint fixed */ // if (!vec) SETERR(MSG_HEAP); // // return vec; // } // // static inline void FREEVEC(void *vec) // { // free(vec); // } /*}}} */ /*{{{ retype defines*/ #define ALLOCRETYPE(symb,type,size) (symb=(type)ALLOCVEC(size)) /* lint fixed */ #define FREERETYPE(s) FREEVEC(s) #if (defined BIG_AND_LITTLE || defined LITTLE_AND_BIG) static inline void RETYPE(int swap,int l,void *d,void *s) { int i; char *from=(char *)s; char *to=(char *)d; for(i = 0; i < l; ++i) to[i ^ swap] = *from++; } #else #define RETYPE(swap,l,d,s) memcpy((char*)d,(char*)s,l); #endif /*}}} */ /*{{{ other primitives*/ #define ASSIGN(d,s,n) memcpy(d,s,(size_t)n) /*{{{ MSG's*/ static char *MSG_ASM = "Array size mismatch"; static char *MSG_ARM = "Array RETYPES abbreviation mismatch"; static char *MSG_AIM = "Array IS abbreviation mismatch"; static char *MSG_CITL = "Counted input too long"; static char *MSG_EACF = "Error- Array check failed : %s\n"; static char *MSG_ERCF = "Error- Range check (0<=%d<%d) failed\n"; static char *MSG_ELBCF = "Error- Lower bound check (0<=%d) failed\n"; static char *MSG_EUBCF = "Error- Upper bound check (0<=%d,%d<=%d) failed\n"; /*}}} */ /*{{{ Shifts*/ #ifdef FAST_SHIFTS #define LOGSHIFTLEFT(t,x,y) ((signed t)(((unsigned t)(x)) << (y))) #define LOGSHIFTRIGHT(t,x,y) ((signed t)(((unsigned t)(x)) >> (y))) //lint -esym(750, BITS_PER_WORD) To accept that it is not referenced #else // "y" appears twice, side effects possible (try "n++" for "y"): // PC-lint could then complain with warning 666, like: // "Expression with side effects passed to repeated parameter 3 in macro LOGSHIFTLEFT" // Example of this in FlashDriver #define LOGSHIFTLEFT(t,x,y) (((y) >= ((INT)(sizeof(t)*BITS_PER_WORD))) ? 0 : ((signed t)(((unsigned t)(x)) << (y)))) #define LOGSHIFTRIGHT(t,x,y) (((y) >= ((INT)(sizeof(t)*BITS_PER_WORD))) ? 0 : ((signed t)(((unsigned t)(x)) >> (y)))) #endif /*}}} */ /*{{{ CHK*/ #ifdef CHECK_ARRAYS #define CHK(c,s) if (!(c)) {SETERR(MSG_NULL);} #else #define CHK(c,s) #endif /*}}} */ #ifdef CHECK_RANGES #ifdef USE_RANGE_MACROS /*{{{ USE_RANGE_MACROS ........................... (not in GL-100)*/ // was (3) s e t e r r (MSG_NULL,__LINE__,__FILE__) #define RNGCHK(v,s) ((((v) < 0) || ((v) >= (s))) ? (,SETERR(MSG_NULL),v) :v) #define RNGCHKLB(v) (((v) < 0) ? (,SETERR(MSG_NULL),v) :v) // GLKDSP=1044.2: Macro RNGCHKUB does not need to return b (never used, discovered by Lint) #define RNGCHKUB(b,f,s) ((((f) < 0) || (((b)+(f)) > (s))) ? (,SETERR(MSG_NULL),b) :b) /*}}} */ #elif (!defined USE_RANGE_FUNCTIONS_NO_LINEFILE) /*{{{ NOT USE_RANGE_FUNCTIONS_NO_LINEFILE ........ (not in GL-100)*/ #define RNGCHK(v,s) rngchk(v,s,__LINE__,__FILE__) static INT inline rngchk(INT v, INT s, int line, char *file) { if ((v<0)||(v>=s)) { // was s e t e r r(MSG_NULL,line,file); //SETERR_MLF(MSG_NULL,line,file); SETERR(MSG_NULL); } return v; } #define RNGCHKLB(v) rngchklb(v,__LINE__,__FILE__) static INT inline rngchklb(INT v, int line, char *file) { if (v<0) { // was s e t e r r(MSG_NULL,line,file); SETERR_MLF(MSG_NULL,line,file); } return v; } // GLKDSP=1044.2: Macro RNGCHKUB does not need to return b (never used, discovered by Lint) #define RNGCHKUB(b,f,s) rngchkub(b,f,s,__LINE__,__FILE__) static INT inline rngchkub(INT b, INT f, INT s, int line, char *file) { if ((f<0)||((b+f)>s)) { // was s e t e r r(MSG_NULL,line,file); SETERR_MLF(MSG_NULL,line,file); } return b; } /*}}} */ #elif (defined USE_RANGE_FUNCTIONS_NO_LINEFILE) /*{{{ USE_RANGE_FUNCTIONS_NO_LINEFILE ............ (in GL-100)*/ // Teig: // Reasons for using USE_RANGE_FUNCTIONS_NO_LINEFILE: // 1. Reduces code (by 1-2% only) // 2. Increases speed of tests // 3. We don't have a "println" that can actually use the line number an file name! // 4. The debugger tells us about the call tree #define RNGCHK(v,s) rngchk_(v,s) static INT inline rngchk_(INT v, INT s) { if ((v<0)||(v>=s)) { // was s e t e r r (MSG_NULL,__LINE__,__FILE__); // Here SETERR(MSG_NULL); // Here } return v; } #define RNGCHKLB(v) rngchklb_(v) static INT inline rngchklb_(INT v) { if (v<0) { // was s e t e r r (MSG_NULL,__LINE__,__FILE__); // Here SETERR(MSG_NULL); // Here } return v; } // GLKDSP=1044.2: Macro rngchkub_ return parameter is never used, so we remove it // GLKDSP=1044.2: RNGCHKUB is always used as the left-hand side of a comma operator // #define RNGCHKUB(b,f,s) rngchkub_(b,f,s) static void inline rngchkub_(INT b, INT f, INT s) { if ((f<0)||((b+f)>s)) { // was s e t e r r (MSG_NULL,__LINE__,__FILE__); // Here SETERR(MSG_NULL); // Here } // return b; } /*}}} */ #endif #else #define RNGCHK(v,s) (v) #define RNGCHKLB(v) (v) #define RNGCHKUB(b,f,s) (b) #endif #ifdef SHOWTASKING #define IDENTIFYTASK() #define IDENTIFYCALL(n) #else #define IDENTIFYCALL(n) #define IDENTIFYTASK() #endif /*}}} */