// /* ml.h Task coordination event structures. Stack sizes for the tasks spawned in mlexec.c. Copyright (c) 1996 Eliot W. Dudley. All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the README file. */ /* 1-Wire, DS, DS1820, DS2405, DS2407, DS9097, and MicroLan are trademarks and/or registered trademarks of Dallas Semiconductor Coporation */ // //============================================================================= //@Man: ml.h constants //@{ //@Memo: Source: \URL{../ml.h.html#constants} /// Maximum event object pointer list size. #define TASK_MAX 64 /// Initial event object pointer list size. #define TASK_SIZ TASK_MAX /// Bit array priority queue dimension when declared as array of long. #define BITPRIQ_DIM ((TASK_MAX + 31) / 32) /// Bit array priority queue number of bits. #define BITPRIQ_BITS (32 * BITPRIQ_DIM) /// Maximum event object pointer list size. #define EVENT_MAX (TASK_MAX * 2) /// Initial event object pointer list size. #define EVENT_SIZ 16 /// Maximum function object pointer list size. #define FNC_MAX 16 /// Initial function object pointer list size. #define FNC_SIZ 16 /// Message buffers. #define BUF_Q_CNT 128 /// Message buffer bytes. #define BUF_SIZ 256 /// Max number of bytes in any one ML bus write/read. #define ML_MAX_IO 128 /// Max number of file descriptors for this process. #define FD_CNT 32 /// Runaway semaphore detect. #define SEM_MAX 1000 //@} //end: ml.h constants //============================================================================= // //============================================================================= //@Man: ml.h typedefs //@{ //@Memo: Source: \URL{../ml.h.html#typedefs} //@Man: EXEC //@Memo: \Ref{EXECt} //@Man: pEXEC //@Memo: \Ref{EXECt} * typedef struct EXECt EXEC, *pEXEC; //@Man: PL //@Memo: \Ref{PLt} //@Man: pPL //@Memo: \Ref{PLt} * typedef struct PLt PL, *pPL; //@Man: PLMBR //@Memo: \Ref{PLMBRt} //@Man: pPLMBR //@Memo: \Ref{PLMBRt} * typedef struct PLMBRt PLMBR, *pPLMBR; //@Man: Q //@Memo: \Ref{Qt} //@Man: pQ //@Memo: \Ref{Qt} typedef struct Qt Q, *pQ; //@Man: EVENT //@Memo: \Ref{EVENTt} //@Man: pEVENT //@Memo: \Ref{EVENTt} * typedef struct EVENTt EVENT, *pEVENT; //@Man: TCB //@Memo: \Ref{TCBt} //@Man: pTCB //@Memo: \Ref{TCBt} typedef struct TCBt TCB, *pTCB; //@Man: VAPRINTF /*@Memo: Variable argument printf type function. */ //@{ //@Type: typedef //@Args: int (*VAPRINTF)(void *stream_or_buf, char *fmt, va_list va_alist); typedef int (*VAPRINTF)(void *stream_or_buf, char *fmt, va_list va_alist); //@} //@Man: BITPRIQ /*@Memo: Priority queue implemented as array of binary digits. */ //@{ //@Type: typedef //@Args: unsigned long BITPRIQ[BITPRIQ_DIM], *pBITPRIQ; typedef unsigned long BITPRIQ[BITPRIQ_DIM], *pBITPRIQ; //@} //@Man: TASKFNC /*@Memo: Task object function. */ //@{ //@Type: typedef //@Args: int (*TASKFNC)(char *name, int pri_ret, va_list va_alist); typedef int (*TASKFNC)(char *name, int pri_ret, va_list va_alist); //@} //@Man: COMPAREFNC /*@Memo: Classic compare function. */ //@{ //@Type: typedef //@Args: int (*COMPAREFNC)(const void *, const void *); typedef int (*COMPAREFNC)(const void *, const void *); //@} //@Man: BYTE /*@Memo: An octet of binary digits. */ //@{ //@Type: typedef //@Args: unsigned char BYTE; typedef unsigned char BYTE; //@} //@} //end: ml.h typedef //============================================================================= //============================================================================= #define EVENT_SEM 0 #define EVENT_MSG 1 #define EVENT_Q 2 #define EVENT_NAME_DEFAULT 0 #define ML_BY_CREATE 0 #define ML_BY_NAME 1 #define ML_BY_ADDR 2 #define ML_BY_PATH 3 //============================================================================= // //============================================================================= //@Man: ml.h structs //@Memo: Source: \URL{../ml.h.html#structs} //@{ /// //@Memo: Pointer list. /** Structure holding an array of pointers to lists of pointers, along with members for maintaining the lists. These are used keep track of pointers to dynamically allocated structures of generic type \Ref{PLMBRt}. The p[0] array is maintained in the order the objects are allocated. The p[1] array is maintained in lexical order according to the *name member that is common to all objects eligible to be maintained under this scheme. The p[2-7] arrays are available for other ordering. */ struct PLt { /*/ Array of pointers to arrays of pointers, each is same list sorted differently. */ pPLMBR *p[8]; /// How many pointer lists are used, i.e. sorted how many ways. int dim; /// Current count of pointers in each of the lists. int cnt; /// Current size allocated. int siz; /// Maximum size allowed. int max; }; /// //@Memo: Pointer list member. /** Base type used by functions that manipulate lists of pointers to objects compatible with this type by virtue of having a char* their first member. */ struct PLMBRt { /// char *name; }; /// //@Memo: The global executive context structure. /** The global executive context structure. */ struct EXECt { /// Task control block pointer list. PL tcb; /// Pointer list for semaphores, mailboxes, and queues. PL event; /// Named function pointer list. PL fnc; /// Task ready-to-run priority queue. BITPRIQ bitpriq_rdy; /// Task control block linked list first pointer. pTCB ptcb_first; /// Pointer to task control block of the currently running task. pTCB ptcb_cur; /// Priority of the currently running task, index into the tcb PL. int pri_cur; /// Highest priority (lowest index) used so far. int pri_min; /// Debug flags. int debug; /// Message buffer supply queue. pEVENT pbufq; /// Lowest point in memory allocated to any task stack. unsigned long sp_min; /// Priority of task waiting on any particular file descriptor. BYTE fd[FD_CNT]; /// Log file. FILE *LOG; /// longjmp() target on fatal error. jmp_buf fatal; /// Argument list for fatal vsprintf(). va_list va_alist; /// Storage for fatal error argument list. BYTE va_buf[64]; }; /// //@Memo: Task control block. /** Task control block. */ struct TCBt { /// Task name. char *name; /// Task context. jmp_buf jmp_buf; /// Time left until task wants to run again or until i/o times out. int delay_usec; /// File descriptor task is waiting on. int fd; /// Task status: BLOCKED or RDY. BYTE status; /// Task priority. BYTE pri; /// This task's message mailbox. pEVENT pmsg; /// Next task in the TCB linked list. pTCB ptcb_next; /// Previous task in the TCB linked list. pTCB ptcb_prev; /// Call trace stack for code instrumentation. char *call_trace[16]; /// Top of the call trace buffer. Fatal if reached. char *call_trace_top; /// Current postion in the call trace stack. char **call; /// Lowest point reached so far in this task's stack. unsigned long sp_low; /// Lowest point allowed for this task's stack. unsigned long sp_min; /// This task's maximum stack size. unsigned long sp_siz; /// Checksum of this task's stack. unsigned long sp_sum; }; //@} //end: ml.h struct //============================================================================= //============================================================================= char *StackInfo(char *cmd); char *TPrintf(char *cmd, int pri_ret); char *TIdle(char *cmd, int pri_ret); char *TMain(char *cmd, int pri_ret); char *Spawn(char *cmd); char *Post(char *cmd); char *Load(char *cmd); void Fatal(unsigned int err_idx, ...); void Enter(unsigned line, char *str); pTCB TaskCreate(char **cmd, int siz); VAFNC GetFncByName(char *fnc_name); pEVENT EventCreate(char *name, int type); pEVENT GetEventByName(char *event_name); pEVENT QCreate(char *name, int siz); void *EventPend(pEVENT pevent, int timeout); int EventSched(pEVENT pevent, void *entity); int EventPost(pEVENT pevent, void *entity); int EventSemCount(pEVENT pevent); char *BufNew(void); int BufDelete(char *ptr); char *Shift(char **ptr); char *FOpen( char *reply, FILE **pFILE, char **pfile_name, char *mode, char **pptr); int VAPrintf(pEVENT pfrom, ...); int NameCmp(const void *p0, const void *p1); void *VAPost(pEVENT pto, pEVENT pfrom, ...); void StackClr(pTCB ptcb); pTCB GetTcbByName(char *task_name); void SpawnRet(int pri_ret, char *msg); void ExecSched(void); void TaskDelayUSec(int delay_usec); void TaskDelaySec(int delay_sec); int ReadYield(int fd, int delay_usec); void PLNew(pPL ppl, int max, int siz, int list_cnt); void PLInsert(pPLMBR pplmbr, pPL ppl, int idx, COMPAREFNC cmp); pPLMBR *PLSearch(pPLMBR pplmbr, pPL ppl, int idx, COMPAREFNC cmp); pPLMBR *PLByName(char *name, pPL ppl); pPLMBR *PLGrow(pPL ppl); char *FncShift(char *reply, VAFNC *pfnc, char **pptr); //============================================================================= //============================================================================= #define FATAL(rrr) Fatal((unsigned)__LINE__, rrr, 0) #define CALLOC(ptr,cnt,typ) \ if(!(ptr = ((typ*)calloc(cnt,sizeof(typ))))) {FATAL(CALLOC_FAILED);} #define MALLOC(ptr,cnt,typ) \ if(!(ptr = ((typ*)malloc((cnt)*(sizeof(typ)))))) {FATAL(MALLOC_FAILED);} #define REALLOC(ptr,cnt,typ) \ if(!(ptr = ((typ*)realloc((ptr),(cnt)*(sizeof(typ)))))) {FATAL(REALLOC_FAILED);} #define ENTER(str) Enter(__LINE__, #str); #define RETURN(val) do{*(--pexec->ptcb_cur->call) = 0; return(val);}while(0); #define STACK_CHECK() \ register unsigned long esp asm("esp"); \ if (esp < pexec->ptcb_cur->sp_low) pexec->ptcb_cur->sp_low = esp; \ if (esp <= pexec->ptcb_cur->sp_min) {FATAL(STACK_OVERFLOW);} //============================================================================= //============================================================================= /// Pointer to the global executive context structure \Ref{EXECt}. extern pEXEC pexec; //=============================================================================