]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/clock_settime.c
Fix sem_post race (bug 14532).
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / clock_settime.c
CommitLineData
8dee4833 1/* Copyright (C) 2003, 2004, 2006, 2010, 2012 Free Software Foundation, Inc.
ad0e8eb0
UD
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
ad0e8eb0 17
f99ed760 18#include <errno.h>
ad0e8eb0 19#include <sysdep.h>
8dee4833 20#include <time.h>
ad0e8eb0 21
f99ed760 22#include "kernel-posix-cpu-timers.h"
6ddd37a4 23#include <kernel-features.h>
ad0e8eb0 24
89c85f87 25#ifndef HAVE_CLOCK_GETRES_VSYSCALL
f99ed760
UD
26# undef INTERNAL_VSYSCALL
27# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
28# undef INLINE_VSYSCALL
29# define INLINE_VSYSCALL INLINE_SYSCALL
30#else
31# include <bits/libc-vdso.h>
32#endif
33
34#if __ASSUME_POSIX_CPU_TIMERS <= 0 && defined __NR_clock_settime
f99ed760
UD
35extern int __libc_missing_posix_cpu_timers attribute_hidden;
36
37static int
38maybe_syscall_settime_cpu (clockid_t clock_id, const struct timespec *tp)
39{
40 int e = EINVAL;
41
42 if (!__libc_missing_posix_cpu_timers)
43 {
44 INTERNAL_SYSCALL_DECL (err);
89c85f87 45 int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp);
f99ed760 46 if (!INTERNAL_SYSCALL_ERROR_P (r, err))
89a4419c 47 return 0;
f99ed760
UD
48
49 e = INTERNAL_SYSCALL_ERRNO (r, err);
93a78ac4 50 if (e == EINVAL)
f99ed760 51 {
93a78ac4
JM
52 /* Check whether the kernel supports CPU clocks at all.
53 If not, record it for the future. */
54 r = INTERNAL_VSYSCALL (clock_getres, err, 2,
55 MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
56 NULL);
57 if (INTERNAL_SYSCALL_ERROR_P (r, err))
58 __libc_missing_posix_cpu_timers = 1;
f99ed760
UD
59 }
60 }
61
62 return e;
63}
64#endif
65
ad0e8eb0 66
93a78ac4
JM
67/* The REALTIME clock is definitely supported in the kernel. */
68#define SYSDEP_SETTIME \
ad0e8eb0
UD
69 case CLOCK_REALTIME: \
70 retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp); \
71 break
ad0e8eb0
UD
72
73#ifdef __NR_clock_settime
74/* We handled the REALTIME clock here. */
75# define HANDLED_REALTIME 1
76#endif
77
f99ed760
UD
78#if __ASSUME_POSIX_CPU_TIMERS > 0
79# define HANDLED_CPUTIME 1
80# define SYSDEP_SETTIME_CPU \
81 retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)
82#elif defined __NR_clock_settime
83# define SYSDEP_SETTIME_CPU \
84 retval = maybe_syscall_settime_cpu (clock_id, tp); \
85 if (retval == 0) \
86 break; \
87 if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \
88 { \
89 __set_errno (retval); \
90 retval = -1; \
91 break; \
92 } \
93 do { } while (0)
94#endif
95
ad0e8eb0 96#include <sysdeps/unix/clock_settime.c>