static __inline__ ClRcT clAmsEntityTriggerRecoveryListAdd(ClAmsEntityTriggerT *pEntityTrigger) { clOsalMutexLock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex); clListAddTail(&pEntityTrigger->list, &gClAmsEntityTriggerRecoveryCtrl.list.list); ++gClAmsEntityTriggerRecoveryCtrl.list.numElements; clOsalCondSignal(&gClAmsEntityTriggerRecoveryCtrl.list.cond); clOsalMutexUnlock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex); return CL_OK; }
ClRcT clTransportNotifyRegister(ClTransportNotifyCallbackT callback, ClPtrT arg) { ClTransportNotifyRegistrantT *registrant = NULL; if(!callback) return CL_ERR_INVALID_PARAMETER; registrant = clHeapCalloc(1, sizeof(*registrant)); CL_ASSERT(registrant != NULL); registrant->callback = callback; registrant->arg = arg; clListAddTail(®istrant->list, &gClXportNotifyRegistrants); return CL_OK; }
static void clAmsEntityTriggerListAdd(ClAmsEntityTriggerT *pEntityTrigger) { ClUint32T hashKey = 0; ClRcT rc = clCksm32bitCompute((ClUint8T*)pEntityTrigger->entity.name.value, pEntityTrigger->entity.name.length, &hashKey); CL_ASSERT(rc == CL_OK); hashKey &= CL_AMS_ENTITY_THRESHOLD_BUCKET_MASK; hashAdd(gClAmsEntityTriggerList.hashTable, hashKey, &pEntityTrigger->hash); clListAddTail(&pEntityTrigger->list, &gClAmsEntityTriggerList.list.list); ++gClAmsEntityTriggerList.list.numElements; }
/* * The recovery thread for entity threshold. */ static ClPtrT clAmsEntityTriggerRecoveryThread(ClPtrT pArg) { #define MAX_RECOVERY_MASK (0x3) static ClInt32T numRecovery = 0; ClTimerTimeOutT timeout = { 0, 0 }; ClTimerTimeOutT delay = { 0, 500 }; static ClAmsListHeadT recoveryList = { 0, CL_LIST_HEAD_INITIALIZER(recoveryList.list) }; clOsalMutexLock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex); while(gClAmsEntityTriggerRecoveryCtrl.running == CL_TRUE) { ClListHeadT *pNext = NULL; while(!gClAmsEntityTriggerRecoveryCtrl.list.numElements) { numRecovery = 0; clOsalCondWait(&gClAmsEntityTriggerRecoveryCtrl.list.cond, &gClAmsEntityTriggerRecoveryCtrl.list.mutex, timeout); if(gClAmsEntityTriggerRecoveryCtrl.running == CL_FALSE) goto out_drain; } /* * We are here when the recovery list isn't empty. * We shove the existing recovery batch into the temp list * and reset the main list to release the lock and go lockless. */ recoveryList.numElements = gClAmsEntityTriggerRecoveryCtrl.list.numElements; gClAmsEntityTriggerRecoveryCtrl.list.numElements = 0; pNext = gClAmsEntityTriggerRecoveryCtrl.list.list.pNext; clListDelInit(&gClAmsEntityTriggerRecoveryCtrl.list.list); clListAddTail(pNext, &recoveryList.list); clOsalMutexUnlock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex); while(gClAmsEntityTriggerRecoveryCtrl.running == CL_TRUE && recoveryList.numElements > 0 && !CL_LIST_HEAD_EMPTY(&recoveryList.list)) { ClListHeadT *pFirst = recoveryList.list.pNext; ClAmsEntityTriggerT *pEntityTrigger = CL_LIST_ENTRY(pFirst, ClAmsEntityTriggerT, list); /* * Take a break incase you have done some recoveries */ if(numRecovery && !(numRecovery & MAX_RECOVERY_MASK)) { clOsalTaskDelay(delay); } ++numRecovery; numRecovery &= 0xffff; /* * Unlink the entry from the recovery list. */ clListDel(pFirst); clAmsEntityTriggerRecovery(pEntityTrigger); clHeapFree(pEntityTrigger); --recoveryList.numElements; } clOsalMutexLock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex); if(gClAmsEntityTriggerRecoveryCtrl.running == CL_FALSE) { goto out_drain; } } /* * Drain the entries holding the lock. */ out_drain: clAmsListHeadDelete(&recoveryList); clAmsListHeadDelete(&gClAmsEntityTriggerRecoveryCtrl.list); clOsalMutexUnlock(&gClAmsEntityTriggerRecoveryCtrl.list.mutex); return NULL; }