📄 tasklib.c
字号:
return (OK); }/********************************************************************************* taskRestart - restart a task** This routine "restarts" a task. The task is first terminated, and then* reinitialized with the same ID, priority, options, original entry point,* stack size, and parameters it had when it was terminated. Self-restarting* of a calling task is performed by the exception task. The shell utilizes* this routine to restart itself when aborted.** NOTE* If the task has modified any of its start-up parameters, the restarted* task will start with the changed values.** RETURNS: OK, or ERROR if the task ID is invalid* or the task could not be restarted.** ERRNO: S_intLib_NOT_ISR_CALLABLE, S_objLib_OBJ_DELETED,* S_objLib_OBJ_UNAVAILABLE, S_objLib_OBJ_ID_ERROR,* S_smObjLib_NOT_INITIALIZED, S_memLib_NOT_ENOUGH_MEMORY,* S_memLib_BLOCK_ERROR**/STATUS taskRestart ( int tid /* task ID of task to restart */ ) { char *name; /* task name */ ULONG priority; /* priority of task */ int options; /* task options */ char *pStackBase; /* bottom of stack */ int stackSize; /* stack size */ FUNCPTR entry; /* entry point of task */ int pArgs[MAX_TASK_ARGS]; /* task's arguments */ BOOL error; /* TRUE if ERROR */ char *rename = NULL; /* place to keep rename */ int sizeName; /* size of task name */ WIND_TCB *pTcb; /* pointer to task control block */ if (INT_RESTRICT () != OK) /* no ISR use */ return (ERROR); if ((tid == 0) || (tid == (int)taskIdCurrent)) { /* self restart not possible because we have we have no context * from which to sucessfully terminate or reinitialize ourself. * We defer all self restarts to the exception task. * To self restart within a critical section, we must TASK_UNSAFE () * until the safeCnt == 0. Otherwise, the excTask would block * forever trying to terminate us. */ while (taskIdCurrent->safeCnt > 0) /* make task unsafe */ TASK_UNSAFE ();#if CPU==SIMSPARCSUNOS || CPU==SIMSPARCSOLARIS bzero ((char *) &taskIdCurrent->excInfo, sizeof (EXC_INFO));#endif /* CPU==SIMSPARCSUNOS || CPU==SIMSPARCSOLARIS */ taskSpawn (restartTaskName, restartTaskPriority, restartTaskOptions, restartTaskStackSize, taskRestart, (int) taskIdCurrent, 0, 0, 0, 0, 0, 0, 0, 0, 0); FOREVER taskSuspend (0); /* wait for restart */ } /* the rest of this routine will only be executed by a task other than * the one being restarted. */ if ((pTcb = taskTcb (tid)) == NULL) /* valid task ID? */ return (ERROR); priority = pTcb->priNormal; /* get the normal priority */ options = pTcb->options; /* get the current options */ entry = pTcb->entry; /* get the entry point */ pStackBase = pTcb->pStackBase; /* get the bottom of stack */ stackSize = (pTcb->pStackEnd - pTcb->pStackBase)*_STACK_DIR; taskArgsGet (pTcb, pStackBase, pArgs); /* get the arguments */ /* If task was named, its name was alloted from the task stack. So we * get a local copy from the stack so it won't be clobbered during task * initialization. */ if ((name = pTcb->name) != NULL) { sizeName = strlen(name) + 1; rename = malloc(sizeName); if (rename != NULL) strcpy (rename, name); /* copy out name */ name = rename; /* name points at name copy */ } TASK_SAFE (); /* TASK SAFE */ if (taskTerminate (tid) != OK) /* terminate the task */ { TASK_UNSAFE (); /* TASK UNSAFE */ return (ERROR); } /* Reinitialize task with original name, stack, priority, options, * arguments, and entry point. Then activate it. */#if CPU==SIMSPARCSUNOS || CPU==SIMHPPA || CPU==SIMSPARCSOLARIS bzero ((char *) &pTcb->excInfo, sizeof (EXC_INFO));#endif /* CPU==SIMSPARCSUNOS || CPU==SIMHPPA || CPU==SIMSPARCSOLARIS */ error = ((taskInit (pTcb, name, (int)priority, options, pStackBase, stackSize, entry, pArgs[0], pArgs[1], pArgs[2], pArgs[3], pArgs[4], pArgs[5], pArgs[6], pArgs[7], pArgs[8], pArgs[9]) != OK) || (taskActivate ((int) pTcb) != OK)); TASK_UNSAFE (); /* TASK UNSAFE */ free (rename); return ((error) ? ERROR : OK); }/********************************************************************************* taskPrioritySet - change the priority of a task** This routine changes a task's priority to a specified priority.* Priorities range from 0, the highest priority, to 255, the lowest priority.** RETURNS: OK, or ERROR if the task ID is invalid.** ERRNO: S_taskLib_ILLEGAL_PRIORITY, S_objLib_OBJ_ID_ERROR** SEE ALSO: taskPriorityGet()*/STATUS taskPrioritySet ( int tid, /* task ID */ int newPriority /* new priority */ ) {#ifdef WV_INSTRUMENTATION int realTid = (tid == 0 ? (int) taskIdCurrent : tid); /* windview - level 1 event logging */ EVT_OBJ_3 (TASK, (WIND_TCB *)realTid, taskClassId, EVENT_TASKPRIORITYSET, realTid, newPriority, ((WIND_TCB *)realTid)->priority);#endif /* make sure priority is in range 0-255 */ if (taskPriRangeCheck) if (newPriority < 0 || newPriority > 255) { errno = S_taskLib_ILLEGAL_PRIORITY; return (ERROR); } if (kernelState) /* already in kernel? */ { if ((tid == 0) || (TASK_ID_VERIFY (tid) != OK)) /* verify task ID */ return (ERROR); workQAdd2 ((FUNCPTR)windPriNormalSet, tid, newPriority); return (OK); } if (tid == 0) tid = (int) taskIdCurrent; kernelState = TRUE; /* KERNEL ENTER */ if (TASK_ID_VERIFY (tid) != OK) /* verify task ID */ { windExit (); /* KERNEL EXIT */ return (ERROR); } windPriNormalSet ((WIND_TCB *) tid, (UINT) newPriority); windExit (); /* KERNEL EXIT */ return (OK); }/********************************************************************************* taskPriorityGet - examine the priority of a task** This routine determines the current priority of a specified task.* The current priority is copied to the integer pointed to by <pPriority>.** RETURNS: OK, or ERROR if the task ID is invalid.** ERRNO: S_objLib_OBJ_ID_ERROR** SEE ALSO: taskPrioritySet()*/STATUS taskPriorityGet ( int tid, /* task ID */ int *pPriority /* return priority here */ ) { WIND_TCB *pTcb = taskTcb (tid); if (pTcb == NULL) /* invalid task ID */ return (ERROR); *pPriority = (int) pTcb->priority; return (OK); }/********************************************************************************* taskLock - disable task rescheduling** This routine disables task context switching. The task that calls this* routine will be the only task that is allowed to execute, unless the task* explicitly gives up the CPU by making itself no longer ready. Typically* this call is paired with taskUnlock(); together they surround a critical* section of code. These preemption locks are implemented with a counting* variable that allows nested preemption locks. Preemption will not be* unlocked until taskUnlock() has been called as many times as taskLock().** This routine does not lock out interrupts; use intLock() to lock out* interrupts.** A taskLock() is preferable to intLock() as a means of mutual exclusion,* because interrupt lock-outs add interrupt latency to the system.** A semTake() is preferable to taskLock() as a means of mutual exclusion,* because preemption lock-outs add preemptive latency to the system.** The taskLock() routine is not callable from interrupt service routines.** RETURNS: OK or ERROR.** ERRNO: S_objLib_OBJ_ID_ERROR, S_intLib_NOT_ISR_CALLABLE** SEE ALSO: taskUnlock(), intLock(), taskSafe(), semTake()*/STATUS taskLock (void) { TASK_LOCK(); /* increment lock cnt */ return (OK); }/********************************************************************************* taskUnlock - enable task rescheduling** This routine decrements the preemption lock count. Typically this call is* paired with taskLock() and concludes a critical section of code.* Preemption will not be unlocked until taskUnlock() has been called as many* times as taskLock(). When the lock count is decremented to zero, any tasks* that were eligible to preempt the current task will execute.** The taskUnlock() routine is not callable from interrupt service routines.** RETURNS: OK or ERROR.** ERRNO: S_intLib_NOT_ISR_CALLABLE** SEE ALSO: taskLock()*/STATUS taskUnlock (void) { FAST WIND_TCB *pTcb = taskIdCurrent;#ifdef WV_INSTRUMENTATION /* windview - level 3 event logging */ EVT_CTX_0 (EVENT_TASKUNLOCK);#endif if ((pTcb->lockCnt > 0) && ((-- pTcb->lockCnt) == 0)) /* unlocked? */ { kernelState = TRUE; /* KERNEL ENTER */ if ((Q_FIRST (&pTcb->safetyQHead) != NULL) && (pTcb->safeCnt == 0)) {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_TASK, pTcb); /* log event */#endif windPendQFlush (&pTcb->safetyQHead); /* flush safe queue */ } windExit (); /* KERNEL EXIT */ } return (OK); }/********************************************************************************* taskSafe - make the calling task safe from deletion** This routine protects the calling task from deletion. Tasks that attempt* to delete a protected task will block until the task is made unsafe, using* taskUnsafe(). When a task becomes unsafe, the deleter will be unblocked* and allowed to delete the task.** The taskSafe() primitive utilizes a count to keep track of nested* calls for task protection. When nesting occurs, the task* becomes unsafe only after the outermost taskUnsafe() is executed.** RETURNS: OK.** SEE ALSO: taskUnsafe(),* .pG "Basic OS"*/STATUS taskSafe (void) { TASK_SAFE (); /* increment safe cnt */ return (OK); }/********************************************************************************* taskUnsafe - make the calling task unsafe from deletion** This routine removes the calling task's protection from deletion. Tasks* that attempt to delete a protected task will block until the task is unsafe.* When a task becomes unsafe, the deleter will be unblocked and allowed to* delete the task.** The taskUnsafe() primitive utilizes a count to keep track of nested* calls for task protection. When nesting occurs, the task* becomes unsafe only after the outermost taskUnsafe() is executed.** RETURNS: OK.** SEE ALSO: taskSafe(),* .pG "Basic OS"*/STATUS taskUnsafe (void) { FAST WIND_TCB *pTcb = taskIdCurrent;#ifdef WV_INSTRUMENTATION /* windvi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -