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