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