Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

posix-timers: Make them configurable

Some embedded systems have no use for them. This removes about
25KB from the kernel binary size 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, setitimer, getitimer, alarm.

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 which should cover the vast
majority of use cases with very little code.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <john.stultz@linaro.org>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Cc: Paul Bolle <pebolle@tiscali.nl>
Cc: linux-kbuild@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: Michal Marek <mmarek@suse.com>
Cc: Edward Cree <ecree@solarflare.com>
Link: http://lkml.kernel.org/r/1478841010-28605-7-git-send-email-nicolas.pitre@linaro.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Nicolas Pitre and committed by
Thomas Gleixner
baa73d9e 53d3eaa3

+200 -13
+8
arch/alpha/kernel/osf_sys.c
··· 1029 1029 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); 1030 1030 } 1031 1031 1032 + asmlinkage long sys_ni_posix_timers(void); 1033 + 1032 1034 SYSCALL_DEFINE2(osf_getitimer, int, which, struct itimerval32 __user *, it) 1033 1035 { 1034 1036 struct itimerval kit; 1035 1037 int error; 1038 + 1039 + if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) 1040 + return sys_ni_posix_timers(); 1036 1041 1037 1042 error = do_getitimer(which, &kit); 1038 1043 if (!error && put_it32(it, &kit)) ··· 1051 1046 { 1052 1047 struct itimerval kin, kout; 1053 1048 int error; 1049 + 1050 + if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) 1051 + return sys_ni_posix_timers(); 1054 1052 1055 1053 if (in) { 1056 1054 if (get_it32(&kin, in))
+1
drivers/char/Kconfig
··· 542 542 config MMTIMER 543 543 tristate "MMTIMER Memory mapped RTC for SGI Altix" 544 544 depends on IA64_GENERIC || IA64_SGI_SN2 545 + depends on POSIX_TIMERS 545 546 default y 546 547 help 547 548 The mmtimer device allows direct userspace access to the
+1 -1
drivers/ptp/Kconfig
··· 6 6 7 7 config PTP_1588_CLOCK 8 8 tristate "PTP clock support" 9 - depends on NET 9 + depends on NET && POSIX_TIMERS 10 10 select PPS 11 11 select NET_PTP_CLASSIFY 12 12 help
+2
fs/exec.c
··· 1169 1169 /* we have changed execution domain */ 1170 1170 tsk->exit_signal = SIGCHLD; 1171 1171 1172 + #ifdef CONFIG_POSIX_TIMERS 1172 1173 exit_itimers(sig); 1173 1174 flush_itimer_signals(); 1175 + #endif 1174 1176 1175 1177 if (atomic_read(&oldsighand->count) != 1) { 1176 1178 struct sighand_struct *newsighand;
+17
init/Kconfig
··· 1445 1445 1446 1446 If unsure say N here. 1447 1447 1448 + config POSIX_TIMERS 1449 + bool "Posix Clocks & timers" if EXPERT 1450 + default y 1451 + help 1452 + This includes native support for POSIX timers to the kernel. 1453 + Some embedded systems have no use for them and therefore they 1454 + can be configured out to reduce the size of the kernel image. 1455 + 1456 + When this option is disabled, the following syscalls won't be 1457 + available: timer_create, timer_gettime: timer_getoverrun, 1458 + timer_settime, timer_delete, clock_adjtime, getitimer, 1459 + setitimer, alarm. Furthermore, the clock_settime, clock_gettime, 1460 + clock_getres and clock_nanosleep syscalls will be limited to 1461 + CLOCK_REALTIME, CLOCK_MONOTONIC and CLOCK_BOOTTIME only. 1462 + 1463 + If unsure say y. 1464 + 1448 1465 config KALLSYMS 1449 1466 bool "Load all symbols for debugging/ksymoops" if EXPERT 1450 1467 default y
+8
kernel/compat.c
··· 307 307 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); 308 308 } 309 309 310 + asmlinkage long sys_ni_posix_timers(void); 311 + 310 312 COMPAT_SYSCALL_DEFINE2(getitimer, int, which, 311 313 struct compat_itimerval __user *, it) 312 314 { 313 315 struct itimerval kit; 314 316 int error; 317 + 318 + if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) 319 + return sys_ni_posix_timers(); 315 320 316 321 error = do_getitimer(which, &kit); 317 322 if (!error && put_compat_itimerval(it, &kit)) ··· 330 325 { 331 326 struct itimerval kin, kout; 332 327 int error; 328 + 329 + if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) 330 + return sys_ni_posix_timers(); 333 331 334 332 if (in) { 335 333 if (get_compat_itimerval(&kin, in))
+9 -2
kernel/exit.c
··· 92 92 lockdep_tasklist_lock_is_held()); 93 93 spin_lock(&sighand->siglock); 94 94 95 + #ifdef CONFIG_POSIX_TIMERS 95 96 posix_cpu_timers_exit(tsk); 96 97 if (group_dead) { 97 98 posix_cpu_timers_exit_group(tsk); 98 - tty = sig->tty; 99 - sig->tty = NULL; 100 99 } else { 101 100 /* 102 101 * This can only happen if the caller is de_thread(). ··· 104 105 */ 105 106 if (unlikely(has_group_leader_pid(tsk))) 106 107 posix_cpu_timers_exit_group(tsk); 108 + } 109 + #endif 107 110 111 + if (group_dead) { 112 + tty = sig->tty; 113 + sig->tty = NULL; 114 + } else { 108 115 /* 109 116 * If there is any task waiting for the group exit 110 117 * then notify it: ··· 808 803 acct_update_integrals(tsk); 809 804 group_dead = atomic_dec_and_test(&tsk->signal->live); 810 805 if (group_dead) { 806 + #ifdef CONFIG_POSIX_TIMERS 811 807 hrtimer_cancel(&tsk->signal->real_timer); 812 808 exit_itimers(tsk->signal); 809 + #endif 813 810 if (tsk->mm) 814 811 setmax_mm_hiwater_rss(&tsk->signal->maxrss, tsk->mm); 815 812 }
+2
kernel/fork.c
··· 1342 1342 seqlock_init(&sig->stats_lock); 1343 1343 prev_cputime_init(&sig->prev_cputime); 1344 1344 1345 + #ifdef CONFIG_POSIX_TIMERS 1345 1346 hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 1346 1347 sig->real_timer.function = it_real_fn; 1348 + #endif 1347 1349 1348 1350 task_lock(current->group_leader); 1349 1351 memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim);
+6
kernel/signal.c
··· 427 427 spin_unlock_irqrestore(&t->sighand->siglock, flags); 428 428 } 429 429 430 + #ifdef CONFIG_POSIX_TIMERS 430 431 static void __flush_itimer_signals(struct sigpending *pending) 431 432 { 432 433 sigset_t signal, retain; ··· 461 460 __flush_itimer_signals(&tsk->signal->shared_pending); 462 461 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 463 462 } 463 + #endif 464 464 465 465 void ignore_signals(struct task_struct *t) 466 466 { ··· 569 567 if (!signr) { 570 568 signr = __dequeue_signal(&tsk->signal->shared_pending, 571 569 mask, info); 570 + #ifdef CONFIG_POSIX_TIMERS 572 571 /* 573 572 * itimer signal ? 574 573 * ··· 593 590 hrtimer_restart(tmr); 594 591 } 595 592 } 593 + #endif 596 594 } 597 595 598 596 recalc_sigpending(); ··· 615 611 */ 616 612 current->jobctl |= JOBCTL_STOP_DEQUEUED; 617 613 } 614 + #ifdef CONFIG_POSIX_TIMERS 618 615 if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) { 619 616 /* 620 617 * Release the siglock to ensure proper locking order ··· 627 622 do_schedule_next_timer(info); 628 623 spin_lock(&tsk->sighand->siglock); 629 624 } 625 + #endif 630 626 return signr; 631 627 } 632 628
+2 -1
kernel/sys.c
··· 1416 1416 * applications, so we live with it 1417 1417 */ 1418 1418 if (!retval && new_rlim && resource == RLIMIT_CPU && 1419 - new_rlim->rlim_cur != RLIM_INFINITY) 1419 + new_rlim->rlim_cur != RLIM_INFINITY && 1420 + IS_ENABLED(CONFIG_POSIX_TIMERS)) 1420 1421 update_rlimit_cpu(tsk, new_rlim->rlim_cur); 1421 1422 out: 1422 1423 read_unlock(&tasklist_lock);
+8 -2
kernel/time/Makefile
··· 1 - obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o 1 + obj-y += time.o timer.o hrtimer.o 2 2 obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o 3 - obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o 3 + obj-y += timeconv.o timecounter.o alarmtimer.o 4 + 5 + ifeq ($(CONFIG_POSIX_TIMERS),y) 6 + obj-y += posix-timers.o posix-cpu-timers.o posix-clock.o itimer.o 7 + else 8 + obj-y += posix-stubs.o 9 + endif 4 10 5 11 obj-$(CONFIG_GENERIC_CLOCKEVENTS) += clockevents.o tick-common.o 6 12 ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
+4 -2
kernel/time/alarmtimer.c
··· 846 846 847 847 alarmtimer_rtc_timer_init(); 848 848 849 - posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock); 850 - posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock); 849 + if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { 850 + posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock); 851 + posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock); 852 + } 851 853 852 854 /* Initialize alarm bases */ 853 855 alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;
+123
kernel/time/posix-stubs.c
··· 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 + 21 + asmlinkage long sys_ni_posix_timers(void) 22 + { 23 + pr_err_once("process %d (%s) attempted a POSIX timer syscall " 24 + "while CONFIG_POSIX_TIMERS is not set\n", 25 + current->pid, current->comm); 26 + return -ENOSYS; 27 + } 28 + 29 + #define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers) 30 + 31 + SYS_NI(timer_create); 32 + SYS_NI(timer_gettime); 33 + SYS_NI(timer_getoverrun); 34 + SYS_NI(timer_settime); 35 + SYS_NI(timer_delete); 36 + SYS_NI(clock_adjtime); 37 + SYS_NI(getitimer); 38 + SYS_NI(setitimer); 39 + #ifdef __ARCH_WANT_SYS_ALARM 40 + SYS_NI(alarm); 41 + #endif 42 + 43 + /* 44 + * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC 45 + * as it is easy to remain compatible with little code. CLOCK_BOOTTIME 46 + * is also included for convenience as at least systemd uses it. 47 + */ 48 + 49 + SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, 50 + const struct timespec __user *, tp) 51 + { 52 + struct timespec new_tp; 53 + 54 + if (which_clock != CLOCK_REALTIME) 55 + return -EINVAL; 56 + if (copy_from_user(&new_tp, tp, sizeof (*tp))) 57 + return -EFAULT; 58 + return do_sys_settimeofday(&new_tp, NULL); 59 + } 60 + 61 + SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, 62 + struct timespec __user *,tp) 63 + { 64 + struct timespec kernel_tp; 65 + 66 + switch (which_clock) { 67 + case CLOCK_REALTIME: ktime_get_real_ts(&kernel_tp); break; 68 + case CLOCK_MONOTONIC: ktime_get_ts(&kernel_tp); break; 69 + case CLOCK_BOOTTIME: get_monotonic_boottime(&kernel_tp); break; 70 + default: return -EINVAL; 71 + } 72 + if (copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) 73 + return -EFAULT; 74 + return 0; 75 + } 76 + 77 + SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp) 78 + { 79 + struct timespec rtn_tp = { 80 + .tv_sec = 0, 81 + .tv_nsec = hrtimer_resolution, 82 + }; 83 + 84 + switch (which_clock) { 85 + case CLOCK_REALTIME: 86 + case CLOCK_MONOTONIC: 87 + case CLOCK_BOOTTIME: 88 + if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp))) 89 + return -EFAULT; 90 + return 0; 91 + default: 92 + return -EINVAL; 93 + } 94 + } 95 + 96 + SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, 97 + const struct timespec __user *, rqtp, 98 + struct timespec __user *, rmtp) 99 + { 100 + struct timespec t; 101 + 102 + switch (which_clock) { 103 + case CLOCK_REALTIME: 104 + case CLOCK_MONOTONIC: 105 + case CLOCK_BOOTTIME: 106 + if (copy_from_user(&t, rqtp, sizeof (struct timespec))) 107 + return -EFAULT; 108 + if (!timespec_valid(&t)) 109 + return -EINVAL; 110 + return hrtimer_nanosleep(&t, rmtp, flags & TIMER_ABSTIME ? 111 + HRTIMER_MODE_ABS : HRTIMER_MODE_REL, 112 + which_clock); 113 + default: 114 + return -EINVAL; 115 + } 116 + } 117 + 118 + #ifdef CONFIG_COMPAT 119 + long clock_nanosleep_restart(struct restart_block *restart_block) 120 + { 121 + return hrtimer_nanosleep_restart(restart_block); 122 + } 123 + #endif
+2 -1
kernel/time/timer.c
··· 1601 1601 irq_work_tick(); 1602 1602 #endif 1603 1603 scheduler_tick(); 1604 - run_posix_cpu_timers(p); 1604 + if (IS_ENABLED(CONFIG_POSIX_TIMERS)) 1605 + run_posix_cpu_timers(p); 1605 1606 } 1606 1607 1607 1608 /**
+7 -4
security/selinux/hooks.c
··· 2525 2525 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); 2526 2526 } 2527 2527 task_unlock(current); 2528 - update_rlimit_cpu(current, rlimit(RLIMIT_CPU)); 2528 + if (IS_ENABLED(CONFIG_POSIX_TIMERS)) 2529 + update_rlimit_cpu(current, rlimit(RLIMIT_CPU)); 2529 2530 } 2530 2531 } 2531 2532 ··· 2556 2555 */ 2557 2556 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); 2558 2557 if (rc) { 2559 - memset(&itimer, 0, sizeof itimer); 2560 - for (i = 0; i < 3; i++) 2561 - do_setitimer(i, &itimer, NULL); 2558 + if (IS_ENABLED(CONFIG_POSIX_TIMERS)) { 2559 + memset(&itimer, 0, sizeof itimer); 2560 + for (i = 0; i < 3; i++) 2561 + do_setitimer(i, &itimer, NULL); 2562 + } 2562 2563 spin_lock_irq(&current->sighand->siglock); 2563 2564 if (!fatal_signal_pending(current)) { 2564 2565 flush_sigqueue(&current->pending);