📄 serlock.c
字号:
/* -*-C-*- * * $Revision: 1.16.4.3 $ * $Author: rivimey $ * $Date: 1998/01/23 18:47:42 $ * * Copyright (c) 1996 Advanced RISC Machines Limited. * All Rights Reserved. * * Project: ANGEL * * Title: Implementation of serialiser module */#include "serlock.h"#include "logging.h"#include "support.h"#include "arm.h"#include "devdriv.h"#include "devconf.h"#include "stacks.h"#if MINIMAL_ANGEL == 0/* #define DEBUG_TASKS *//* * Function: angel_StartTask * * Purpose: To execute a task. * * Arguments: regblock: a pointer to the angel_RegBlock structure * containing the registers to be instated * when the tasks executes * * Special Note: This is coded in serlasm.s, as it is not a normal * function. However, the prototype is here because * it is needed by functions in this module. * * Pre-conditions: This code is called from SVC mode with IRQ and FIQ * disabled. * * Effect: The task described is executed - when that task * completes control will be returned to angel_NextTask. * This code just inststes all the registers precisely * as set up in regblock. Thus for tasks which are being * started for the first time, sl, sp, fp, lr and cpsr * must have already been set up. * * Special Note: A second entry point to this function, * angel_StartTask_NonSVCEntry, which allows the exception * handlers a way to restart an aborted task using this * function, but without having to go into SVC mode. */extern void angel_StartTask(angel_RegBlock * regblock);/* * Function: angel_NextTask * * Purpose: Entered when any task completes * * Arguments: None * * Special Note: This is coded in serlasm.s, as it is not a normal * function. However, the prototype is here because * it is needed by functions in this module. * * Pre-conditions: This code is called from either SVC mode or USR mode * with IRQ and FIQ enabled. * * Effect: SVC mode is entered and the SVC stack grabbed. * Interrupts are disabled, and then angel_SelectNextTask * is called. */extern void angel_NextTask(void);/* * Function: angel_IdleLoop * * Purpose: Entered when there are no tasks ready to execute and * there is nothing to do right now. * * Arguments: None * * Special Note: This is coded in serlasm.s, as it is not a normal * function. However, the prototype is here because * it is needed by functions in this module. * * Pre-conditions: This code is called from either SVC mode * with IRQ and FIQ enabled. * * Effect: The SVC stack is emptied, and then interrupts are enabled * angel_Yield is then repeatedly called to see if there is * anything to do. */extern void angel_IdleLoop(void);/**********************************************************************/angel_RegBlock Angel_MutexSharedTempRegBlocks[2];/* * angel_TaskQueueItem: each item has a forward pointer a RegBlock * index and a priority. * * The index is the bit number used in angel_FreeBitmap. */typedef struct angel_TaskQueueItem{ struct angel_TaskQueueItem *next; int index; angel_TaskPriority pri; bool new_task; /* FALSE if interrupted thread */ angel_RegBlock rb;} angel_TaskQueueItem;static angel_TaskQueueItem *angel_TaskQueueHead;/* * This is the number of RegBlocks we support, and also the number of * entries we can cope with in the Task Queue. If it is made to * exceed 31 then we must recode the bitmap manipulation stuff. */#define POOLSIZE 12/* This holds which of the pool entries are free and which used. * A set bit means that entry is FREE */static unsigned angel_FreeBitMap;static int angel_ApplicationBlocked;static angel_TaskPriority angel_LastExecutedTaskPriority;static angel_TaskQueueItem angel_TQ_Pool[POOLSIZE];/**********************************************************************//* * The freeing and allocation of register blocks may be done by index only. */#define ISFREE(n) ((angel_FreeBitMap & (1 << (n))) != 0)#define ISALLOC(n) ((angel_FreeBitMap & (1 << (n))) == 0)#define FREE(n) angel_FreeBitMap |= (1 << (n))#define ALLOC(n) angel_FreeBitMap &= ~(1 << (n))/* angel_FreeToPool * * This function is passed the index of a pool entry to be freed. * * It will modify the queue pointers appropriately as well as marking * this pool element as free. */static void angel_FreeToPool(int n){ angel_TaskQueueItem *my_tqi = &angel_TQ_Pool[n]; angel_TaskQueueItem *tqi, *l_tqi; if (ISFREE(n)) LogError(LOG_SERLOCK, ( "Attempt to deallocate free block %d.\n", n)); FREE(n); /* Now we find it on the queue and remove it */ for (tqi = angel_TaskQueueHead, l_tqi = NULL; (tqi != my_tqi && tqi != NULL);) { l_tqi = tqi; tqi = tqi->next; } if (tqi == NULL) { LogError(LOG_SERLOCK, ( "Block could not be dequeued (%d).\n", n)); return; }#ifdef DO_TRACE LogTrace(LOG_SERLOCK, "SFreePool: %d\n", n);#endif if (l_tqi == NULL) angel_TaskQueueHead = my_tqi->next; else l_tqi->next = my_tqi->next; my_tqi->next = NULL;}/* angel_AllocateFromPool * * This function is passed a priority and 'new task' flag and will return * the index number of the pool entry which has been set up. * * It will modify the queue pointers appropriately, and sets up the * priorities and new_flag members. It does not set up the regblock * in any way. * * A task is put on the front of the part of the queue of the * appropriate priority only if it is neither a new task nor a yielded * task (ie. a real interrupted task). All others are put an the end * of the part of the queue with the appropriate priority */static int angel_AllocateFromPool(angel_TaskPriority pri, bool new_task, bool yielded){ int i; for (i = 0; i < POOLSIZE; i++) { if (ISFREE(i)) { angel_TaskQueueItem *my_tqi = &angel_TQ_Pool[i]; angel_TaskQueueItem *tqi, *l_tqi;#ifdef DO_TRACE LogTrace(LOG_SERLOCK, "SAllocPool: %d-p%d-n%d\n", i, pri, new_task);#endif ALLOC(i); /* Set up the priorities */ my_tqi->pri = pri; my_tqi->new_task = new_task; /* And insert the item into the queue. * which first involves finding a task of same priority and * inserting this task before it if not new, or after it if new. */ /* if new or yielded, ensure it goes after any exisiting entry at pri */ if (new_task || yielded) pri = (angel_TaskPriority) (pri - 1); for (tqi = angel_TaskQueueHead, l_tqi = NULL; (tqi != NULL) && (tqi->pri > pri);) { l_tqi = tqi; tqi = tqi->next; } /* We may have reached the end of the list, or we may not have */ my_tqi->next = tqi; if (l_tqi == NULL) angel_TaskQueueHead = my_tqi; else l_tqi->next = my_tqi; /* LogInfo(LOG_SERLOCK, ( "Allocated RegBlock %d\n",i)); */ return i; } } LogError(LOG_SERLOCK, ( "AllocateFromPool: No free RegBlock\n"));#if DEBUG == 1 /* * for (i = 0; i < POOLSIZE; i++) *{ * angel_TaskQueueItem *my_tqi = &angel_TQ_Pool[i]; * * LogWarning(LOG_SERLOCK, ( "Task %d: Pri=%d, New=%d, PC=%8x, PSR=%08x\n", * i, my_tqi->pri, my_tqi->new_task, * my_tqi->rb.r[15], my_tqi->rb.cpsr)); *} */#endif return -1;}/**********************************************************************//* * This routine looks for an interrupted queued task at the given * priority */static angel_RegBlock *angel_AccessQueuedRegBlock(angel_TaskPriority pri){ angel_TaskQueueItem *tqi; /* Find a task with the required priority, not marked as new */ for (tqi = angel_TaskQueueHead; (tqi != NULL) && !((tqi->pri == pri) && (!tqi->new_task)); ) { tqi = tqi->next; } if (tqi == NULL) { LogTrace1("SAccessQueue: p%d-NT ", pri); return NULL; } else { LogTrace2("SAccessQueue: p%d-t%d ", pri, tqi->index); return &(tqi->rb); }}angel_RegBlock *Angel_AccessApplicationRegBlock(void){ angel_RegBlock *rb; /* Find a task with the Application priority */ rb = angel_AccessQueuedRegBlock(TP_Application); if (rb == NULL) { LogWarning(LOG_SERLOCK, ( "Could not find application task.\n")); return NULL; } return rb;}void Angel_BlockApplication(int value){ LogInfo(LOG_SERLOCK, ( "angel_BlockApplication - set to %d.\n", value)); angel_ApplicationBlocked = value; /* yes, folks - that simple */}int Angel_IsApplicationBlocked(void){ LogInfo(LOG_SERLOCK, ("angel_IsApplicationBlocked - returns %d.\n", angel_ApplicationBlocked)); return angel_ApplicationBlocked;}int Angel_IsApplicationRunning(void){ int running = (angel_LastExecutedTaskPriority == TP_Application) || (angel_LastExecutedTaskPriority == TP_ApplCallBack); LogInfo(LOG_SERLOCK, ( "angel_IsApplicationRunning - returns %d.\n", running)); return running;}void Angel_FlushApplicationCallbacks(void){ angel_TaskQueueItem *tqi; int found; LogInfo(LOG_SERLOCK, ( "angel_FlushApplicationCallBakcs entered\n")); /* Find all tasks with the Application priority. * We have to start the loop from scratch each time we find one * because angel_FreeToPool changes all the pointers ! */ do { for (found = 0, tqi = angel_TaskQueueHead; (tqi != NULL && tqi->pri != TP_ApplCallBack);) { tqi = tqi->next; } if (tqi != NULL) { LogInfo(LOG_SERLOCK, ( "angel_FlushApplicationCallbacks - found task to flush\n")); angel_FreeToPool(tqi->index); found = 1; } } while (found == 1);}/* * Function: angel_SetUpTaskEnvironment * * Purpose: To set up the execution environment for a task * depeneding on its priority. * * Arguments: rb a pointer to the RegBlock to be updated. * * pri the priority of the task * * Pre-conditions: None * * Effect: sl, sp, fp, lr, cpsr are set up appropriately * according to the priority requested. * * Post-conditions: None */static void angel_SetUpTaskEnvironment(angel_RegBlock * rb, angel_TaskPriority pri){ angel_RegBlock *env_rb; /* LogInfo(LOG_SERLOCK, ("SetUpTaskEnvironment: p%d\n", pri)); */ switch (pri) { case TP_ApplCallBack: { LogInfo(LOG_SERLOCK, ( "SetUpTask: ApplCallBack\n")); env_rb = Angel_AccessApplicationRegBlock(); rb->r[10] = env_rb->r[10]; /* Copy sl from Application */ rb->r[13] = env_rb->r[13]; /* Copy sp from Application */ rb->r[11] = 0; /* fp = 0 */ rb->r[14] = (unsigned)angel_NextTask; rb->cpsr = USRmode; break; } case TP_AngelCallBack: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -