⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serlock.c

📁 AT91所有开发板的资料 AT91所有开发板的资料
💻 C
📖 第 1 页 / 共 4 页
字号:
        tqi->rb.r13svc = Angel_StackBase + Angel_SVCStackOffset;        tqi->rb.r13usr = tqi->stack->stackBase;                /* copy the state of the non-Angel interrupt bit to the new task */        tqi->rb.cpsr = USRmode | (cpsr & NotAngelInterruptMask);        tqi->rb.r14usr = (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    }        cpsr = Angel_DisableInterruptsFromSVC();    switch (state)    {        case TS_Runnable:                        /* now we've set up the task, change it's state to runnable.             * And insert the item into the run queue.             */            tqi->state = TS_Runnable;            Task_Enqueue(&angel_TQI_Run, tqi);            break;                    case TS_Blocked:                        /* now we've set up the task, change it's state to runnable.             * And insert the item into the wait queue.             */            tqi->state = TS_Blocked;            Task_AddTail(&angel_TQI_Wait, tqi);            break;                    default:            LogFatalError(LOG_SERLOCK, ("Angel_NewTask: Invalid state %d.\n", state));    }#ifdef DEBUG_TASKS    angel_PrintTaskQueueShort("NT-R", &angel_TQI_Run);    angel_PrintTaskQueueShort("NT-W", &angel_TQI_Wait);    LogInfo(LOG_SERLOCK, ("Angel_NewTask: New task %d returning to %lx.\n",                          tqi->index, tqi->rb.pc));#endif    LogInfo(LOG_SERLOCK, ("Angel_NewTask: func: 0x%08lx, arg %lx, type: %d => ID %d\n",                          fn, (int)a1, (int)type, tqi->index));    Angel_RestoreInterruptsFromSVC(cpsr);        return tqi;}/* *        Function:  angel_DeleteTask * *         Purpose:  To remove the task pointed to by oldtask, freeing up *                   its stack and other resources and removing the TQI *                   from the queue. * *       Arguments:  oldtask - a pointer to the TQI for the task to remove * *          Return:  none. *                    *  Pre-conditions:  Serialiser initialised; oldtask should not point to the *                   idle task, and must point to a valid TQI structure. * * * Post-conditions: * */void angel_DeleteTask(angel_TaskQueueItem *tqi){#ifdef DEBUG_TASKS    LogInfo(LOG_SERLOCK, ("DeleteTask: task %d (task stack HWM %d bytes, alloc %d bytes)\n", tqi->index,                             tqi->stack->stackBase - tqi->stack->HWM,                             tqi->stack->stackBase - tqi->stack->stackLimit));#endif    #if DEBUG    Angel_DebugLog(0, tqi, 10);#endif    ASSERT((tqi->type != TP_IdleLoop), ("angel_DeleteTask: Cannot delete idle task\n"));    ASSERT((tqi == angel_CurrentTask), ("angel_DeleteTask: tqi expected to be current task\n"));    ASSERT(((Angel_GetCPSR() & 0xf) != 0), ("angel_DeleteTask: in USR mode\n"));        ASSERT(((Angel_GetCPSR() & AngelInterruptMask) == AngelInterruptMask),           ("angel_DeleteTask: interrupts must be disabled\n"));    /*     * SVC tasks have a "stack" value which isn't on the free list, so     * don't add it onto the free list.     */    if (tqi->type != TP_AngelWantLock)    {#ifdef DEBUG_TASKS	LogInfo(LOG_SERLOCK, ("DeleteTask: remove stack %p\n", tqi->stack ));#endif	Stack_AddTail(&angel_Stack_Free, tqi->stack);    }#if DEBUG    tqi->stack = 0;#endif        /*     * remove TQI from run list, add to free list and mark deleted     */    DEC_STAT(angel_NumCurrentTasks);    tqi->state = TS_Undefined;    /* Task_Remove(tqi); current task not in list; atm, we only delete current task */    Task_AddTail(&angel_TQI_Free, tqi);    /*     * tell SelectNextTask that we haven't got a current task.     */    angel_CurrentTask = NULL;}/* *        Function:  angel_BlockAndSchedule * *         Purpose:  Remove task from current (run) list, put it on the waiting list *                   and set currenttask to NULL so Select doesn't enqueue it again on *                   the run list. Call SelectNextTask to schedule another task. *                    *       Arguments:  rb - the register block into which the task context was saved *                   tqi - the task queue referring to the task being inspected. * *          Return:  none. *                    *  Pre-conditions:  Must be called from the SWi return code in except.s with *                   currenttask pointing at the application. * * Post-conditions:   * */void angel_BlockAndSchedule(angel_RegBlock *rb, angel_TaskQueueItem *tqi){    ASSERT(((Angel_GetCPSR() & 0xf) != 0),           ("angel_BlockAndSchedule: in USR mode\n"));        ASSERT(((Angel_GetCPSR() & AngelInterruptMask) == AngelInterruptMask),           ("angel_BlockAndSchedule: interrupts must be disabled\n"));    ASSERT((tqi == angel_CurrentTask),           ("angel_BlockAndSchedule: code expects tqi to be current\n"));#ifdef DEBUG_TASKS    LogInfo(LOG_SERLOCK, ("angel_BlockAndSchedule: task %d\n", tqi->index ));#endif        tqi->state = TS_Blocked;        /* copy the register context to the given TQI */    angel_QueueTask(rb, tqi);        /* do this if tqi can be something other than current:     * if (tqi != angel_CurrentTask) Task_Remove(tqi);     */    Task_AddTail(&angel_TQI_Wait, tqi);    angel_CurrentTask = NULL;        /* jump to scheduler to find a new task */    angel_SelectNextTask();}/* *        Function:  angel_WaitCore * *         Purpose:  The core routine for Angel_Wait (see serlasm.s), which *                   overall deschedules the calling task waiting for an event *                   of some sort. By the time we get here, we have: *                    *                   a. entered SVC mode with interrupts disabled  *                    *                   b. saved the task context in RB_Yield *                    *                   c. saved the wait parameter (the value to wait on) in *                      the regblock r0 value. *                    *      Description  The event value is a bitmask; each bit is significant, but *      -----------  the meaning of the bits must be pre-arranged bu the tasks *                   (although this can happen at run-time if needed). A task *                   may validaly wait for a number of events by setting more than *                   one bit in the parameter to wait. If any one of these events *                   has happened, wait will return immediately with a bitmask *                   indicating which events out of those requested have happened. *                   If no events have yet happened, wait causes the task to sleep *                   until something Signal()s the task. Note that as Signal does *                   not cause a reschedule, more than one signal may occur before *                   wait finally returns; again, all the events signalled will be *                   returned to the waiting task. *                    *      Action       The core code must thus check whether the event to be waited *      ------       for has already happened (by examining signalsReceived), and *                   if it has to return, modifying signalsReceived to remove the *                   events this wait was waiting for. If the event has yet to *                   happen, the routine records the event in the TQI for this *                   task and deschedule itself. *                    *                   The anomalous case when a task waits for no events results *                   in Angel_Wait returning a result of 0 immediately. * *       Arguments:  rb - the register block into which the task context was saved *                   tqi - the task queue referring to the task being inspected. * *          Return:  none (returns via StartTask on rb, or via serialiser). *                    *  Pre-conditions:  serialiser must be initialised. Only validly called via Angel_Wait * * Post-conditions:  (none). * */void angel_WaitCore(angel_RegBlock *rb, angel_TaskQueueItem *tqi){    register int b;    ASSERT(((Angel_GetCPSR() & AngelInterruptMask) == AngelInterruptMask),           ("angel_WaitCore: interrupts must be disabled\n"));    ASSERT(((Angel_GetCPSR() & 0xf) != 0), ("angel_WaitCore: in USR mode\n"));        /* if we ask for no events happening, just return 0 to caller */    if (rb->r0 == 0)    {        LogInfo(LOG_SERLOCK, ("WaitCore: task %d returning: r0 is 0\n", Angel_TaskID() ));        angel_StartTask(rb);    }    /* find out if (at least one of) the events has already happened */    b = rb->r0 & tqi->signalReceived;    /* reset the events in received which we have now accepted */    tqi->signalReceived &= ~b;    if (b)    {#ifdef DEBUG_SIGNALS        LogInfo(LOG_SERLOCK, ("WaitCore: task %d returning: signalReceived matched\n",                              Angel_TaskID()));#endif                /* one of the events has happened; return which event in r0         * and return now.         */         tqi->signalWaiting = 0;        rb->r0 = b;        angel_StartTask(rb);    }    else    {#ifdef DEBUG_SIGNALS        LogInfo(LOG_SERLOCK, ("WaitCore: task %d waiting for signal %x...\n",                              Angel_TaskID(), rb->r0));#endif                /* no event we are interested in has happened yet. Tell the         * scheduler to deschedule us until they do.         */        tqi->signalWaiting = rb->r0;        /*         * reset the value of r0 -- this will return signals accepted.         */        rb->r0 = 0;                angel_BlockAndSchedule(rb, tqi);    }}/* *        Function:  Angel_Signal * *         Purpose:  To cause an event to be sent to a task which is now, or will *                   in the future Wait() for it. In itself, Signal() does nothing *                   useful. *                    *                   Signal takes a task id (a small integer) identifying a current *                   task and marks that task as having received the passed event *                   bits (see the description for Angel_Wait). If the task is already *                   blocked, it is assumed that the task is Wait()ing and, having *                   subtracted the new signals from the signals the task was waiting *                   for it (potentially) wakes up that task. *                    *                   If the task was running, it is assumed that sometime it will call *                   wait(), and the signals are just marked in the task signalWaiting *                   member. * *                   Task ID's are returned by the call Angel_TaskID(), which returns *                   a tasks own id. It must use other means to communicate this id *                   to whatever needs to signal it. *                    *       Arguments:  task - the task id (NOT TQI pointer) for the task to signal. *                   signals - one or more bits set in a word corresponding to events. * *          Return:  none. *                    *  Pre-conditions:  serialiser initialised; task identified by 'task' is a current *                   task. * * Post-conditions:  task state modified. * */int Angel_Signal(unsigned task, unsigned signals){    register int needsched = 0;    register int b;    Angel_EnterCriticalSection();                if (task > 0 && task < POOLSIZE)    {        angel_TaskQueueItem *tqi = &angel_TQ_Pool[task];                switch (tqi->state)        {	    case TS_Blocked:		/* if current task is already waiting, then signal it directly */#ifdef DEBUG_SIGNALS		LogInfo(LOG_SERLOCK, ("Signal: from task %d, waiting task %d; sig %04x "				      "[sigRec was %04x, sigWait %04x].\n",				      Angel_TaskID(), task, signals, tqi->signalReceived,				      tqi->signalWaiting));#endif		/* get the intersection of events signalled and waited on */		b = (tqi->signalWaiting & signals);		/* set bits in signalReceived which were not waited for */		tqi->signalReceived |= signals & ( ~tqi->signalWaiting);		/* clear bits set in signalWaiting which are being accepted */		tqi->signalWaiting &= ~b;                                /*                 * poke r0 in task RB so when task resumes the return value                 * is the signals we have just changed                 */                tqi->rb.r0 |= b;#ifdef DEBUG_SIGNALS		LogInfo(LOG_SERLOCK, ("Signal: R0 |= %04x -> %04x [sigRec %04x, sigWait %04x.]\n",                                      b, tqi->rb.r0, tqi->signalReceived, tqi->signalWaiting));#endif		/* if b != 0, we can make the task runnable. */		if (b != 0)		{                    /* remove task from wait list and make task runnable again */		    tqi->state = TS_Runnable;                    Task_Remove(tqi);                    Task_Enqueue(&angel_TQI_Run, tqi);                    /* if in interrupt, we need to get into the scheduler before the                     * ISR returns                     */		    needsched = 1;		}		break;            case TS_Runnable:	    case TS_Running:#ifdef DEBUG_SIGNALS		LogInfo(LOG_SERLOCK, ("Signal: from task %d, running task %d; signal %04x, "				      "old signalReceived %04x.\n",				      Angel_TaskID(), task, signals, tqi->signalReceived));#endif            		/* current task is not waiting for us. Assume that it will		 * sometime in the future...		 */		tqi->signalReceived |= signals;		break;	    default:		LogError(LOG_SERLOCK, ("Signal: task in strange state %d\n", tqi->state));    	}    }    else        LogError(LOG_SERLOCK, ("Signal: invalid task id %d\n", task));    Angel_LeaveCriticalSection();    return needsched;}/* *        Function:  Angel_DeferredBlockCore * *         Purpose:  Called to complete the blocking of the application task *                   when it was deferred because Angel was processing a SWI *                   on behalf of the application at the time of the original *                   request. *                    *                   Resetting the blocked flag is done by the assembler in *                   except.s, as it's address has already been loaded. * *       Arguments:  none. * *          Return:  none. *                    *  Pre-conditions:  Must be called from the SWi return code in except.s with *                   currenttask pointing at the application. * * Post-conditions:   * */void Angel_DeferredBlockCore(void){    ASSERT((angel_CurrentTask->type == TP_Application),           ("Angel_DeferredBlockCore: not appl task"));        angel_BlockAndSchedule(&Angel_GlobalRegBlock[RB_SWI], angel_CurrentTask);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -