1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "hdf_task_queue.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "securec.h"
13
14 static int32_t HdfThreadTasker(void *data);
15
16 #define HDF_LOG_TAG hdf_task_queue
17
HdfCreateThread(struct HdfTaskQueue * queue)18 static int32_t HdfCreateThread(struct HdfTaskQueue *queue)
19 {
20 int32_t ret;
21
22 ret = OsalThreadCreate(&queue->thread, (OsalThreadEntry)HdfThreadTasker, queue);
23 if (ret != HDF_SUCCESS) {
24 HDF_LOGE("HdfCreateThread: create thread fail!");
25 }
26
27 return ret;
28 }
29
HdfTaskQueueCreate(HdfTaskFunc func,const char * name)30 struct HdfTaskQueue *HdfTaskQueueCreate(HdfTaskFunc func, const char *name)
31 {
32 int32_t ret;
33 struct HdfTaskQueue *queue = NULL;
34
35 queue = (struct HdfTaskQueue *)OsalMemCalloc(sizeof(*queue));
36 if (queue == NULL) {
37 HDF_LOGE("%s malloc fail", __func__);
38 return queue;
39 }
40
41 DListHeadInit(&queue->head);
42
43 ret = OsalMutexInit(&queue->mutex);
44 if (ret != HDF_SUCCESS) {
45 HDF_LOGE("%s OsalMutexInit fail", __func__);
46 OsalMemFree(queue);
47 return NULL;
48 }
49
50 ret = OsalSemInit(&queue->sem, 0);
51 if (ret != HDF_SUCCESS) {
52 HDF_LOGE("%s OsalSemInit fail", __func__);
53 OsalMutexDestroy(&queue->mutex);
54 OsalMemFree(queue);
55 return NULL;
56 }
57
58 ret = HdfCreateThread(queue);
59 if (ret != HDF_SUCCESS) {
60 HDF_LOGE("%s HdfCreateThread fail", __func__);
61 (void)OsalMutexDestroy(&queue->mutex);
62 (void)OsalSemDestroy(&queue->sem);
63 OsalMemFree(queue);
64 return NULL;
65 }
66
67 queue->queueName = name;
68 queue->threadRunFlag = false;
69
70 if (func != NULL) {
71 queue->queueFunc = func;
72 }
73
74 return queue;
75 }
76
hdfQueueStopThread(struct HdfTaskQueue * queue)77 static void hdfQueueStopThread(struct HdfTaskQueue *queue)
78 {
79 int32_t ret;
80
81 if (queue == NULL) {
82 HDF_LOGE("%s queue ptr is null", __func__);
83 return;
84 }
85
86 queue->threadRunFlag = false;
87
88 ret = OsalSemPost(&queue->sem);
89 if (ret != HDF_SUCCESS) {
90 HDF_LOGE("%s OsalSemPost fail", __func__);
91 }
92 }
93
HdfTaskQueueDestroy(struct HdfTaskQueue * queue)94 void HdfTaskQueueDestroy(struct HdfTaskQueue *queue)
95 {
96 if (queue == NULL) {
97 HDF_LOGE("%s queue ptr is null", __func__);
98 return;
99 }
100 hdfQueueStopThread(queue);
101 }
102
hdfQueueStartThread(struct HdfTaskQueue * queue)103 static void hdfQueueStartThread(struct HdfTaskQueue *queue)
104 {
105 int32_t ret;
106 struct OsalThreadParam param;
107
108 (void)memset_s(¶m, sizeof(param), 0, sizeof(param));
109 param.name = (char *)queue->queueName;
110 param.priority = OSAL_THREAD_PRI_HIGH;
111 queue->threadRunFlag = true;
112
113 ret = OsalThreadStart(&queue->thread, ¶m);
114 if (ret != HDF_SUCCESS) {
115 HDF_LOGE("%s OsalThreadStart fail", __func__);
116 }
117 }
118
HdfTaskEnqueue(struct HdfTaskQueue * queue,struct HdfTaskType * task)119 void HdfTaskEnqueue(struct HdfTaskQueue *queue, struct HdfTaskType *task)
120 {
121 int32_t ret;
122
123 if (queue == NULL || task == NULL) {
124 HDF_LOGE("%s ptr is null", __func__);
125 return;
126 }
127
128 ret = OsalMutexLock(&queue->mutex);
129 if (ret != HDF_SUCCESS) {
130 HDF_LOGE("%s OsalMutexLock fail", __func__);
131 return;
132 }
133
134 if (!queue->threadRunFlag) {
135 hdfQueueStartThread(queue);
136 }
137
138 DListInsertTail(&task->node, &queue->head);
139
140 ret = OsalMutexUnlock(&queue->mutex);
141 if (ret != HDF_SUCCESS) {
142 HDF_LOGE("%s OsalMutexUnlock fail", __func__);
143 return;
144 }
145
146 ret = OsalSemPost(&queue->sem);
147 if (ret != HDF_SUCCESS) {
148 HDF_LOGE("%s OsalSemPost fail", __func__);
149 }
150 }
151
HdfTaskDequeue(struct HdfTaskQueue * queue)152 static struct HdfTaskType *HdfTaskDequeue(struct HdfTaskQueue *queue)
153 {
154 struct HdfTaskType *task = NULL;
155
156 if (!DListIsEmpty(&queue->head)) {
157 task = DLIST_FIRST_ENTRY(&queue->head, struct HdfTaskType, node);
158 DListRemove(&task->node);
159 }
160
161 return task;
162 }
163
HdfThreadTasker(void * data)164 static int32_t HdfThreadTasker(void *data)
165 {
166 int32_t ret;
167 struct HdfTaskType *task = NULL;
168 struct HdfTaskQueue *queue = (struct HdfTaskQueue *)data;
169
170 while (queue->threadRunFlag) {
171 ret = OsalSemWait(&queue->sem, HDF_WAIT_FOREVER);
172 if (ret != HDF_SUCCESS) {
173 continue;
174 }
175 ret = OsalMutexLock(&queue->mutex);
176 if (ret != HDF_SUCCESS) {
177 HDF_LOGE("%s OsalMutexLock fail", __func__);
178 continue;
179 }
180 task = HdfTaskDequeue(queue);
181 while (task != NULL) {
182 if (task->func) {
183 task->func(task);
184 } else if (queue->queueFunc) {
185 queue->queueFunc(task);
186 } else {
187 HDF_LOGE("%s no task and queue function", __func__);
188 }
189 task = HdfTaskDequeue(queue);
190 }
191 ret = OsalMutexUnlock(&queue->mutex);
192 if (ret != HDF_SUCCESS) {
193 HDF_LOGE("%s OsalMutexUnlock fail", __func__);
194 }
195 }
196
197 (void)OsalMutexDestroy(&queue->mutex);
198 (void)OsalSemDestroy(&queue->sem);
199 OsalMemFree(queue);
200 HDF_LOGI("%s thread exit", __func__);
201
202 return HDF_SUCCESS;
203 }
204