Re-organized sub-directory by category
[staging/basesystem.git] / service / other / event_library / library / src / ev_lib.c
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * @file ev_lib.c
19  * @brief Events Library -- Implementing API Functions
20  */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/ioctl.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <pthread.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>
33 #include <assert.h>
34 #define EV_perror perror
35 #define EV_assert assert
36
37 /*
38  * Not use dbg_output in the EV so that the DTV apps and semiconductor vendor use this function.
39  */
40 #define ev_log(format, arg...) \
41 { \
42   { \
43     char procname[33]; \
44     prctl(PR_GET_NAME, procname); \
45     int pid = getpid(); \
46     printf(format, procname, pid, ##arg); \
47   } \
48 }
49
50 #define EV_DEBUG_INFO(format, arg...) \
51 { \
52   if (getenv("EV_DEBUG") != NULL) { \
53     ev_log("[EV: info](%s:%d) " format, ##arg); \
54   } \
55 }
56
57 #define EV_DEBUG_WARNING(format, arg...) \
58 { \
59   ev_log("[EV: warning](%s:%d) " format, ##arg); \
60 }
61
62 #define EV_DEBUG_ERR(format, arg...) \
63 { \
64   ev_log("[EV: ERR](%s:%d) " format, ##arg); \
65 }
66
67 /** @brief Structures for managing ID and FD in use by processes
68  */
69 typedef struct {
70     EV_ID id; /**< flag/queue ID */
71     INT32 fd; /**< file descriptor */
72 }
73 EV_Info;
74
75 /*----------------------------------------*/
76 /** @brief EV management information table per thread */
77 /*----------------------------------------*/
78 typedef struct {
79     /** Thread calling the EV library */
80     pthread_t    thread;
81     /** Registration information by ID */
82     EV_Info      ev_info[EV_MAX_IDS_IN_THREAD];
83     /** Number of registered IDs */
84     UINT8        num;
85 }
86 EV_thread_info_type;
87
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
92
93 /* Related process exclusion control in the process  */
94 const char *g_ev_lock_func;
95 int g_ev_lock_line;
96 int g_ev_lock_pid;
97 pthread_mutex_t g_ev_process_global_mutex = PTHREAD_MUTEX_INITIALIZER;
98
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);
106
107 /** @mainpage
108  * This document describes the following specifications:
109  * - Event Library (EV) API specifications
110  * - Event ID specifications
111  *
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".
115  */
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
122  * @{ */
123
124 /** EV thread information management table */
125 EV_thread_info_type  *EV_thread_info[EV_MAX_THREADS_IN_PROCESS];
126
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  ----------------------------------------------------------------------*/
134 EV_ERR
135 EV_thread_id_check(int *index, int flag) {
136   int i, empty;
137
138   /* Current threadID */
139   pthread_t EV_self_thread_id;
140
141   /* Get thread ID */
142   EV_self_thread_id = pthread_self();
143
144   /* Control-process lock */
145   EV_PROCESS_MUTEX_LOCK;
146
147   /* Whether or not the thread has already been registered. */
148   for(i = 0, empty = -1; i < EV_MAX_THREADS_IN_PROCESS; i++) {
149     /* Free space */
150     if(EV_thread_info[i] == NULL) {
151       /* Set free space index */
152       empty = (empty == -1) ? i: empty;
153       continue;
154     }
155
156     if(EV_thread_info[i]->thread == EV_self_thread_id) {
157       *index = i;
158
159       /* Cancel in-process mutual exclusion */
160       EV_PROCESS_MUTEX_UNLOCK;
161       return EV_OK;
162     }
163   }
164
165   if(flag == EV_THREAD_INFO_PEEK) {
166     EV_DEBUG_ERR("thread id is not found.\n");
167
168     /* Cancel in-process mutual exclusion */
169     EV_PROCESS_MUTEX_UNLOCK;
170     return EV_ERR_Invalid_Thread;
171   }
172
173   /* If there are no unregistered threads and there is no space */
174   if(empty == -1) {
175     EV_DEBUG_ERR("thread id is full.\n");
176
177     /* Cancel in-process mutual exclusion */
178     EV_PROCESS_MUTEX_UNLOCK;
179     return EV_ERR_Thread_Over;
180   }
181
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];
185
186   /* malloc failed */
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
190
191     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
192
193     EV_PROCESS_MUTEX_UNLOCK;
194     return EV_ERR_Fatal;
195   }
196   // LCOV_EXCL_STOP
197
198   /* Initialization */
199   memset(th, '\0', sizeof(*th));
200   th->thread = EV_self_thread_id;
201   /* th->num = 0; */
202
203   /* Cancel in-process mutual exclusion */
204   EV_PROCESS_MUTEX_UNLOCK;
205
206   /* Set registration position */
207   *index = empty;
208
209   return EV_OK;
210 }
211
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.
216 static void
217 free_thread_buffer(int th_index) {
218   /* in-process mutual exclusion */
219   EV_PROCESS_MUTEX_LOCK;
220   if ((th_index >= 0)
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);
227   }
228   /* in-process mutual exclusion */
229   EV_PROCESS_MUTEX_UNLOCK;
230 }
231
232 /* EV_info update function */
233 static void
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;
238
239   int id_index = EV_thread_info[th_index]->num;
240   EV_assert(id_index < EV_MAX_IDS_IN_THREAD);
241
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++;
246
247   /* end of in-process mutual exclusion */
248   EV_PROCESS_MUTEX_UNLOCK;
249 }
250
251 /* EV_info search function */
252 static int
253 find_ev_info(int th_index, EV_ID id) {
254   int i, j, start, end;
255   int ret = -1;
256
257   /* Search all threads */
258   if(th_index == EV_SEARCH_ALL_THREAD) {
259     start = 0;
260     end = EV_MAX_THREADS_IN_PROCESS;
261   } else {
262     start = th_index;
263     end = th_index + 1;
264   }
265
266   /* in-process mutual exclusion */
267   EV_PROCESS_MUTEX_LOCK;
268
269   for(j = start; j < end; j++) {
270     if(EV_thread_info[j] == NULL) {
271       continue;
272     }
273
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;
277         break;
278       }
279     }
280   }
281
282   /* Cancel in-process mutual exclusion */
283   EV_PROCESS_MUTEX_UNLOCK;
284
285   return ret;
286 }
287
288 static int
289 delete_ev_info(EV_ID id) {
290   int fd = -1;
291   int i, j;
292   int found_th_index = -1;
293   int found_idx = -1;
294   EV_thread_info_type *th = NULL;
295
296   /* beginning of in-thread mutual exclusion */
297   EV_PROCESS_MUTEX_LOCK;
298
299   for(i = 0 ; i < EV_MAX_THREADS_IN_PROCESS && found_idx == -1 ; i++) {
300     th = EV_thread_info[i];
301     if (th == NULL) {
302       continue;
303     }
304     for(j = 0 ; j < th->num ; j++) {
305       if (th->ev_info[j].id == id) {
306       fd = th->ev_info[j].fd;
307       found_th_index = i;
308       found_idx = j;
309       break;
310       }
311     }
312   }
313
314   if(found_idx == -1) {
315     EV_PROCESS_MUTEX_UNLOCK;
316     return -1;
317   }
318
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));
322   }
323   th->num--;
324
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;
329   }
330   EV_PROCESS_MUTEX_UNLOCK;
331   return fd;
332 }
333
334 /** @} */
335 /** @addtogroup EV
336  * @{ */
337
338 static EV_ERR
339 EV_create_flag_in(int th_index, EV_ID flag_id, int is64bit) {
340   int fd;
341
342   /* Open device driver */
343   fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
344   EV_assert(fd >= 0);
345
346   int ret = ioctl(fd, is64bit ? EVK_IOC_CREATE_FLAG64:
347         EVK_IOC_CREATE_FLAG, flag_id);
348   int myerrno = errno;
349
350   if(ret < 0) {
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
353
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
357     } else {
358       close(fd);
359       errno = myerrno;
360       return EV_ERR_Fatal;
361     }
362   }
363
364   ret = ioctl(fd, EVK_IOC_SET_POLL, flag_id);
365   if(ret < 0) {
366     close(fd);
367     EV_DEBUG_ERR("set_poll: internal error\n");
368     return EV_ERR_Fatal;
369   }
370
371   add_ev_info(th_index, flag_id, fd);
372   return EV_OK;
373 }
374
375 /** @brief Create flag
376  *
377  * Create a flag with the given ID.
378  * Return error if a flag with the same flag ID already exists
379  *
380  * @param flag_id [IN]flag ID
381  * @see EV_ID
382  *
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
387  */
388 EV_ERR
389 EV_create_flag (EV_ID flag_id) {
390   EV_ERR err;
391   int th_index;
392
393   /* Flag ID check */
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;
397   }
398
399   /* Thread information check */
400   err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
401   if(err != EV_OK) {
402     return err;
403   }
404
405   EV_DEBUG_INFO("EV_create_flag (th_index=%d)\n", th_index);
406
407   /* case of already created */
408   int fd = find_ev_info(th_index, flag_id);
409   if(fd >= 0) {
410     EV_DEBUG_ERR("create_flag: You already created flag_id %x.\n", flag_id);
411     return EV_ERR_Exist;
412   }
413
414   err = EV_create_flag_in(th_index, flag_id, 0);
415   if (EV_OK != err) {
416     free_thread_buffer(th_index);
417   }
418
419   return err;
420 }
421
422 /** @brief Create 64-bit flag
423  *
424  * Create a 64-bit flag with the given ID.
425  * Return error if a flag with the same flag ID already exists
426  *
427  * @param flag_id [IN]64-bit flag ID
428  * @see EV_ID
429  *
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
434  */
435 EV_ERR
436 EV_create_flag64(EV_ID flag_id) {
437   EV_ERR err;
438   int th_index;
439
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;
443   }
444
445   /* Thread information check */
446   err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
447   if(err != EV_OK) {
448     return err;
449   }
450
451   int fd = find_ev_info(th_index, flag_id);
452   if(fd >= 0) {
453     EV_DEBUG_ERR("create_flag: You already created flag_id %x.\n", flag_id);
454     return EV_ERR_Exist;
455   }
456
457   err =  EV_create_flag_in(th_index, flag_id, 1);
458   if (EV_OK != err) {
459     free_thread_buffer(th_index);
460   }
461
462   return err;
463 }
464
465 /** @brief Create flag (auto-assign ID)
466  *
467  * Automatically assign a flag ID and creates a flag.
468  * Same as EV_create_flag(), except that ID is automatically assigned.
469  *
470  * @param flag_id [OUT]Area for storing the assigned flag ID
471  *
472  * @see EV_create_flag
473  */
474 EV_ERR
475 EV_create_flag_auto_id(EV_ID *flag_id) {
476   EV_assert(flag_id != NULL);
477
478   EV_ERR err;
479   int fd, th_index;
480   fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
481   EV_assert(fd >= 0);
482
483   int ret = ioctl(fd, EVK_IOC_ALLOC_FLAG_ID, flag_id);
484   close(fd);
485   EV_assert(ret == 0);
486
487   /* Thread information check */
488   err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
489   if(err != EV_OK) {
490     *flag_id = EV_NO_ID;
491     return err;
492   }
493
494   err = EV_create_flag_in(th_index, *flag_id, 0);
495   if (err != EV_OK) {
496     free_thread_buffer(th_index);
497
498     *flag_id = EV_NO_ID;
499     return EV_ERR_Fatal;
500   }
501   return EV_OK;
502 }
503
504 /** @brief Create 64-bit flag(auto-assign ID)
505  *
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.
508  *
509  * @param flag_id [OUT]Area for storing the assigned 64-bit flag ID
510  *
511  * @see EV_create_flag64
512  */
513 EV_ERR
514 EV_create_flag64_auto_id(EV_ID *flag_id) {
515   EV_assert(flag_id != NULL);
516
517   EV_ERR err;
518   int fd, th_index;
519   fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
520   EV_assert(fd >= 0);
521
522   int ret = ioctl(fd, EVK_IOC_ALLOC_FLAG64_ID, flag_id);
523   close(fd);
524   EV_assert(ret == 0);
525
526   /* Thread information check */
527   err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
528   if(err != EV_OK) {
529     *flag_id = EV_NO_ID;
530     return err;
531   }
532
533   err = EV_create_flag_in(th_index, *flag_id, 1);
534   if (err != EV_OK) {
535     free_thread_buffer(th_index);
536
537     *flag_id = EV_NO_ID;
538     return EV_ERR_Fatal;
539   }
540   return EV_OK;
541 }
542
543 static EV_ERR
544 EV_create_queue_in(int th_index, EV_ID queue_id, UINT8 length,
545   UINT16 max_bytes, EV_Message_Queue_Type type) {
546   int fd;
547   fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
548   EV_assert(fd >= 0);
549
550   EVK_Message_Queue_Request req;
551   req.queueID = queue_id;
552   req.length = length;
553   req.max_bytes = max_bytes;
554   req.type = type;
555
556   int ret = ioctl(fd, EVK_IOC_CREATE_MESSAGE_QUEUE, &req);
557   int myerrno = errno;
558   if (ret < 0) {
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
561
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
565     } else {
566       close(fd);
567       errno = myerrno;
568       //EV_perror("create queue");
569       return EV_ERR_Fatal;
570     }
571   }
572
573   ret = ioctl(fd, EVK_IOC_SET_POLL, queue_id);
574   if (ret < 0) {
575     close(fd);
576     EV_DEBUG_ERR("set_poll: internal error\n");
577     return EV_ERR_Fatal;
578   }
579
580   add_ev_info(th_index, queue_id, fd);
581   return EV_OK;
582 }
583
584 /** @brief message event queue creation
585  *
586  * Create a queue of message event with the specified ID.
587  * Return error if a queue with the same ID already exists.
588  *
589  * A memory area corresponding to the specified maximum number of bytes x queue length is allocated dynamically.
590  *
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
595  * @see EV_ID
596  * @see ev_message_queue_type
597  *
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
602  */
603 EV_ERR
604 EV_create_queue(EV_ID queue_id, UINT8 length, UINT16 max_bytes,
605     EV_Message_Queue_Type type) {
606     EV_ERR err;
607     int th_index;
608
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",
611         queue_id);
612     return EV_ERR_Invalid_ID;
613   }
614
615   /* Thread information check */
616   err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
617   if(err != EV_OK) {
618     return err;
619   }
620
621   int fd = find_ev_info(th_index, queue_id);
622   if(fd >= 0) {
623     EV_DEBUG_ERR("create_queue: You already created queue_id %x.\n",
624         queue_id);
625     return EV_ERR_Exist;
626   }
627
628   err = EV_create_queue_in(th_index, queue_id, length, max_bytes, type);
629   if (EV_OK != err) {
630     free_thread_buffer(th_index);
631   }
632
633   return err;
634 }
635
636 /** @brief message event queue creation(auto-assign ID)
637  *
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.
640  *
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
645  *
646  * @see EV_create_queue
647  */
648 EV_ERR
649 EV_create_queue_auto_id(EV_ID *queue_id, UINT8 length, UINT16 max_bytes,
650       EV_Message_Queue_Type type) {
651       int th_index;
652
653   EV_assert(queue_id != NULL);
654   EV_ERR err;
655   int fd;
656   fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
657   EV_assert(fd >= 0);
658
659   int ret = ioctl(fd, EVK_IOC_ALLOC_QUEUE_ID, queue_id);
660   close(fd);
661   EV_assert(ret == 0);
662
663   /* Thread information check */
664   err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE);
665   if(err != EV_OK) {
666     *queue_id = EV_NO_ID;
667     return err;
668   }
669
670   err = EV_create_queue_in(th_index, *queue_id, length, max_bytes,
671           type);
672   if (err != EV_OK) {
673     free_thread_buffer(th_index);
674
675     *queue_id = EV_NO_ID;
676     return EV_ERR_Fatal;
677   }
678   return EV_OK;
679 }
680
681 /** @brief Deleting flag event
682  *
683  * Delete the flag with the specified ID.
684  * Only flags created by this process can be deleted.
685  *
686  * - differences in kernel versions
687  * EVK_destroy_flag can be used to delete any existing message event queue.
688  *
689  * @note The program wakes up that waiting for this queue (poll or wait) 
690  * due to deletion.
691  *
692  * @param flag_id [IN] ID of flag
693  *
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
698  */
699 EV_ERR
700 EV_destroy_flag(EV_ID flag_id) {
701   int fd = delete_ev_info(flag_id);
702   if (fd < 0) {
703     EV_DEBUG_ERR("You haven't created flag/queue_id %x.\n", flag_id);
704     return EV_ERR_Invalid_ID;
705   }
706
707   int ret = ioctl(fd, EVK_IOC_DESTROY_QUEUE, flag_id);
708   int myerrno = errno;
709   close(fd);
710   if (ret < 0) {
711     if (myerrno == ENOENT) {
712       EV_DEBUG_ERR("destroy: no such ID %x\n", flag_id);
713       return EV_ERR_Invalid_ID;
714     } else {
715       errno = myerrno;
716       EV_perror("destroy");
717       return EV_ERR_Fatal;
718     }
719   }
720   return EV_OK;
721 }
722
723 /** @brief Delete message event queue
724  *
725  * Delete the message event queue with the specified ID.
726  * Only message event queues created by this process can be deleted.
727  *
728  * - differences in kernel versions
729  * EVK_destroy_queue can be used to delete any existing message event queue.
730  *
731  * @note The program wakes up that waiting for this queue (poll or wait) 
732  * due to deletion.
733  *
734  * @param flag_id [IN] Message event queue ID
735  *
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
740  */
741 EV_ERR
742 EV_destroy_queue(EV_ID queue_id) {
743   return EV_destroy_flag(queue_id);
744 }
745
746 static EV_ERR
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;
750   flag->bits = 0;
751
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;
755   }
756
757   int fd = find_ev_info(EV_SEARCH_ALL_THREAD, flag_id);
758   if(fd < 0) {
759     EV_DEBUG_ERR("You have not created flag_id %x.\n", flag_id);
760     return EV_ERR_Invalid_ID;
761   }
762
763   EV_Event ev;
764   ev.type = EV_EVENT_Flag;
765   ev.u.flag.flagID = flag_id;
766   ev.u.flag.bits = 0;
767   int ret = ioctl(
768     fd,
769     (peek_only ? EVK_IOC_PEEK_EVENT : (wait ? EVK_IOC_WAIT_EVENT : EVK_IOC_GET_EVENT)),
770     &ev);
771
772   int myerrno = errno;
773   if (ret < 0) {
774     if (myerrno == ENOENT) {
775       EV_DEBUG_ERR("get_flag: No such flag_id %x.\n", flag_id);
776       return EV_ERR_Invalid_ID;
777     }
778     else if (myerrno == EINTR) {
779       EV_DEBUG_ERR("get_flag: Interrupted\n");
780       return EV_ERR_Interrupted;
781     } else {
782       errno = myerrno;
783       EV_perror("get flag");
784       return EV_ERR_Fatal;
785     }
786   }
787
788   if (ev.type == EV_EVENT_Flag) {
789     flag->flagID = ev.u.flag.flagID;
790     flag->bits = ev.u.flag.bits;
791   }
792   return EV_OK;
793 }
794
795 static EV_ERR
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;
799   flag->bits = 0;
800
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;
804   }
805
806   int fd = find_ev_info(EV_SEARCH_ALL_THREAD, flag_id);
807   if (fd < 0) {
808     EV_DEBUG_ERR("You have not created flag_id %x.\n", flag_id);
809     return EV_ERR_Invalid_ID;
810   }
811
812   EV_Event ev;
813   ev.type = EV_EVENT_Flag64;
814   ev.u.flag64.flagID = flag_id;
815   ev.u.flag64.bits = 0;
816   int ret = ioctl(
817     fd,
818     (peek_only ? EVK_IOC_PEEK_EVENT : (wait ? EVK_IOC_WAIT_EVENT : EVK_IOC_GET_EVENT)),
819     &ev);
820
821   int myerrno = errno;
822   if (ret < 0) {
823     if (myerrno == ENOENT) {
824       EV_DEBUG_ERR("get_flag: No such flag_id %x.\n", flag_id);
825       return EV_ERR_Invalid_ID;
826     }
827     else if (myerrno == EINTR) {
828       EV_DEBUG_ERR("get_flag: Interrupted\n");
829       return EV_ERR_Interrupted;
830     } else {
831       errno = myerrno;
832       EV_perror("get flag");
833       return EV_ERR_Fatal;
834     }
835   }
836
837   if (ev.type == EV_EVENT_Flag64) {
838     flag->flagID = ev.u.flag64.flagID;
839     flag->bits = ev.u.flag64.bits;
840   }
841   return EV_OK;
842 }
843
844 /** @brief Get flag event(non-block)
845  *
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.
851  *
852  * @param flag_id [IN] Message event queue ID
853  * @param flag [OUT] Flag Structure
854  *
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
859  */
860 EV_ERR
861 EV_get_flag(EV_ID flag_id, EV_Flag *flag) {
862   return EV_get_flag_in(flag_id, flag, 0, 0);
863 }
864
865 /** @brief Get 64bit flag event(non-block)
866  *
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.
873  *
874  * @param flag_id [IN] Message event queue ID
875  * @param flag [OUT] 64-bit flag struct
876  *
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
881  */
882 EV_ERR
883 EV_get_flag64(EV_ID flag_id, EV_Flag64 *flag) {
884   return EV_get_flag64_in(flag_id, flag, 0, 0);
885 }
886
887 /** @brief Get flag event(block)
888  *
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.
896  *
897  * @param flag_id [IN] Message event queue ID
898  * @param flag [OUT] Flag Structure
899  *
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
905  */
906 EV_ERR
907 EV_wait_flag(EV_ID flag_id, EV_Flag *flag) {
908   return EV_get_flag_in(flag_id, flag, 0, 1);
909 }
910
911 /** @brief Get 64bit flag event(block)
912  *
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.
921  *
922  * @param flag_id [IN] Message event queue ID
923  * @param flag [OUT] 64-bit flag structure
924  *
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
930  */
931 EV_ERR
932 EV_wait_flag64(EV_ID flag_id, EV_Flag64 *flag) {
933   return EV_get_flag64_in(flag_id, flag, 0, 1);
934 }
935
936 /** @brief Get flag event(non-destructive)
937  *
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.
942  *
943  * @param flag_id [IN] Message event queue ID
944  * @param flag [OUT] Flag Structure
945  *
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
950  */
951 EV_ERR
952 EV_peek_flag(EV_ID flag_id, EV_Flag *flag) {
953   return EV_get_flag_in(flag_id, flag, 1, 0);
954 }
955
956 /** @brief Get 64bit flag event(non-destructive)
957  *
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.
962  *
963  * @param flag_id [IN] Message event queue ID
964  * @param flag [OUT] 64-bit flag structure
965  *
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
970  */
971 EV_ERR
972 EV_peek_flag64(EV_ID flag_id, EV_Flag64 *flag) {
973   return EV_get_flag64_in(flag_id, flag, 1, 0);
974 }
975
976 static EV_ERR
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;
983   message->length = 0;
984
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;
988   }
989
990   int fd = find_ev_info(EV_SEARCH_ALL_THREAD, queue_id);
991   if(fd < 0) {
992     EV_DEBUG_ERR("You have not created queue_id %x.\n", queue_id);
993     return EV_ERR_Invalid_ID;
994   }
995
996   EV_Event ev;
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);
1003   } else {
1004     ev.u.message.length = 0;
1005   }
1006
1007   int ret = ioctl(
1008     fd,
1009     (peek_only ? EVK_IOC_PEEK_EVENT : (wait ? EVK_IOC_WAIT_EVENT : EVK_IOC_GET_EVENT)),
1010     &ev);
1011
1012   int myerrno = errno;
1013   if (ret < 0) {
1014     if (myerrno == ENOENT) {
1015       EV_DEBUG_ERR("No such queue_id %x\n", queue_id);
1016       return EV_ERR_Invalid_ID;
1017     }
1018     else if (myerrno == EINTR) {
1019       EV_DEBUG_INFO("Interrupted.\n");
1020       return EV_ERR_Interrupted;
1021     } else {
1022       errno = myerrno;
1023       EV_perror("get message");
1024       return EV_ERR_Fatal;
1025     }
1026   }
1027
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);
1034   }
1035
1036   return EV_OK;
1037 }
1038
1039 /** @brief Get message events(non-block)
1040  *
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.
1045  *
1046  * @param queue_id [IN] Message event queue ID
1047  * @param message [OUT] Message Event Structure
1048  *
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
1053  */
1054 EV_ERR
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);
1057 }
1058
1059 /** @brief Get message event(block)
1060  *
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.
1067  *
1068  * @param queue_id [IN] Message event queue ID
1069  * @param message [OUT] Message Event Structure
1070  *
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
1076  */
1077 EV_ERR
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);
1080 }
1081
1082 /** @brief Get message event(non-destructive)
1083  *
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.
1088  *
1089  * @param queue_id [IN] Message event queue ID
1090  * @param message [OUT] Message Event Structure
1091  *
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
1096  */
1097 EV_ERR
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);
1100 }
1101
1102 static EV_ERR
1103 EV_get_next_event_in(EV_Event *ev, int peek_only) {
1104   int i, th_index;
1105   EV_ERR err;
1106   EVK_Next_Event_Query query;
1107
1108   EV_assert(ev != NULL);
1109   ev->type = EV_EVENT_None;
1110
1111   bzero(&query, sizeof(query));
1112
1113   err = EV_thread_id_check(&th_index, EV_THREAD_INFO_PEEK);
1114   if(err != EV_OK) {
1115     return err;
1116   }
1117
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;
1122   }
1123   EV_PROCESS_MUTEX_UNLOCK;
1124
1125   if (query.num == 0) {
1126     return EV_OK;
1127   }
1128
1129   int fd;
1130   fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
1131   EV_assert(fd >= 0);
1132
1133   int ret = ioctl(
1134     fd,
1135     (peek_only ? EVK_IOC_PEEK_NEXT_EVENT: EVK_IOC_GET_NEXT_EVENT),
1136     &query);
1137
1138   int myerrno = errno;
1139   close(fd);
1140
1141   if (ret < 0) {
1142     errno = myerrno;
1143     EV_perror("get_next_event");
1144     return EV_ERR_Fatal;
1145   }
1146   memcpy(ev, &(query.ev), sizeof(*ev));
1147   return EV_OK;
1148 }
1149
1150 /** @brief Get the first event that arrived(non-block)
1151  *
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.
1155  *
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.
1159  *
1160  * @retval EV_OK: Normal completion
1161  * @retval Otherwise: FATAL error
1162  */
1163 EV_ERR
1164 EV_get_next_event(EV_Event *ev) {
1165   return EV_get_next_event_in(ev, 0);
1166 }
1167
1168 /** @brief Get the first event that arrived(non-destructive)
1169  *
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.
1175  *
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.
1179  *
1180  * @retval EV_OK: Normal completion
1181  * @retval Otherwise: FATAL error
1182  */
1183 EV_ERR
1184 EV_peek_next_event(EV_Event *ev) {
1185   return EV_get_next_event_in(ev, 1);
1186 }
1187
1188 /** @brief Get message event(search by source info)
1189  *
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.
1194  *
1195  * @param queue_id [IN] Message event queue ID
1196  * @param senderInfo [IN] Source Info
1197  * @param message [OUT] Message Event Structure
1198  *
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
1203  */
1204 EV_ERR
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);
1210 }
1211
1212 /** @brief Get message event(search by content)
1213  *
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.
1218  *
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
1223  *
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
1228  */
1229 EV_ERR
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);
1236
1237   return EV_get_message_in(queue_id, message, 0, bytes,
1238           compare_bytes, 0, 0);
1239 }
1240
1241 /** @brief Set flag event
1242  *
1243  * Set the flag with the specified ID.
1244  *
1245  * @param queue_id [IN] Flag ID
1246  * @param bits [IN] Flag bit-pattern
1247  *
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
1251  */
1252 EV_ERR
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;
1257   }
1258
1259   int fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
1260   EV_assert(fd >= 0);
1261
1262   EV_Flag flag;
1263   flag.flagID = flag_id;
1264   flag.bits = bits;
1265
1266   int ret = ioctl(fd, EVK_IOC_STORE_FLAG, &flag);
1267   int myerrno = errno;
1268   close(fd);
1269
1270   if (ret < 0) {
1271     if (myerrno == ENOENT) {
1272       EV_DEBUG_WARNING("set_flag: No such flag_id %x.\n", flag_id);
1273       return EV_ERR_Invalid_ID;
1274     }
1275     errno = myerrno;
1276     EV_perror("set flag");
1277     return EV_ERR_Fatal;
1278   }
1279   return EV_OK;
1280 }
1281
1282 /** @brief Set 64bit flag event
1283  *
1284  * Set the flag with the specified ID.
1285  *
1286  * @param queue_id [IN] Flag ID
1287  * @param bits [IN] Bit pattern of 64-bit flag
1288  *
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
1292  */
1293 EV_ERR
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;
1298   }
1299
1300   int fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC);
1301   EV_assert(fd >= 0);
1302
1303   EV_Flag64 flag;
1304   flag.flagID = flag_id;
1305   flag.bits = bits;
1306
1307   int ret = ioctl(fd, EVK_IOC_STORE_FLAG64, &flag);
1308   int myerrno = errno;
1309   close(fd);
1310
1311   if (ret < 0) {
1312     if (myerrno == ENOENT) {
1313       EV_DEBUG_ERR("set_flag: No such flag_id %x.\n", flag_id);
1314       return EV_ERR_Invalid_ID;
1315     }
1316
1317     errno = myerrno;
1318     EV_perror("set flag");
1319     return EV_ERR_Fatal;
1320   }
1321
1322   return EV_OK;
1323 }
1324
1325 /** @brief Send Messaging Event
1326  *
1327  * Send a message event to the specified queue ID.
1328  *
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.
1335  *
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
1340  */
1341 EV_ERR
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;
1348   }
1349
1350
1351   /*
1352    * Open fd at the first time of send_message in process, 
1353    * and continue to use the fd with it open after that.
1354    * Reason:
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.
1360    */
1361   static int fd = -1;
1362   EV_PROCESS_MUTEX_LOCK;
1363   if (fd < 0) {
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
1367
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
1370     }
1371     fcntl(fd, F_SETFD, FD_CLOEXEC|(fcntl(fd, F_GETFD, 0)));
1372   }
1373
1374   EV_Message msg;
1375   msg.queueID = queue_id;
1376   msg.senderInfo = senderInfo;
1377   msg.length = bytes;
1378   memcpy(msg.message, buf, bytes);
1379
1380   int ret = ioctl(fd, EVK_IOC_STORE_MESSAGE, &msg);
1381   int myerrno = errno;
1382   EV_PROCESS_MUTEX_UNLOCK;
1383
1384   if (ret < 0) {
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);
1390       return EV_ERR_Busy;
1391     }
1392
1393     errno = myerrno;
1394     EV_perror("send message");
1395     return EV_ERR_Fatal;
1396   }
1397
1398   return EV_OK;
1399 }
1400
1401 /** @brief Get fd for poll flag event
1402  *
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.
1406  *
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.
1411  *
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).
1414  *
1415  * - differences in kernel versions
1416  * - This API is not provided in the EVK.
1417  *
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.
1421  *
1422  * @param flag_id [IN] Flag ID
1423  * @param fd [OUT] Pointer to the area to store the file descriptor
1424  *
1425  * @retval EV_OK: Normal completion
1426  * @retval EV_ERR_Invalid_ID: An invalid flag ID was specified.
1427  * @retval Otherwise: FATAL error
1428  */
1429 EV_ERR
1430 EV_get_flag_fd(EV_ID flag_id, int *fd) {
1431   EV_assert(fd != NULL);
1432   *fd = -1;
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;
1436   }
1437
1438   *fd = find_ev_info(EV_SEARCH_ALL_THREAD, flag_id);
1439   if (*fd < 0) {
1440     EV_DEBUG_ERR("You have not created flag_id %x.\n", flag_id);
1441     return EV_ERR_Invalid_ID;
1442   }
1443
1444   return EV_OK;
1445 }
1446
1447 /** @brief Get fd for message event queue poll
1448  *
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.
1452  *
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.
1457  *
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).
1460  *
1461  * - differences in kernel versions
1462  * - This API is not provided in the EVK.
1463  *
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.
1467  *
1468  * @param queue_id [IN] Message event queue ID
1469  * @param fd [OUT] Pointer to the area to store the file descriptor
1470  *
1471  * @retval EV_OK: Normal completion
1472  * @retval EV_ERR_Invalid_ID: An invalid flag ID was specified.
1473  * @retval Otherwise: FATAL error
1474  */
1475 EV_ERR
1476 EV_get_queue_fd(EV_ID queue_id, int *fd) {
1477   EV_assert(fd != NULL);
1478   *fd = -1;
1479   if (!EV_ID_IS_QUEUE(queue_id)) {
1480     EV_DEBUG_ERR("get_queue_fd: %x is not a valid queue_id.\n",
1481         queue_id);
1482     return EV_ERR_Invalid_ID;
1483   }
1484
1485   *fd = find_ev_info(EV_SEARCH_ALL_THREAD, queue_id);
1486   if (*fd < 0) {
1487     EV_DEBUG_ERR("You have not created queue_id %x.\n", queue_id);
1488     return EV_ERR_Invalid_ID;
1489   }
1490   return EV_OK;
1491 }
1492
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)
1495 {
1496   return EV_Flag_ID_Base(mID);
1497 }
1498
1499 EV_ID EV_moduleID_to_flag64ID(UINT16 mID)
1500 {
1501   return EV_Flag64_ID_Base(mID);
1502 }
1503
1504 EV_ID EV_moduleID_to_queueID(UINT16 mID)
1505 {
1506   return EV_Queue_ID_Base(mID);
1507 }
1508
1509 EV_ERR EV_create_flag_by_mID(UINT16 mID)
1510 {
1511   return EV_create_flag(EV_moduleID_to_flagID(mID));
1512 }
1513
1514 EV_ERR EV_create_flag64_by_mID(UINT16 mID)
1515 {
1516   return EV_create_flag64(EV_moduleID_to_flag64ID(mID));
1517 }
1518
1519 EV_ERR EV_create_queue_by_mID(UINT16 mID, UINT8 length,UINT16 max_bytes,
1520                        EV_Message_Queue_Type type)
1521 {
1522   return EV_create_queue(EV_moduleID_to_queueID(mID), length, max_bytes, type);
1523 }
1524
1525 EV_ERR EV_destroy_flag_by_mID(UINT16 mID)
1526 {
1527   return EV_destroy_flag(EV_moduleID_to_flagID(mID));
1528 }
1529
1530 EV_ERR EV_destroy_queue_by_mID(UINT16 mID)
1531 {
1532   return EV_destroy_queue(EV_moduleID_to_queueID(mID));
1533 }
1534
1535 EV_ERR EV_set_flag_by_mID(UINT16 mID, UINT32 bits)
1536 {
1537   return EV_set_flag(EV_moduleID_to_flagID(mID), bits);
1538 }
1539
1540 EV_ERR EV_set_flag64_by_mID(UINT16 mID, UINT64 bits)
1541 {
1542   return EV_set_flag64(EV_moduleID_to_flag64ID(mID), bits);
1543 }
1544
1545 EV_ERR EV_send_message_by_mID(UINT16 mID, UINT16 bytes, const void *message,
1546                               UINT32 senderInfo)
1547 {
1548   return EV_send_message(EV_moduleID_to_queueID(mID),
1549                          bytes, message, senderInfo);
1550 }
1551 /** @} */