1 /*
2 * Copyright (c) 2020-2023 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_syscall_adapter.h"
10
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <limits.h>
14 #include <poll.h>
15 #include <sched.h>
16 #include <securec.h>
17 #include <sys/ioctl.h>
18 #include <sys/prctl.h>
19 #include <sys/syscall.h>
20 #include <unistd.h>
21
22 #include "hdf_base.h"
23 #include "hdf_io_service.h"
24 #include "hdf_log.h"
25 #include "hdf_sbuf.h"
26 #include "osal_mem.h"
27 #include "osal_thread.h"
28 #include "osal_time.h"
29
30 #define HDF_LOG_TAG hdf_syscall_adapter
31 #define EPOLL_MAX_EVENT_SIZE 4
32 #define HDF_DEFAULT_BWR_READ_SIZE 1024
33 #define EVENT_READ_BUFF_GROWTH_RATE 2
34 #define EVENT_READ_BUFF_MAX (20 * 1024) // 20k
35 #define SYSCALL_INVALID_FD (-1)
36 #define HDF_PFD_GROW_SIZE 4
37 #define TIMEOUT_US 100000 // 100ms
38 #define LOAD_IOSERVICE_WAIT_TIME 10 // ms
39 #define LOAD_IOSERVICE_WAIT_COUNT 20 // ms
40 #define THREAD_NAME_LEN_MAX 16
41
HaveOnlyOneElement(const struct DListHead * head)42 static bool HaveOnlyOneElement(const struct DListHead *head)
43 {
44 if (head->next != head && head->next->next == head) {
45 return true;
46 }
47
48 return false;
49 }
50
HdfDevEventGrowReadBuffer(struct HdfWriteReadBuf * buffer)51 static int32_t HdfDevEventGrowReadBuffer(struct HdfWriteReadBuf *buffer)
52 {
53 size_t newSize = buffer->readSize;
54
55 if (newSize > EVENT_READ_BUFF_MAX) {
56 HDF_LOGE("%s: report event size out of max limit", __func__);
57 return HDF_DEV_ERR_NORANGE;
58 }
59
60 void *newBuff = OsalMemAlloc(newSize);
61 if (newBuff == NULL) {
62 HDF_LOGE("%s:oom,%d", __func__, (int)newSize);
63 return HDF_DEV_ERR_NO_MEMORY;
64 }
65
66 OsalMemFree((void *)(uintptr_t)buffer->readBuffer);
67 buffer->readBuffer = (uintptr_t)newBuff;
68 return HDF_SUCCESS;
69 }
70
HdfFdToAdapterLocked(const struct HdfDevListenerThread * thread,int32_t fd)71 static struct HdfSyscallAdapter *HdfFdToAdapterLocked(const struct HdfDevListenerThread *thread, int32_t fd)
72 {
73 if (thread->adapter != NULL && thread->adapter->fd == fd) {
74 return thread->adapter;
75 }
76
77 if (thread->adapterListPtr == NULL) {
78 return NULL;
79 }
80
81 struct HdfSyscallAdapter *adapter = NULL;
82 DLIST_FOR_EACH_ENTRY(adapter, thread->adapterListPtr, struct HdfSyscallAdapter, listNode) {
83 if (adapter->fd == fd) {
84 return adapter;
85 }
86 }
87
88 return NULL;
89 }
90
HdfDevEventDispatchLocked(const struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter,const struct HdfWriteReadBuf * bwr)91 static int32_t HdfDevEventDispatchLocked(
92 const struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter, const struct HdfWriteReadBuf *bwr)
93 {
94 struct HdfDevEventlistener *listener = NULL;
95 struct HdfSBuf *sbuf = NULL;
96
97 if (bwr->readConsumed > 0) {
98 sbuf = HdfSbufBind(bwr->readBuffer, bwr->readConsumed);
99 } else {
100 sbuf = HdfSbufObtain(sizeof(int));
101 }
102
103 if (sbuf == NULL) {
104 HDF_LOGE("%s:sbuf oom", __func__);
105 return HDF_DEV_ERR_NO_MEMORY;
106 }
107
108 /* Dispatch events to the service group listener */
109 if (thread->listenerListPtr != NULL) {
110 DLIST_FOR_EACH_ENTRY(listener, thread->listenerListPtr, struct HdfDevEventlistener, listNode) {
111 if (listener->onReceive != NULL) {
112 (void)listener->onReceive(listener, &adapter->super, bwr->cmdCode, sbuf);
113 } else if (listener->callBack != NULL) {
114 (void)listener->callBack(listener->priv, bwr->cmdCode, sbuf);
115 }
116 HdfSbufSetDataSize(sbuf, bwr->readConsumed);
117 }
118 }
119
120 OsalMutexLock(&adapter->mutex);
121 /* Dispatch events to the service (SyscallAdapter) listener */
122 DLIST_FOR_EACH_ENTRY(listener, &adapter->listenerList, struct HdfDevEventlistener, listNode) {
123 if (listener->onReceive != NULL) {
124 (void)listener->onReceive(listener, &adapter->super, bwr->cmdCode, sbuf);
125 } else if (listener->callBack != NULL) {
126 (void)listener->callBack(listener->priv, bwr->cmdCode, sbuf);
127 }
128 HdfSbufSetDataSize(sbuf, bwr->readConsumed);
129 }
130 OsalMutexUnlock(&adapter->mutex);
131
132 HdfSbufRecycle(sbuf);
133 return HDF_SUCCESS;
134 }
135
HdfDevEventReadAndDispatch(struct HdfDevListenerThread * thread,int32_t fd)136 static int32_t HdfDevEventReadAndDispatch(struct HdfDevListenerThread *thread, int32_t fd)
137 {
138 struct HdfWriteReadBuf bwr = {0};
139 int32_t ret = HDF_SUCCESS;
140
141 bwr.readBuffer = (uintptr_t)OsalMemAlloc(HDF_DEFAULT_BWR_READ_SIZE);
142 if (bwr.readBuffer == (uintptr_t)NULL) {
143 HDF_LOGE("%s: oom", __func__);
144 return HDF_DEV_ERR_NO_MEMORY;
145 }
146 bwr.cmdCode = -1;
147 bwr.readConsumed = 0;
148 bwr.readSize = HDF_DEFAULT_BWR_READ_SIZE;
149
150 OsalMutexLock(&thread->mutex);
151
152 struct HdfSyscallAdapter *adapter = HdfFdToAdapterLocked(thread, fd);
153 if (adapter == NULL) {
154 HDF_LOGI("%s: invalid adapter", __func__);
155 OsalMSleep(1); // yield to sync adapter list
156 goto FINISH;
157 }
158
159 while (true) {
160 ret = ioctl(adapter->fd, HDF_READ_DEV_EVENT, &bwr);
161 if (ret == 0) {
162 break;
163 }
164 ret = errno;
165 if (ret == -HDF_DEV_ERR_NORANGE) {
166 if (HdfDevEventGrowReadBuffer(&bwr) == HDF_SUCCESS) {
167 /* read buffer may not enough, grow read buffer and try again--The read buffere is insufficient.
168 Expand the buffer and try again. */
169 continue;
170 }
171 }
172 if (ret == -HDF_DEV_ERR_NODATA) {
173 ret = HDF_SUCCESS;
174 } else {
175 HDF_LOGE("%s:ioctl failed, errno=%d", __func__, ret);
176 }
177
178 goto FINISH;
179 }
180
181 ret = HdfDevEventDispatchLocked(thread, adapter, &bwr);
182
183 FINISH:
184 OsalMemFree((void *)(uintptr_t)bwr.readBuffer);
185 OsalMutexUnlock(&thread->mutex);
186 return ret;
187 }
188
AssignPfds(struct HdfDevListenerThread * thread,struct pollfd ** pfds,uint16_t * pfdSize)189 static int32_t AssignPfds(struct HdfDevListenerThread *thread, struct pollfd **pfds, uint16_t *pfdSize)
190 {
191 struct pollfd *pfdPtr = *pfds;
192 uint16_t pfdCount = 0;
193
194 OsalMutexLock(&thread->mutex);
195 if (*pfdSize < thread->pfdSize) {
196 pfdPtr = OsalMemAlloc(sizeof(struct pollfd) * thread->pfdSize);
197 if (pfdPtr == NULL) {
198 HDF_LOGE("%s: oom", __func__);
199 OsalMutexUnlock(&thread->mutex);
200 return HDF_ERR_MALLOC_FAIL;
201 }
202
203 *pfdSize = thread->pfdSize;
204 OsalMemFree(*pfds);
205 *pfds = pfdPtr;
206 }
207
208 for (uint32_t i = 0; i < thread->pfdSize; i++) {
209 if (thread->pfds[i].fd != SYSCALL_INVALID_FD) {
210 pfdPtr[pfdCount].fd = thread->pfds[i].fd;
211 pfdPtr[pfdCount].events = thread->pfds[i].events;
212 pfdPtr[pfdCount].revents = 0;
213 pfdCount++;
214 }
215 }
216
217 thread->pollChanged = false;
218 OsalMutexUnlock(&thread->mutex);
219 return pfdCount;
220 }
221
SetThreadName(void)222 static void SetThreadName(void)
223 {
224 char newTitle[THREAD_NAME_LEN_MAX] = {0};
225
226 int32_t tid = syscall(SYS_gettid);
227 int32_t ret = sprintf_s(newTitle, THREAD_NAME_LEN_MAX, "%s%d", "evt_list_", tid);
228 if (ret > 0) {
229 ret = prctl(PR_SET_NAME, newTitle);
230 if (ret < 0) {
231 HDF_LOGE("%s: failed to set thread name, errno is %d", __func__, errno);
232 }
233 }
234
235 return;
236 }
237
238 #define POLL_WAIT_TIME_MS 100
HdfDevEventListenTask(void * para)239 static int32_t HdfDevEventListenTask(void *para)
240 {
241 struct HdfDevListenerThread *thread = (struct HdfDevListenerThread *)para;
242 struct pollfd *pfds = NULL;
243 uint16_t pfdSize = 0;
244 int32_t pollCount = 0;
245
246 thread->status = LISTENER_RUNNING;
247 SetThreadName();
248 while (!thread->shouldStop) {
249 if (thread->pollChanged) {
250 pollCount = AssignPfds(thread, &pfds, &pfdSize);
251 }
252 if (pollCount <= 0) {
253 goto EXIT;
254 }
255 int32_t pollSize = poll(pfds, pollCount, -1);
256 if (pollSize <= 0) {
257 HDF_LOGE("%s: poll fail (%d)%s", __func__, errno, strerror(errno));
258 OsalMSleep(POLL_WAIT_TIME_MS);
259 continue;
260 }
261 for (uint32_t i = 0; i < (uint32_t)pollCount; i++) {
262 if (pfds[i].fd == SYSCALL_INVALID_FD) {
263 continue;
264 }
265 if ((((uint32_t)pfds[i].revents) & POLLIN) &&
266 HdfDevEventReadAndDispatch(thread, pfds[i].fd) != HDF_SUCCESS) {
267 goto EXIT;
268 } else if (((uint32_t)pfds[i].revents) & POLLHUP) {
269 HDF_LOGI("event listener task received exit event");
270 goto EXIT;
271 } else if (((uint32_t)pfds[i].revents) & POLLNVAL) {
272 OsalMSleep(1); // polled closed fd, yield to sync
273 }
274 }
275 }
276
277 EXIT:
278 HDF_LOGI("event listener task exit");
279
280 thread->status = LISTENER_EXITED;
281 OsalMemFree(pfds);
282
283 if (thread->shouldStop) {
284 /* Exit due to async call and free the thread struct. */
285 OsalMutexDestroy(&thread->mutex);
286 OsalThreadDestroy(&thread->thread);
287 OsalMemFree(thread->pfds);
288 OsalMemFree(thread);
289 }
290
291 return HDF_SUCCESS;
292 }
293
HdfAdapterStartListenIoctl(int fd)294 static int32_t HdfAdapterStartListenIoctl(int fd)
295 {
296 int32_t ret = ioctl(fd, HDF_LISTEN_EVENT_START, 0);
297 if (ret) {
298 HDF_LOGE("%s: failed to notify drv(%d) of start %d %{public}s", __func__, fd, errno, strerror(errno));
299 return HDF_ERR_IO;
300 }
301
302 return HDF_SUCCESS;
303 }
304
HdfAdapterStopListenIoctl(int fd)305 static int32_t HdfAdapterStopListenIoctl(int fd)
306 {
307 int32_t ret = ioctl(fd, HDF_LISTEN_EVENT_STOP, 0);
308 if (ret) {
309 HDF_LOGE("%s: failed to notify drv(%d) of stop %d %{public}s", __func__, fd, errno, strerror(errno));
310 return HDF_ERR_IO;
311 }
312
313 return HDF_SUCCESS;
314 }
315
HdfAdapterExitListenIoctl(int fd)316 static int32_t HdfAdapterExitListenIoctl(int fd)
317 {
318 int32_t ret = ioctl(fd, HDF_LISTEN_EVENT_EXIT, 0);
319 if (ret) {
320 HDF_LOGE("%s: failed to notify drv(%d) of exit %d %{public}s", __func__, fd, errno, strerror(errno));
321 return HDF_ERR_IO;
322 }
323 HDF_LOGD("ioctl send poll thread(%d) exit event, ret=%d", fd, ret);
324 return HDF_SUCCESS;
325 }
326
HdfDevListenerThreadDoInit(struct HdfDevListenerThread * thread)327 static int32_t HdfDevListenerThreadDoInit(struct HdfDevListenerThread *thread)
328 {
329 if (OsalMutexInit(&thread->mutex) != HDF_SUCCESS) {
330 HDF_LOGE("%s: failed to create thread lock", __func__);
331 return HDF_FAILURE;
332 }
333
334 int32_t ret = OsalThreadCreate(&thread->thread, HdfDevEventListenTask, thread);
335 if (ret != HDF_SUCCESS) {
336 HDF_LOGE("%s: failed to create thread", __func__);
337 thread->status = LISTENER_UNINITED;
338 OsalMutexDestroy(&thread->mutex);
339 return HDF_ERR_THREAD_CREATE_FAIL;
340 }
341
342 thread->status = LISTENER_INITED;
343 thread->shouldStop = false;
344 thread->pollChanged = true;
345 thread->policy = SCHED_OTHER;
346
347 return HDF_SUCCESS;
348 }
349
HdfDevListenerThreadInit(struct HdfDevListenerThread * thread)350 static int32_t HdfDevListenerThreadInit(struct HdfDevListenerThread *thread)
351 {
352 switch (thread->status) {
353 case LISTENER_STARTED: // fall-through
354 case LISTENER_RUNNING: // fall-through
355 case LISTENER_INITED: // fall-through
356 case LISTENER_WAITING:
357 return HDF_SUCCESS;
358 case LISTENER_EXITED:
359 thread->status = LISTENER_INITED;
360 thread->shouldStop = false;
361 return HDF_SUCCESS;
362 case LISTENER_UNINITED:
363 return HdfDevListenerThreadDoInit(thread);
364 default:
365 break;
366 }
367
368 return HDF_FAILURE;
369 }
370
GetValidPfdIndexLocked(struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter)371 static int32_t GetValidPfdIndexLocked(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter)
372 {
373 uint32_t index = 0;
374 struct pollfd *pfds = thread->pfds;
375 for (; index < thread->pfdSize; index++) {
376 if (pfds[index].fd == SYSCALL_INVALID_FD) {
377 break;
378 }
379
380 if (pfds[index].fd == adapter->fd) {
381 return index;
382 }
383 }
384
385 if (index >= thread->pfdSize) {
386 uint32_t newSize = thread->pfdSize + HDF_PFD_GROW_SIZE;
387 struct pollfd *newPfds = OsalMemCalloc(sizeof(struct pollfd) * newSize);
388 if (newPfds == NULL) {
389 return HDF_ERR_MALLOC_FAIL;
390 }
391 if (thread->pfdSize != 0) {
392 (void)memcpy_s(
393 newPfds, sizeof(struct pollfd) * newSize, thread->pfds, sizeof(struct pollfd) * thread->pfdSize);
394 }
395
396 for (uint32_t i = index; i < newSize; i++) {
397 newPfds[i].fd = SYSCALL_INVALID_FD;
398 }
399
400 OsalMemFree(thread->pfds);
401 thread->pfds = newPfds;
402 thread->pfdSize = newSize;
403 }
404
405 return index;
406 }
407
HdfAddAdapterToPfds(struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter)408 static int32_t HdfAddAdapterToPfds(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter)
409 {
410 int32_t index = GetValidPfdIndexLocked(thread, adapter);
411 if (index < 0) {
412 return HDF_ERR_MALLOC_FAIL;
413 }
414
415 thread->pfds[index].fd = adapter->fd;
416 thread->pfds[index].events = POLLIN;
417 thread->pfds[index].revents = 0;
418
419 return HDF_SUCCESS;
420 }
421
HdfListenThreadInitPollFds(struct HdfDevListenerThread * thread)422 static int32_t HdfListenThreadInitPollFds(struct HdfDevListenerThread *thread)
423 {
424 struct HdfSyscallAdapter *adapter = NULL;
425 if (thread->adapterListPtr != NULL) {
426 DLIST_FOR_EACH_ENTRY(adapter, thread->adapterListPtr, struct HdfSyscallAdapter, listNode) {
427 if (HdfAddAdapterToPfds(thread, adapter) != HDF_SUCCESS) {
428 return HDF_ERR_MALLOC_FAIL;
429 }
430 }
431 }
432
433 if (thread->adapter != NULL) {
434 return HdfAddAdapterToPfds(thread, thread->adapter);
435 }
436
437 return HDF_SUCCESS;
438 }
439
HdfDevListenerThreadStart(struct HdfDevListenerThread * thread)440 static int32_t HdfDevListenerThreadStart(struct HdfDevListenerThread *thread)
441 {
442 if (thread->status >= LISTENER_STARTED) {
443 return HDF_SUCCESS;
444 }
445
446 if (thread->status != LISTENER_INITED) {
447 return HDF_ERR_INVALID_PARAM;
448 }
449
450 int32_t ret = HdfListenThreadInitPollFds(thread);
451 if (ret != HDF_SUCCESS || thread->pfdSize <= 0) {
452 HDF_LOGE("%s:invalid poll list", __func__);
453 return HDF_DEV_ERR_NO_DEVICE;
454 }
455
456 do {
457 for (uint16_t i = 0; i < thread->pfdSize; i++) {
458 if (thread->pfds[i].fd == SYSCALL_INVALID_FD) {
459 continue;
460 }
461 if (HdfAdapterStartListenIoctl(thread->pfds[i].fd)) {
462 return HDF_ERR_IO;
463 }
464 }
465
466 struct OsalThreadParam config = {
467 .name = "evt_listen",
468 .priority = OSAL_THREAD_PRI_DEFAULT,
469 .stackSize = 0,
470 .policy = thread->policy,
471 };
472
473 thread->status = LISTENER_STARTED;
474 if (OsalThreadStart(&thread->thread, &config) != HDF_SUCCESS) {
475 HDF_LOGE("%s:OsalThreadStart failed", __func__);
476 ret = HDF_FAILURE;
477 break;
478 }
479 return HDF_SUCCESS;
480 } while (0);
481
482 return ret;
483 }
484
HdfDevListenerThreadObtain(void)485 static struct HdfDevListenerThread *HdfDevListenerThreadObtain(void)
486 {
487 struct HdfDevListenerThread *thread = OsalMemCalloc(sizeof(struct HdfDevListenerThread));
488 if (thread == NULL) {
489 return NULL;
490 }
491 thread->status = LISTENER_UNINITED;
492 if (HdfDevListenerThreadInit(thread) != HDF_SUCCESS) {
493 OsalMemFree(thread);
494 return NULL;
495 }
496 return thread;
497 }
498
HdfIoServiceGroupThreadInit(struct HdfSyscallAdapterGroup * group)499 static int32_t HdfIoServiceGroupThreadInit(struct HdfSyscallAdapterGroup *group)
500 {
501 if (group->thread == NULL) {
502 struct HdfDevListenerThread *listenerThread = HdfDevListenerThreadObtain();
503 if (listenerThread == NULL) {
504 return HDF_ERR_THREAD_CREATE_FAIL;
505 }
506 group->thread = listenerThread;
507 }
508 group->thread->adapterListPtr = &group->adapterList;
509 group->thread->listenerListPtr = &group->listenerList;
510 return HdfDevListenerThreadInit(group->thread);
511 }
512
HdfIoServiceGroupThreadStart(struct HdfSyscallAdapterGroup * group,int policy)513 static int32_t HdfIoServiceGroupThreadStart(struct HdfSyscallAdapterGroup *group, int policy)
514 {
515 OsalMutexLock(&group->mutex);
516 if (HdfIoServiceGroupThreadInit(group) != HDF_SUCCESS) {
517 OsalMutexUnlock(&group->mutex);
518 return HDF_FAILURE;
519 }
520 group->thread->policy = policy;
521 int32_t ret = HdfDevListenerThreadStart(group->thread);
522 OsalMutexUnlock(&group->mutex);
523 return ret;
524 }
525
HdfListenThreadPollAdd(struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter)526 static int32_t HdfListenThreadPollAdd(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter)
527 {
528 /* If thread is not bound to a service group, you do not need to add a poll. */
529 if (thread->adapterListPtr == NULL) {
530 return HDF_SUCCESS;
531 }
532
533 OsalMutexLock(&thread->mutex);
534 struct HdfSyscallAdapter *headAdapter = DListIsEmpty(thread->adapterListPtr) ?
535 NULL :
536 DLIST_FIRST_ENTRY(thread->adapterListPtr, struct HdfSyscallAdapter, listNode);
537
538 DListInsertTail(&adapter->listNode, thread->adapterListPtr);
539
540 if (thread->status < LISTENER_STARTED) {
541 OsalMutexUnlock(&thread->mutex);
542 return HDF_SUCCESS;
543 }
544
545 int32_t ret = HDF_SUCCESS;
546 do {
547 int32_t index = GetValidPfdIndexLocked(thread, adapter);
548 if (index < 0) {
549 ret = HDF_ERR_MALLOC_FAIL;
550 break;
551 }
552
553 thread->pfds[index].fd = adapter->fd;
554 thread->pfds[index].events = POLLIN;
555 thread->pfds[index].revents = 0;
556
557 if (headAdapter != NULL) {
558 if (ioctl(headAdapter->fd, HDF_LISTEN_EVENT_WAKEUP, 0) != 0) {
559 HDF_LOGE("%s: failed to wakeup drv to add poll %d %{public}s", __func__, errno, strerror(errno));
560 thread->pfds[index].fd = SYSCALL_INVALID_FD;
561 ret = HDF_ERR_IO;
562 break;
563 }
564 }
565
566 if (HdfAdapterStartListenIoctl(adapter->fd) != HDF_SUCCESS) {
567 thread->pfds[index].fd = SYSCALL_INVALID_FD;
568 ret = HDF_DEV_ERR_OP;
569 break;
570 }
571 thread->pollChanged = true;
572 OsalMutexUnlock(&thread->mutex);
573 return ret;
574 } while (false);
575
576 DListRemove(&adapter->listNode);
577 OsalMutexUnlock(&thread->mutex);
578 return ret;
579 }
580
HdfListenThreadPollDel(struct HdfDevListenerThread * thread,struct HdfSyscallAdapter * adapter)581 static void HdfListenThreadPollDel(struct HdfDevListenerThread *thread, struct HdfSyscallAdapter *adapter)
582 {
583 if (thread == NULL) {
584 DListRemove(&adapter->listNode);
585 adapter->group = NULL;
586 return;
587 }
588 OsalMutexLock(&thread->mutex);
589 struct pollfd *pfds = thread->pfds;
590 for (uint32_t index = 0; index < thread->pfdSize; index++) {
591 if (pfds[index].fd == adapter->fd) {
592 pfds[index].fd = SYSCALL_INVALID_FD;
593 break;
594 }
595 }
596
597 HdfAdapterStopListenIoctl(adapter->fd);
598 if (ioctl(adapter->fd, HDF_LISTEN_EVENT_WAKEUP, 0) != 0) {
599 HDF_LOGE("%s: failed to wakeup drv to del poll %d %s", __func__, errno, strerror(errno));
600 }
601 DListRemove(&adapter->listNode);
602 adapter->group = NULL;
603 thread->pollChanged = true;
604 OsalMutexUnlock(&thread->mutex);
605 }
606
HdfDevListenerThreadFree(struct HdfDevListenerThread * thread)607 static void HdfDevListenerThreadFree(struct HdfDevListenerThread *thread)
608 {
609 OsalMutexDestroy(&thread->mutex);
610 OsalMemFree(thread->pfds);
611 OsalThreadDestroy(&thread->thread);
612 OsalMemFree(thread);
613 }
614
HdfDevListenerThreadDestroy(struct HdfDevListenerThread * thread)615 static void HdfDevListenerThreadDestroy(struct HdfDevListenerThread *thread)
616 {
617 if (thread == NULL) {
618 return;
619 }
620
621 switch (thread->status) {
622 case LISTENER_RUNNING: {
623 int count = 0;
624 uint32_t stopCount = 0;
625 OsalMutexLock(&thread->mutex);
626 thread->adapter = NULL;
627 thread->adapterListPtr = NULL;
628 thread->listenerListPtr = NULL;
629 OsalMutexUnlock(&thread->mutex);
630 for (uint16_t i = 0; i < thread->pfdSize; i++) {
631 if (thread->pfds[i].fd != SYSCALL_INVALID_FD &&
632 HdfAdapterExitListenIoctl(thread->pfds[i].fd) == HDF_SUCCESS) {
633 stopCount++;
634 }
635 thread->pfds[i].fd = SYSCALL_INVALID_FD;
636 }
637
638 if (stopCount == 0) {
639 thread->shouldStop = true;
640 HDF_LOGE("%s:failed to exit listener thread with ioctl, will go async way", __func__);
641 return;
642 }
643 while (thread->status != LISTENER_EXITED && count <= TIMEOUT_US) {
644 OsalUSleep(1);
645 count++;
646 }
647 if (thread->status == LISTENER_EXITED) {
648 HDF_LOGI("poll thread exited");
649 HdfDevListenerThreadFree(thread);
650 } else {
651 thread->shouldStop = true;
652 HDF_LOGE("wait poll thread exit timeout, async exit");
653 }
654 return;
655 }
656 case LISTENER_STARTED:
657 thread->shouldStop = true;
658 break;
659 case LISTENER_EXITED: // fall-through
660 case LISTENER_INITED:
661 HdfDevListenerThreadFree(thread);
662 break;
663 default:
664 break;
665 }
666 }
667
HdfSyscallAdapterDispatch(struct HdfObject * object,int32_t code,struct HdfSBuf * data,struct HdfSBuf * reply)668 static int32_t HdfSyscallAdapterDispatch(
669 struct HdfObject *object, int32_t code, struct HdfSBuf *data, struct HdfSBuf *reply)
670 {
671 if (object == NULL) {
672 HDF_LOGE("Input object is null");
673 return HDF_FAILURE;
674 }
675 struct HdfSyscallAdapter *ioService = (struct HdfSyscallAdapter *)object;
676 struct HdfWriteReadBuf wrBuf;
677 if (reply != NULL) {
678 wrBuf.readBuffer = (uintptr_t)HdfSbufGetData(reply);
679 wrBuf.readSize = HdfSbufGetCapacity(reply);
680 } else {
681 wrBuf.readBuffer = 0;
682 wrBuf.readSize = 0;
683 }
684 if (data != NULL) {
685 wrBuf.writeBuffer = (uintptr_t)HdfSbufGetData(data);
686 wrBuf.writeSize = HdfSbufGetDataSize(data);
687 } else {
688 wrBuf.writeBuffer = 0;
689 wrBuf.writeSize = 0;
690 }
691
692 wrBuf.readConsumed = 0;
693 wrBuf.writeConsumed = 0;
694 wrBuf.cmdCode = code;
695 int32_t ret = ioctl(ioService->fd, HDF_WRITE_READ, &wrBuf);
696 if (ret < 0) {
697 HDF_LOGE("Failed to dispatch serv call ioctl %{public}d", -errno);
698 ret = -errno;
699 }
700 if (reply != NULL) {
701 HdfSbufSetDataSize(reply, wrBuf.readConsumed);
702 }
703 return ret;
704 }
705
TrytoLoadIoService(const char * serviceName,char * devNodePath,char * realPath)706 static int TrytoLoadIoService(const char *serviceName, char *devNodePath, char *realPath)
707 {
708 if (HdfLoadDriverByServiceName(serviceName) != HDF_SUCCESS) {
709 HDF_LOGE("%s: load %{public}s driver failed", __func__, serviceName);
710 return HDF_DEV_ERR_NO_DEVICE;
711 }
712
713 int waitCount = LOAD_IOSERVICE_WAIT_COUNT;
714 while (realpath(devNodePath, realPath) == NULL && waitCount > 0) {
715 OsalMSleep(LOAD_IOSERVICE_WAIT_TIME); // wait ueventd to crater dev
716 waitCount--;
717 }
718 if (waitCount <= 0) {
719 HDF_LOGE("%s: char dev %{public}s is invalid", __func__, devNodePath);
720 return HDF_DEV_ERR_NO_DEVICE_SERVICE;
721 }
722
723 return HDF_SUCCESS;
724 }
725
HdfIoServiceAdapterObtain(const char * serviceName)726 struct HdfIoService *HdfIoServiceAdapterObtain(const char *serviceName)
727 {
728 struct HdfSyscallAdapter *adapter = NULL;
729 struct HdfIoService *ioService = NULL;
730 char *nodePath = NULL;
731 char *realPath = NULL;
732
733 const char *devPath = DEV_NODE_PATH;
734 if (access(DEV_NODE_PATH, F_OK) != 0) {
735 devPath = DEV_PATH;
736 }
737
738 nodePath = OsalMemCalloc(PATH_MAX);
739 realPath = OsalMemCalloc(PATH_MAX);
740 if (nodePath == NULL || realPath == NULL) {
741 HDF_LOGE("%s: out of memory", __func__);
742 goto OUT;
743 }
744
745 if (sprintf_s(nodePath, PATH_MAX - 1, "%s%s", devPath, serviceName) < 0) {
746 HDF_LOGE("Failed to get the node path");
747 goto OUT;
748 }
749
750 if (realpath(nodePath, realPath) == NULL && TrytoLoadIoService(serviceName, nodePath, realPath) != HDF_SUCCESS) {
751 goto OUT;
752 }
753
754 adapter = (struct HdfSyscallAdapter *)OsalMemCalloc(sizeof(struct HdfSyscallAdapter));
755 if (adapter == NULL) {
756 HDF_LOGE("Failed to allocate SyscallAdapter");
757 goto OUT;
758 }
759
760 DListHeadInit(&adapter->listenerList);
761 if (OsalMutexInit(&adapter->mutex)) {
762 HDF_LOGE("%s: Failed to create mutex", __func__);
763 OsalMemFree(adapter);
764 goto OUT;
765 }
766
767 adapter->fd = open(realPath, O_RDWR);
768 if (adapter->fd < 0) {
769 HDF_LOGE("Open file node %{public}s failed, (%d)%{public}s", realPath, errno, strerror(errno));
770 OsalMutexDestroy(&adapter->mutex);
771 OsalMemFree(adapter);
772 goto OUT;
773 }
774 ioService = &adapter->super;
775 static struct HdfIoDispatcher dispatch = {
776 .Dispatch = HdfSyscallAdapterDispatch,
777 };
778 ioService->dispatcher = &dispatch;
779 OUT:
780 OsalMemFree(nodePath);
781 OsalMemFree(realPath);
782 return ioService;
783 }
784
HdfIoServiceAdapterRecycle(struct HdfIoService * service)785 void HdfIoServiceAdapterRecycle(struct HdfIoService *service)
786 {
787 struct HdfSyscallAdapter *adapter = (struct HdfSyscallAdapter *)service;
788 if (adapter != NULL) {
789 HdfDevListenerThreadDestroy(adapter->thread);
790 adapter->thread = NULL;
791 if (adapter->fd >= 0) {
792 close(adapter->fd);
793 adapter->fd = -1;
794 }
795 OsalMutexDestroy(&adapter->mutex);
796 OsalMemFree(adapter);
797 }
798 }
799
HdfIoServiceThreadBindLocked(struct HdfSyscallAdapter * adapter)800 static int32_t HdfIoServiceThreadBindLocked(struct HdfSyscallAdapter *adapter)
801 {
802 if (adapter->thread == NULL) {
803 struct HdfDevListenerThread *listenerthread = HdfDevListenerThreadObtain();
804 if (listenerthread == NULL) {
805 return HDF_ERR_THREAD_CREATE_FAIL;
806 }
807 adapter->thread = listenerthread;
808 }
809 adapter->thread->adapter = adapter;
810 return HdfDevListenerThreadInit(adapter->thread);
811 }
812
HdfIoServiceStartListen(struct HdfSyscallAdapter * adapter,int policy)813 static int32_t HdfIoServiceStartListen(struct HdfSyscallAdapter *adapter, int policy)
814 {
815 if (HdfIoServiceThreadBindLocked(adapter) != HDF_SUCCESS) {
816 HDF_LOGE("%s: Failed to bind a thread to SyscallAdapter", __func__);
817 return HDF_FAILURE;
818 }
819 adapter->thread->policy = policy;
820
821 return HdfDevListenerThreadStart(adapter->thread);
822 }
823
AddListenerToAdapterLocked(struct HdfSyscallAdapter * adapter,struct HdfDevEventlistener * listener)824 static bool AddListenerToAdapterLocked(struct HdfSyscallAdapter *adapter, struct HdfDevEventlistener *listener)
825 {
826 struct HdfDevEventlistener *it = NULL;
827 DLIST_FOR_EACH_ENTRY(it, &adapter->listenerList, struct HdfDevEventlistener, listNode) {
828 if (it == listener) {
829 HDF_LOGE("Add a listener for duplicate dev-event");
830 return false;
831 }
832 }
833 DListInsertTail(&listener->listNode, &adapter->listenerList);
834 return true;
835 }
836
HdfDeviceRegisterEventListenerWithSchedPolicy(struct HdfIoService * target,struct HdfDevEventlistener * listener,int policy)837 int32_t HdfDeviceRegisterEventListenerWithSchedPolicy(
838 struct HdfIoService *target, struct HdfDevEventlistener *listener, int policy)
839 {
840 if (target == NULL || listener == NULL) {
841 return HDF_ERR_INVALID_PARAM;
842 }
843
844 if (policy != SCHED_FIFO && policy != SCHED_RR && policy != SCHED_OTHER) {
845 HDF_LOGE("%{public}s: Register event listener with invalid sched policy", __func__);
846 return HDF_ERR_INVALID_PARAM;
847 }
848
849 if (listener->callBack == NULL && listener->onReceive == NULL) {
850 HDF_LOGE("%{public}s: Listener onReceive func not implemented", __func__);
851 return HDF_ERR_INVALID_OBJECT;
852 }
853
854 struct HdfSyscallAdapter *adapter = CONTAINER_OF(target, struct HdfSyscallAdapter, super);
855 int32_t ret = HDF_SUCCESS;
856
857 OsalMutexLock(&adapter->mutex);
858 if (!AddListenerToAdapterLocked(adapter, listener)) {
859 OsalMutexUnlock(&adapter->mutex);
860 return HDF_ERR_INVALID_PARAM;
861 }
862
863 if (adapter->group != NULL) {
864 /* Do not bind any service in a service goup to its own thread or start the group thread. */
865 ret = HdfIoServiceGroupThreadStart(adapter->group, policy);
866 OsalMutexUnlock(&adapter->mutex);
867 return ret;
868 }
869
870 if (HdfIoServiceStartListen(adapter, policy) != HDF_SUCCESS) {
871 DListRemove(&listener->listNode);
872 ret = HDF_FAILURE;
873 }
874
875 OsalMutexUnlock(&adapter->mutex);
876 return ret;
877 }
878
HdfDeviceRegisterEventListener(struct HdfIoService * target,struct HdfDevEventlistener * listener)879 int32_t HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener)
880 {
881 return HdfDeviceRegisterEventListenerWithSchedPolicy(target, listener, SCHED_OTHER);
882 }
883
HdfDeviceUnregisterEventListener(struct HdfIoService * target,struct HdfDevEventlistener * listener)884 int32_t HdfDeviceUnregisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener)
885 {
886 if (target == NULL || listener == NULL) {
887 return HDF_ERR_INVALID_PARAM;
888 }
889
890 if (listener->listNode.next == NULL || listener->listNode.prev == NULL) {
891 HDF_LOGE("%s: broken listener, may double unregister", __func__);
892 return HDF_ERR_INVALID_OBJECT;
893 }
894
895 struct HdfSyscallAdapter *adapter = (struct HdfSyscallAdapter *)target;
896 OsalMutexLock(&adapter->mutex);
897
898 DListRemove(&listener->listNode);
899
900 if (DListIsEmpty(&adapter->listenerList)) {
901 HdfDevListenerThreadDestroy(adapter->thread);
902 adapter->thread = NULL;
903 }
904 OsalMutexUnlock(&adapter->mutex);
905
906 return HDF_SUCCESS;
907 }
908
HdfIoServiceGroupObtain(void)909 struct HdfIoServiceGroup *HdfIoServiceGroupObtain(void)
910 {
911 struct HdfSyscallAdapterGroup *adapterGroup = OsalMemCalloc(sizeof(struct HdfSyscallAdapterGroup));
912 if (adapterGroup == NULL) {
913 return NULL;
914 }
915
916 if (OsalMutexInit(&adapterGroup->mutex)) {
917 OsalMemFree(adapterGroup);
918 return NULL;
919 }
920 DListHeadInit(&adapterGroup->adapterList);
921 DListHeadInit(&adapterGroup->listenerList);
922 return &adapterGroup->serviceGroup;
923 }
924
HdfIoServiceGroupRecycle(struct HdfIoServiceGroup * group)925 void HdfIoServiceGroupRecycle(struct HdfIoServiceGroup *group)
926 {
927 if (group == NULL) {
928 return;
929 }
930
931 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
932 OsalMutexLock(&adapterGroup->mutex);
933
934 HdfDevListenerThreadDestroy(adapterGroup->thread);
935 adapterGroup->thread = NULL;
936
937 struct HdfSyscallAdapter *adapter = NULL;
938 struct HdfSyscallAdapter *tmp = NULL;
939 DLIST_FOR_EACH_ENTRY_SAFE(adapter, tmp, &adapterGroup->adapterList, struct HdfSyscallAdapter, listNode) {
940 DListRemove(&adapter->listNode);
941 adapter->group = NULL;
942 }
943
944 OsalMutexUnlock(&adapterGroup->mutex);
945
946 OsalMutexDestroy(&adapterGroup->mutex);
947 OsalMemFree(adapterGroup);
948 }
949
HdfIoServiceGroupRegisterListenerWithSchedPolicy(struct HdfIoServiceGroup * group,struct HdfDevEventlistener * listener,int policy)950 int32_t HdfIoServiceGroupRegisterListenerWithSchedPolicy(
951 struct HdfIoServiceGroup *group, struct HdfDevEventlistener *listener, int policy)
952 {
953 if (group == NULL || listener == NULL) {
954 return HDF_ERR_INVALID_PARAM;
955 }
956
957 if (policy != SCHED_FIFO && policy != SCHED_RR && policy != SCHED_OTHER) {
958 HDF_LOGE("Group register event listener with invalid sched policy");
959 return HDF_ERR_INVALID_PARAM;
960 }
961
962 if (listener->callBack == NULL && listener->onReceive == NULL) {
963 HDF_LOGE("Listener onReceive func not implemented");
964 return HDF_ERR_INVALID_OBJECT;
965 }
966 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
967
968 OsalMutexLock(&adapterGroup->mutex);
969 if (HdfIoServiceGroupThreadInit(adapterGroup) != HDF_SUCCESS) {
970 HDF_LOGE("%s:failed to bind listener thread for service group", __func__);
971 OsalMutexUnlock(&adapterGroup->mutex);
972 return HDF_FAILURE;
973 }
974
975 int32_t ret = HDF_SUCCESS;
976 struct HdfDevListenerThread *listenerThread = adapterGroup->thread;
977 listenerThread->policy = policy;
978
979 OsalMutexLock(&listenerThread->mutex);
980 struct HdfDevEventlistener *it = NULL;
981 DLIST_FOR_EACH_ENTRY(it, &adapterGroup->listenerList, struct HdfDevEventlistener, listNode) {
982 if (it == listener) {
983 HDF_LOGE("Failed to add group listener, repeated registration");
984 ret = HDF_ERR_INVALID_PARAM;
985 goto FINISH;
986 }
987 }
988 DListInsertTail(&listener->listNode, &adapterGroup->listenerList);
989 if (!DListIsEmpty(&adapterGroup->adapterList) && listenerThread->status < LISTENER_STARTED) {
990 ret = HdfDevListenerThreadStart(listenerThread);
991 if (ret != HDF_SUCCESS) {
992 DListRemove(&listener->listNode);
993 }
994 }
995
996 FINISH:
997 OsalMutexUnlock(&listenerThread->mutex);
998 OsalMutexUnlock(&adapterGroup->mutex);
999 return ret;
1000 }
1001
HdfIoServiceGroupRegisterListener(struct HdfIoServiceGroup * group,struct HdfDevEventlistener * listener)1002 int32_t HdfIoServiceGroupRegisterListener(struct HdfIoServiceGroup *group, struct HdfDevEventlistener *listener)
1003 {
1004 return HdfIoServiceGroupRegisterListenerWithSchedPolicy(group, listener, SCHED_OTHER);
1005 }
1006
GetListenerCount(struct HdfDevListenerThread * thread)1007 static int32_t GetListenerCount(struct HdfDevListenerThread *thread)
1008 {
1009 struct HdfDevEventlistener *listener = NULL;
1010 int32_t count = 0;
1011
1012 OsalMutexLock(&thread->mutex);
1013 if (thread->listenerListPtr != NULL) {
1014 DLIST_FOR_EACH_ENTRY(listener, thread->listenerListPtr, struct HdfDevEventlistener, listNode) {
1015 count++;
1016 }
1017 }
1018
1019 struct HdfSyscallAdapter *adapter = NULL;
1020 DLIST_FOR_EACH_ENTRY(adapter, thread->adapterListPtr, struct HdfSyscallAdapter, listNode) {
1021 OsalMutexLock(&adapter->mutex);
1022 DLIST_FOR_EACH_ENTRY(listener, &adapter->listenerList, struct HdfDevEventlistener, listNode) {
1023 count++;
1024 }
1025 OsalMutexUnlock(&adapter->mutex);
1026 }
1027 OsalMutexUnlock(&thread->mutex);
1028
1029 return count;
1030 }
1031
HdfIoServiceGroupUnregisterListener(struct HdfIoServiceGroup * group,struct HdfDevEventlistener * listener)1032 int32_t HdfIoServiceGroupUnregisterListener(struct HdfIoServiceGroup *group, struct HdfDevEventlistener *listener)
1033 {
1034 if (group == NULL || listener == NULL) {
1035 return HDF_ERR_INVALID_PARAM;
1036 }
1037
1038 if (listener->listNode.next == NULL || listener->listNode.prev == NULL) {
1039 HDF_LOGE("%s:broken listener, may double unregister", __func__);
1040 return HDF_ERR_INVALID_OBJECT;
1041 }
1042
1043 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
1044
1045 OsalMutexLock(&adapterGroup->mutex);
1046 struct HdfDevListenerThread *listenerThread = adapterGroup->thread;
1047
1048 DListRemove(&listener->listNode);
1049
1050 if (listenerThread != NULL && GetListenerCount(listenerThread) == 0) {
1051 HdfDevListenerThreadDestroy(listenerThread);
1052 adapterGroup->thread = NULL;
1053 }
1054 OsalMutexUnlock(&adapterGroup->mutex);
1055
1056 return HDF_SUCCESS;
1057 }
1058
HdfIoServiceGroupAddService(struct HdfIoServiceGroup * group,struct HdfIoService * service)1059 int32_t HdfIoServiceGroupAddService(struct HdfIoServiceGroup *group, struct HdfIoService *service)
1060 {
1061 if (group == NULL || service == NULL) {
1062 return HDF_ERR_INVALID_PARAM;
1063 }
1064 struct HdfSyscallAdapter *adapter = CONTAINER_OF(service, struct HdfSyscallAdapter, super);
1065 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
1066
1067 if (adapter->group != NULL) {
1068 HDF_LOGE("service already in group");
1069 return HDF_ERR_DEVICE_BUSY;
1070 }
1071
1072 if (adapter->thread != NULL) {
1073 HDF_LOGE("service already has independent thread");
1074 return HDF_ERR_DEVICE_BUSY;
1075 }
1076
1077 OsalMutexLock(&adapterGroup->mutex);
1078 if (HdfIoServiceGroupThreadInit(adapterGroup) != HDF_SUCCESS) {
1079 HDF_LOGE("%s:failed to bind listener thread for service group", __func__);
1080 OsalMutexUnlock(&adapterGroup->mutex);
1081 return HDF_FAILURE;
1082 }
1083
1084 struct HdfDevListenerThread *listenerThread = adapterGroup->thread;
1085 int32_t ret = HdfListenThreadPollAdd(listenerThread, adapter);
1086 if (ret != HDF_SUCCESS) {
1087 OsalMutexUnlock(&adapterGroup->mutex);
1088 return ret;
1089 }
1090
1091 adapter->group = adapterGroup;
1092
1093 OsalMutexLock(&listenerThread->mutex);
1094 if ((!DListIsEmpty(&adapterGroup->listenerList) || !DListIsEmpty(&adapter->listenerList)) &&
1095 listenerThread->status < LISTENER_STARTED) {
1096 ret = HdfDevListenerThreadStart(adapterGroup->thread);
1097 if (ret != HDF_SUCCESS) {
1098 HdfListenThreadPollDel(adapterGroup->thread, adapter);
1099 }
1100 }
1101 OsalMutexUnlock(&listenerThread->mutex);
1102 OsalMutexUnlock(&adapterGroup->mutex);
1103 return ret;
1104 }
1105
HdfIoServiceGroupRemoveService(struct HdfIoServiceGroup * group,struct HdfIoService * service)1106 void HdfIoServiceGroupRemoveService(struct HdfIoServiceGroup *group, struct HdfIoService *service)
1107 {
1108 if (group == NULL || service == NULL) {
1109 return;
1110 }
1111 struct HdfSyscallAdapter *adapter = CONTAINER_OF(service, struct HdfSyscallAdapter, super);
1112 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
1113 if (adapterGroup->thread == NULL || adapter->group == NULL) {
1114 return;
1115 }
1116
1117 OsalMutexLock(&adapterGroup->mutex);
1118 if (HaveOnlyOneElement(&adapterGroup->adapterList)) {
1119 HdfDevListenerThreadDestroy(adapterGroup->thread);
1120 adapterGroup->thread = NULL;
1121 DListRemove(&adapter->listNode);
1122 adapter->group = NULL;
1123 } else {
1124 HdfListenThreadPollDel(adapterGroup->thread, adapter);
1125 }
1126 OsalMutexUnlock(&adapterGroup->mutex);
1127 adapter->group = NULL;
1128 }
1129
HdfIoserviceGetListenerCount(const struct HdfIoService * service)1130 int HdfIoserviceGetListenerCount(const struct HdfIoService *service)
1131 {
1132 if (service == NULL) {
1133 return 0;
1134 }
1135
1136 struct HdfSyscallAdapter *adapter = CONTAINER_OF(service, struct HdfSyscallAdapter, super);
1137
1138 OsalMutexLock(&adapter->mutex);
1139 int count = DListGetCount(&adapter->listenerList);
1140 OsalMutexUnlock(&adapter->mutex);
1141 return count;
1142 }
1143
HdfIoserviceGroupGetListenerCount(const struct HdfIoServiceGroup * group)1144 int HdfIoserviceGroupGetListenerCount(const struct HdfIoServiceGroup *group)
1145 {
1146 if (group == NULL) {
1147 return 0;
1148 }
1149
1150 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
1151 OsalMutexLock(&adapterGroup->mutex);
1152 if (adapterGroup->thread == NULL) {
1153 OsalMutexUnlock(&adapterGroup->mutex);
1154 return 0;
1155 }
1156 int count = GetListenerCount(adapterGroup->thread);
1157 OsalMutexUnlock(&adapterGroup->mutex);
1158 return count;
1159 }
1160
HdfIoserviceGroupGetServiceCount(const struct HdfIoServiceGroup * group)1161 int HdfIoserviceGroupGetServiceCount(const struct HdfIoServiceGroup *group)
1162 {
1163 if (group == NULL) {
1164 return 0;
1165 }
1166
1167 struct HdfSyscallAdapterGroup *adapterGroup = CONTAINER_OF(group, struct HdfSyscallAdapterGroup, serviceGroup);
1168
1169 OsalMutexLock(&adapterGroup->mutex);
1170 if (adapterGroup->thread == NULL) {
1171 OsalMutexUnlock(&adapterGroup->mutex);
1172 return 0;
1173 }
1174
1175 OsalMutexLock(&adapterGroup->thread->mutex);
1176 int count = DListGetCount(&adapterGroup->adapterList);
1177 OsalMutexUnlock(&adapterGroup->thread->mutex);
1178
1179 OsalMutexUnlock(&adapterGroup->mutex);
1180
1181 return count;
1182 }
1183