ClRcT clJobQueueStatsGet(ClJobQueueT *hdl, ClJobQueueWalkCallbackT cb, ClPtrT arg, ClJobQueueUsageT *pJobQueueUsage) { ClRcT rc = CL_OK; ClJobQueueWalkArgT walkArg = {0}; if(!hdl || !pJobQueueUsage) return CL_JOBQUEUE_RC(CL_ERR_INVALID_PARAMETER); if(!(hdl->flags & CreatedQueue)) return CL_JOBQUEUE_RC(CL_ERR_INVALID_STATE); JQ_PFX(hdl); rc = clQueueSizeGet(hdl->queue, &pJobQueueUsage->numMsgs); if(rc != CL_OK) { pJobQueueUsage->numMsgs = 0; goto out; } rc = clTaskPoolStatsGet(hdl->pool, &pJobQueueUsage->taskPoolUsage); if(rc != CL_OK) goto out; if(cb) { walkArg.cb = cb; walkArg.cbArg = arg; rc = clQueueWalk(hdl->queue, jobQueueWalkCallback, &walkArg); } out: JQ_SFX(hdl); return rc; }
static ClRcT clJobQueuePushConditional(ClJobQueueT* hdl, ClCallbackT job, ClPtrT data, ClBoolT isEmpty) { ClRcT rc = CL_OK; ClJobT* jb; if(!(hdl->flags & CreatedQueue)) return CL_JOBQUEUE_RC(CL_ERR_INVALID_STATE); JQ_PFX(hdl); if (!(hdl->flags & Running)) { rc = CL_JOBQUEUE_RC(CL_ERR_INVALID_STATE); goto out; } if(isEmpty) { ClUint32T queueSize = 0; (void)clQueueSizeGet(hdl->queue, &queueSize); if(queueSize) goto out; } jb = getJob(hdl, job,data); if (!jb) { rc = CL_JOBQUEUE_RC(CL_ERR_NO_MEMORY); goto out; } rc = clQueueNodeInsert(hdl->queue,jb); if (rc != CL_OK) releaseJob(hdl,jb); else clTaskPoolWake(hdl->pool); /* Wake any idle pool tasks because there's work on the q (the idle callback handles the dequeuing) */ out: JQ_SFX(hdl); return rc; }
/* Handle destructor function. */ static void clDispatchHandleDestructor(void* cbArgs) { ClRcT rc = CL_OK; ClDispatchDbEntryT* thisDbEntry = NULL; ClUint32T queueSize = 0; ClDispatchCbQueueDataT* queueData = NULL; if (cbArgs == NULL) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Handle destructor is called with NULL pointer")); return; } thisDbEntry = (ClDispatchDbEntryT*)cbArgs; /* Lock the queue mutex */ rc = clOsalMutexLock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Unable to lock dispatch Mutex in Handle destructor callback")); return; } /* * Before deleting the queue you need to flush the queue. * Even though clQueueDelete will flush the node, we need * handle it explicitly so that we can invoke * ClDispatchQueueDestroyCallbackT registered during Register * which will deallocate the memory for the callback arguments. */ rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize); if (rc != CL_OK) { goto proceed_other_functions; } while (queueSize != 0) { rc = clQueueNodeDelete(thisDbEntry->cbQueue, (ClQueueDataT*)&queueData); if (rc != CL_OK) { goto proceed_other_functions; } CL_ASSERT(queueData != NULL); /* Invoke the queue destroy callback function */ thisDbEntry->queueDestroyCallback(queueData->callbackType, queueData->callbackArgs); rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize); if (rc != CL_OK) { goto proceed_other_functions; } } proceed_other_functions: /* * Delete the queue. This will also flush the queue. So all the * pending callbacks will be flushed. */ rc = clQueueDelete(&thisDbEntry->cbQueue); if (rc != CL_OK) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Unable to delete the queue. Rc = 0x%x",rc)); } /* Delete the pipe */ errno = 0; if ((close(thisDbEntry->readFd)) < 0) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Unable to close write fd of the pipe:%s",strerror(errno))); } errno = 0; if ((close(thisDbEntry->writeFd)) < 0) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Unable to close read fd of the pipe:%s",strerror(errno))); } /* Delete the mutex */ rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Failed to unlock the dispatch mutex")); } rc = clOsalMutexDelete(thisDbEntry->dispatchMutex); if (rc != CL_OK) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Failed to delete the dispatch mutex")); } return; }
/* * clDispatchCbDispatch will dequeue the pending callback and invokes the * service client specific generic callback. The service client should make * sure that it handles the invocation of the associated callback. */ ClRcT clDispatchCbDispatch( CL_IN ClHandleT dispatchHandle, CL_IN ClDispatchFlagsT dispatchFlag) { ClRcT rc = CL_OK; ClDispatchDbEntryT* thisDbEntry = NULL; ClUint32T queueSize = 0; ClDispatchCbQueueDataT* queueData = NULL; ClCharT ch = pipeNotifyChar; if ((dispatchFlag != CL_DISPATCH_ONE) && (dispatchFlag != CL_DISPATCH_ALL) && (dispatchFlag != CL_DISPATCH_BLOCKING)) { return CL_ERR_INVALID_PARAMETER; } CHECK_LIB_INIT; rc = clHandleCheckout(databaseHandle, dispatchHandle, (void *)&thisDbEntry); if (rc != CL_OK) { return CL_ERR_INVALID_HANDLE; } CL_ASSERT(thisDbEntry != NULL); /* Lock the mutex */ rc = clOsalMutexLock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { goto error_return; } if (thisDbEntry->shouldDelete == CL_TRUE) { rc = CL_ERR_INVALID_HANDLE; goto error_unlock_return; } switch (dispatchFlag) { case CL_DISPATCH_ONE: { rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize); if (rc != CL_OK) { goto error_unlock_return; } if (queueSize < 1) { /* Dont return any error. So rc = CL_OK */ goto error_unlock_return; } /* Dequeue the node */ rc = clQueueNodeDelete(thisDbEntry->cbQueue, (ClQueueDataT*)&queueData); if (rc != CL_OK) { goto error_unlock_return; } CL_ASSERT(queueData != NULL); /* Read a character from the pipe */ errno = 0; if ((read(thisDbEntry->readFd, (void*)&ch, 1)) < 1) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("read error on pipe: %s",strerror(errno))); } rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { goto error_return; } /* Invoke the generic callback */ thisDbEntry->svcCallback(thisDbEntry->svcInstanceHandle, queueData->callbackType, queueData->callbackArgs); clHeapFree(queueData); } /* Dont do break, as we have already unlocked the mutex */ goto error_return; case CL_DISPATCH_ALL: { rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize); if (rc != CL_OK) { goto error_unlock_return; } while (queueSize != 0) { rc = clQueueNodeDelete(thisDbEntry->cbQueue, (ClQueueDataT*)&queueData); if (rc != CL_OK) { goto error_unlock_return; } CL_ASSERT(queueData != NULL); /* Read the byte */ errno = 0; if ((read(thisDbEntry->readFd,(void*)&ch,1)) < 1) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Read error on the pipe: %s",strerror(errno))); } rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { goto error_return; } /* Invoke the generic callback */ thisDbEntry->svcCallback(thisDbEntry->svcInstanceHandle, queueData->callbackType, queueData->callbackArgs); /* Free the queueData */ clHeapFree(queueData); /* Get the lock again */ rc = clOsalMutexLock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { goto error_return; } if (thisDbEntry->shouldDelete == CL_TRUE) { rc = CL_ERR_INVALID_HANDLE; goto error_unlock_return; } rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize); if (rc != CL_OK) { goto error_unlock_return; } } /* End of while */ } /* Just break, as we need to unlock and return */ break; case CL_DISPATCH_BLOCKING: { while (1) { rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { goto error_return; } /* Block on the readFd */ errno = 0; if ((read(thisDbEntry->readFd,(void*)&ch,1)) < 1) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Read error on the pipe: %s",strerror(errno))); /* * This might be because finalize has been done and write fd * is closed. So return */ goto error_return; } rc = clOsalMutexLock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { goto error_return; } if (thisDbEntry->shouldDelete == CL_TRUE) { rc = CL_OK; goto error_unlock_return; } rc = clQueueSizeGet(thisDbEntry->cbQueue, &queueSize); if (rc != CL_OK) { goto error_unlock_return; } if (queueSize < 1) { /* * This would happen when read has come out due * to signal */ continue; } /* Dequeue the node */ rc = clQueueNodeDelete(thisDbEntry->cbQueue, (ClQueueDataT*)&queueData); if (rc != CL_OK) { goto error_unlock_return; } CL_ASSERT(queueData != NULL); rc = clOsalMutexUnlock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { goto error_return; } /* Invoke the generic callback */ thisDbEntry->svcCallback(thisDbEntry->svcInstanceHandle, queueData->callbackType, queueData->callbackArgs); /* Free the queueData */ clHeapFree(queueData); /* Get the lock again */ rc = clOsalMutexLock(thisDbEntry->dispatchMutex); if (rc != CL_OK) { goto error_return; } if (thisDbEntry->shouldDelete == CL_TRUE) { rc = CL_ERR_INVALID_HANDLE; goto error_unlock_return; } } break; } } /* End of switch */ error_unlock_return: if ((clOsalMutexUnlock(thisDbEntry->dispatchMutex)) != CL_OK) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("Mutex Unlock failed\n")); } error_return: if ((clHandleCheckin(databaseHandle, dispatchHandle)) != CL_OK) { CL_DEBUG_PRINT(CL_DEBUG_ERROR, ("clHandleCheckin failed")); } return rc; }