2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 * @brief Events Library -- Implementing API Functions
23 #include <sys/ioctl.h>
29 #include <sys/prctl.h>
30 #include <other_service/ev_lib.h>
31 #include <agldd/evk_lib.h>
32 #include <agldd/ev_common.h>
34 #define EV_perror perror
35 #define EV_assert assert
38 * Not use dbg_output in the EV so that the DTV apps and semiconductor vendor use this function.
40 #define ev_log(format, arg...) \
44 prctl(PR_GET_NAME, procname); \
46 printf(format, procname, pid, ##arg); \
50 #define EV_DEBUG_INFO(format, arg...) \
52 if (getenv("EV_DEBUG") != NULL) { \
53 ev_log("[EV: info](%s:%d) " format, ##arg); \
57 #define EV_DEBUG_WARNING(format, arg...) \
59 ev_log("[EV: warning](%s:%d) " format, ##arg); \
62 #define EV_DEBUG_ERR(format, arg...) \
64 ev_log("[EV: ERR](%s:%d) " format, ##arg); \
67 /** @brief Structures for managing ID and FD in use by processes
70 EV_ID id; /**< flag/queue ID */
71 INT32 fd; /**< file descriptor */
75 /*----------------------------------------*/
76 /** @brief EV management information table per thread */
77 /*----------------------------------------*/
79 /** Thread calling the EV library */
81 /** Registration information by ID */
82 EV_Info ev_info[EV_MAX_IDS_IN_THREAD];
83 /** Number of registered IDs */
88 /** Thread information acquisition mode */
89 #define EV_THREAD_INFO_CREATE 0
90 #define EV_THREAD_INFO_PEEK 1
91 #define EV_SEARCH_ALL_THREAD -1
93 /* Related process exclusion control in the process */
94 const char *g_ev_lock_func;
97 pthread_mutex_t g_ev_process_global_mutex = PTHREAD_MUTEX_INITIALIZER;
99 #define EV_PROCESS_MUTEX_LOCK \
100 pthread_mutex_lock(&g_ev_process_global_mutex); \
101 g_ev_lock_func = __FUNCTION__; \
102 g_ev_lock_line = __LINE__; \
103 g_ev_lock_pid = getpid();
104 #define EV_PROCESS_MUTEX_UNLOCK \
105 pthread_mutex_unlock(&g_ev_process_global_mutex);
108 * This document describes the following specifications:
109 * - Event Library (EV) API specifications
110 * - Event ID specifications
112 * In principle, the API specifications of the event library for kernel space (EVK) is
113 * the same as the event library for user space (EV) except for the function name prefixed ""EVK"".
114 * If there are differences between the EV and EVK, it is described as "difference in kernel version".
116 /** @defgroup Event Library (EV) API specifications */
117 /** @defgroup EV_ID_spec Event ID specifications */
118 /** @defgroup EV_m_id Function specifying module ID instead of event ID */
119 /** @defgroup EV_in internal specifications of the event library for user space (EV) */
120 /** @defgroup EVK_in Internal specifications of the event library for kernel space (EVK) */
121 /** @addtogroup EV_in
124 /** EV thread information management table */
125 EV_thread_info_type *EV_thread_info[EV_MAX_THREADS_IN_PROCESS];
127 /*----------------------------------------------------------------------
128 * Return the registered position of the thread ID
129 * Allocate and initialize space for unregistered threads
130 * @brief Sending message (specified module-ID)
131 * @param index [OUT] Thread index
132 * @param flag [IN] Operating Mode
133 ----------------------------------------------------------------------*/
135 EV_thread_id_check(int *index, int flag) {
138 /* Current threadID */
139 pthread_t EV_self_thread_id;
142 EV_self_thread_id = pthread_self();
144 /* Control-process lock */
145 EV_PROCESS_MUTEX_LOCK;
147 /* Whether or not the thread has already been registered. */
148 for(i = 0, empty = -1; i < EV_MAX_THREADS_IN_PROCESS; i++) {
150 if(EV_thread_info[i] == NULL) {
151 /* Set free space index */
152 empty = (empty == -1) ? i: empty;
156 if(EV_thread_info[i]->thread == EV_self_thread_id) {
159 /* Cancel in-process mutual exclusion */
160 EV_PROCESS_MUTEX_UNLOCK;
165 if(flag == EV_THREAD_INFO_PEEK) {
166 EV_DEBUG_ERR("thread id is not found.\n");
168 /* Cancel in-process mutual exclusion */
169 EV_PROCESS_MUTEX_UNLOCK;
170 return EV_ERR_Invalid_Thread;
173 /* If there are no unregistered threads and there is no space */
175 EV_DEBUG_ERR("thread id is full.\n");
177 /* Cancel in-process mutual exclusion */
178 EV_PROCESS_MUTEX_UNLOCK;
179 return EV_ERR_Thread_Over;
182 /* Set to free space */
183 EV_thread_info[empty] = malloc(sizeof(*(EV_thread_info[empty])));
184 EV_thread_info_type *th = EV_thread_info[empty];
187 if(th == NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function malloc
188 /* Cancel in-process mutual exclusion */
189 // LCOV_EXCL_START 5: fail safe for glibc function malloc
191 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
193 EV_PROCESS_MUTEX_UNLOCK;
199 memset(th, '\0', sizeof(*th));
200 th->thread = EV_self_thread_id;
203 /* Cancel in-process mutual exclusion */
204 EV_PROCESS_MUTEX_UNLOCK;
206 /* Set registration position */
212 // free thread information when create event/message fail and no release thread buffer.
213 // If no release thread buffer will cause be error:
214 // Creation event's Thread count num less than MAX count(16) when one thread create event/message
215 // fail and no longer to create event/message.
217 free_thread_buffer(int th_index) {
218 /* in-process mutual exclusion */
219 EV_PROCESS_MUTEX_LOCK;
221 &&(th_index < EV_MAX_THREADS_IN_PROCESS)
222 && (NULL != EV_thread_info[th_index])
223 && (0 == EV_thread_info[th_index]->num)) {
224 free(EV_thread_info[th_index]);
225 EV_thread_info[th_index] = NULL;
226 EV_DEBUG_ERR("Free thread buffer by th_index:%d.\n", th_index);
228 /* in-process mutual exclusion */
229 EV_PROCESS_MUTEX_UNLOCK;
232 /* EV_info update function */
234 add_ev_info(int th_index, EV_ID id, int fd) {
235 /* Check storage position of ID information */
236 /* beginning of in-process mutual exclusion */
237 EV_PROCESS_MUTEX_LOCK;
239 int id_index = EV_thread_info[th_index]->num;
240 EV_assert(id_index < EV_MAX_IDS_IN_THREAD);
242 /* Set information */
243 EV_thread_info[th_index]->ev_info[id_index].id = id;
244 EV_thread_info[th_index]->ev_info[id_index].fd = fd;
245 EV_thread_info[th_index]->num++;
247 /* end of in-process mutual exclusion */
248 EV_PROCESS_MUTEX_UNLOCK;
251 /* EV_info search function */
253 find_ev_info(int th_index, EV_ID id) {
254 int i, j, start, end;
257 /* Search all threads */
258 if(th_index == EV_SEARCH_ALL_THREAD) {
260 end = EV_MAX_THREADS_IN_PROCESS;
266 /* in-process mutual exclusion */
267 EV_PROCESS_MUTEX_LOCK;
269 for(j = start; j < end; j++) {
270 if(EV_thread_info[j] == NULL) {
274 for(i = 0; i < EV_thread_info[j]->num; i++) {
275 if(id == EV_thread_info[j]->ev_info[i].id) {
276 ret = EV_thread_info[j]->ev_info[i].fd;
282 /* Cancel in-process mutual exclusion */
283 EV_PROCESS_MUTEX_UNLOCK;
289 delete_ev_info(EV_ID id) {
292 int found_th_index = -1;
294 EV_thread_info_type *th = NULL;
296 /* beginning of in-thread mutual exclusion */
297 EV_PROCESS_MUTEX_LOCK;
299 for(i = 0 ; i < EV_MAX_THREADS_IN_PROCESS && found_idx == -1 ; i++) {
300 th = EV_thread_info[i];
304 for(j = 0 ; j < th->num ; j++) {
305 if (th->ev_info[j].id == id) {
306 fd = th->ev_info[j].fd;
314 if(found_idx == -1) {
315 EV_PROCESS_MUTEX_UNLOCK;
319 if (found_idx < th->num - 1) { /* pgr0060 */
320 memmove(&(th->ev_info[found_idx]), &(th->ev_info[found_idx+1]),
321 sizeof(th->ev_info[0]) * (size_t)(th->num - 1 - found_idx));
325 /* If everything is deleted */
326 if(th->num == 0 && EV_thread_info[found_th_index] != NULL) {
327 free(EV_thread_info[found_th_index]);
328 EV_thread_info[found_th_index] = NULL;
330 EV_PROCESS_MUTEX_UNLOCK;
339 EV_create_flag_in(int th_index, EV_ID flag_id, int is64bit) {
342 /* Open device driver */
343 fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
346 int ret = ioctl(fd, is64bit ? EVK_IOC_CREATE_FLAG64:
347 EVK_IOC_CREATE_FLAG, flag_id);
351 if(myerrno == EEXIST) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function ioctl
352 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
354 close(fd); // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl
355 EV_DEBUG_ERR("flag_id %x already exists.\n", flag_id); // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl
356 return EV_ERR_Exist; // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl
364 ret = ioctl(fd, EVK_IOC_SET_POLL, flag_id);
367 EV_DEBUG_ERR("set_poll: internal error\n");
371 add_ev_info(th_index, flag_id, fd);
375 /** @brief Create flag
377 * Create a flag with the given ID.
378 * Return error if a flag with the same flag ID already exists
380 * @param flag_id [IN]flag ID
383 * @retval EV_OK: Normal completion
384 * @retval EV_ERR_Invalid_ID: Specified an invalid flag ID
385 * @retval EV_ERR_Exist: A flag with the same ID already exists
386 * @retval Otherwise: FATAL error
389 EV_create_flag (EV_ID flag_id) {
394 if(!EV_ID_IS_FLAG(flag_id) || EV_ID_IS_AUTO_ID(flag_id)) {
395 EV_DEBUG_ERR("create_flag: Invalid flag_id %x.\n", flag_id);
396 return EV_ERR_Invalid_ID;
399 /* Thread information check */
400 err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
405 EV_DEBUG_INFO("EV_create_flag (th_index=%d)\n", th_index);
407 /* case of already created */
408 int fd = find_ev_info(th_index, flag_id);
410 EV_DEBUG_ERR("create_flag: You already created flag_id %x.\n", flag_id);
414 err = EV_create_flag_in(th_index, flag_id, 0);
416 free_thread_buffer(th_index);
422 /** @brief Create 64-bit flag
424 * Create a 64-bit flag with the given ID.
425 * Return error if a flag with the same flag ID already exists
427 * @param flag_id [IN]64-bit flag ID
430 * @retval EV_OK: Normal completion
431 * @retval EV_ERR_Invalid_ID: Specified an invalid 64-bit flag ID
432 * @retval EV_ERR_Exist: A 64-bit flag with same ID already exists
433 * @retval Otherwise: FATAL error
436 EV_create_flag64(EV_ID flag_id) {
440 if(!EV_ID_IS_FLAG64(flag_id) || EV_ID_IS_AUTO_ID(flag_id)) {
441 EV_DEBUG_ERR("create_flag: Invalid flag_id %x.\n", flag_id);
442 return EV_ERR_Invalid_ID;
445 /* Thread information check */
446 err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
451 int fd = find_ev_info(th_index, flag_id);
453 EV_DEBUG_ERR("create_flag: You already created flag_id %x.\n", flag_id);
457 err = EV_create_flag_in(th_index, flag_id, 1);
459 free_thread_buffer(th_index);
465 /** @brief Create flag (auto-assign ID)
467 * Automatically assign a flag ID and creates a flag.
468 * Same as EV_create_flag(), except that ID is automatically assigned.
470 * @param flag_id [OUT]Area for storing the assigned flag ID
472 * @see EV_create_flag
475 EV_create_flag_auto_id(EV_ID *flag_id) {
476 EV_assert(flag_id != NULL);
480 fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
483 int ret = ioctl(fd, EVK_IOC_ALLOC_FLAG_ID, flag_id);
487 /* Thread information check */
488 err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
494 err = EV_create_flag_in(th_index, *flag_id, 0);
496 free_thread_buffer(th_index);
504 /** @brief Create 64-bit flag(auto-assign ID)
506 * Automatically assign a 64-bit flag ID and creates a 64-bit flag.
507 * Same as EV_create_flag64(), except that ID is automatically assigned.
509 * @param flag_id [OUT]Area for storing the assigned 64-bit flag ID
511 * @see EV_create_flag64
514 EV_create_flag64_auto_id(EV_ID *flag_id) {
515 EV_assert(flag_id != NULL);
519 fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
522 int ret = ioctl(fd, EVK_IOC_ALLOC_FLAG64_ID, flag_id);
526 /* Thread information check */
527 err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
533 err = EV_create_flag_in(th_index, *flag_id, 1);
535 free_thread_buffer(th_index);
544 EV_create_queue_in(int th_index, EV_ID queue_id, UINT8 length,
545 UINT16 max_bytes, EV_Message_Queue_Type type) {
547 fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
550 EVK_Message_Queue_Request req;
551 req.queueID = queue_id;
553 req.max_bytes = max_bytes;
556 int ret = ioctl(fd, EVK_IOC_CREATE_MESSAGE_QUEUE, &req);
559 if (myerrno == EEXIST) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function ioctl
560 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
562 close(fd); // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl
563 EV_DEBUG_ERR("queue %x already exists.\n", queue_id); // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl
564 return EV_ERR_Exist; // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl
568 //EV_perror("create queue");
573 ret = ioctl(fd, EVK_IOC_SET_POLL, queue_id);
576 EV_DEBUG_ERR("set_poll: internal error\n");
580 add_ev_info(th_index, queue_id, fd);
584 /** @brief message event queue creation
586 * Create a queue of message event with the specified ID.
587 * Return error if a queue with the same ID already exists.
589 * A memory area corresponding to the specified maximum number of bytes x queue length is allocated dynamically.
591 * @param queue_id [IN] Message queue ID
592 * @param length [IN] Message queue length
593 * @param max_bytes [IN] - Maximum number of bytes per message
594 * @param type [IN] Type of action to take when more events are received when the queue is full
596 * @see ev_message_queue_type
598 * @retval EV_OK: Normal completion
599 * @retval EV_ERR_Invalid_ID: Specified an invalid flag ID
600 * @retval EV_ERR_Exist: A flag with the same ID already exists
601 * @retval Otherwise: FATAL error
604 EV_create_queue(EV_ID queue_id, UINT8 length, UINT16 max_bytes,
605 EV_Message_Queue_Type type) {
609 if(!EV_ID_IS_QUEUE(queue_id) || EV_ID_IS_AUTO_ID(queue_id)) {
610 EV_DEBUG_ERR("create_queue: Invalid queue_id %x was specified.\n",
612 return EV_ERR_Invalid_ID;
615 /* Thread information check */
616 err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
621 int fd = find_ev_info(th_index, queue_id);
623 EV_DEBUG_ERR("create_queue: You already created queue_id %x.\n",
628 err = EV_create_queue_in(th_index, queue_id, length, max_bytes, type);
630 free_thread_buffer(th_index);
636 /** @brief message event queue creation(auto-assign ID)
638 * Automatically assigns a queue ID and creates a queue for message events.
639 * Same as EV_create_queue(), except that ID is automatically assigned.
641 * @param queue_id [OUT] Area for storing the assigned flag ID
642 * @param length [IN] Message queue length
643 * @param max_bytes [IN] - Maximum number of bytes per message
644 * @param type [IN] Type of action to take when more events are received when the queue is full
646 * @see EV_create_queue
649 EV_create_queue_auto_id(EV_ID *queue_id, UINT8 length, UINT16 max_bytes,
650 EV_Message_Queue_Type type) {
653 EV_assert(queue_id != NULL);
656 fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
659 int ret = ioctl(fd, EVK_IOC_ALLOC_QUEUE_ID, queue_id);
663 /* Thread information check */
664 err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
666 *queue_id = EV_NO_ID;
670 err = EV_create_queue_in(th_index, *queue_id, length, max_bytes,
673 free_thread_buffer(th_index);
675 *queue_id = EV_NO_ID;
681 /** @brief Deleting flag event
683 * Delete the flag with the specified ID.
684 * Only flags created by this process can be deleted.
686 * - differences in kernel versions
687 * EVK_destroy_flag can be used to delete any existing message event queue.
689 * @note The program wakes up that waiting for this queue (poll or wait)
692 * @param flag_id [IN] ID of flag
694 * @retval EV_OK: Normal completion
695 * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist,
696 * Or it is not a flag created by invoking process
697 * @retval Otherwise: FATAL error
700 EV_destroy_flag(EV_ID flag_id) {
701 int fd = delete_ev_info(flag_id);
703 EV_DEBUG_ERR("You haven't created flag/queue_id %x.\n", flag_id);
704 return EV_ERR_Invalid_ID;
707 int ret = ioctl(fd, EVK_IOC_DESTROY_QUEUE, flag_id);
711 if (myerrno == ENOENT) {
712 EV_DEBUG_ERR("destroy: no such ID %x\n", flag_id);
713 return EV_ERR_Invalid_ID;
716 EV_perror("destroy");
723 /** @brief Delete message event queue
725 * Delete the message event queue with the specified ID.
726 * Only message event queues created by this process can be deleted.
728 * - differences in kernel versions
729 * EVK_destroy_queue can be used to delete any existing message event queue.
731 * @note The program wakes up that waiting for this queue (poll or wait)
734 * @param flag_id [IN] Message event queue ID
736 * @retval EV_OK: Normal completion
737 * @retval EV_ERR_Invalid_ID: The message queue with the specified ID does not exist,
738 * or there is no message event queue created by this process.
739 * @retval Otherwise: FATAL error
742 EV_destroy_queue(EV_ID queue_id) {
743 return EV_destroy_flag(queue_id);
747 EV_get_flag_in(EV_ID flag_id, EV_Flag *flag, int peek_only, int wait) {
748 EV_assert(flag != NULL);
749 flag->flagID = EV_NO_ID;
752 if (!EV_ID_IS_FLAG(flag_id)) {
753 EV_DEBUG_ERR("get_flag: %x is not a flag_id.\n", flag_id);
754 return EV_ERR_Invalid_ID;
757 int fd = find_ev_info(EV_SEARCH_ALL_THREAD, flag_id);
759 EV_DEBUG_ERR("You have not created flag_id %x.\n", flag_id);
760 return EV_ERR_Invalid_ID;
764 ev.type = EV_EVENT_Flag;
765 ev.u.flag.flagID = flag_id;
769 (peek_only ? EVK_IOC_PEEK_EVENT : (wait ? EVK_IOC_WAIT_EVENT : EVK_IOC_GET_EVENT)),
774 if (myerrno == ENOENT) {
775 EV_DEBUG_ERR("get_flag: No such flag_id %x.\n", flag_id);
776 return EV_ERR_Invalid_ID;
778 else if (myerrno == EINTR) {
779 EV_DEBUG_ERR("get_flag: Interrupted\n");
780 return EV_ERR_Interrupted;
783 EV_perror("get flag");
788 if (ev.type == EV_EVENT_Flag) {
789 flag->flagID = ev.u.flag.flagID;
790 flag->bits = ev.u.flag.bits;
796 EV_get_flag64_in(EV_ID flag_id, EV_Flag64 *flag, int peek_only, int wait) {
797 EV_assert(flag != NULL);
798 flag->flagID = EV_NO_ID;
801 if (!EV_ID_IS_FLAG64(flag_id)) {
802 EV_DEBUG_ERR("get_flag: %x is not a flag_id.\n", flag_id);
803 return EV_ERR_Invalid_ID;
806 int fd = find_ev_info(EV_SEARCH_ALL_THREAD, flag_id);
808 EV_DEBUG_ERR("You have not created flag_id %x.\n", flag_id);
809 return EV_ERR_Invalid_ID;
813 ev.type = EV_EVENT_Flag64;
814 ev.u.flag64.flagID = flag_id;
815 ev.u.flag64.bits = 0;
818 (peek_only ? EVK_IOC_PEEK_EVENT : (wait ? EVK_IOC_WAIT_EVENT : EVK_IOC_GET_EVENT)),
823 if (myerrno == ENOENT) {
824 EV_DEBUG_ERR("get_flag: No such flag_id %x.\n", flag_id);
825 return EV_ERR_Invalid_ID;
827 else if (myerrno == EINTR) {
828 EV_DEBUG_ERR("get_flag: Interrupted\n");
829 return EV_ERR_Interrupted;
832 EV_perror("get flag");
837 if (ev.type == EV_EVENT_Flag64) {
838 flag->flagID = ev.u.flag64.flagID;
839 flag->bits = ev.u.flag64.bits;
844 /** @brief Get flag event(non-block)
846 * Get the flag event with the specified ID, and clears the flag.
847 * Even if there is no event, it returns immediately.
848 * If there are no events, EV_NO_ID is stored in flag->flagID.
849 * A flag->bits of 0 can also be used to determine no events.
850 * Only flags created by this process can be gotten.
852 * @param flag_id [IN] Message event queue ID
853 * @param flag [OUT] Flag Structure
855 * @retval EV_OK: Normal completion
856 * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist,
857 * Or it is not a flag created by invoking process
858 * @retval Otherwise: FATAL error
861 EV_get_flag(EV_ID flag_id, EV_Flag *flag) {
862 return EV_get_flag_in(flag_id, flag, 0, 0);
865 /** @brief Get 64bit flag event(non-block)
867 * Get the 64-bit flag event with the specified ID, and clears the 64-bit flag.
868 * Even if there is no event, it returns immediately.
869 * If there are no events, EV_NO_ID is stored in flag->flagID.
870 * A flag->bits of 0 can also be used to determine no events.
871 * Only flags created by this process can be gotten.
872 * Be sure to specify the flag ID created by specifying 64-bits.
874 * @param flag_id [IN] Message event queue ID
875 * @param flag [OUT] 64-bit flag struct
877 * @retval EV_OK: Normal completion
878 * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist,
879 * Or it is not a flag created by invoking process
880 * @retval Otherwise: FATAL error
883 EV_get_flag64(EV_ID flag_id, EV_Flag64 *flag) {
884 return EV_get_flag64_in(flag_id, flag, 0, 0);
887 /** @brief Get flag event(block)
889 * Get the flag event with the specified ID, and clear the flag.
890 * If there is no event, block until an event is received.
891 * However, if the interrupt is interrupted by a signal interrupt, EV_ERR_Interrupted is returned.
892 * If the flag is deleted while waiting, the wait is suspended
893 * and EV_ERR_Invalid_ID is returned.
894 * When interrupted, EV_NO_ID is stored in flag->flagID.
895 * A flag->bits of 0 can also be judged to have been interrupted.
897 * @param flag_id [IN] Message event queue ID
898 * @param flag [OUT] Flag Structure
900 * @retval EV_OK: Normal completion
901 * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist,
902 * Or it is not a flag created by invoking process
903 * @retval EV_ERR_Interrupted: Interrupted by a signal interrupt
904 * @retval Otherwise: FATAL error
907 EV_wait_flag(EV_ID flag_id, EV_Flag *flag) {
908 return EV_get_flag_in(flag_id, flag, 0, 1);
911 /** @brief Get 64bit flag event(block)
913 * Get the 64-bit flag event with the specified ID, and clear the 64-bit flag.
914 * If there is no event, block until an event is received.
915 * However, if the interrupt is interrupted by a signal interrupt, EV_ERR_Interrupted is returned.
916 * If the flag is deleted while waiting, the wait is suspended
917 * and EV_ERR_Invalid_ID is returned.
918 * When interrupted, EV_NO_ID is stored in flag->flagID.
919 * A flag->bits of 0 can also be judged to have been interrupted.
920 * Be sure to specify the flag ID created by specifying 64 bits.
922 * @param flag_id [IN] Message event queue ID
923 * @param flag [OUT] 64-bit flag structure
925 * @retval EV_OK: Normal completion
926 * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist,
927 * Or it is not a flag created by invoking process
928 * @retval EV_ERR_Interrupted: Interrupted by a signal interrupt
929 * @retval Otherwise: FATAL error
932 EV_wait_flag64(EV_ID flag_id, EV_Flag64 *flag) {
933 return EV_get_flag64_in(flag_id, flag, 0, 1);
936 /** @brief Get flag event(non-destructive)
938 * Get the flag event with the specified ID non-destructively.
939 * Even if there is no event, it returns immediately.
940 * If there are no events, EV_NO_ID is stored in flag->flagID.
941 * A flag->bits of 0 can also be used to determine no events.
943 * @param flag_id [IN] Message event queue ID
944 * @param flag [OUT] Flag Structure
946 * @retval EV_OK: Normal completion
947 * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist,
948 * Or it is not a flag created by invoking process
949 * @retval Otherwise: FATAL error
952 EV_peek_flag(EV_ID flag_id, EV_Flag *flag) {
953 return EV_get_flag_in(flag_id, flag, 1, 0);
956 /** @brief Get 64bit flag event(non-destructive)
958 * Gets the 64-bit flag event with the specified ID non-destructively.
959 * Even if there is no event, it returns immediately.
960 * If there are no events, EV_NO_ID is stored in flag->flagID.
961 * A flag->bits of 0 can also be used to determine no events.
963 * @param flag_id [IN] Message event queue ID
964 * @param flag [OUT] 64-bit flag structure
966 * @retval EV_OK: Normal completion
967 * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist,
968 * Or it is not a flag created by invoking process
969 * @retval Otherwise: FATAL error
972 EV_peek_flag64(EV_ID flag_id, EV_Flag64 *flag) {
973 return EV_get_flag64_in(flag_id, flag, 1, 0);
977 EV_get_message_in(EV_ID queue_id, EV_Message *message, UINT32 senderInfo,
978 UINT32 length, const void *compare_bytes,
979 int peek_only, int wait) {
980 EV_assert(message != NULL);
981 message->queueID = EV_NO_ID;
982 message->senderInfo = 0;
985 if (!EV_ID_IS_QUEUE(queue_id)) {
986 EV_DEBUG_ERR("get_message: Invalid queue_id %x\n", queue_id);
987 return EV_ERR_Invalid_ID;
990 int fd = find_ev_info(EV_SEARCH_ALL_THREAD, queue_id);
992 EV_DEBUG_ERR("You have not created queue_id %x.\n", queue_id);
993 return EV_ERR_Invalid_ID;
997 ev.type = EV_EVENT_Message;
998 ev.u.message.queueID = queue_id;
999 ev.u.message.senderInfo = senderInfo;
1000 if(length > 0 && compare_bytes != NULL) {
1001 ev.u.message.length = length;
1002 memcpy(ev.u.message.message, compare_bytes, length);
1004 ev.u.message.length = 0;
1009 (peek_only ? EVK_IOC_PEEK_EVENT : (wait ? EVK_IOC_WAIT_EVENT : EVK_IOC_GET_EVENT)),
1012 int myerrno = errno;
1014 if (myerrno == ENOENT) {
1015 EV_DEBUG_ERR("No such queue_id %x\n", queue_id);
1016 return EV_ERR_Invalid_ID;
1018 else if (myerrno == EINTR) {
1019 EV_DEBUG_INFO("Interrupted.\n");
1020 return EV_ERR_Interrupted;
1023 EV_perror("get message");
1024 return EV_ERR_Fatal;
1028 if(ev.type == EV_EVENT_Message) {
1029 message->queueID = ev.u.message.queueID;
1030 message->senderInfo = ev.u.message.senderInfo;
1031 message->length = ev.u.message.length;
1032 memcpy(message->message, ev.u.message.message,
1033 ev.u.message.length);
1039 /** @brief Get message events(non-block)
1041 * Get one message event from the queue with the specified ID.
1042 * Even if there is no event, it returns immediately.
1043 * If there are no events, EV_NO_ID is stored in message-> queue_id.
1044 * The acquired message is deleted from the queue.
1046 * @param queue_id [IN] Message event queue ID
1047 * @param message [OUT] Message Event Structure
1049 * @retval EV_OK: Normal completion
1050 * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist
1051 * Or not a message event queue created by invoking process
1052 * @retval Otherwise: FATAL error
1055 EV_get_message(EV_ID queue_id, EV_Message *message) {
1056 return EV_get_message_in(queue_id, message, 0, 0, NULL, 0, 0);
1059 /** @brief Get message event(block)
1061 * Get one message event from the queue with the specified ID.
1062 * If there is no event, block until an event is received.
1063 * However, if the interrupt is interrupted by a signal interrupt, EV_ERR_Interrupted is returned.
1064 * If the queue is deleted while waiting, the waiting is suspended,
1065 * EV_ERR_Invalid_ID is returned.
1066 * When interrupted, EV_NO_ID is stored in message-> queue_id.
1068 * @param queue_id [IN] Message event queue ID
1069 * @param message [OUT] Message Event Structure
1071 * @retval EV_OK: Normal completion
1072 * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist
1073 * Or not a message event queue created by invoking process
1074 * @retval EV_ERR_Interrupted: Interrupted by a signal interrupt
1075 * @retval Otherwise: FATAL error
1078 EV_wait_message(EV_ID queue_id, EV_Message *message) {
1079 return EV_get_message_in(queue_id, message, 0, 0, NULL, 0, 1);
1082 /** @brief Get message event(non-destructive)
1084 * Get one message event queue of the specified ID non-destructively.
1085 * Even if there is no event, it returns immediately.
1086 * If there are no events, EV_NO_ID is stored in message-> queue_id.
1087 * Same as EV_get_message(), except that the retrieved message remains in the queue.
1089 * @param queue_id [IN] Message event queue ID
1090 * @param message [OUT] Message Event Structure
1092 * @retval EV_OK: Normal completion
1093 * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist
1094 * Or not a message event queue created by invoking process
1095 * @retval Otherwise: FATAL error
1098 EV_peek_message(EV_ID queue_id, EV_Message *message) {
1099 return EV_get_message_in(queue_id, message, 0, 0, NULL, 1, 0);
1103 EV_get_next_event_in(EV_Event *ev, int peek_only) {
1106 EVK_Next_Event_Query query;
1108 EV_assert(ev != NULL);
1109 ev->type = EV_EVENT_None;
1111 bzero(&query, sizeof(query));
1113 err = EV_thread_id_check(&th_index, EV_THREAD_INFO_PEEK);
1118 EV_PROCESS_MUTEX_LOCK;
1119 query.num = EV_thread_info[th_index]->num;
1120 for(i = 0 ; i < query.num ; i++) {
1121 query.ids[i] = EV_thread_info[th_index]->ev_info[i].id;
1123 EV_PROCESS_MUTEX_UNLOCK;
1125 if (query.num == 0) {
1130 fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
1135 (peek_only ? EVK_IOC_PEEK_NEXT_EVENT: EVK_IOC_GET_NEXT_EVENT),
1138 int myerrno = errno;
1143 EV_perror("get_next_event");
1144 return EV_ERR_Fatal;
1146 memcpy(ev, &(query.ev), sizeof(*ev));
1150 /** @brief Get the first event that arrived(non-block)
1152 * Get the first arrival of a flag created by invoking process or an event
1153 * that occurred in the message queue.
1154 * If there are no events, EV_EVENT_None is stored in the ev->type and returned immediately.
1156 * @param ev [OUT] Event Structure
1157 * Whether the acquired event type is flag or message is determined
1158 * by ev->type is EV_EVENT_Flag or EV_EVENT_Message.
1160 * @retval EV_OK: Normal completion
1161 * @retval Otherwise: FATAL error
1164 EV_get_next_event(EV_Event *ev) {
1165 return EV_get_next_event_in(ev, 0);
1168 /** @brief Get the first event that arrived(non-destructive)
1170 * Get the first arrival of a flag created by invoking process or an event
1171 * that occurred in the message queue non-destructively.
1172 * The next call to EV_get_next_event() or EV_peek_next_event(),
1173 * return the same event as long as no other program gets it.
1174 * If there are no events, EV_EVENT_None is stored in the ev->type and returned immediately.
1176 * @param ev [OUT] Event Structure
1177 * Whether the acquired event flag or message is a message is determined
1178 * by whether ev->type is EV_EVENT_Flag or EV_EVENT_Message.
1180 * @retval EV_OK: Normal completion
1181 * @retval Otherwise: FATAL error
1184 EV_peek_next_event(EV_Event *ev) {
1185 return EV_get_next_event_in(ev, 1);
1188 /** @brief Get message event(search by source info)
1190 * If there is an event whose source information matches
1191 * in the message event queue of the specified ID,it is gotten and deleted from the queue.
1192 * If there are no such messages,
1193 * EV_NO_ID is stored in message->queue_id, and the system call returns immediately.
1195 * @param queue_id [IN] Message event queue ID
1196 * @param senderInfo [IN] Source Info
1197 * @param message [OUT] Message Event Structure
1199 * @retval EV_OK: Normal completion
1200 * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist
1201 * Or not a message event queue created by invoking process
1202 * @retval Otherwise: FATAL error
1205 EV_find_message_by_sender(EV_ID queue_id, UINT32 senderInfo,
1206 EV_Message *message) {
1207 EV_assert(message != NULL);
1208 EV_assert(senderInfo != 0);
1209 return EV_get_message_in(queue_id, message, senderInfo, 0, NULL, 0, 0);
1212 /** @brief Get message event(search by content)
1214 * If there is an event with byte sequence matching the specified bytes from the beginning
1215 * in the message event queue of the specified ID,it is gotten and deleted from the queue.
1216 * If there are no such messages,
1217 * EV_NO_ID is stored in message->queue_id, and the system call returns immediately.
1219 * @param queue_id [IN] Message event queue ID
1220 * @param bytes [IN] Bytes to compare
1221 * @param compare_bytes [IN] Byte sequence to compare content against
1222 * @param message [OUT] Message Event Structure
1224 * @retval EV_OK: Normal completion
1225 * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist
1226 * Or not a message event queue created by invoking process
1227 * @retval Otherwise: FATAL error
1230 EV_find_message_by_content(EV_ID queue_id,
1231 UINT16 bytes, const void *compare_bytes,
1232 EV_Message *message) {
1233 EV_assert(message != NULL);
1234 EV_assert(bytes <= EV_MAX_MESSAGE_LENGTH);
1235 EV_assert(compare_bytes != NULL);
1237 return EV_get_message_in(queue_id, message, 0, bytes,
1238 compare_bytes, 0, 0);
1241 /** @brief Set flag event
1243 * Set the flag with the specified ID.
1245 * @param queue_id [IN] Flag ID
1246 * @param bits [IN] Flag bit-pattern
1248 * @retval EV_OK: Normal completion
1249 * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist.
1250 * @retval Otherwise: FATAL error
1253 EV_set_flag(EV_ID flag_id, UINT32 bits) {
1254 if (!EV_ID_IS_FLAG(flag_id)) {
1255 EV_DEBUG_ERR("set_flag: %x is not a valid flag_id.\n", flag_id);
1256 return EV_ERR_Invalid_ID;
1259 int fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
1263 flag.flagID = flag_id;
1266 int ret = ioctl(fd, EVK_IOC_STORE_FLAG, &flag);
1267 int myerrno = errno;
1271 if (myerrno == ENOENT) {
1272 EV_DEBUG_WARNING("set_flag: No such flag_id %x.\n", flag_id);
1273 return EV_ERR_Invalid_ID;
1276 EV_perror("set flag");
1277 return EV_ERR_Fatal;
1282 /** @brief Set 64bit flag event
1284 * Set the flag with the specified ID.
1286 * @param queue_id [IN] Flag ID
1287 * @param bits [IN] Bit pattern of 64-bit flag
1289 * @retval EV_OK: Normal completion
1290 * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist.
1291 * @retval Otherwise: FATAL error
1294 EV_set_flag64(EV_ID flag_id, UINT64 bits) {
1295 if (!EV_ID_IS_FLAG64(flag_id)) {
1296 EV_DEBUG_ERR("set_flag: %x is not a valid flag_id.\n", flag_id);
1297 return EV_ERR_Invalid_ID;
1300 int fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
1304 flag.flagID = flag_id;
1307 int ret = ioctl(fd, EVK_IOC_STORE_FLAG64, &flag);
1308 int myerrno = errno;
1312 if (myerrno == ENOENT) {
1313 EV_DEBUG_ERR("set_flag: No such flag_id %x.\n", flag_id);
1314 return EV_ERR_Invalid_ID;
1318 EV_perror("set flag");
1319 return EV_ERR_Fatal;
1325 /** @brief Send Messaging Event
1327 * Send a message event to the specified queue ID.
1329 * @param queue_id [IN] Queue ID
1330 * @param bytes [IN] Bytes to send
1331 * @param buf [IN] Pointer to the byte sequence to send
1332 * @param senderInfo [IN] Source info
1333 * Specify this option to identify applications, etc.
1334 * When not used, specify 0.
1336 * @retval EV_OK: Normal completion
1337 * @retval EV_ERR_Invalid_ID: Message event queue with specified ID does not exist
1338 * @retval EV_ERR_Busy: Queue overflow
1339 * @retval Otherwise: FATAL error
1342 EV_send_message(EV_ID queue_id, UINT16 bytes, const void *buf, UINT32 senderInfo) {
1343 EV_assert(buf != NULL);
1344 EV_assert(bytes <= EV_MAX_MESSAGE_LENGTH);
1345 if (!EV_ID_IS_QUEUE(queue_id)) {
1346 EV_DEBUG_ERR("send_message: %x is not a valid queue_id.\n", queue_id);
1347 return EV_ERR_Invalid_ID;
1352 * Open fd at the first time of send_message in process,
1353 * and continue to use the fd with it open after that.
1355 * - Prevent frequent use of open/close system calls.
1356 * - If the process is nonresident, the fd is close after the process is terminated.
1357 * - Even for resident processes, there is no problem because processes
1358 * that use event library normally continue to use event library
1359 * from the beginning to the end.
1362 EV_PROCESS_MUTEX_LOCK;
1364 fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
1365 if (fd < 0) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function open
1366 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
1368 EV_PROCESS_MUTEX_UNLOCK; // LCOV_EXCL_LINE 5: fail safe for glibc function open
1369 return EV_ERR_Fatal; // LCOV_EXCL_LINE 5: fail safe for glibc function open
1371 fcntl(fd, F_SETFD, FD_CLOEXEC|(fcntl(fd, F_GETFD, 0)));
1375 msg.queueID = queue_id;
1376 msg.senderInfo = senderInfo;
1378 memcpy(msg.message, buf, bytes);
1380 int ret = ioctl(fd, EVK_IOC_STORE_MESSAGE, &msg);
1381 int myerrno = errno;
1382 EV_PROCESS_MUTEX_UNLOCK;
1385 if (myerrno == ENOENT) {
1386 EV_DEBUG_WARNING("send_message: No such queue_id %x.\n", queue_id);
1387 return EV_ERR_Invalid_ID;
1388 } else if (myerrno == EBUSY) {
1389 EV_DEBUG_WARNING("send_message: queue_id %x returned BUSY.\n", queue_id);
1394 EV_perror("send message");
1395 return EV_ERR_Fatal;
1401 /** @brief Get fd for poll flag event
1403 * Get file descriptor (FD) that used to wait for a flag
1404 * with the specified ID in a poll/select.
1405 * Only flags created by invoked process can be specified.
1407 * This FD can only be used to specify a poll/select.
1408 * Subsequent operations are not guaranteed if any other operations are performed.
1409 * When use poll, only POLLIN can be specified in events.
1410 * When use select, you can only check if it is readable.
1412 * If the same flag_id is called more than once,
1413 * The same FD is returned each time (unless there is a destroy/create during that time).
1415 * - differences in kernel versions
1416 * - This API is not provided in the EVK.
1418 * @note If the flag is deleted during poll/select using the FD gotten by the API,
1419 * the poll/select is exited.
1420 * POLLERR is set as event for poll.
1422 * @param flag_id [IN] Flag ID
1423 * @param fd [OUT] Pointer to the area to store the file descriptor
1425 * @retval EV_OK: Normal completion
1426 * @retval EV_ERR_Invalid_ID: An invalid flag ID was specified.
1427 * @retval Otherwise: FATAL error
1430 EV_get_flag_fd(EV_ID flag_id, int *fd) {
1431 EV_assert(fd != NULL);
1433 if ((!EV_ID_IS_FLAG(flag_id))&& (!EV_ID_IS_FLAG64(flag_id))) {
1434 EV_DEBUG_ERR("get_flag_fd: %x is not a valid flag_id.\n", flag_id);
1435 return EV_ERR_Invalid_ID;
1438 *fd = find_ev_info(EV_SEARCH_ALL_THREAD, flag_id);
1440 EV_DEBUG_ERR("You have not created flag_id %x.\n", flag_id);
1441 return EV_ERR_Invalid_ID;
1447 /** @brief Get fd for message event queue poll
1449 * Get file descriptor (FD) that used to wait for a queue
1450 * with the specified ID in a poll/select.
1451 * Only message event queues created by invoked process can be specified.
1453 * This FD can only be used to specify a poll/select.
1454 * Subsequent operations are not guaranteed if any other operations are performed.
1455 * When use poll, only POLLIN can be specified in events.
1456 * When use select, you can only check if it is readable.
1458 * If the same queue_id is called more than once,
1459 * The same FD is returned each time (unless there is a destroy/create during that time).
1461 * - differences in kernel versions
1462 * - This API is not provided in the EVK.
1464 * @note If the queue is deleted during poll/select using the FD gotten by the API,
1465 * the poll/select is exited.
1466 * POLLERR is set as event for poll.
1468 * @param queue_id [IN] Message event queue ID
1469 * @param fd [OUT] Pointer to the area to store the file descriptor
1471 * @retval EV_OK: Normal completion
1472 * @retval EV_ERR_Invalid_ID: An invalid flag ID was specified.
1473 * @retval Otherwise: FATAL error
1476 EV_get_queue_fd(EV_ID queue_id, int *fd) {
1477 EV_assert(fd != NULL);
1479 if (!EV_ID_IS_QUEUE(queue_id)) {
1480 EV_DEBUG_ERR("get_queue_fd: %x is not a valid queue_id.\n",
1482 return EV_ERR_Invalid_ID;
1485 *fd = find_ev_info(EV_SEARCH_ALL_THREAD, queue_id);
1487 EV_DEBUG_ERR("You have not created queue_id %x.\n", queue_id);
1488 return EV_ERR_Invalid_ID;
1493 /* \~english Functions that specify the module ID (16 bits) instead of the flag ID and queue ID */
1494 EV_ID EV_moduleID_to_flagID(UINT16 mID)
1496 return EV_Flag_ID_Base(mID);
1499 EV_ID EV_moduleID_to_flag64ID(UINT16 mID)
1501 return EV_Flag64_ID_Base(mID);
1504 EV_ID EV_moduleID_to_queueID(UINT16 mID)
1506 return EV_Queue_ID_Base(mID);
1509 EV_ERR EV_create_flag_by_mID(UINT16 mID)
1511 return EV_create_flag(EV_moduleID_to_flagID(mID));
1514 EV_ERR EV_create_flag64_by_mID(UINT16 mID)
1516 return EV_create_flag64(EV_moduleID_to_flag64ID(mID));
1519 EV_ERR EV_create_queue_by_mID(UINT16 mID, UINT8 length,UINT16 max_bytes,
1520 EV_Message_Queue_Type type)
1522 return EV_create_queue(EV_moduleID_to_queueID(mID), length, max_bytes, type);
1525 EV_ERR EV_destroy_flag_by_mID(UINT16 mID)
1527 return EV_destroy_flag(EV_moduleID_to_flagID(mID));
1530 EV_ERR EV_destroy_queue_by_mID(UINT16 mID)
1532 return EV_destroy_queue(EV_moduleID_to_queueID(mID));
1535 EV_ERR EV_set_flag_by_mID(UINT16 mID, UINT32 bits)
1537 return EV_set_flag(EV_moduleID_to_flagID(mID), bits);
1540 EV_ERR EV_set_flag64_by_mID(UINT16 mID, UINT64 bits)
1542 return EV_set_flag64(EV_moduleID_to_flag64ID(mID), bits);
1545 EV_ERR EV_send_message_by_mID(UINT16 mID, UINT16 bytes, const void *message,
1548 return EV_send_message(EV_moduleID_to_queueID(mID),
1549 bytes, message, senderInfo);