• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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