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