• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-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 "platform_queue.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "osal_mutex.h"
13 #include "osal_thread.h"
14 #include "platform_log.h"
15 
16 #define PLAT_QUEUE_THREAD_STAK 20000
17 
PlatformQueueDoDestroy(struct PlatformQueue * queue)18 static void PlatformQueueDoDestroy(struct PlatformQueue *queue)
19 {
20     (void)OsalThreadDestroy(&queue->thread);
21     (void)OsalSemDestroy(&queue->sem);
22     (void)OsalSpinDestroy(&queue->spin);
23     OsalMemFree(queue);
24 }
25 
PlatformQueueThreadWorker(void * data)26 static int32_t PlatformQueueThreadWorker(void *data)
27 {
28     int32_t ret;
29     struct PlatformQueue *queue = (struct PlatformQueue *)data;
30     struct PlatformMsg *msg = NULL;
31 
32     while (true) {
33         /* wait envent */
34         ret = OsalSemWait(&queue->sem, HDF_WAIT_FOREVER);
35         if (ret != HDF_SUCCESS) {
36             continue;
37         }
38 
39         if (!queue->start) {
40             PlatformQueueDoDestroy(queue);
41             break;
42         }
43 
44         (void)OsalSpinLock(&queue->spin);
45         if (DListIsEmpty(&queue->msgs)) {
46             msg = NULL;
47         } else {
48             msg = DLIST_FIRST_ENTRY(&queue->msgs, struct PlatformMsg, node);
49             DListRemove(&msg->node);
50         }
51         (void)OsalSpinUnlock(&queue->spin);
52         /* message process */
53         if (msg != NULL) {
54             (void)(queue->handle(queue, msg));
55         }
56     }
57     return HDF_SUCCESS;
58 }
59 
PlatformQueueCreate(PlatformMsgHandle handle,const char * name,void * data)60 struct PlatformQueue *PlatformQueueCreate(PlatformMsgHandle handle, const char *name, void *data)
61 {
62     int32_t ret;
63     struct PlatformQueue *queue = NULL;
64 
65     if (handle == NULL) {
66         return NULL;
67     }
68 
69     queue = (struct PlatformQueue *)OsalMemCalloc(sizeof(*queue));
70     if (queue == NULL) {
71         PLAT_LOGE("PlatformQueueCreate: alloc queue fail!");
72         return NULL;
73     }
74 
75     ret = OsalThreadCreate(&queue->thread, (OsalThreadEntry)PlatformQueueThreadWorker, (void *)queue);
76     if (ret != HDF_SUCCESS) {
77         PLAT_LOGE("PlatformQueueCreate: create thread fail!");
78         OsalMemFree(queue);
79         return NULL;
80     }
81 
82     (void)OsalSpinInit(&queue->spin);
83     (void)OsalSemInit(&queue->sem, 0);
84     DListHeadInit(&queue->msgs);
85     queue->name = (name == NULL) ? "PlatformWorkerThread" : name;
86     queue->handle = handle;
87     queue->data = data;
88     queue->start = false;
89     return queue;
90 }
91 
PlatformQueueStart(struct PlatformQueue * queue)92 int32_t PlatformQueueStart(struct PlatformQueue *queue)
93 {
94     int32_t ret;
95     struct OsalThreadParam cfg;
96 
97     if (queue == NULL) {
98         return HDF_ERR_INVALID_OBJECT;
99     }
100 
101     cfg.name = (char *)queue->name;
102     cfg.priority = OSAL_THREAD_PRI_HIGHEST;
103     cfg.stackSize = PLAT_QUEUE_THREAD_STAK;
104     ret = OsalThreadStart(&queue->thread, &cfg);
105     if (ret != HDF_SUCCESS) {
106         PLAT_LOGE("PlatformQueueStart: start thread fail:%d", ret);
107         return ret;
108     }
109     queue->start = true;
110 
111     return HDF_SUCCESS;
112 }
113 
PlatformQueueDestroy(struct PlatformQueue * queue)114 void PlatformQueueDestroy(struct PlatformQueue *queue)
115 {
116     if (queue == NULL) {
117         return;
118     }
119 
120     if (queue->start) {
121         queue->start = false;
122         (void)OsalSemPost(&queue->sem);
123     } else {
124         PlatformQueueDoDestroy(queue);
125     }
126 }
127 
PlatformQueueAddMsg(struct PlatformQueue * queue,struct PlatformMsg * msg)128 int32_t PlatformQueueAddMsg(struct PlatformQueue *queue, struct PlatformMsg *msg)
129 {
130     if (queue == NULL || msg == NULL) {
131         return HDF_ERR_INVALID_OBJECT;
132     }
133 
134     DListHeadInit(&msg->node);
135     msg->error = HDF_SUCCESS;
136     (void)OsalSpinLock(&queue->spin);
137     DListInsertTail(&msg->node, &queue->msgs);
138     (void)OsalSpinUnlock(&queue->spin);
139     /* notify the worker thread */
140     (void)OsalSemPost(&queue->sem);
141     return HDF_SUCCESS;
142 }
143