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