mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-23 05:16:30 +01:00
3f652d3caa
This commit adds support of waiter for Linux specific epoll(7) system call. For portability to the other Unix-like systems such as xBSD, modification of Makefile.am may be required for conditional build, but this commit includes no changes for it. Below lines are examples to use this option: $ axfer transfer --waiter-type=epoll -M -P -d 2 -D hw:0,3 /dev/urandom -f dat -vvv $ axfer transfer --waiter-type=epoll -M -C -d 2 -D hw:1,0 /dev/null -r 48000 -vvv Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
104 lines
2.2 KiB
C
104 lines
2.2 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
//
|
|
// waiter.c - I/O event waiter.
|
|
//
|
|
// Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
|
|
//
|
|
// Licensed under the terms of the GNU General Public License, version 2.
|
|
|
|
#include "waiter.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include "misc.h"
|
|
|
|
static const char *const waiter_type_labels[] = {
|
|
[WAITER_TYPE_DEFAULT] = "default",
|
|
[WAITER_TYPE_POLL] = "poll",
|
|
[WAITER_TYPE_SELECT] = "select",
|
|
[WAITER_TYPE_EPOLL] = "epoll",
|
|
};
|
|
|
|
enum waiter_type waiter_type_from_label(const char *label)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(waiter_type_labels); ++i) {
|
|
if (!strcmp(waiter_type_labels[i], label))
|
|
return i;
|
|
}
|
|
|
|
return WAITER_TYPE_DEFAULT;
|
|
}
|
|
|
|
const char *waiter_label_from_type(enum waiter_type type)
|
|
{
|
|
return waiter_type_labels[type];
|
|
}
|
|
|
|
int waiter_context_init(struct waiter_context *waiter,
|
|
enum waiter_type type, unsigned int pfd_count)
|
|
{
|
|
struct {
|
|
enum waiter_type type;
|
|
const struct waiter_data *waiter;
|
|
} entries[] = {
|
|
{WAITER_TYPE_POLL, &waiter_poll},
|
|
{WAITER_TYPE_SELECT, &waiter_select},
|
|
{WAITER_TYPE_EPOLL, &waiter_epoll},
|
|
};
|
|
int i;
|
|
|
|
if (pfd_count == 0)
|
|
return -EINVAL;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(entries); ++i) {
|
|
if (entries[i].type == type)
|
|
break;
|
|
}
|
|
if (i == ARRAY_SIZE(entries))
|
|
return -EINVAL;
|
|
|
|
waiter->private_data = malloc(entries[i].waiter->private_size);
|
|
if (waiter->private_data == NULL)
|
|
return -ENOMEM;
|
|
memset(waiter->private_data, 0, entries[i].waiter->private_size);
|
|
|
|
waiter->type = type;
|
|
waiter->ops = &entries[i].waiter->ops;
|
|
|
|
waiter->pfds = calloc(pfd_count, sizeof(*waiter->pfds));
|
|
if (waiter->pfds == NULL)
|
|
return -ENOMEM;
|
|
waiter->pfd_count = pfd_count;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int waiter_context_prepare(struct waiter_context *waiter)
|
|
{
|
|
return waiter->ops->prepare(waiter);
|
|
}
|
|
|
|
int waiter_context_wait_event(struct waiter_context *waiter,
|
|
int timeout_msec)
|
|
{
|
|
return waiter->ops->wait_event(waiter, timeout_msec);
|
|
}
|
|
|
|
void waiter_context_release(struct waiter_context *waiter)
|
|
{
|
|
waiter->ops->release(waiter);
|
|
}
|
|
|
|
void waiter_context_destroy(struct waiter_context *waiter)
|
|
{
|
|
if (waiter->pfds)
|
|
free(waiter->pfds);
|
|
waiter->pfd_count = 0;
|
|
if (waiter->private_data)
|
|
free(waiter->private_data);
|
|
waiter->private_data = NULL;
|
|
}
|