* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "hdf_task_queue.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "securec.h"
static int32_t HdfThreadTasker(void *data);
#define HDF_LOG_TAG hdf_task_queue
static int32_t HdfCreateThread(struct HdfTaskQueue *queue)
{
int32_t ret;
ret = OsalThreadCreate(&queue->thread, (OsalThreadEntry)HdfThreadTasker, queue);
if (ret != HDF_SUCCESS) {
HDF_LOGE("HdfCreateThread: create thread fail!");
}
return ret;
}
struct HdfTaskQueue *HdfTaskQueueCreate(HdfTaskFunc func, const char *name)
{
int32_t ret;
struct HdfTaskQueue *queue = NULL;
queue = (struct HdfTaskQueue *)OsalMemCalloc(sizeof(*queue));
if (queue == NULL) {
HDF_LOGE("%s malloc fail", __func__);
return queue;
}
DListHeadInit(&queue->head);
ret = OsalMutexInit(&queue->mutex);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s OsalMutexInit fail", __func__);
OsalMemFree(queue);
return NULL;
}
ret = OsalSemInit(&queue->sem, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s OsalSemInit fail", __func__);
OsalMutexDestroy(&queue->mutex);
OsalMemFree(queue);
return NULL;
}
ret = HdfCreateThread(queue);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s HdfCreateThread fail", __func__);
(void)OsalMutexDestroy(&queue->mutex);
(void)OsalSemDestroy(&queue->sem);
OsalMemFree(queue);
return NULL;
}
queue->queueName = name;
queue->threadRunFlag = false;
if (func != NULL) {
queue->queueFunc = func;
}
return queue;
}
static void hdfQueueStopThread(struct HdfTaskQueue *queue)
{
int32_t ret;
if (queue == NULL) {
HDF_LOGE("%s queue ptr is null", __func__);
return;
}
queue->threadRunFlag = false;
ret = OsalSemPost(&queue->sem);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s OsalSemPost fail", __func__);
}
}
void HdfTaskQueueDestroy(struct HdfTaskQueue *queue)
{
if (queue == NULL) {
HDF_LOGE("%s queue ptr is null", __func__);
return;
}
hdfQueueStopThread(queue);
}
static void hdfQueueStartThread(struct HdfTaskQueue *queue)
{
int32_t ret;
struct OsalThreadParam param;
(void)memset_s(¶m, sizeof(param), 0, sizeof(param));
param.name = (char *)queue->queueName;
param.priority = OSAL_THREAD_PRI_HIGH;
queue->threadRunFlag = true;
ret = OsalThreadStart(&queue->thread, ¶m);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s OsalThreadStart fail", __func__);
}
}
void HdfTaskEnqueue(struct HdfTaskQueue *queue, struct HdfTaskType *task)
{
int32_t ret;
if (queue == NULL || task == NULL) {
HDF_LOGE("%s ptr is null", __func__);
return;
}
ret = OsalMutexLock(&queue->mutex);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s OsalMutexLock fail", __func__);
return;
}
if (!queue->threadRunFlag) {
hdfQueueStartThread(queue);
}
DListInsertTail(&task->node, &queue->head);
ret = OsalMutexUnlock(&queue->mutex);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s OsalMutexUnlock fail", __func__);
return;
}
ret = OsalSemPost(&queue->sem);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s OsalSemPost fail", __func__);
}
}
static struct HdfTaskType *HdfTaskDequeue(struct HdfTaskQueue *queue)
{
struct HdfTaskType *task = NULL;
if (!DListIsEmpty(&queue->head)) {
task = DLIST_FIRST_ENTRY(&queue->head, struct HdfTaskType, node);
DListRemove(&task->node);
}
return task;
}
static int32_t HdfThreadTasker(void *data)
{
int32_t ret;
struct HdfTaskType *task = NULL;
struct HdfTaskQueue *queue = (struct HdfTaskQueue *)data;
while (queue->threadRunFlag) {
ret = OsalSemWait(&queue->sem, HDF_WAIT_FOREVER);
if (ret != HDF_SUCCESS) {
continue;
}
ret = OsalMutexLock(&queue->mutex);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s OsalMutexLock fail", __func__);
continue;
}
task = HdfTaskDequeue(queue);
while (task != NULL) {
if (task->func) {
task->func(task);
} else if (queue->queueFunc) {
queue->queueFunc(task);
} else {
HDF_LOGE("%s no task and queue function", __func__);
}
task = HdfTaskDequeue(queue);
}
ret = OsalMutexUnlock(&queue->mutex);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s OsalMutexUnlock fail", __func__);
}
}
(void)OsalMutexDestroy(&queue->mutex);
(void)OsalSemDestroy(&queue->sem);
OsalMemFree(queue);
HDF_LOGI("%s thread exit", __func__);
return HDF_SUCCESS;
}