/* qLibP.h - multi-way queue library header */ /* * Copyright (c) 2008-2011 Wind River Systems, Inc. * * The right to copy, distribute, modify or otherwise make use * of this software may be licensed only pursuant to the terms * of an applicable Wind River license agreement. */ /* modification history -------------------- 01g,19jan11,gls added qPriDelta prototypes (WIND00200778) 01f,17may10,kk added QUEUE_KERNEL_INTERRUPTIBLE for (WND00193764) 01f,29apr10,pad Moved extern C statement after include statements. 01f,29apr10,pad Moved extern C statement after include statements. 01e,01oct09,zl removed qInit() 01d,20feb09,zl changed advanceRtn nTicks argument to ULONG. 01c,17feb09,zl included vsbConfig.h, fixed Q_PRI_NODE_KEY definiton. 01b,11feb09,zl moved queue class definitions from public header files 01a,27aug08,zl created. */ #ifndef __INCqLibPh #define __INCqLibPh #include #include #include #ifdef __cplusplus extern "C" { #endif /* * qFifoGRemove returns a particular status called ALREADY_REMOVED * when the shared TCB has been removed on give side. */ #define ALREADY_REMOVED 1 #ifndef _ASMLANGUAGE /* All queue class nodes must not exceed the sizeof (Q_NODE). If larger data * structures must be used, use one of the private fields as pointer to provide * a level on indirection so the size of Q_NODE is not exceeded. */ typedef struct q_node /* Q_NODE */ { ULONG qPriv1; /* use is queue type dependent */ ULONG qPriv2; /* use is queue type dependent */ ULONG qPriv3; /* use is queue type dependent */ ULONG qPriv4; /* use is queue type dependent */ } Q_NODE; typedef struct /* Q_FIFO_NODE */ { DL_NODE node; /* qPriv1/qPriv2 */ ULONG qPriv3; /* unused for FIFO queues */ ULONG qPriv4; /* unused for FIFO queues */ } Q_FIFO_NODE; typedef struct /* Q_PRI_NODE */ { DL_NODE node; /* priority doubly linked node */ ULONG key; /* insertion key (ie. priority) */ ULONG qPriv4; /* unused for priority queues */ } Q_PRI_NODE; /* priority bitmap lists */ /* * Q_PRI_BMAP_MAX_PRIORITIES must satisfy the following conditions: * a) 288 <= Q_PRI_BMAP_MAX_PRIORITIES <= 1024 * b) Must be a multiple of 32 */ #define Q_PRI_BMAP_MAX_PRIORITIES 288 #define BMAP_BITS (8 * sizeof (UINT32)) /* typedefs */ typedef struct /* BMAP_LIST */ { UINT32 metaBMap; /* lookup table for map array */ UINT32 bMap [Q_PRI_BMAP_MAX_PRIORITIES / BMAP_BITS]; DL_LIST listArray [Q_PRI_BMAP_MAX_PRIORITIES]; } BMAP_LIST; /* All queue classes must not exceed the sizeof (Q_HEAD). If larger data * structures must be used, use one of the private fields as pointer to provide * a level on indirection so the size of Q_HEAD is not exceeded. * * The first field in the Q_HEAD must contain the highest priority Q_NODE. * The routine qFirst () makes this assumption. The scheduler does a qFirst * on the ready queue as part of its scheduling. */ typedef struct q_head /* Q_HEAD */ { Q_NODE * pFirstNode; /* first node in queue based on key */ ULONG qPriv1; /* use is queue type dependent */ ULONG qPriv2; /* use is queue type dependent */ struct q_class *pQClass; /* pointer to queue class */ } Q_HEAD; typedef struct /* Q_FIFO_HEAD */ { DL_LIST list; /* pFirstNode/qPriv1 */ ULONG attr; /* attributes (qPriv2) */ struct q_class *pQClass; /* pointer to queue class */ } Q_FIFO_HEAD; typedef struct /* Q_PRI_HEAD */ { DL_LIST list; /* pFirstNode/qPriv1 */ ULONG attr; /* qPriv2 */ struct q_class *pQClass; /* pointer to queue class */ } Q_PRI_HEAD; typedef struct /* Q_PRI_BMAP_HEAD */ { Q_PRI_NODE * highNode; /* highest priority node */ BMAP_LIST * pBMapList; /* pointer to mapped list */ ULONG nPriority; /* priorities in queue (1,288) */ struct q_class *pQClass; /* pointer to queue class */ } Q_PRI_BMAP_HEAD; typedef struct q_fifo_g_head /* Q_FIFO_G_HEAD */ { ULONG first; /* NOT USED */ UINT32 * pLock; /* NULL if already acquired */ struct sm_dl_list * pFifoQ; /* shared memory pend queue */ struct q_class *pQClass; /* pointer to class */ } Q_FIFO_G_HEAD; typedef void (*QCLASS_RESORT_FUNC) (Q_HEAD *pQHead, Q_NODE *pQNode, ULONG key); typedef BOOL (*QEACH_USR_FUNC) (Q_NODE * pQNode, void * arg); typedef struct q_class /* Q_CLASS */ { void (*putRtn) /* insert a node into q */ ( Q_HEAD * pQHead, Q_NODE * pQNode, ULONG key ); Q_NODE * (*getRtn) /* return and remove lead node */ ( Q_HEAD * pQHead ); STATUS (*removeRtn) /* remove routine */ ( Q_HEAD * pQHead, Q_NODE * pQNode ); void (*resortRtn) /* resort node to new priority */ ( Q_HEAD * pQHead, Q_NODE * pQNode, ULONG key ); void (*advanceRtn) /* advance queue */ ( Q_HEAD * pQHead, ULONG nTicks ); Q_NODE * (*getExpiredRtn) /* return and remove expired Q_NODE */ ( Q_HEAD * pQHead ); ULONG (*keyRtn) /* return insertion key of node */ ( Q_NODE * pQNode ); int (*infoRtn) /* return array of nodes in queue */ ( Q_HEAD * pQHead, Q_NODE * nodeArray[], int maxNodes ); Q_NODE * (*eachRtn) /* call a user routine for each node */ ( Q_HEAD * pQHead, QEACH_USR_FUNC routine, void * routineArg ); void (*restoreRtn) /* restore a node position in queue */ ( Q_HEAD * pQHead, Q_NODE * pQNode, ULONG key ); Q_NODE * (*nextRtn) /* return next node in a queue */ ( Q_HEAD * pQHead, Q_NODE * pNode ); struct q_class * valid; /* valid == pointer to queue class */ } Q_CLASS; typedef Q_CLASS * Q_CLASS_ID; /* Q_CLASS_ID */ /* private queue classes */ IMPORT Q_CLASS_ID qFifoClassId; IMPORT Q_CLASS_ID qFifoGClassId; IMPORT Q_CLASS_ID qPriListClassId; IMPORT Q_CLASS_ID qPriListFromTailClassId; IMPORT Q_CLASS_ID qPriDeltaClassId; IMPORT Q_CLASS_ID qPriBMapClassId; IMPORT Q_CLASS_ID qTradPriListClassId; IMPORT Q_CLASS_ID qTradPriBMapClassId; IMPORT Q_CLASS_ID qPxPriBMapClassId; IMPORT Q_CLASS_ID qPxSSPriBMapClassId; /* private queue types */ #define Q_FIFO qFifoClassId #define Q_FIFO_G qFifoGClassId #define Q_PRI_LIST qPriListClassId #define Q_PRI_LIST_FROM_TAIL qPriListFromTailClassId #define Q_PRI_DELTA qPriDeltaClassId #define Q_PRI_BMAP qPriBMapClassId #define Q_TRAD_PRI_LIST qTradPriListClassId #define Q_TRAD_PRI_BMAP qTradPriBMapClassId #define Q_PX_PRI_BMAP qPxPriBMapClassId #define Q_PX_SS_PRI_BMAP qPxSSPriBMapClassId /* * Queue can have attributes. The qPriv2 member of Q_HEAD represents the * queue attribute. The attributes supported are * 1) Queue interruptibiliy * QUEUE_INTERRUPTIBLE implies that the task pended on this queue can * be made ready by a signal. QUEUE_NONINTERRUPTIBLE is the negate of * QUEUE_INTERRUPTIBLE. By default, queue interrupt-ability attribute for * a queue is QUEUE_NONINTERRUPTIBLE. * QUEUE_INTERRUPTIBLE allows an RTP task pended on this queue to * be made ready by a signal. * QUEUE_KERNEL_INTERRUPTIBLE allows a kernel task pended on this * queue to be made ready by a signal. * QUEUE_NONINTERRUPTIBLE prevents any task pended on this queue from * being made ready by a signal. * * By default, queue interrupt-ability attribute for a queue is * QUEUE_NONINTERRUPTIBLE. * * Currently only Q_PRI_LIST , Q_FIFO_HEAD, Q_PRI_LIST_FROM_TAIL have * the queue attribute support. */ #define QUEUE_INTERRUPTIBLE 0x01 #define QUEUE_KERNEL_INTERRUPTIBLE 0x02 #define QUEUE_NONINTERRUPTIBLE 0x00 #define QUEUE_ATTRIBUTE_MASK 0x03 #define Q_ATTRIBUTE_GET(qHead) (((Q_HEAD *)(qHead))->qPriv2) #define Q_ATTRIBUTE_SET(qHead, value) (((Q_HEAD *)(qHead))->qPriv2 = \ (ULONG)(value)) #define IS_Q_ATTRIBUTE_OK(value) (((value) & ~QUEUE_ATTRIBUTE_MASK) == 0) /******************************************************************************* * * Q_CLASS_VERIFY - check the validity of an queue class pointer * * This macro verifies the existence of the specified queue class by comparing * the queue classes valid field to the pointer to the queue class. * * RETURNS: OK or ERROR if invalid class pointer * * \NOMANUAL */ #define Q_CLASS_VERIFY(pQClass) \ ( \ (((Q_CLASS *)(pQClass))->valid == (Q_CLASS *) pQClass) ? \ OK \ : \ ERROR \ ) /******************************************************************************* * * Q_FIRST - return first node in multi-way queue * * This routine returns a pointer to the first node in the specified multi-way * queue head. If the queue is empty, NULL is returned. * * RETURNS * Pointer to first queue node in queue head, or * NULL if queue is empty. * * \NOMANUAL */ #define Q_FIRST(pQHead) \ ((Q_NODE *)(((Q_HEAD *)(pQHead))->pFirstNode)) /******************************************************************************* * * Q_NEXT - return the next node in the queue * * This routine returns a pointer to the next node in the specified queue. For * the last node, Q_NEXT() returns NULL. * * \NOMANUAL */ #define Q_NEXT(pQHead,pQNode) \ ((Q_NODE *)((*(((Q_HEAD *)(pQHead))->pQClass->nextRtn)) \ (((Q_HEAD *)(pQHead)), ((Q_NODE *)(pQNode))))) /******************************************************************************* * * Q_PUT - insert a node into a multi-way queue * * This routine inserts a node into a multi-way queue. The insertion is based * on the key and the underlying queue class. * * \NOMANUAL */ #define Q_PUT(pQHead,pQNode,key) \ (*(((Q_HEAD *)(pQHead))->pQClass->putRtn)) \ (((Q_HEAD *)(pQHead)), ((Q_NODE *)(pQNode)), (ULONG)(key)) /******************************************************************************* * * Q_RESTORE - restore a node position in multi-way queue * * This routine inserts a node into a multi-way queue and restores its position. * The insertion is based on the key and the underlying queue class. * * \NOMANUAL */ #define Q_RESTORE(pQHead,pQNode,key) \ (*(((Q_HEAD *)(pQHead))->pQClass->restoreRtn)) \ (((Q_HEAD *)(pQHead)), ((Q_NODE *)(pQNode)), (ULONG)(key)) /******************************************************************************* * * Q_GET - remove and return first node in multi-way queue * * This routine removes and returns the first node in a multi-way queue. If * the queue is empty, NULL is returned. * * RETURNS * Pointer to first queue node in queue head, or * NULL if queue is empty. * * \NOMANUAL */ #define Q_GET(pQHead) \ ((Q_NODE *)((*(((Q_HEAD *)(pQHead))->pQClass->getRtn)) \ ((Q_HEAD *)(pQHead)))) /******************************************************************************* * * Q_REMOVE - remove a node from a multi-way queue * * This routine removes a node from the specified multi-way queue. * * \NOMANUAL */ #define Q_REMOVE(pQHead,pQNode) \ (*(((Q_HEAD *)(pQHead))->pQClass->removeRtn)) \ (((Q_HEAD *)(pQHead)), ((Q_NODE *)(pQNode))) /******************************************************************************* * * Q_RESORT - resort a node to a new position based on a new key * * This routine resorts a node to a new position based on a new key. It can * be used to change the priority of a queued element, for instance. * * \NOMANUAL */ #define Q_RESORT(pQHead,pQNode,newKey) \ (*(((Q_HEAD *)(pQHead))->pQClass->resortRtn)) \ (((Q_HEAD *)(pQHead)), ((Q_NODE *)(pQNode)), ((ULONG)(newKey))) /******************************************************************************* * * Q_ADVANCEN - advance a queues concept of time by N tick (timer queues only) * * Time queues that keep nodes prioritized by time-to-fire utilize this * routine to advance time by N tick after e.g., a power save sleep. * * \NOMANUAL */ #define Q_ADVANCEN(pQHead, n) \ (*(((Q_HEAD *)(pQHead))->pQClass->advanceRtn)) \ ((Q_HEAD *)(pQHead), (ULONG)(n)) /******************************************************************************* * * Q_GET_EXPIRED - return a time-to-fire expired node * * This routine returns a time-to-fire expired node in a multi-way timer queue. * Expired nodes result from a qAdvance(2) advancing a node beyond its delay. * As many nodes may expire on a single qAdvance(2), this routine should be * called inside a while loop until NULL is returned. NULL is returned when * there are no expired nodes. * * RETURNS * Pointer to first queue node in queue head, or * NULL if queue is empty. * * \NOMANUAL */ #define Q_GET_EXPIRED(pQHead) \ ((Q_NODE *)((*(((Q_HEAD *)(pQHead))->pQClass->getExpiredRtn)) \ ((Q_HEAD *)(pQHead)))) /******************************************************************************* * * Q_KEY - return the key of a node * * This routine returns the key of a node currently in a multi-way queue. The * keyType determines key style on certain queue classes. * * RETURNS * Node's key. * * \NOMANUAL */ #define Q_KEY(pQHead,pQNode,keyType) \ (*(((Q_HEAD *)(pQHead))->pQClass->keyRtn)) ((Q_NODE *)(pQNode)) /******************************************************************************* * * Q_INFO - gather information on a multi-way queue * * This routine fills up to maxNodes elements of a nodeArray with nodes * currently in a multi-way queue. The actual number of nodes copied to the * array is returned. If the nodeArray is NULL, then the number of nodes in * the multi-way queue is returned. * * RETURNS * Number of node pointers copied into the nodeArray, or * Number of nodes in multi-way queue if nodeArray is NULL * * \NOMANUAL */ #define Q_INFO(pQHead,nodeArray,maxNodes) \ (*(((Q_HEAD *)(pQHead))->pQClass->infoRtn)) \ (((Q_HEAD *)(pQHead)),((Q_NODE **)(nodeArray)),((int)(maxNodes))) /******************************************************************************* * * Q_EACH - call a routine for each node in a queue * * This routine calls a user-supplied routine once for each node in the * queue. The routine should be declared as follows: * \cs * BOOL routine (pQNode, arg) * Q_NODE *pQNode; * pointer to a queue node * * long arg; * arbitrary user-supplied argument * * \ce * The user-supplied routine should return TRUE if qEach (2) is to continue * calling it for each entry, or FALSE if it is done and qEach can exit. * * RETURNS: NULL if traversed whole queue, or pointer to Q_NODE that * qEach ended with. * * \NOMANUAL */ #define Q_EACH(pQHead,routine,routineArg) \ ((Q_NODE *)((*(((Q_HEAD *)(pQHead))->pQClass->eachRtn)) \ (((Q_HEAD *)(pQHead)),(QEACH_USR_FUNC)(routine),(void *)(routineArg)))) extern STATUS qFifoInit (Q_HEAD *pQHead, Q_CLASS_ID qClass, UINT attribute); extern STATUS qPriListInit (Q_HEAD *pQHead, Q_CLASS_ID qClass, UINT attr); extern STATUS qPriDeltaInit (Q_HEAD *pQHead, Q_CLASS_ID qClass); extern STATUS qPriBMapInit (Q_HEAD *pQHead, Q_CLASS_ID qClassId, BMAP_LIST *pBMapList, UINT maxPriority); extern STATUS qFifoGInit (Q_FIFO_G_HEAD * pQHead); extern Q_NODE * qPriDeltaEach (Q_HEAD * pQHead, QEACH_USR_FUNC routine, void * pArg); extern Q_NODE * qPriDeltaGet (Q_HEAD * pQHead); extern Q_NODE * qPriDeltaGetExpired (Q_HEAD * pQHead); extern ULONG qPriDeltaKey (Q_NODE * pQNode); extern int qPriDeltaInfo (Q_HEAD * pQHead, Q_NODE * nodes [], int maxNodes); extern void qPriDeltaAdvance (Q_HEAD * pQHead, ULONG nTicks); extern void qPriDeltaPut (Q_HEAD * pQHead, Q_NODE * pQNode, ULONG key); extern STATUS qPriDeltaRemove (Q_HEAD * pQHead, Q_NODE * pQNode); extern void qPriDeltaResort (Q_HEAD * pQHead, Q_NODE * pQNode, ULONG newKey); extern Q_NODE * qPriDeltaNext (Q_HEAD * pQHead, Q_NODE * pQNode); /* for migration, provided for a limited time */ extern void qTradPriListSetCompatible (void); extern void qTradPriBMapSetCompatible (void); #else /* _ASMLANGUAGE */ #ifdef _WRS_CONFIG_LP64 # define Q_PRI_NODE_KEY 0x10 /* queue insertion key, LP64 */ #else # define Q_PRI_NODE_KEY 0x08 /* queue insertion key, ILP32 */ #endif #endif /* _ASMLANGUAGE */ #ifdef __cplusplus } #endif #endif /* __INCqLibh */