mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-08-16 21:07:13 +00:00

Add a test for the new functionality of userspace-driven timers and the tool which allows us to count timer ticks in a certain time period. The test: 1. Creates a userspace-driven timer with ioctl to /dev/snd/timer 2. Starts the `global-timer` application to count the ticks of the timer from step 1. 3. Asynchronously triggers the timer multiple times with some interval 4. Compares the amount of caught ticks with the amount of trigger calls. Since we can't include <alsa/asoundlib.h> and <sound/asound.h> in one file due to overlapping declarations, I have to split the test into two applications: one of them counts the amount of timer ticks in the defined time period, and another one is the actual test which creates the timer, triggers it periodically and starts the first app to count the amount of ticks in a separate thread. Besides from testing the functionality itself, the test represents a sample application showing userspace-driven ALSA timers API. Also, the timer test includes a test case which tries to create a timer with invalid resolution (=0), and NULL as a timer info structure. Signed-off-by: Ivan Orlov <ivan.orlov0322@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20240813120701.171743-5-ivan.orlov0322@gmail.com
88 lines
2.0 KiB
C
88 lines
2.0 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* This tool is used by the utimer test, and it allows us to
|
|
* count the ticks of a global timer in a certain time frame
|
|
* (which is set by `timeout` parameter).
|
|
*
|
|
* Author: Ivan Orlov <ivan.orlov0322@gmail.com>
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <alsa/asoundlib.h>
|
|
#include <time.h>
|
|
|
|
static int ticked;
|
|
static void async_callback(snd_async_handler_t *ahandler)
|
|
{
|
|
ticked++;
|
|
}
|
|
|
|
static char timer_name[64];
|
|
static void bind_to_timer(int device, int subdevice, int timeout)
|
|
{
|
|
snd_timer_t *handle;
|
|
snd_timer_params_t *params;
|
|
snd_async_handler_t *ahandler;
|
|
|
|
time_t end;
|
|
|
|
sprintf(timer_name, "hw:CLASS=%d,SCLASS=%d,DEV=%d,SUBDEV=%d",
|
|
SND_TIMER_CLASS_GLOBAL, SND_TIMER_SCLASS_NONE,
|
|
device, subdevice);
|
|
|
|
snd_timer_params_alloca(¶ms);
|
|
|
|
if (snd_timer_open(&handle, timer_name, SND_TIMER_OPEN_NONBLOCK) < 0) {
|
|
perror("Can't open the timer");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
snd_timer_params_set_auto_start(params, 1);
|
|
snd_timer_params_set_ticks(params, 1);
|
|
if (snd_timer_params(handle, params) < 0) {
|
|
perror("Can't set timer params");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (snd_async_add_timer_handler(&ahandler, handle, async_callback, NULL) < 0) {
|
|
perror("Can't create a handler");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
end = time(NULL) + timeout;
|
|
if (snd_timer_start(handle) < 0) {
|
|
perror("Failed to start the timer");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf("Timer has started\n");
|
|
while (time(NULL) <= end) {
|
|
/*
|
|
* Waiting for the timeout to elapse. Can't use sleep here, as it gets
|
|
* constantly interrupted by the signal from the timer (SIGIO)
|
|
*/
|
|
}
|
|
snd_timer_stop(handle);
|
|
snd_timer_close(handle);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int device, subdevice, timeout;
|
|
|
|
if (argc < 4) {
|
|
perror("Usage: %s <device> <subdevice> <timeout>");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
setlinebuf(stdout);
|
|
|
|
device = atoi(argv[1]);
|
|
subdevice = atoi(argv[2]);
|
|
timeout = atoi(argv[3]);
|
|
|
|
bind_to_timer(device, subdevice, timeout);
|
|
|
|
printf("Total ticks count: %d\n", ticked);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|