support: Add support_create_timer

It is a simple wrapper over timer_create, timer_settime, and
sigaction.  It will be used to check for large timeout to trigger an
EINTR and to avoid use a large timeout (as for alarm()).

Reviewed-by: Lukasz Majewski <lukma@denx.de>
This commit is contained in:
Adhemerval Zanella 2021-06-16 13:44:03 -03:00
parent 52a5fe70a2
commit 92f7b46510
3 changed files with 81 additions and 0 deletions

View File

@ -50,6 +50,7 @@ libsupport-routines = \
support_chroot \
support_copy_file \
support_copy_file_range \
support_create_timer \
support_descriptor_supports_holes \
support_descriptors \
support_enter_mount_namespace \

View File

@ -24,6 +24,7 @@
#define SUPPORT_H
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <sys/cdefs.h>
/* For mode_t. */
@ -153,6 +154,16 @@ extern bool support_select_modifies_timeout (void);
tv_usec larger than 1000000. */
extern bool support_select_normalizes_timeout (void);
/* Create a timer that trigger after SEC seconds and NSEC nanoseconds. If
REPEAT is true the timer will repeat indefinitely. If CALLBACK is not
NULL, the function will be called when the timer expires; otherwise a
dummy empty function is used instead.
This is implemented with POSIX per-process timer with SIGEV_SIGNAL. */
timer_t support_create_timer (uint64_t sec, long int nsec, bool repeat,
void (*callback)(int));
/* Disable the timer TIMER. */
void support_delete_timer (timer_t timer);
__END_DECLS
#endif /* SUPPORT_H */

View File

@ -0,0 +1,69 @@
/* Create a periodic timer.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <support/check.h>
#include <support/support.h>
#include <support/xsignal.h>
#include <time.h>
static void
dummy_alrm_handler (int sig)
{
}
timer_t
support_create_timer (uint64_t sec, long int nsec, bool repeat,
void (*callback)(int))
{
struct sigaction sa;
sa.sa_handler = callback != NULL ? callback : dummy_alrm_handler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
xsigaction (SIGALRM, &sa, NULL);
struct sigevent ev = {
.sigev_notify = SIGEV_SIGNAL,
.sigev_signo = SIGALRM
};
timer_t timerid;
int r = timer_create (CLOCK_REALTIME, &ev, &timerid);
if (r == -1)
FAIL_EXIT1 ("timer_create: %m");
/* Single timer with 0.1s. */
struct itimerspec its =
{
{ .tv_sec = repeat ? sec : 0, .tv_nsec = repeat ? nsec : 0 },
{ .tv_sec = sec, .tv_nsec = nsec }
};
r = timer_settime (timerid, 0, &its, NULL);
if (r == -1)
FAIL_EXIT1 ("timer_settime: %m");
return timerid;
}
/* Disable the timer TIMER. */
void
support_delete_timer (timer_t timer)
{
int r = timer_delete (timer);
if (r == -1)
FAIL_EXIT1 ("timer_delete: %m");
xsignal (SIGALRM, SIG_DFL);
}