📄 dot11timerlib.c
字号:
/* dot11TimerLib.c - A generic timer library for the dot11 framework *//* Copyright 2004-2005 Wind River Systems, Inc. *//* Modification History--------------------02e,28sep05,rb Update header comments and copyright02d,27apr05,rb Updated routines with APIGEN tags02c,02feb05,rb Compatability issue with vxWorks 6.0 resolved02b,07oct04,rb Fix for SPR 102322: Random AP cluster overwrites02a,23aug04,rb Wind River Wireless Ethernet Driver 2.0 FCS*//*DESCRIPTIONThis is a basic timer library that executes functions for the DOT11 framework.It is not meant for a high density of timers, or for timers that need to beprecise. The timeout is expected within one tick - on a typicalsystem, this is +/- 16.67 ms unless a higher priority task prempts this one, which is possible in a highly utilized system.ARCHITECTUREThe basic architecture is a task that pends on a message queue. Messages are sent to the message queue to add or delete timers. The timer task pends on this message queue with a timeout equal to the time until the next event. Thus, the timer task is activated when the next event occurs or when thereis a message on the queue. If there is a message, it is processed (events are added or removed from the sorted event-queue). The head of the event queue is then examined. If there are events due (or past, since our task could be prempted) the event queue is drained until the next event is in thefuture. The time until this event is calculated, andThe priority setting of this task is slightly greater than tNetTask to ensure that timeouts for network events are not preempted by high volumes of network traffic.NOTESThe events are called from the context of the timer task. Thus, any event functions should be short in duration and conservative in stack usage to avoid compromising the timer task.SEE ALSOWind Net 802.11 Station 2.0 High Level Design Document\IFSET KERNEL*/#include <vxWorks.h>#include <tickLib.h>#include <taskLib.h>#include <msgQLib.h>#include <logLib.h>#include <stdio.h>#include <intLib.h>#include <memPartLib.h>#include <string.h>#include <netLib.h>/* #define this only if you are debugging the timer library */#undef DOT11_TIMER_DEBUG#ifdef DOT11_TIMER_DEBUG #define DOT11_TIMER_LOG(a,b,c,d,e,f,g) logMsg(a,b,c,d,e,f,g)#else #define DOT11_TIMER_LOG(a,b,c,d,e,f,g)#endif/* A high volume of messages is not anticipated. */#define DOT11_TIMER_MAX_MSGS 512/* There is only one instance of the timer library regardless of the numberof devices using it */#define DOT11_TIMER_TASK_NAME "tDot11Timer"#define DOT11_TIMER_TASK_PRI_TNET (-2)#define DOT11_TIMER_TASK_STACK 4096#define DOT11_TIMER_ALLOC dot11TimerCalloc#define DOT11_TIMER_FREE dot11TimerFree#define DOT11_TIMER_MEM_PART_SZ (1024)/* Delay to allow the task to delete itself on de-initialization. Two ticks of the kernel clock should be more than enough time for this to occur */#define DOT11_TIMER_TASK_DELETE_TIMEOUT 2/******************************************************************** DOT11_TIMER - Struct identifying a particular timer in the LL *******************************************************************/typedef struct dot11Timer { int timerId; /* Unique identifier */ UINT32 fireTime; /* tick time when this timer fires */ FUNCPTR action; /* What to do when they fire. */ UINT32 actionParam0; UINT32 actionParam1; struct dot11Timer * pNext; } DOT11_TIMER;/******************************************************************** DOT11_TIMER_OP - A specific operation to be queued. These operations* correspond to functions in dot11TimerOpFuncs[]*******************************************************************/typedef enum { DOT11_TIMER_ADD = 0, /* Add the specified timer */ DOT11_TIMER_DEL, /* Cancel the specified timer */ DOT11_TIMER_QUIT, /* Shut down the timer task */ DOT11_TIMER_NOP, /* No operation */ DOT11_TIMER_MAX_OPS } DOT11_TIMER_OP;/******************************************************************** DOT11_TIMER_REQ - A message passing a request up timerQueue*******************************************************************/typedef struct { DOT11_TIMER_OP operation; /* Operation to perform */ int timerId; /* ID of timer to add/delete */ /* The following are only used for additions */ UINT32 fireTime; /* Number of ticks to delay */ FUNCPTR actionPtr; /* Function to execute when done */ UINT32 param0; /* First parameter to actionPtr() */ UINT32 param1; /* Second parameter to actionPtr() */ } DOT11_TIMER_REQ;/******************************************************************** DOT11_MEM_PART_T - Memory partition descriptor*******************************************************************/typedef struct dot11_mem_part_s { PART_ID id; /* partition ID */ UINT32 allocError; /* allocation error count */ UINT32 freeError; /* deallocation error count */ UINT32 allocSuccess;/* allocation success count */ UINT32 freeSuccess; /* deallocation success count */ struct dot11_block_s /* Basis parition element */ { DOT11_TIMER timer; /* defines the timer element */ UINT32 overhead[4]; /* overhead per allocated elem */ } block[DOT11_TIMER_MEM_PART_SZ]; } DOT11_MEM_PART_T;/******************************************************************** dot11TimerLib - Global structure containing *******************************************************************/struct dot11TimerStruct { DOT11_TIMER* pHead; /* Pointer to next time to expire */ MSG_Q_ID timerQueue; /* MEssage queue used to add/delete items */ int lastTimerId; /* Last timerId allocated */ int tid; /* Task ID of timer task */ DOT11_MEM_PART_T* memPart; /* Private memory partition */ } dot11TimerLib;/* Determine whether the timer library has been initialized yet. Also storesthe number of tasks using the library */static INT32 dot11TimerUsage = 0;/* Local prototypes */LOCAL void dot11TimerTask();LOCAL STATUS dot11TimerOpAdd(DOT11_TIMER_REQ * pReq);LOCAL STATUS dot11TimerOpDel(DOT11_TIMER_REQ * pReq);LOCAL STATUS dot11TimerFlush();LOCAL void* dot11TimerCalloc(size_t elemNum, size_t elemSize);LOCAL STATUS dot11TimerFree(char* pBlock);/* These are internal function pointers, not necessary for the user to use.These functions correspond to the ennumerated values in DOT11_TIMER_OP */LOCAL FUNCPTR dot11TimerOpFuncs[DOT11_TIMER_MAX_OPS] = { (FUNCPTR)dot11TimerOpAdd, /* DOT11_TIMER_ADD */ (FUNCPTR)dot11TimerOpDel, /* DOT11_TIMER_DEL */ NULL, /* Quit message doesn't need a pointer */ NULL /* A NOP */ };/* Compile time static allocation of memory partition descriptor */static DOT11_MEM_PART_T dot11MemPartition;IMPORT INT32 sysClkRateGet();/***************************************************************************** dot11TimerInit - Initializes the timer object. ** There is just one timer object for all of the interfaces. The initialization* routine will be run once for each interface, but only the first one will * succeed. Subsequent calls will still return OK, but will not do anything.* The number of initializations will be tracked so that only the last * de-initialization will actually free the memory.** RETURNS: OK or ERROR on allocation error.** ERRNO: N/A*/STATUS dot11TimerInit() { int tNetTaskPriority; /* Check if the initialization has been run already. If so, don't run it again*/ dot11TimerUsage ++; if (dot11TimerUsage > 1) { DOT11_TIMER_LOG("dot11TimerInit: already started %d times\n", dot11TimerUsage,0,0,0,0,0); return OK; } dot11TimerLib.pHead = NULL; dot11TimerLib.lastTimerId = 0; dot11TimerLib.memPart = (DOT11_MEM_PART_T*)&dot11MemPartition; if ((dot11TimerLib.timerQueue = msgQCreate(DOT11_TIMER_MAX_MSGS, sizeof(DOT11_TIMER_REQ), MSG_Q_FIFO)) == NULL) { DOT11_TIMER_LOG("dot11TimerInit: Can't create msgq\n",0,0,0,0,0,0); dot11TimerUsage = 0; return ERROR; } /* Create the dot11TimerLib memory parition */ if ((dot11TimerLib.memPart->id = memPartCreate((char*)dot11TimerLib.memPart->block, sizeof(dot11TimerLib.memPart->block))) == NULL) { DOT11_TIMER_LOG ("dot11TimerInit: Can't create memory partition\n",0,0,0,0,0,0); return(ERROR); } /* Reset the timer statistics counters */ dot11TimerLib.memPart->allocError = 0; dot11TimerLib.memPart->freeError = 0; dot11TimerLib.memPart->allocSuccess = 0; dot11TimerLib.memPart->freeSuccess = 0; /* Get the priority of tNetTask so that we can assume that we will always be higher priority than it. If it fails, use a hardcoded value of 50 */ if (taskPriorityGet(taskNameToId("tNetTask"), &tNetTaskPriority) != OK) { DOT11_TIMER_LOG("dot11TimerInit: Can't get pri of tNetTask. " "Using 50.\n",0,0,0,0,0,0); tNetTaskPriority = 50; } if (taskSpawn(DOT11_TIMER_TASK_NAME, tNetTaskPriority + DOT11_TIMER_TASK_PRI_TNET, 0, DOT11_TIMER_TASK_STACK, (FUNCPTR)dot11TimerTask, 0,0,0,0,0,0,0,0,0,0) == ERROR) { DOT11_TIMER_LOG("dot11TimerInit: Can't create task\n",0,0,0,0,0,0); dot11TimerUsage = 0; return ERROR; } DOT11_TIMER_LOG("dot11TimerInit: started\n",0,0,0,0,0,0); return OK; }/***************************************************************************** dot11TimerAdd - Adds a timer to the event queue** This function sends a message to the timer task to add an event to the * event queue. The timer does not actually start until the message is * received by the event queue, so there is a slight delay possible if a high* priority task is running.** RETURNS: Timer ID or ERROR (-1) on error.** ERRNO: N/A*/int dot11TimerAdd ( int delayTicks, FUNCPTR action, int param0, int param1 ) { int intLevel; DOT11_TIMER_REQ req; if (dot11TimerUsage == 0) { DOT11_TIMER_LOG("dot11TimerAdd: Device not initialized\n",0,0,0,0,0,0); return ERROR; } if (action == NULL) { DOT11_TIMER_LOG("dot11TimerAdd: NULL action\n",0,0,0,0,0,0); return ERROR; } /* Setup the request message. Since this is running in the caller's context, intLock() when setting the timerID to prevent two tasks doing it at the same time and doing something weird. An intLock() is necessary since this could conceivably be running in the ISR contect.*/ intLevel = intLock(); /* Handle the rollover case cleanly */ if (++dot11TimerLib.lastTimerId == ERROR) { dot11TimerLib.lastTimerId = 1; } req.timerId = dot11TimerLib.lastTimerId; intUnlock(intLevel); req.operation = DOT11_TIMER_ADD; req.fireTime = delayTicks + tickGet(); req.actionPtr = action; req.param0 = param0; req.param1 = param1; /* Send it off to the task */ if (msgQSend(dot11TimerLib.timerQueue, (char *)&req, sizeof(DOT11_TIMER_REQ), sysClkRateGet() / 10, MSG_PRI_NORMAL) != OK) { return ERROR; } DOT11_TIMER_LOG("dot11TimerAdd: Allocated timer %d\n", req.timerId,0,0,0,0,0); return req.timerId; }/***************************************************************************** dot11TimerDel - Removes the specified timer** This routine sends a message to the timer task informing it to delete the * specified timer. The timer is specified by the timerId returned by * dot11TimerAdd()** RETURNS: OK or ERROR if the message could not be sent.** ERRNO: N/A*/STATUS dot11TimerDel ( int timerId /* The timerId returned by dot11TimerAdd */ ) { DOT11_TIMER_REQ req; if (dot11TimerUsage == 0) { return ERROR; } DOT11_TIMER_LOG("dot11TimerDel: Deleting timer %d\n", timerId,0,0,0,0,0); req.timerId = timerId; req.operation = DOT11_TIMER_DEL; if (msgQSend(dot11TimerLib.timerQueue, (char *)&req, sizeof(DOT11_TIMER_REQ), sysClkRateGet() / 10, MSG_PRI_NORMAL) != OK) { return ERROR; } return OK; }/***************************************************************************** dot11TimerDestroy - De-initializes the timer object. ** This routine is the opposite of dot11TimerDestroy. It will delete the * message queue and the listening task.** RETURNS: OK or ERROR if already destroyed** ERRNO: N/A*/STATUS dot11TimerDestroy() { DOT11_TIMER_REQ req; int intLevel; /* Check if it's even initialized */ if (dot11TimerUsage == 0) { DOT11_TIMER_LOG("dot11TimerDestroy: not initialized\n",0,0,0,0,0,0); return ERROR; } /* If it's running, decrement the usage parameter */ if ((--dot11TimerUsage) > 0) { DOT11_TIMER_LOG("dot11TimerDestroy: somebody still using timer\n", 0,0,0,0,0,0); return OK; } /* Try a gracefull exit first - Send the QUIT message */ req.operation = DOT11_TIMER_QUIT; msgQSend(dot11TimerLib.timerQueue, (char *)&req, sizeof(DOT11_TIMER_REQ), NO_WAIT, MSG_PRI_URGENT); /* Delay to allow the task to delete itself if it got the message */ taskDelay(DOT11_TIMER_TASK_DELETE_TIMEOUT); /* If the task hasn't deleted itself, then it must be stuck. Kill it */ if (taskIdVerify(dot11TimerLib.tid) != ERROR) { /* Grab the context and prevent the task from getting it back */ intLevel = intLock(); dot11TimerFlush(); intUnlock(intLevel); taskDelete(dot11TimerLib.tid); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -