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