📄 tasklib.c
字号:
* RETURNS: OK, or ERROR if the task cannot be suspended.** ERRNO: S_objLib_OBJ_ID_ERROR**/STATUS taskSuspend ( int tid /* task ID of task to suspend */ ) {#ifdef WV_INSTRUMENTATION int realTid = (tid == 0 ? (int) taskIdCurrent : tid); /* windview - level 1 event logging */ EVT_OBJ_1 (TASK, (WIND_TCB *)realTid, taskClassId, EVENT_TASKSUSPEND, realTid);#endif if (kernelState) /* defer work if in kernel */ { if ((tid == 0) || (TASK_ID_VERIFY ((void *)tid) != OK)) return (ERROR); workQAdd1 ((FUNCPTR)windSuspend, tid); /* add work to kernel work q */ return (OK); } if (tid == 0) tid = (int) taskIdCurrent; kernelState = TRUE; /* KERNEL ENTER */ if (TASK_ID_VERIFY ((void *)tid) != OK) /* verify task */ { windExit (); /* KERNEL EXIT */ return (ERROR); } windSuspend ((WIND_TCB *) tid); /* suspend a task */ windExit (); /* KERNEL EXIT */ return (OK); }/********************************************************************************* taskResume - resume a task** This routine resumes a specified task. Suspension is cleared, and* the task operates in the remaining state.** RETURNS: OK, or ERROR if the task cannot be resumed.** ERRNO: S_objLib_OBJ_ID_ERROR**/STATUS taskResume ( int tid /* task ID of task to resume */ ) {#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging */ EVT_OBJ_2 (TASK, (WIND_TCB *)tid, taskClassId, EVENT_TASKRESUME, tid, ((WIND_TCB *)tid)->priority);#endif if (kernelState) /* defer work if in kernel */ { if ((tid == 0) || (TASK_ID_VERIFY ((void *)tid) != OK)) return (ERROR);#if CPU==SIMSPARCSUNOS || CPU==SIMSPARCSOLARIS bzero ((char *) &((WIND_TCB *) tid)->excInfo, sizeof (EXC_INFO));#endif /* CPU==SIMSPARCSUNOS || CPU==SIMSPARCSOLARIS */ workQAdd1 ((FUNCPTR)windResume, tid); /* add work to kernel work q */ return (OK); } if (tid == 0) /* zero is calling task */ return (OK); /* presumably we're running */ kernelState = TRUE; /* KERNEL ENTER */ if (TASK_ID_VERIFY ((void *)tid) != OK) /* check for invalid ID */ { windExit (); /* KERNEL EXIT */ return (ERROR); }#if CPU==SIMSPARCSUNOS || CPU==SIMSPARCSOLARIS bzero ((char *) &((WIND_TCB *) tid)->excInfo, sizeof (EXC_INFO));#endif /* CPU==SIMSPARCSUNOS || CPU==SIMSPARCSOLARIS */ windResume ((WIND_TCB *) tid); /* resume task */ windExit (); /* KERNEL EXIT */ 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, S_taskLib_ILLEGAL_PRIORITY**/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 & 0xffffff00) != 0) /* ! (0 <= x <= 255) */ { errno = S_taskLib_ILLEGAL_PRIORITY; return (ERROR); } } if (kernelState) /* already in kernel? */ { if ((tid == 0) || (TASK_ID_VERIFY ((void *)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 ((void *)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(); /
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -