📄 serlock.c
字号:
/* -*-C-*- * * $Revision: 1.2 $ * $Author: rivimey $ * $Date: 1999/03/22 17:47:08 $ * * Copyright (c) 1996-1998 ARM Limited. * All Rights Reserved. * * Project: ANGEL * * Title: Implementation of serialiser module */#include "angel.h"#include "devconf.h"#include "logging.h"#include "serlock.h"#include "support.h"#include "arm.h"#include "devdriv.h"#include "stacks.h"#include "serial.h"#include "timerd.h"#include "tasklist.h"#if MINIMAL_ANGEL == 0static List angel_TQI_Free; /* free angel_TaskQueueItem's */List angel_TQI_Wait; /* waiting tasks, not ordered */List angel_TQI_Run; /* running tasks, priority ordered */angel_TaskQueueItem *angel_CurrentTask; /* points at running task, not on any list */static angel_TaskQueueItem *angel_ApplTask;static angel_TaskQueueItem *angel_IdleTask;#if POLLING_SUPPORTEDstatic angel_TaskQueueItem *angel_PollTask;#endifstatic List angel_Stack_Free; /* free stack regions */unsigned long angel_SWIReturnToApp; /* if in appl SWI, 0 otherwise */unsigned long angel_SWIDeferredBlock; /* if in appl SWI, 0 otherwise */unsigned long Angel_Needschedule; /* if TRUE, enter scheduler at end of current interrupt *//* pool of task descriptors, managed by lists above */angel_TaskQueueItem angel_TQ_Pool[POOLSIZE];/* pool of stack descriptors, managed by lists above. */static angel_StackDesc angel_Stack_Pool[POOLSIZE];/* supervisor stack descriptor -- refers to distinct stack region, not list-managed */static angel_StackDesc angel_SVCStack;/* global reg blocks -- used to save context info until scheduler entered. */angel_RegBlock Angel_GlobalRegBlock[RB_NumRegblocks];/* the externs here are defined in startrom.s */extern unsigned long angel_GhostCount; /* interrupts */extern unsigned long angel_SWIReturnToApp; /* in appl SWI */extern unsigned long angel_ComplexSWILock; /* in complex SWI */extern void angel_NextTask(void);extern void angel_StartTask(angel_RegBlock *);#if DEBUG#define INC_STAT(x) (x)++#define DEC_STAT(x) (x)--#undef DEBUG_TASKS#undef DEBUG_APPLINT#undef DEBUG_SIGNALSstatic unsigned long angel_NumCurrentTasks = 0;static unsigned long angel_NumTasksHWM = 0;extern unsigned long angel_InterruptCount;extern unsigned long angel_DebugStartTaskCount;extern unsigned long angel_DebugQueueTaskCount;extern unsigned long angel_SysCallCount;#else /* not DEBUG */#define INC_STAT(x)#define DEC_STAT(x)#undef DEBUG_TASKS#undef DEBUG_APPLINT#undef DEBUG_SIGNALS#endif#if DEBUGstruct StatInfo intr_stat_info[] ={ "Interrupt Stats:\n" " Total Interrupts %8d\n", &angel_InterruptCount, " Ghost Interrupts %8d\n", &angel_GhostCount, NULL, NULL};struct StatInfo task_stat_info[] ={ "Task Stats:\n" " Total Task Switches %8d\n", &angel_DebugStartTaskCount, " Tasks Interruped %8d\n", &angel_DebugQueueTaskCount, " System Calls %8d\n", &angel_SysCallCount, " Number of tasks (HWM) %8d\n", &angel_NumTasksHWM, "\n" "Current State:\n" " Number of tasks %8d\n", &angel_NumCurrentTasks, " Complex SWI Lock %8d\n", &angel_ComplexSWILock, " Current Task %8x\n", (unsigned long *)&angel_CurrentTask, NULL, NULL};#endif/**********************************************************************/#if defined( DEBUG_TASKS )void angel_PrintTaskQueue(List *q){ angel_TaskQueueItem *tqi; for(tqi = Task_FirstNode(q); !Task_AtEndOfList(tqi); ) { LogInfo(LOG_SERLOCK, ("Task Queue %d: (%08lx) %s\n" "Next = %08lx, Type = %d, State = %d, Priority = %u\n", tqi->index, tqi, (tqi->name) ? tqi->name : "", tqi->n.n.mn_next, tqi->type, tqi->state, tqi->priority)); LogInfo(LOG_SERLOCK, ("Stack Base = %08lx, Limit = %08lx, Entrypoint = %08lx\n", tqi->stack->stackBase, tqi->stack->stackLimit, tqi->entryPoint)); LogInfo(LOG_SERLOCK, ("Signal Wait = %08lx, Signal Bits = %08lx\n", tqi->signalWaiting, tqi->signalReceived)); LogInfo(LOG_SERLOCK, (" pc = %08lx cpsr = %08lx\n", tqi->rb.pc, tqi->rb.cpsr)); LogInfo(LOG_SERLOCK, (" r0 = %08lx r1 = %08lx r2 = %08lx r3 = %08lx\n", tqi->rb.r0, tqi->rb.r1, tqi->rb.r2, tqi->rb.r3)); tqi = Task_Succ(tqi); if (!Task_AtEndOfList(tqi)) LogInfo(LOG_SERLOCK, ("\n")); }}#else#define angel_PrintTaskQueue(l)#endif#ifdef DEBUG_TASKSstatic void angel_PrintTaskQueueShort(char *s, List *q){ angel_TaskQueueItem *tqi; LogInfo(LOG_SERLOCK, ("Task Queue: %s: ", s)); if (q == &angel_TQI_Run && (tqi = angel_CurrentTask) != NULL) { LogInfo(LOG_SERLOCK, ("*(%d %c %d)", tqi->priority, (tqi->state == TS_Blocked) ? 'B' : 'R', tqi->index)); tqi = Task_FirstNode(q); if (!Task_AtEndOfList(tqi)) LogInfo(LOG_SERLOCK, (" -> ")); } else tqi = Task_FirstNode(q); while(!Task_AtEndOfList(tqi) ) { LogInfo(LOG_SERLOCK, ("(%d %c %d)", tqi->priority, (tqi->state == TS_Blocked) ? 'B' : 'R', tqi->index)); tqi = Task_Succ(tqi); if (!Task_AtEndOfList(tqi)) LogInfo(LOG_SERLOCK, (" -> ")); } LogInfo(LOG_SERLOCK, ("\n"));}#else#define angel_PrintTaskQueueShort(s, l)#endif/**********************************************************************/void Task_Enqueue(List *lp, angel_TaskQueueItem *np){ if (IsListEmpty(lp)) { AddHead(lp, (MinNode *)np); } else { angel_TaskQueueItem *fp = (angel_TaskQueueItem *)FirstNode(lp); angel_TaskQueueItem *bp = (angel_TaskQueueItem *)LastNode(lp); short pri = np->priority; if (pri > fp->priority) { AddHead(lp, (MinNode*)np); } else if (pri <= bp->priority) { AddTail(lp, (MinNode*)np); } else { /* we've checked start & end of list; it must be in the middle! */ while(pri <= fp->priority) { fp = (angel_TaskQueueItem*)Succ((MinNode*)fp); } InsertBefore((MinNode*)fp, (MinNode*)np); } }}/* * Function: Angel_AccessApplicationTask * * Purpose: This routine looks for the application task * queue item. * * Arguments: none * * Return: tqi a pointer to the task queue for the * appl task, or NULL if no task found. * * Pre-conditions: angel_TaskQueueHead initialised. * * Post-conditions: none */angel_TaskQueueItem *Angel_AccessApplicationTask(void){ return angel_ApplTask;}/* * Function: Angel_GetBankedReg * * Purpose: Read the register 'regno' for mode 'mode' from * register block 'rb'. * * Arguments: rb a pointer to the RegBlock to be updated. * regno the number of the register to read * mode the CPU mode (as CPSR) * * Coding for 'regno': 13 => r13, 14 ->r14, 15 -> SPSR * * Pre-conditions: None * * Post-conditions: None */ extern unsigned char ContextLookuptable[3][16];unsigned Angel_GetBankedReg(angel_RegBlock *rb, unsigned int mode, int regno){ unsigned char rboffset = ContextLookuptable[regno - 13][mode & 0xf]; unsigned char *rbptr = (unsigned char *)rb + rboffset; return *((unsigned int *)rbptr);}/* * Function: Angel_AdrBankedReg * * Purpose: Read the address of register 'regno' for mode 'mode' * in register block 'rb'. * * Arguments: rb a pointer to the RegBlock to be updated. * regno the number of the register to read * mode the CPU mode (as CPSR) * * Coding for 'regno': 13 => r13, 14 ->r14, 15 -> SPSR * * Pre-conditions: None * * Post-conditions: None */unsigned *Angel_AdrBankedReg(angel_RegBlock *rb, unsigned int mode, int regno){ unsigned char rboffset = ContextLookuptable[regno - 13][mode & 0xf]; unsigned char *rbptr = (unsigned char *)rb + rboffset; return ((unsigned *)rbptr);}/* * Function: angel_QueueTask * * Purpose: To copy a regblock context into the task queue item, used * when saving a task context for later execution. * * The routine modifies the run state; if the task was running * it patently isn't anymore, and the state is set to runnable. * As this must not happen if state was blocked, the initial * state must be verified as Running first. * * Arguments: regblock - the regblock from which to take the processor * context. * tqi - the tqi into which the context must be saved * * Return: none. * * Pre-conditions: the context in regblock must be the context for the task * referenced in tqi. * * Post-conditions: the TQI is up-to-date w.r.t. it's task. * */voidangel_QueueTask(angel_RegBlock * regblock, angel_TaskQueueItem *tqi){ /* LogInfo(LOG_SERLOCK, ("QueueTask: rb %x, tq %x\n", regblock, tqi )); */ __rt_memcpy((void *)&(tqi->rb), (const void *)regblock, sizeof(angel_RegBlock)); #if DEBUG != 0 Angel_DebugLog(regblock, tqi, 2) ;#endif /* if this task was running, it isn't any longer. Mark it so. */ if (tqi->state == TS_Running) { tqi->state = TS_Runnable; }}/**********************************************************************//* * Function: angel_FindTask * * Purpose: This routine looks for a task on the task queue * with the given type. * * Arguments: type the type of task being searched for * * Return: tqi a pointer to the task queue for the * required task, or NULL if no task found. * * Pre-conditions: angel_TaskQueueHead initialised. * * Post-conditions: none */angel_TaskQueueItem *angel_FindTask(List *q, angel_TaskType type){ angel_TaskQueueItem *tqi; /* Find a task with the required type, not marked as new */ tqi = Task_FirstNode(q); while (!Task_AtEndOfList(tqi)) { if (tqi->type == type) { return tqi; } tqi = Task_Succ(tqi); } return NULL;}/* * Function: angel_AccessQueuedRegBlock * * Purpose: This routine looks for a task on the task queue * with the given type. * * Arguments: type the type of task being searched for * * Return: rb a pointer to the regblock for the * required task, or NULL if no task found. * * Pre-conditions: angel_TaskQueueHead initialised. * * Post-conditions: none */angel_RegBlock *angel_AccessQueuedRegBlock(angel_TaskType type){ angel_TaskQueueItem *t; /* Find a task with the requested priority */ t = angel_FindTask(&angel_TQI_Run, type); if (t == NULL) t = angel_FindTask(&angel_TQI_Wait, type);#if DEBUG if (t == NULL) { LogWarning(LOG_SERLOCK, ( "Could not find application task.\n")); return NULL; }#endif return &(t->rb);}/* * Function: Angel_BlockApplication * * Purpose: Block or unblock the application task; that is * either allow or prevent it from executing any * further. If Angel is currently executing a SWI * on behalf of the application, the SWI is allowed * to complete, but the application is not resumed. * * Arguments: value TRUE to block, FALSE to unblock appl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -