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