From patchwork Wed Sep 14 20:46:54 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 76242 Delivered-To: patch@linaro.org Received: by 10.140.106.72 with SMTP id d66csp2066603qgf; Wed, 14 Sep 2016 13:47:01 -0700 (PDT) X-Received: by 10.66.131.4 with SMTP id oi4mr8119784pab.66.1473886021570; Wed, 14 Sep 2016 13:47:01 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id fn10si49526pab.94.2016.09.14.13.47.01; Wed, 14 Sep 2016 13:47:01 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1765124AbcINUq7 (ORCPT + 27 others); Wed, 14 Sep 2016 16:46:59 -0400 Received: from mail-qk0-f169.google.com ([209.85.220.169]:36250 "EHLO mail-qk0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756094AbcINUq5 (ORCPT ); Wed, 14 Sep 2016 16:46:57 -0400 Received: by mail-qk0-f169.google.com with SMTP id z190so27539348qkc.3 for ; Wed, 14 Sep 2016 13:46:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:user-agent:mime-version; bh=p+ZT3AkY/YhQDG/hISI04geZjmY3iUGiJ1l6WYX4BFo=; b=IzPxNDxMjy4YVRrAIHX0pIYVUTk1h2zaHo/hFnvcgP9pY2jNEcNt0od2nmA8kyYCJe NktKQf9S/ryz3Z80PzRk0pl1L1ZMn3RxkaqPm+90FhD9MFu+Xzx9ieORiPFKlbU8ZuoH R0+yPSMP7FLrBiGKrsGSxiMf5/FjkRavRkLHA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:user-agent :mime-version; bh=p+ZT3AkY/YhQDG/hISI04geZjmY3iUGiJ1l6WYX4BFo=; b=mDnp2YeLftzsrMXk5UUzRccf02ozpxdbhUMWvtlZl61RYotdrUvZcRvwcAwDqVDWdg npbWLcAdK1zXS9SMHU6uz2cla3QDyotGHC+R1t2UkEoFTDngBf+IlIR+zu2McbI9DDJ2 1LgiCuBMnICT4v5BVXZMYnUxUYq2nqhDAVsU2VJ0fJhOmf/V1+7UQ5T76kTlF9N15Dp2 Oi+KHgZvdui40W2M1ewLc0MPJHk+f4ctjjRv1l/qs/KxyiU0Wl3wI2JkCYIkqGFMNrAv LlYdmfAorrCknTq+wngvRY4PwNXaQFUNytHFPth16dedf0iCU7mj91YVjolp7gSDXneE 00nA== X-Gm-Message-State: AE9vXwOxC9yZ1txx9B70bOL0lf8K2pnKSvH3sb/JN5azmRSQBA+N2Ia33d9tVmS1jyal8UJW X-Received: by 10.55.41.232 with SMTP id p101mr5755389qkp.93.1473886015913; Wed, 14 Sep 2016 13:46:55 -0700 (PDT) Received: from xanadu.home ([2607:fa48:6e39:d410:feaa:14ff:fea7:ed77]) by smtp.gmail.com with ESMTPSA id 5sm3383qts.45.2016.09.14.13.46.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Sep 2016 13:46:55 -0700 (PDT) Date: Wed, 14 Sep 2016 16:46:54 -0400 (EDT) From: Nicolas Pitre To: Thomas Gleixner , John Stultz cc: Josh Triplett , Richard Cochran , linux-kernel@vger.kernel.org Subject: [PATCH v2) posix-timers: make it configurable Message-ID: User-Agent: Alpine 2.20 (LFD 67 2015-01-07) MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Many embedded systems typically don't need them. This removes about 22KB from the kernel binary size on ARM when configured out. Corresponding syscalls are routed to a stub logging the attempt to use those syscalls which should be enough of a clue if they were disabled without proper consideration. They are: timer_create, timer_gettime: timer_getoverrun, timer_settime, timer_delete, clock_adjtime. The clock_settime, clock_gettime, clock_getres and clock_nanosleep syscalls are replaced by simple wrappers compatible with CLOCK_REALTIME, CLOCK_MONOTONIC and CLOCK_BOOTTIME only. Signed-off-by: Nicolas Pitre --- Changes from RFC/v1: - Stubbed-out functions moved to static inlines. - The timer signal handling code is now removed. - The list of removed syscalls is explicitly documented. - The clock_settime, clock_gettime, clock_getres and clock_nanosleep syscalls are minimally preserved as this required very little code. I'm now able to boot a copy of Fedora 21 with this patch and CONFIG_POSIX_TIMERS=n with no apparent issues. diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index ee3de3421f..00e6098e9a 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -6,7 +6,7 @@ menu "PTP clock support" config PTP_1588_CLOCK tristate "PTP clock support" - depends on NET + depends on NET && POSIX_TIMERS select PPS select NET_PTP_CLASSIFY help diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 62d44c1760..9a193243f2 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -118,6 +118,8 @@ struct k_clock { extern struct k_clock clock_posix_cpu; extern struct k_clock clock_posix_dynamic; +#ifdef CONFIG_POSIX_TIMERS + void posix_timers_register_clock(const clockid_t clock_id, struct k_clock *new_clock); /* function to call to trigger timer event */ @@ -135,4 +137,26 @@ long clock_nanosleep_restart(struct restart_block *restart_block); void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); +#else + +#include + +static inline void posix_timers_register_clock(const clockid_t clock_id, + struct k_clock *new_clock) {} +static inline int posix_timer_event(struct k_itimer *timr, int si_private) +{ return 0; } +static inline void run_posix_cpu_timers(struct task_struct *task) {} +static inline void posix_cpu_timers_exit(struct task_struct *task) +{ + add_device_randomness((const void*) &task->se.sum_exec_runtime, + sizeof(unsigned long long)); +} +static inline void posix_cpu_timers_exit_group(struct task_struct *task) {} +static inline void set_process_cpu_timer(struct task_struct *task, + unsigned int clock_idx, cputime_t *newval, cputime_t *oldval) {} +static inline void update_rlimit_cpu(struct task_struct *task, + unsigned long rlim_new) {} + +#endif + #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index 54182d52a0..39a1d6d3f5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2924,8 +2924,13 @@ static inline void exit_thread(struct task_struct *tsk) extern void exit_files(struct task_struct *); extern void __cleanup_sighand(struct sighand_struct *); +#ifdef CONFIG_POSIX_TIMERS extern void exit_itimers(struct signal_struct *); extern void flush_itimer_signals(void); +#else +static inline void exit_itimers(struct signal_struct *s) {} +static inline void flush_itimer_signals(void) {} +#endif extern void do_group_exit(int); @@ -3382,7 +3387,12 @@ static __always_inline bool need_resched(void) * Thread group CPU time accounting. */ void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times); +#ifdef CONFIG_POSIX_TIMERS void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times); +#else +static inline void thread_group_cputimer(struct task_struct *tsk, + struct task_cputime *times) {} +#endif /* * Reevaluate whether the task has signals pending delivery. diff --git a/kernel/signal.c b/kernel/signal.c index af21afc00d..ea75065e29 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -427,6 +427,7 @@ void flush_signals(struct task_struct *t) spin_unlock_irqrestore(&t->sighand->siglock, flags); } +#ifdef CONFIG_POSIX_TIMERS static void __flush_itimer_signals(struct sigpending *pending) { sigset_t signal, retain; @@ -460,6 +461,7 @@ void flush_itimer_signals(void) __flush_itimer_signals(&tsk->signal->shared_pending); spin_unlock_irqrestore(&tsk->sighand->siglock, flags); } +#endif void ignore_signals(struct task_struct *t) { @@ -611,6 +613,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) */ current->jobctl |= JOBCTL_STOP_DEQUEUED; } +#ifdef CONFIG_POSIX_TIMERS if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) { /* * Release the siglock to ensure proper locking order @@ -622,6 +625,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) do_schedule_next_timer(info); spin_lock(&tsk->sighand->siglock); } +#endif return signr; } diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig index 62824f2fe4..62504a2c9f 100644 --- a/kernel/time/Kconfig +++ b/kernel/time/Kconfig @@ -195,3 +195,21 @@ config HIGH_RES_TIMERS endmenu endif + +config POSIX_TIMERS + bool "Posix Clocks & timers" if EMBEDDED + default y + help + This includes native support for POSIX timers to the kernel. + Most embedded systems may have no use for them and therefore they + can be configured out to reduce the size of the kernel image. + + When this option is disabled, the following syscalls won't be + available: timer_create, timer_gettime: timer_getoverrun, + timer_settime, timer_delete, clock_adjtime. Furthermore, the + clock_settime, clock_gettime, clock_getres and clock_nanosleep + syscalls will be limited to CLOCK_REALTIME and CLOCK_MONOTONIC + only. + + If unsure say y. + diff --git a/kernel/time/Makefile b/kernel/time/Makefile index 49eca0beed..fc26c308f5 100644 --- a/kernel/time/Makefile +++ b/kernel/time/Makefile @@ -1,6 +1,12 @@ -obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o +obj-y += time.o timer.o hrtimer.o itimer.o obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o -obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o +obj-y += timeconv.o timecounter.o alarmtimer.o + +ifeq ($(CONFIG_POSIX_TIMERS),y) + obj-y += posix-timers.o posix-cpu-timers.o posix-clock.o +else + obj-y += posix-stubs.o +endif obj-$(CONFIG_GENERIC_CLOCKEVENTS) += clockevents.o tick-common.o ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y) diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c new file mode 100644 index 0000000000..442b0a92e0 --- /dev/null +++ b/kernel/time/posix-stubs.c @@ -0,0 +1,110 @@ +/* + * Dummy stubs used when CONFIG_POSIX_TIMERS=n + * + * Created by: Nicolas Pitre, July 2016 + * Copyright: (C) 2016 Linaro Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +asmlinkage long sys_ni_posix_timers(void) +{ + pr_err_once("process %d (%s) attempted a POSIX timer syscall " + "while CONFIG_POSIX_TIMERS is not set\n", + current->pid, current->comm); + return -ENOSYS; +} + +#define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers) + +SYS_NI(timer_create); +SYS_NI(timer_gettime); +SYS_NI(timer_getoverrun); +SYS_NI(timer_settime); +SYS_NI(timer_delete); +SYS_NI(clock_adjtime); + +/* + * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC + * as it is easy to remain compatible with little code. CLOCK_BOOTTIME + * is also included for convenience as at least systemd uses it. + */ + +SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, + const struct timespec __user *, tp) +{ + struct timespec new_tp; + + if (which_clock != CLOCK_REALTIME) + return -EINVAL; + if (copy_from_user(&new_tp, tp, sizeof (*tp))) + return -EFAULT; + return do_sys_settimeofday(&new_tp, NULL); +} + +SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, + struct timespec __user *,tp) +{ + struct timespec kernel_tp; + + switch (which_clock) { + case CLOCK_REALTIME: ktime_get_real_ts(&kernel_tp); break; + case CLOCK_MONOTONIC: ktime_get_ts(&kernel_tp); break; + case CLOCK_BOOTTIME: get_monotonic_boottime(&kernel_tp); break; + default: return -EINVAL; + } + if (copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) + return -EFAULT; + return 0; +} + +SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp) +{ + struct timespec rtn_tp = { + .tv_sec = 0, + .tv_nsec = hrtimer_resolution, + }; + + switch (which_clock) { + case CLOCK_REALTIME: + case CLOCK_MONOTONIC: + case CLOCK_BOOTTIME: + if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp))) + return -EFAULT; + return 0; + default: + return -EINVAL; + } +} + +SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, + const struct timespec __user *, rqtp, + struct timespec __user *, rmtp) +{ + struct timespec t; + + switch (which_clock) { + case CLOCK_REALTIME: + case CLOCK_MONOTONIC: + case CLOCK_BOOTTIME: + if (copy_from_user(&t, rqtp, sizeof (struct timespec))) + return -EFAULT; + if (!timespec_valid(&t)) + return -EINVAL; + return hrtimer_nanosleep(&t, rmtp, flags & TIMER_ABSTIME ? + HRTIMER_MODE_ABS : HRTIMER_MODE_REL, + which_clock); + default: + return -EINVAL; + } +}