📄 windlib.c
字号:
/* windview - level 2 event logging */ EVT_TASK_1 (EVENT_WINDDELETE, (int) pTcb); /* log event */#endif if (pTcb->status == WIND_READY) /* if task is ready */ Q_REMOVE (&readyQHead, pTcb); /* remove from queue */ else { if (pTcb->status & WIND_PEND) /* if task is pended */ status = windPendQRemove (pTcb); /* remove from queue */ if (pTcb->status & WIND_DELAY) /* if task is delayed */ Q_REMOVE (&tickQHead, &pTcb->tickNode); /* remove from queue */ } /* disconnect all the swap in hooks the task has connected to */ for (ix = 0, mask = pTcb->swapInMask; mask != 0; ix++, mask = mask << 1) if (mask & 0x8000) taskSwapReference [ix] --; /* disconnect all the swap out hooks the task has connected to */ for (ix = 0, mask = pTcb->swapOutMask; mask != 0; ix++, mask = mask << 1) if (mask & 0x8000) taskSwapReference [ix] --; Q_REMOVE (&activeQHead, &pTcb->activeNode); /* deactivate it */ pTcb->status = WIND_DEAD; /* kill it */ return (status); }/********************************************************************************* windSuspend - suspend a task** Suspension is an additive state. When a task is on the ready queue it* is removed and changed to suspended. Otherwise, the status is updated* to include suspended in addition to the state it is already in.** NOMANUAL*/void windSuspend ( FAST WIND_TCB *pTcb /* address of task's tcb, 0 = current task */ ) {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_WINDSUSPEND, (int) pTcb); /* log event */#endif if (pTcb->status == WIND_READY) Q_REMOVE (&readyQHead, pTcb); pTcb->status |= WIND_SUSPEND; /* update status */ }/********************************************************************************* windResume - resume a task** Resume the specified task and place in the ready queue if necessary.** NOMANUAL*/void windResume ( FAST WIND_TCB *pTcb /* task to resume */ ) {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_WINDRESUME, (int) pTcb); /* log event */#endif if (pTcb->status == WIND_SUSPEND) /* just suspended so */ Q_PUT (&readyQHead, pTcb, pTcb->priority); /* put in ready queue */ pTcb->status &= ~WIND_SUSPEND; /* mask out the suspend state */ }/********************************************************************************* windPriNormalSet - set the normal priority of a task** Set the normal priority of a task. A task will execute at its normal priority* as long as no priority inheritance has taken place.** NOMANUAL*/void windPriNormalSet ( WIND_TCB *pTcb, /* address of task's tcb */ UINT priNormal /* new normal priority */ ) { pTcb->priNormal = priNormal; /* update normal priority */ windPrioritySet (pTcb, priNormal); /* resort to appropriate priority */ }/********************************************************************************* windPrioritySet - resort the specified task to the appropriate priority** This routine sets the actual priority of task, taking into account priority* inversion safety. If a task owns any priority inversion safety semaphores* then the priority will not be allowed to lower.** NOMANUAL*/void windPrioritySet ( FAST WIND_TCB *pTcb, /* address of task's tcb */ FAST UINT priority /* new priority */ ) { /* if lowering the current priority and the task doesn't own any mutex * semaphores with inheritance, then go ahead and lower current priority. */ if ((pTcb->priMutexCnt == 0) && (pTcb->priority < priority)) {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_3 (EVENT_WINDPRIORITYSETLOWER, (int) pTcb, pTcb->priority, priority);#endif pTcb->priority = priority; /* lower current priority */ if (pTcb->status == WIND_READY) /* task is in ready Q? */ { Q_RESORT (&readyQHead, pTcb, priority); } else if (pTcb->status & WIND_PEND) /* task is in pend Q? */ { Q_RESORT (pTcb->pPendQ, pTcb, priority); } return; /* no inheritance if lowering */ } while (pTcb->priority > priority) /* current priority too low? */ {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_3 (EVENT_WINDPRIORITYSETRAISE, (int) pTcb, pTcb->priority, priority);#endif pTcb->priority = priority; /* raise current priority */ if (pTcb->status == WIND_READY) /* task is in ready Q? */ { Q_RESORT (&readyQHead, pTcb, priority); } else if (pTcb->status & WIND_PEND) /* task is in pend Q? */ { Q_RESORT (pTcb->pPendQ, pTcb, priority); if (pTcb->pPriMutex != NULL) /* chain up for inheritance */ pTcb = pTcb->pPriMutex->semOwner; } } }/********************************************************************************* windSemDelete - delete a semaphore** Delete a semaphore and unblock any tasks pended on it. Unblocked tasks* will be returned ERROR.** NOMANUAL*/void windSemDelete ( FAST SEM_ID semId /* semaphore to delete */ ) { FAST WIND_TCB *pTcb;#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_WINDSEMDELETE, (int) semId); /* log event */#endif windPendQTerminate (&semId->qHead); /* terminate pend q */ if ((semId->semType == SEM_TYPE_MUTEX) && /* mutex semaphore? */ ((pTcb = semId->semOwner) != NULL) && /* is there an owner? */ (OBJ_VERIFY (&((WIND_TCB *)(pTcb))->objCore, taskClassId) == OK)) { if ((semId->options & SEM_INVERSION_SAFE) && /* inversion safe opt?*/ (-- pTcb->priMutexCnt == 0) && /* last mutex owned? */ (pTcb->priority != pTcb->priNormal)) /* priority inherited?*/ { windPrioritySet (pTcb, pTcb->priNormal); /* back to normal pri */ } if ((semId->options & SEM_DELETE_SAFE) && /* deletion safe opt? */ ((-- pTcb->safeCnt) == 0) && /* unsafe now? */ (Q_FIRST (&pTcb->safetyQHead) != NULL)) /* deleters pended? */ { windPendQFlush (&pTcb->safetyQHead); /* flush deleters */ } } }/********************************************************************************* windTickAnnounce - acknowledge the passing of time** Process delay list. Make tasks at the end of their delay, ready.* Perform round robin scheduling if selected.* Call any expired watchdog routines.** NOMANUAL*/void windTickAnnounce (void) { FAST Q_NODE * pNode; /* node of tick queue */ FAST WIND_TCB * pTcb; /* pointer to task control block */ FAST WDOG * wdId; /* pointer to a watchdog */ FUNCPTR wdRtn; /* watch dog routine to invoke */ int wdArg; /* watch dog argument to pass with wdRtn */ int status; /* status return by Q_REMOVE */ /* advance and manage the tick queue */ vxTicks ++; /* advance rel time */ vxAbsTicks++; /* advance abs time */ Q_ADVANCE (&tickQHead); /* advance tick queue */ while ((pNode = (Q_NODE *) Q_GET_EXPIRED (&tickQHead)) != NULL) { pTcb = (WIND_TCB *) ((int)pNode - OFFSET (WIND_TCB, tickNode)); if ( (pTcb->objCore.pObjClass == taskClassId) /* is it a task? */#ifdef WV_INSTRUMENTATION || (pTcb->objCore.pObjClass == taskInstClassId)#endif ) { pTcb->status &= ~WIND_DELAY; /* out of delay state */ if (pTcb->status == WIND_READY) /* taskDelay done */ {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_WINDTICKUNDELAY, (int) pTcb); #endif taskRtnValueSet (pTcb, OK); /* return OK */ } else if (pTcb->status & WIND_PEND) /* semaphore timeout */ { /* * if the task was pended on a shared semaphore * windPendQRemove can return : * ERROR if lock cannot be taken * ALREADY_REMOVED if the shared tcb is already removed * from the pend Q on the give side but has not * shows up on this side. */#ifdef WV_INSTRUMENTATION EVT_TASK_1 (EVENT_WINDTICKTIMEOUT, (int )pTcb); #endif status = windPendQRemove (pTcb); /* out of semaphore q */ switch (status) { case ALREADY_REMOVED: { /* the semaphore was given in time, return OK */ taskRtnValueSet (pTcb, OK); break; } case ERROR: { taskRtnValueSet (pTcb, ERROR); /* return ERROR */ pTcb->errorStatus = S_smObjLib_LOCK_TIMEOUT; break; } default: { taskRtnValueSet (pTcb, ERROR); /* return ERROR */ pTcb->errorStatus = S_objLib_OBJ_TIMEOUT; } } } if (pTcb->status == WIND_READY) /* if ready, enqueue */ Q_PUT (&readyQHead, pTcb, pTcb->priority); } else /* must be a watchdog */ { wdId = (WDOG *) ((int)pNode - OFFSET (WDOG, tickNode));#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_WINDTICKANNOUNCETMRWD, (int) wdId);#endif wdId->status = WDOG_OUT_OF_Q; /* mark as out of q */ /* We get the watch dog routine and argument before testing * deferStartCnt to avoid having to lock interrupts. The RACE * to worry about is a wdStart () or wdCancel () occuring after * the test of deferStartCnt and before invoking the routine. */ wdRtn = wdId->wdRoutine; /* get watch dog rtn */ wdArg = wdId->wdParameter; /* get watch dog arg */ intCnt ++; /* fake ISR context */ if (wdId->deferStartCnt == 0) /* check validity */ (* wdRtn) (wdArg); /* invoke wdog rtn */ intCnt --; /* unfake ISR context */ workQDoWork (); /* do deferred work */ } } /* perform round robin scheduling if selected */ if ((roundRobinOn) && (taskIdCurrent->lockCnt == 0) && (taskIdCurrent->status == WIND_READY) && (++ taskIdCurrent->tslice >= roundRobinSlice)) {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_0 (EVENT_WINDTICKANNOUNCETMRSLC); /* log event */#endif taskIdCurrent->tslice = 0; /* reset time slice */ Q_REMOVE (&readyQHead, taskIdCurrent); /* no Q_RESORT here! */ Q_PUT (&readyQHead, taskIdCurrent, taskIdCurrent->priority); } }/********************************************************************************* windDelay - put running task asleep for specified ticks** Insert task in delay queue at correct spot dictated by the specified duration.** RETURNS: OK** NOMANUAL*/STATUS windDelay ( FAST int timeout ) {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_WINDDELAY, timeout); /* log event */#endif Q_REMOVE (&readyQHead, taskIdCurrent); /* out of ready queue */ if ((unsigned)(vxTicks + timeout) < vxTicks) /* rollover? */ { Q_CALIBRATE (&tickQHead, ~vxTicks + 1); vxTicks = 0; } Q_PUT (&tickQHead, &taskIdCurrent->tickNode, timeout + vxTicks); taskIdCurrent->status |= WIND_DELAY; /* set delay status */ return (OK); }/********************************************************************************* windUndelay - wake a sleeping task up*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -