📄 serlock.c
字号:
* * Return: none. * * Pre-conditions: angel_TaskQueueHead initialised. * * Post-conditions: none */void Angel_BlockApplication(int value){ angel_TaskQueueItem *tqi; if (angel_SWIReturnToApp) { LogInfo(LOG_SERLOCK, ( "angel_BlockApplication - (deferred) set to %d.\n", value)); angel_SWIDeferredBlock = 1; } else { Angel_EnterCriticalSection(); tqi = angel_ApplTask; ASSERT((tqi != angel_CurrentTask), ("Angel_BlockApplication: tqi cannot be current task\n")); if ((value == 0) && (tqi->state == TS_Blocked)) { LogInfo(LOG_SERLOCK, ( "angel_BlockApplication - set to %d (was blocked)\n", value)); tqi->signalWaiting = 1; tqi->state = TS_Runnable; Task_Remove(tqi); Task_Enqueue(&angel_TQI_Run, tqi); } else if ((value == 1) && (tqi->state == TS_Runnable)) { LogInfo(LOG_SERLOCK, ( "angel_BlockApplication - set to %d (was run)\n", value)); tqi->signalWaiting = 0; Task_Remove(tqi); tqi->state = TS_Blocked; Task_Enqueue(&angel_TQI_Wait, tqi); } else { /* else task is already in correct state -- * either blocked and value == 1, or runnable and value == 0 */ LogInfo(LOG_SERLOCK, ( "angel_BlockApplication - set to %d (ignored)\n", value)); } Angel_LeaveCriticalSection(); }}/* * Function: Angel_IsApplicationBlocked * * Purpose: Return whether the application task is blocked. Being * blocked is indicated by two things: a deferred block * caused by BlockApplication called during an appl SWI, * and a 'real' block, indicated by the task having status * TS_Blocked. * * Arguments: value TRUE if blocked, FALSE otherwise * * Return: none. * * Pre-conditions: angel_TaskQueueHead initialised. * * Post-conditions: none */int Angel_IsApplicationBlocked(void){ int blocked; if (angel_SWIDeferredBlock) blocked = 1; else { blocked = (angel_ApplTask->state == TS_Blocked); } LogInfo(LOG_SERLOCK, ("angel_IsApplicationBlocked - returns %d.\n", blocked)); return blocked;}/* * Function: angel_SetPriority * * Purpose: To change the scheduler priority of a task on the task * queue. As the priority is implicit in the position in the * task list it is not possible to just poke the priority * value in the TQI; the task must be requeued as well. * * The task is located in the task queue, which ensures it has * been initialised and to find the next higher priority task. * 'olstask' is then removed from the list, the priority in * its TQI modifined, and the task enqueue routine called to * place it in the correct place. * * This routine will not cause a task switch to 'oldtask' * if it is made higher priority than the current task, nor * can it cause the current task to be suspended if it is * set to a lower priority than another runnable task. * * Arguments: oldtask - the task whose priority is to be changed * priority - the new task priority * * Return: none. * * Pre-conditions: Serialiser initialised; the task pointed to by 'oldtask' * must have previously been added with Angel_NewTask; the * routine must be called with interrupts disabled. * * Effect: 'oldtask' is requeued to reflect the assigned priority. * * Post-conditions: * */void angel_SetPriority(angel_TaskQueueItem *oldtask, unsigned priority){ register List *lp; ASSERT(((Angel_GetCPSR() & 0xf) != 0), ("angel_SetPriority: in USR mode\n")); oldtask->priority = priority; /* if not changing current task re-enqueue it */ if (oldtask != angel_CurrentTask) { Task_Remove(oldtask); if (oldtask->state == TS_Blocked) lp = &angel_TQI_Wait; else lp = &angel_TQI_Run; Task_Enqueue(lp, oldtask); }}/* * Function: angel_EnterSWI * * Purpose: Routine called when an Angel Complex SWI is entered. * Used to perform some housekeeping, including raising * the priority of the application task to that of Angel * callbacks. This is necessary so that an incoming packet * cannot interrupt the processing of a SWI; if this were * allowed, deadlock could occur if the incoming packet * needed to send a reply while the SWI request packet was * still being processed. * * To enable Angel to tell that Angel is executing code on * behalf of the application task, the flag SWIReturnToApp * is set. This is used in the SWI return code and within the * BlockApplication routine. * * Arguments: none. * * Return: none. * * Pre-conditions: Must be called with interrupts disabled (because SetPriority * must be). angel_CurrentTask must point to an Application task * * Post-conditions: The application task temporarily has a higher priority; * the Application-is-executing-SWI flag is set. * */void angel_EnterSWI(void){#if DEBUG if (angel_CurrentTask->type != TP_Application) { LogFatalError(LOG_SERLOCK, ("Complex SWI called from within Angel: stack use conflict\n")); }#endif angel_SetPriority(angel_CurrentTask, TaskPriorityOf(TP_AngelCallBack)); angel_SWIReturnToApp = 1;}/* * Function: angel_ExitSWI * * Purpose: Undo the effects of angel_EnterSWI. Return the application * to it's normal priority and reset the in-swi flag. This routine * is called by return-from-complex-SWI routine. * * Arguments: none. * * Return: none. * * Pre-conditions: Must be called with interrupts disabled (because SetPriority * must be). angel_CurrentTask must point to an Application task * angel_SWIReturnToApp should be set. * * Post-conditions: The application task priority is returned to normal; the in-swi * flag is reset. * */void angel_ExitSWI(void){ ASSERT(((Angel_GetCPSR() & 0xf) != 0), ("angel_ExitSWI: in USR mode\n")); ASSERT((angel_SWIReturnToApp == 1), ("System Call Return with no Call -- what happened?\n")); angel_SetPriority(angel_CurrentTask, TaskPriorityOf(TP_Application)); angel_SWIReturnToApp = 0;}/* * Function: Angel_QueueCallback * * Purpose: The external API for the NewTask function, called by routines * within Angel wishing to create callback tasks. * * Arguments: fn - the function to call * type - the task type (e.g. TP_AngelCallback) to create * a1.. a4 - (up to) 4 parameters for the new task. * * Return: none. * * Pre-conditions: The serialiser must have been initialised. * * Post-conditions: The new task will have been added to the task queue as a * runnable task, unless there was no TQI or stack available for * it. * */angel_TaskQueueItem *Angel_QueueCallback(angel_CallbackFn fn, angel_TaskType type, void *a1, void *a2, void *a3, void *a4){ angel_TaskQueueItem *tqi; Angel_EnterSVC(); tqi = Angel_NewTask(TS_Runnable, type, (unsigned)fn, a1); tqi->rb.r1 = (unsigned)a2; tqi->rb.r2 = (unsigned)a3; tqi->rb.r3 = (unsigned)a4; Angel_ExitToUSR(); return tqi;}/* * Function: angel_SetupExceptionRegisters * * Purpose: * * * Arguments: * * * Return: none. * * Pre-conditions: The serialiser must have been initialised. * * Post-conditions: * * */void Angel_SetupExceptionRegisters(angel_TaskQueueItem * tqi){ register unsigned base = Angel_StackBase; tqi->rb.r14fiq = 0; tqi->rb.r14irq = 0; tqi->rb.r14und = 0; tqi->rb.r14abt = 0; /* set up the new task's exception registers. */ tqi->rb.r13fiq = base + Angel_FIQStackOffset; tqi->rb.r13irq = base + Angel_IRQStackOffset; tqi->rb.r13und = base + Angel_UNDStackOffset; tqi->rb.r13abt = base + Angel_ABTStackOffset;}/* * Function: Angel_NewTask * * Purpose: To create a new task context. This is the only way to create * a new task, and may be executed in USR or Supervisor mode. The * new task will not be executed immediately, but will be queued * according to it's priority and may be executed as soon as * SelectNextTask is run again. * * The new task context's mode will depend on it's type: all tasks * other than AngelWantLock are given a USR mode context, with a * stack allocated in the AngelAngelStack area; AngelWantLock tasks * (which are only created by SerialiseTaskCore) are run in SVC mode * with a statically allocated SVC stack. * * The processor registers pc, r0 - r3 are set using the arguments * 'fn' and 'a1'-'a4' respectively; lr is set to angel_NextTask, which * will kill the task and enter the scheduler on it's exit. The * sp of the exception modes is set to their stack top, and their lr * registers to a routine which will cause a fatal error (the LR should * be overwritten on entry to the handler by the processor; therefore, * if the value written here the program has already gone wrong. * * The SVC stack is set up for USR mode tasks, but not vice versa; * the SVC task is not expected to use or need r13usr to be set. (The * reverse is also true, but SVC sp can be set up easily). * * Arguments: fn - the function to call * type - the task type (e.g. TP_AngelCallback) to create * a1 - the first parameter for the new task. * * Return: a pointer to the TQI allocated to the task or NULL if task not * initialised (an error). * * Pre-conditions: The serialiser, and exception subsystems must have been set up. * * Post-conditions: The new task added to the task queue, or NULL returned. * */angel_TaskQueueItem * Angel_NewTask(angel_TaskState state, angel_TaskType type, unsigned fn, void *a1){ unsigned int cpsr; angel_TaskQueueItem *tqi; ASSERT(((Angel_GetCPSR() & 0xf) != 0), ("NewTask: in USR mode\n")); /* enter critical section */ cpsr = Angel_DisableInterruptsFromSVC(); tqi = Task_RemHead(&angel_TQI_Free); if (tqi == NULL) {#if DEBUG LogFatalError(LOG_SERLOCK, ("Angel_NewTask: Cannot create new task.\n"));#endif Angel_RestoreInterruptsFromSVC(cpsr); return NULL; }#if DEBUG == 1 INC_STAT(angel_NumCurrentTasks); if (angel_NumTasksHWM < angel_NumCurrentTasks) angel_NumTasksHWM = angel_NumCurrentTasks;#endif /* Set up the type and priority */ tqi->type = type; /* the initial task priority is determined by the type */ tqi->priority = TaskPriorityOf(type); tqi->name = 0; tqi->signalReceived = 0; tqi->signalWaiting = 0; tqi->stack = 0; if (type == TP_AngelWantLock) { tqi->stack = &angel_SVCStack; } else { tqi->stack = Stack_RemHead(&angel_Stack_Free); if (tqi->stack == NULL) /* sorry, can't do it! */ { DEC_STAT(angel_NumCurrentTasks); Task_Remove(tqi); tqi->state = TS_Undefined; Task_AddTail(&angel_TQI_Free, tqi); Angel_RestoreInterruptsFromSVC(cpsr); LogFatalError(LOG_SERLOCK, ("Angel_NewTask: Cannot allocate new stack.\n")); return NULL; } }#if DEBUG tqi->stack->HWM = tqi->stack->stackBase;#endif Angel_RestoreInterruptsFromSVC(cpsr); /* set up the registers we want for this call */ tqi->rb.r0 = (unsigned)a1; tqi->rb.pc = (unsigned)fn;#if DEBUG tqi->entryPoint = (unsigned)fn;#endif /* set up the new task's exception registers. */ Angel_SetupExceptionRegisters(tqi); if (type == TP_AngelWantLock) { tqi->rb.r13svc = tqi->stack->stackBase; /* copy the state of the non-Angel interrupt bit to the new task */ tqi->rb.cpsr = SVCmode | (cpsr & NotAngelInterruptMask); tqi->rb.r14svc = (unsigned)angel_NextTask; #ifdef R10_IS_SL /* The stack limit is not used in standard Angel: this code is here to` * show where and how to set up SL. */ tqi->rb.r10usr = tqi->stack->stackLimit;#endif } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -