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