xref: /third_party/alsa-utils/axfer/waiter.c (revision c72fcc34)
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
17static 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
24enum waiter_type waiter_type_from_label(const char *label)
25{
26	int i;
27
28	for (i = 0; i < (int)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
36const char *waiter_label_from_type(enum waiter_type type)
37{
38	return waiter_type_labels[type];
39}
40
41int 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 < (int)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
80int waiter_context_prepare(struct waiter_context *waiter)
81{
82	return waiter->ops->prepare(waiter);
83}
84
85int waiter_context_wait_event(struct waiter_context *waiter,
86				int timeout_msec)
87{
88	return waiter->ops->wait_event(waiter, timeout_msec);
89}
90
91void waiter_context_release(struct waiter_context *waiter)
92{
93	waiter->ops->release(waiter);
94}
95
96void 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