blob: 2e8b88623eab2605cebf7e0f2429fd490fb9f3e8 [file] [log] [blame]
Michael Bestas3a0209e2023-05-04 01:15:47 +03001/* Copyright (c) 2011-2012, 2014, 2017 The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation, nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29// Uncomment to log verbose logs
30#define LOG_NDEBUG 1
31#define LOG_TAG "LocSvc_utils_q"
32#include <stdio.h>
33#include <stdlib.h>
34#include <pthread.h>
35#include <loc_pla.h>
36#include <log_util.h>
37#include "linked_list.h"
38#include "msg_q.h"
39
40typedef struct msg_q {
41 void* msg_list; /* Linked list to store information */
42 pthread_cond_t list_cond; /* Condition variable for waiting on msg queue */
43 pthread_mutex_t list_mutex; /* Mutex for exclusive access to message queue */
44 int unblocked; /* Has this message queue been unblocked? */
45} msg_q;
46
47/*===========================================================================
48FUNCTION convert_linked_list_err_type
49
50DESCRIPTION
51 Converts from one set of enum values to another.
52
53 linked_list_val: Value to convert to msg_q_enum_type
54
55DEPENDENCIES
56 N/A
57
58RETURN VALUE
59 Corresponding linked_list_enum_type in msg_q_enum_type
60
61SIDE EFFECTS
62 N/A
63
64===========================================================================*/
65static msq_q_err_type convert_linked_list_err_type(linked_list_err_type linked_list_val)
66{
67 switch( linked_list_val )
68 {
69 case eLINKED_LIST_SUCCESS:
70 return eMSG_Q_SUCCESS;
71 case eLINKED_LIST_INVALID_PARAMETER:
72 return eMSG_Q_INVALID_PARAMETER;
73 case eLINKED_LIST_INVALID_HANDLE:
74 return eMSG_Q_INVALID_HANDLE;
75 case eLINKED_LIST_UNAVAILABLE_RESOURCE:
76 return eMSG_Q_UNAVAILABLE_RESOURCE;
77 case eLINKED_LIST_INSUFFICIENT_BUFFER:
78 return eMSG_Q_INSUFFICIENT_BUFFER;
Albert I15cb0c92021-06-26 04:21:58 +080079 case eLINKED_LIST_EMPTY:
80 return eMSG_Q_EMPTY;
Michael Bestas3a0209e2023-05-04 01:15:47 +030081
82 case eLINKED_LIST_FAILURE_GENERAL:
83 default:
84 return eMSG_Q_FAILURE_GENERAL;
85 }
86}
87
88/* ----------------------- END INTERNAL FUNCTIONS ---------------------------------------- */
89
90/*===========================================================================
91
92 FUNCTION: msg_q_init
93
94 ===========================================================================*/
95msq_q_err_type msg_q_init(void** msg_q_data)
96{
97 if( msg_q_data == NULL )
98 {
99 LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
100 return eMSG_Q_INVALID_PARAMETER;
101 }
102
103 msg_q* tmp_msg_q;
104 tmp_msg_q = (msg_q*)calloc(1, sizeof(msg_q));
105 if( tmp_msg_q == NULL )
106 {
107 LOC_LOGE("%s: Unable to allocate space for message queue!\n", __FUNCTION__);
108 return eMSG_Q_FAILURE_GENERAL;
109 }
110
111 if( linked_list_init(&tmp_msg_q->msg_list) != 0 )
112 {
113 LOC_LOGE("%s: Unable to initialize storage list!\n", __FUNCTION__);
114 free(tmp_msg_q);
115 return eMSG_Q_FAILURE_GENERAL;
116 }
117
118 if( pthread_mutex_init(&tmp_msg_q->list_mutex, NULL) != 0 )
119 {
120 LOC_LOGE("%s: Unable to initialize list mutex!\n", __FUNCTION__);
121 linked_list_destroy(&tmp_msg_q->msg_list);
122 free(tmp_msg_q);
123 return eMSG_Q_FAILURE_GENERAL;
124 }
125
126 if( pthread_cond_init(&tmp_msg_q->list_cond, NULL) != 0 )
127 {
128 LOC_LOGE("%s: Unable to initialize msg q cond var!\n", __FUNCTION__);
129 linked_list_destroy(&tmp_msg_q->msg_list);
130 pthread_mutex_destroy(&tmp_msg_q->list_mutex);
131 free(tmp_msg_q);
132 return eMSG_Q_FAILURE_GENERAL;
133 }
134
135 tmp_msg_q->unblocked = 0;
136
137 *msg_q_data = tmp_msg_q;
138
139 return eMSG_Q_SUCCESS;
140}
141
142/*===========================================================================
143
144 FUNCTION: msg_q_init2
145
146 ===========================================================================*/
147const void* msg_q_init2()
148{
149 void* q = NULL;
150 if (eMSG_Q_SUCCESS != msg_q_init(&q)) {
151 q = NULL;
152 }
153 return q;
154}
155
156/*===========================================================================
157
158 FUNCTION: msg_q_destroy
159
160 ===========================================================================*/
161msq_q_err_type msg_q_destroy(void** msg_q_data)
162{
163 if( msg_q_data == NULL )
164 {
165 LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
166 return eMSG_Q_INVALID_HANDLE;
167 }
168
169 msg_q* p_msg_q = (msg_q*)*msg_q_data;
170
171 linked_list_destroy(&p_msg_q->msg_list);
172 pthread_mutex_destroy(&p_msg_q->list_mutex);
173 pthread_cond_destroy(&p_msg_q->list_cond);
174
175 p_msg_q->unblocked = 0;
176
177 free(*msg_q_data);
178 *msg_q_data = NULL;
179
180 return eMSG_Q_SUCCESS;
181}
182
183/*===========================================================================
184
185 FUNCTION: msg_q_snd
186
187 ===========================================================================*/
188msq_q_err_type msg_q_snd(void* msg_q_data, void* msg_obj, void (*dealloc)(void*))
189{
190 msq_q_err_type rv;
191 if( msg_q_data == NULL )
192 {
193 LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
194 return eMSG_Q_INVALID_HANDLE;
195 }
196 if( msg_obj == NULL )
197 {
198 LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);
199 return eMSG_Q_INVALID_PARAMETER;
200 }
201
202 msg_q* p_msg_q = (msg_q*)msg_q_data;
203
204 pthread_mutex_lock(&p_msg_q->list_mutex);
205 LOC_LOGV("%s: Sending message with handle = %p\n", __FUNCTION__, msg_obj);
206
207 if( p_msg_q->unblocked )
208 {
209 LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
210 pthread_mutex_unlock(&p_msg_q->list_mutex);
211 return eMSG_Q_UNAVAILABLE_RESOURCE;
212 }
213
214 rv = convert_linked_list_err_type(linked_list_add(p_msg_q->msg_list, msg_obj, dealloc));
215
216 /* Show data is in the message queue. */
217 pthread_cond_signal(&p_msg_q->list_cond);
218
219 pthread_mutex_unlock(&p_msg_q->list_mutex);
220
221 LOC_LOGV("%s: Finished Sending message with handle = %p\n", __FUNCTION__, msg_obj);
222
223 return rv;
224}
225
226/*===========================================================================
227
228 FUNCTION: msg_q_rcv
229
230 ===========================================================================*/
231msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj)
232{
233 msq_q_err_type rv;
234 if( msg_q_data == NULL )
235 {
236 LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
237 return eMSG_Q_INVALID_HANDLE;
238 }
239
240 if( msg_obj == NULL )
241 {
242 LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);
243 return eMSG_Q_INVALID_PARAMETER;
244 }
245
246 msg_q* p_msg_q = (msg_q*)msg_q_data;
247
248 pthread_mutex_lock(&p_msg_q->list_mutex);
249
250 if( p_msg_q->unblocked )
251 {
252 LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
253 pthread_mutex_unlock(&p_msg_q->list_mutex);
254 return eMSG_Q_UNAVAILABLE_RESOURCE;
255 }
256
257 /* Wait for data in the message queue */
258 while( linked_list_empty(p_msg_q->msg_list) && !p_msg_q->unblocked )
259 {
260 pthread_cond_wait(&p_msg_q->list_cond, &p_msg_q->list_mutex);
261 }
262
263 rv = convert_linked_list_err_type(linked_list_remove(p_msg_q->msg_list, msg_obj));
264
265 pthread_mutex_unlock(&p_msg_q->list_mutex);
266
267 LOC_LOGV("%s: Received message %p rv = %d\n", __FUNCTION__, *msg_obj, rv);
268
269 return rv;
270}
271
272/*===========================================================================
273
274 FUNCTION: msg_q_rmv
275
276 ===========================================================================*/
277msq_q_err_type msg_q_rmv(void* msg_q_data, void** msg_obj)
278{
279 msq_q_err_type rv;
280 if (msg_q_data == NULL) {
281 LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
282 return eMSG_Q_INVALID_HANDLE;
283 }
284
285 if (msg_obj == NULL) {
286 LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);
287 return eMSG_Q_INVALID_PARAMETER;
288 }
289
290 msg_q* p_msg_q = (msg_q*)msg_q_data;
291
292 pthread_mutex_lock(&p_msg_q->list_mutex);
293
294 if (p_msg_q->unblocked) {
295 LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
296 pthread_mutex_unlock(&p_msg_q->list_mutex);
297 return eMSG_Q_UNAVAILABLE_RESOURCE;
298 }
299
300 if (linked_list_empty(p_msg_q->msg_list)) {
301 LOC_LOGW("%s: list is empty !!\n", __FUNCTION__);
302 pthread_mutex_unlock(&p_msg_q->list_mutex);
Albert I15cb0c92021-06-26 04:21:58 +0800303 return eMSG_Q_EMPTY;
Michael Bestas3a0209e2023-05-04 01:15:47 +0300304 }
305
306 rv = convert_linked_list_err_type(linked_list_remove(p_msg_q->msg_list, msg_obj));
307
308 pthread_mutex_unlock(&p_msg_q->list_mutex);
309
310 LOC_LOGV("%s: Removed message %p rv = %d\n", __FUNCTION__, *msg_obj, rv);
311
312 return rv;
313}
314
315
316
317/*===========================================================================
318
319 FUNCTION: msg_q_flush
320
321 ===========================================================================*/
322msq_q_err_type msg_q_flush(void* msg_q_data)
323{
324 msq_q_err_type rv;
325 if ( msg_q_data == NULL )
326 {
327 LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
328 return eMSG_Q_INVALID_HANDLE;
329 }
330
331 msg_q* p_msg_q = (msg_q*)msg_q_data;
332
333 LOC_LOGD("%s: Flushing Message Queue\n", __FUNCTION__);
334
335 pthread_mutex_lock(&p_msg_q->list_mutex);
336
337 /* Remove all elements from the list */
338 rv = convert_linked_list_err_type(linked_list_flush(p_msg_q->msg_list));
339
340 pthread_mutex_unlock(&p_msg_q->list_mutex);
341
342 LOC_LOGD("%s: Message Queue flushed\n", __FUNCTION__);
343
344 return rv;
345}
346
347/*===========================================================================
348
349 FUNCTION: msg_q_unblock
350
351 ===========================================================================*/
352msq_q_err_type msg_q_unblock(void* msg_q_data)
353{
354 if ( msg_q_data == NULL )
355 {
356 LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
357 return eMSG_Q_INVALID_HANDLE;
358 }
359
360 msg_q* p_msg_q = (msg_q*)msg_q_data;
361 pthread_mutex_lock(&p_msg_q->list_mutex);
362
363 if( p_msg_q->unblocked )
364 {
365 LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
366 pthread_mutex_unlock(&p_msg_q->list_mutex);
367 return eMSG_Q_UNAVAILABLE_RESOURCE;
368 }
369
370 LOC_LOGD("%s: Unblocking Message Queue\n", __FUNCTION__);
371 /* Unblocking message queue */
372 p_msg_q->unblocked = 1;
373
374 /* Allow all the waiters to wake up */
375 pthread_cond_broadcast(&p_msg_q->list_cond);
376
377 pthread_mutex_unlock(&p_msg_q->list_mutex);
378
379 LOC_LOGD("%s: Message Queue unblocked\n", __FUNCTION__);
380
381 return eMSG_Q_SUCCESS;
382}