/*----------------------------------------------------------+ | SHARE Multi-tasking Example - 1998 Winter conference | | session 5957 | +----------------------------------------------------------*/ /*-------------------------------------------------------------------+ | Miscellaneous includes. | +-------------------------------------------------------------------*/ #include #include #include #include #include #include #include "shrtyp.h" #include "shrpro.h" #define DECLARE_GLOBALS 1 #include "shrgbl.h" int _stack = 8192; int _heap = 16382; static ECB ulStimerECB; /* ecb to be posted by stimer exit */ static PTASK pTask; /* task pointer for this timer task */ static ULONG ulDataLength; /* length of element received */ static void *pStimer; /* address of exit to pass to MVS */ static PTASK pTimerChain; /* points to first TASK on timer chain */ static void StimerExit(void); static int CheckMsgQueue(void); /*-------------------------------------------------------------------+ | The SPE environment requires the use of osmain() rather than main()| | The arguments are not parsed. argv[0] points to the PARM string | | passed by the operating system, which includes a 2-byte length | | in front of the PARM text. | +-------------------------------------------------------------------*/ UINT osmain(int argc, char *argv[]) { char buffer[100]; char *pStopchar; ULONG ulTimeRemaining; PECB aulECBList[2]; /* ecb list passed to WAITM */ time_t dCurTime, dLowestTime; PTASK pTaskCaller, pPrevCaller; MSG stMsg; UINT bLowestTimeSet; ULONG ulTimeToWait; pTask = (PTASK) strtoul(argv[0]+2, &pStopchar, 16); if (pStopchar == argv[0]+2) exit(20); pAnchor = pTask->pAnchor; format(buffer,"Entered Timer subtask"); Log(buffer); format(buffer,"Timer subtask, pAnchor = %08X", pAnchor); Log(buffer); format(buffer,"Timer subtask, pTask = %08X", pTask); Log(buffer); ulDataLength = sizeof(stMsg); /* set max received msg length */ /* set first ecb to wait on. This is the ReadQueue ecb */ aulECBList[0] = &pTask->stQueue.uCDS.stCDS.ulQECB; /* set the stimer ecb in the wait list, and mark it as the end */ aulECBList[1] = (PECB) ((ULONG) &ulStimerECB | (ULONG) 0x80000000); pStimer = bldexit(&StimerExit, ASYNCH); ulStimerECB = 0; /* initialize the STIMER ecb */ pTimerChain = 0; /* initialize the timer chain */ while (1) { /* wait for a message or a timer pop */ WAITM(1, aulECBList); /* see if a timer request has arrived */ if (1 == CheckMsgQueue()) /* if shutdown msg received... */ { format(buffer,"Timer subtask, shutting down"); Log(buffer); TTIMER(CANCEL, TU, &ulTimeRemaining); freeexit(pStimer); /* free the storage allocated by bldexit() */ return (EXIT_SUCCESS); } ulStimerECB = 0; /* reset the STIMER ecb */ if ((pTaskCaller = pTimerChain) == 0) continue; TTIMER(CANCEL, TU, &ulTimeRemaining); time(&dCurTime); bLowestTimeSet = 0; /* indicate that no time limit has been set yet */ pPrevCaller = 0; while (pTaskCaller != 0) { if (dCurTime >= pTaskCaller->dWakeUpTime) { stMsg.uiMsg = TIMERPOP; WriteQueue(&pTaskCaller->stQueue, 4, (PUCHAR) &stMsg); /* unchain this element from the timer queue */ if (pPrevCaller) pPrevCaller->pNextTimeTask = pTaskCaller->pNextTimeTask; else pTimerChain = pTaskCaller->pNextTimeTask; } else { if (!bLowestTimeSet) { dLowestTime = pTaskCaller->dWakeUpTime; bLowestTimeSet = 1; } else { if (pTaskCaller->dWakeUpTime < dLowestTime) dLowestTime = pTaskCaller->dWakeUpTime; } } pPrevCaller = pTaskCaller; pTaskCaller = pTaskCaller->pNextTimeTask; } if (!bLowestTimeSet) continue; ulTimeToWait = 100 * (dLowestTime - dCurTime); STIMER(REAL, pStimer, BINTVL, &ulTimeToWait); } } static int CheckMsgQueue(void) { char buffer[100]; MSG stMsg; PTREQUEST pstTimerRequest; PTASK pTaskCaller, pTaskCur; if (pTask->stQueue.uCDS.stCDS.ulQECB & POSTED) { ReadQueue(&pTask->stQueue, &ulDataLength, (PUCHAR) &stMsg); switch (stMsg.uiMsg) { case SHUTDOWN: { format(buffer, "Timer subtask, SHUTDOWN received"); Log(buffer); return (1); } case TIMERREQ: { format(buffer, "Timer subtask, TIMERREQ received"); Log(buffer); pstTimerRequest = (PTREQUEST) stMsg.ucData; pTaskCaller = pstTimerRequest->pTask; pTaskCaller->dWakeUpTime = pstTimerRequest->dWakeUpTime; if (pTimerChain) { pTaskCur = pTimerChain; while (pTaskCur) { /* if the task already has an outstanding timer request, just update the wake up time and exit */ if (pTaskCur == pTaskCaller) break; pTaskCur = pTaskCur->pNextTimeTask; } if (!pTaskCur) { pTaskCaller->pNextTimeTask = pTimerChain; pTimerChain = pTaskCaller; } } else { pTaskCaller->pNextTimeTask = 0; pTimerChain = pTaskCaller; } break; } default: { format(buffer, "Timer subtask, unknown message received %08x", stMsg.uiMsg); Log(buffer); break; } } } return (0); } static void StimerExit(void) { POST(&ulStimerECB, 0); }