linux/kernel/time/posix-stubs.c
<<
>>
Prefs
   1/*
   2 * Dummy stubs used when CONFIG_POSIX_TIMERS=n
   3 *
   4 * Created by:  Nicolas Pitre, July 2016
   5 * Copyright:   (C) 2016 Linaro Limited
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/linkage.h>
  13#include <linux/kernel.h>
  14#include <linux/sched.h>
  15#include <linux/errno.h>
  16#include <linux/syscalls.h>
  17#include <linux/ktime.h>
  18#include <linux/timekeeping.h>
  19#include <linux/posix-timers.h>
  20#include <linux/compat.h>
  21
  22asmlinkage long sys_ni_posix_timers(void)
  23{
  24        pr_err_once("process %d (%s) attempted a POSIX timer syscall "
  25                    "while CONFIG_POSIX_TIMERS is not set\n",
  26                    current->pid, current->comm);
  27        return -ENOSYS;
  28}
  29
  30#define SYS_NI(name)  SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
  31#define COMPAT_SYS_NI(name)  SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers)
  32
  33SYS_NI(timer_create);
  34SYS_NI(timer_gettime);
  35SYS_NI(timer_getoverrun);
  36SYS_NI(timer_settime);
  37SYS_NI(timer_delete);
  38SYS_NI(clock_adjtime);
  39SYS_NI(getitimer);
  40SYS_NI(setitimer);
  41#ifdef __ARCH_WANT_SYS_ALARM
  42SYS_NI(alarm);
  43#endif
  44
  45/*
  46 * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
  47 * as it is easy to remain compatible with little code. CLOCK_BOOTTIME
  48 * is also included for convenience as at least systemd uses it.
  49 */
  50
  51SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
  52                const struct timespec __user *, tp)
  53{
  54        struct timespec64 new_tp;
  55
  56        if (which_clock != CLOCK_REALTIME)
  57                return -EINVAL;
  58        if (get_timespec64(&new_tp, tp))
  59                return -EFAULT;
  60
  61        return do_sys_settimeofday64(&new_tp, NULL);
  62}
  63
  64int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
  65{
  66        switch (which_clock) {
  67        case CLOCK_REALTIME:
  68                ktime_get_real_ts64(tp);
  69                break;
  70        case CLOCK_MONOTONIC:
  71                ktime_get_ts64(tp);
  72                break;
  73        case CLOCK_BOOTTIME:
  74                get_monotonic_boottime64(tp);
  75                break;
  76        default:
  77                return -EINVAL;
  78        }
  79
  80        return 0;
  81}
  82SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
  83                struct timespec __user *, tp)
  84{
  85        int ret;
  86        struct timespec64 kernel_tp;
  87
  88        ret = do_clock_gettime(which_clock, &kernel_tp);
  89        if (ret)
  90                return ret;
  91
  92        if (put_timespec64(&kernel_tp, tp))
  93                return -EFAULT;
  94        return 0;
  95}
  96
  97SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp)
  98{
  99        struct timespec64 rtn_tp = {
 100                .tv_sec = 0,
 101                .tv_nsec = hrtimer_resolution,
 102        };
 103
 104        switch (which_clock) {
 105        case CLOCK_REALTIME:
 106        case CLOCK_MONOTONIC:
 107        case CLOCK_BOOTTIME:
 108                if (put_timespec64(&rtn_tp, tp))
 109                        return -EFAULT;
 110                return 0;
 111        default:
 112                return -EINVAL;
 113        }
 114}
 115
 116SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 117                const struct timespec __user *, rqtp,
 118                struct timespec __user *, rmtp)
 119{
 120        struct timespec64 t64;
 121        struct timespec t;
 122
 123        switch (which_clock) {
 124        case CLOCK_REALTIME:
 125        case CLOCK_MONOTONIC:
 126        case CLOCK_BOOTTIME:
 127                break;
 128        default:
 129                return -EINVAL;
 130        }
 131
 132        if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
 133                return -EFAULT;
 134        t64 = timespec_to_timespec64(t);
 135        if (!timespec64_valid(&t64))
 136                return -EINVAL;
 137        if (flags & TIMER_ABSTIME)
 138                rmtp = NULL;
 139        current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
 140        current->restart_block.nanosleep.rmtp = rmtp;
 141        return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
 142                                 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
 143                                 which_clock);
 144}
 145
 146#ifdef CONFIG_COMPAT
 147COMPAT_SYS_NI(timer_create);
 148COMPAT_SYS_NI(clock_adjtime);
 149COMPAT_SYS_NI(timer_settime);
 150COMPAT_SYS_NI(timer_gettime);
 151COMPAT_SYS_NI(getitimer);
 152COMPAT_SYS_NI(setitimer);
 153
 154COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
 155                       struct compat_timespec __user *, tp)
 156{
 157        struct timespec64 new_tp;
 158
 159        if (which_clock != CLOCK_REALTIME)
 160                return -EINVAL;
 161        if (compat_get_timespec64(&new_tp, tp))
 162                return -EFAULT;
 163
 164        return do_sys_settimeofday64(&new_tp, NULL);
 165}
 166
 167COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
 168                       struct compat_timespec __user *, tp)
 169{
 170        int ret;
 171        struct timespec64 kernel_tp;
 172
 173        ret = do_clock_gettime(which_clock, &kernel_tp);
 174        if (ret)
 175                return ret;
 176
 177        if (compat_put_timespec64(&kernel_tp, tp))
 178                return -EFAULT;
 179        return 0;
 180}
 181
 182COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
 183                       struct compat_timespec __user *, tp)
 184{
 185        struct timespec64 rtn_tp = {
 186                .tv_sec = 0,
 187                .tv_nsec = hrtimer_resolution,
 188        };
 189
 190        switch (which_clock) {
 191        case CLOCK_REALTIME:
 192        case CLOCK_MONOTONIC:
 193        case CLOCK_BOOTTIME:
 194                if (compat_put_timespec64(&rtn_tp, tp))
 195                        return -EFAULT;
 196                return 0;
 197        default:
 198                return -EINVAL;
 199        }
 200}
 201
 202COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
 203                       struct compat_timespec __user *, rqtp,
 204                       struct compat_timespec __user *, rmtp)
 205{
 206        struct timespec64 t64;
 207        struct timespec t;
 208
 209        switch (which_clock) {
 210        case CLOCK_REALTIME:
 211        case CLOCK_MONOTONIC:
 212        case CLOCK_BOOTTIME:
 213                break;
 214        default:
 215                return -EINVAL;
 216        }
 217
 218        if (compat_get_timespec(&t, rqtp))
 219                return -EFAULT;
 220        t64 = timespec_to_timespec64(t);
 221        if (!timespec64_valid(&t64))
 222                return -EINVAL;
 223        if (flags & TIMER_ABSTIME)
 224                rmtp = NULL;
 225        current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
 226        current->restart_block.nanosleep.compat_rmtp = rmtp;
 227        return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
 228                                 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
 229                                 which_clock);
 230}
 231#endif
 232