1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // waiter.c - I/O event waiter.
4 //
5 // Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6 //
7 // Licensed under the terms of the GNU General Public License, version 2.
8
9 #include "waiter.h"
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include <errno.h>
14
15 #include "misc.h"
16
17 static const char *const waiter_type_labels[] = {
18 [WAITER_TYPE_DEFAULT] = "default",
19 [WAITER_TYPE_POLL] = "poll",
20 [WAITER_TYPE_SELECT] = "select",
21 [WAITER_TYPE_EPOLL] = "epoll",
22 };
23
waiter_type_from_label(const char * label)24 enum waiter_type waiter_type_from_label(const char *label)
25 {
26 int i;
27
28 for (i = 0; i < ARRAY_SIZE(waiter_type_labels); ++i) {
29 if (!strcmp(waiter_type_labels[i], label))
30 return i;
31 }
32
33 return WAITER_TYPE_DEFAULT;
34 }
35
waiter_label_from_type(enum waiter_type type)36 const char *waiter_label_from_type(enum waiter_type type)
37 {
38 return waiter_type_labels[type];
39 }
40
waiter_context_init(struct waiter_context * waiter,enum waiter_type type,unsigned int pfd_count)41 int waiter_context_init(struct waiter_context *waiter,
42 enum waiter_type type, unsigned int pfd_count)
43 {
44 struct {
45 enum waiter_type type;
46 const struct waiter_data *waiter;
47 } entries[] = {
48 {WAITER_TYPE_POLL, &waiter_poll},
49 {WAITER_TYPE_SELECT, &waiter_select},
50 {WAITER_TYPE_EPOLL, &waiter_epoll},
51 };
52 int i;
53
54 if (pfd_count == 0)
55 return -EINVAL;
56
57 for (i = 0; i < ARRAY_SIZE(entries); ++i) {
58 if (entries[i].type == type)
59 break;
60 }
61 if (i == ARRAY_SIZE(entries))
62 return -EINVAL;
63
64 waiter->private_data = malloc(entries[i].waiter->private_size);
65 if (waiter->private_data == NULL)
66 return -ENOMEM;
67 memset(waiter->private_data, 0, entries[i].waiter->private_size);
68
69 waiter->type = type;
70 waiter->ops = &entries[i].waiter->ops;
71
72 waiter->pfds = calloc(pfd_count, sizeof(*waiter->pfds));
73 if (waiter->pfds == NULL)
74 return -ENOMEM;
75 waiter->pfd_count = pfd_count;
76
77 return 0;
78 }
79
waiter_context_prepare(struct waiter_context * waiter)80 int waiter_context_prepare(struct waiter_context *waiter)
81 {
82 return waiter->ops->prepare(waiter);
83 }
84
waiter_context_wait_event(struct waiter_context * waiter,int timeout_msec)85 int waiter_context_wait_event(struct waiter_context *waiter,
86 int timeout_msec)
87 {
88 return waiter->ops->wait_event(waiter, timeout_msec);
89 }
90
waiter_context_release(struct waiter_context * waiter)91 void waiter_context_release(struct waiter_context *waiter)
92 {
93 waiter->ops->release(waiter);
94 }
95
waiter_context_destroy(struct waiter_context * waiter)96 void waiter_context_destroy(struct waiter_context *waiter)
97 {
98 if (waiter->pfds)
99 free(waiter->pfds);
100 waiter->pfd_count = 0;
101 if (waiter->private_data)
102 free(waiter->private_data);
103 waiter->private_data = NULL;
104 }
105