• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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