aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/ia32/sys_ia32.c14
-rw-r--r--arch/mips/kernel/sysirix.c22
-rw-r--r--arch/x86_64/ia32/sys_ia32.c16
-rw-r--r--include/linux/time.h1
-rw-r--r--kernel/itimer.c37
-rw-r--r--kernel/timer.c14
6 files changed, 43 insertions, 61 deletions
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 70dba1f0e2ee..13e739e4c84d 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -1166,19 +1166,7 @@ put_tv32 (struct compat_timeval __user *o, struct timeval *i)
1166asmlinkage unsigned long 1166asmlinkage unsigned long
1167sys32_alarm (unsigned int seconds) 1167sys32_alarm (unsigned int seconds)
1168{ 1168{
1169 struct itimerval it_new, it_old; 1169 return alarm_setitimer(seconds);
1170 unsigned int oldalarm;
1171
1172 it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
1173 it_new.it_value.tv_sec = seconds;
1174 it_new.it_value.tv_usec = 0;
1175 do_setitimer(ITIMER_REAL, &it_new, &it_old);
1176 oldalarm = it_old.it_value.tv_sec;
1177 /* ehhh.. We can't return 0 if we have an alarm pending.. */
1178 /* And we'd better return too much than too little anyway */
1179 if (it_old.it_value.tv_usec)
1180 oldalarm++;
1181 return oldalarm;
1182} 1170}
1183 1171
1184/* Translations due to time_t size differences. Which affects all 1172/* Translations due to time_t size differences. Which affects all
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 0fc3730a294f..5407b784cd01 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -645,27 +645,7 @@ static inline void getitimer_real(struct itimerval *value)
645 645
646asmlinkage unsigned int irix_alarm(unsigned int seconds) 646asmlinkage unsigned int irix_alarm(unsigned int seconds)
647{ 647{
648 struct itimerval it_new, it_old; 648 return alarm_setitimer(seconds);
649 unsigned int oldalarm;
650
651 if (!seconds) {
652 getitimer_real(&it_old);
653 del_timer(&current->real_timer);
654 } else {
655 it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
656 it_new.it_value.tv_sec = seconds;
657 it_new.it_value.tv_usec = 0;
658 do_setitimer(ITIMER_REAL, &it_new, &it_old);
659 }
660 oldalarm = it_old.it_value.tv_sec;
661 /*
662 * ehhh.. We can't return 0 if we have an alarm pending ...
663 * And we'd better return too much than too little anyway
664 */
665 if (it_old.it_value.tv_usec)
666 oldalarm++;
667
668 return oldalarm;
669} 649}
670 650
671asmlinkage int irix_pause(void) 651asmlinkage int irix_pause(void)
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 2bc55af95419..2b2d029f477c 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -430,24 +430,12 @@ put_tv32(struct compat_timeval __user *o, struct timeval *i)
430 return err; 430 return err;
431} 431}
432 432
433extern int do_setitimer(int which, struct itimerval *, struct itimerval *); 433extern unsigned int alarm_setitimer(unsigned int seconds);
434 434
435asmlinkage long 435asmlinkage long
436sys32_alarm(unsigned int seconds) 436sys32_alarm(unsigned int seconds)
437{ 437{
438 struct itimerval it_new, it_old; 438 return alarm_setitimer(seconds);
439 unsigned int oldalarm;
440
441 it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
442 it_new.it_value.tv_sec = seconds;
443 it_new.it_value.tv_usec = 0;
444 do_setitimer(ITIMER_REAL, &it_new, &it_old);
445 oldalarm = it_old.it_value.tv_sec;
446 /* ehhh.. We can't return 0 if we have an alarm pending.. */
447 /* And we'd better return too much than too little anyway */
448 if (it_old.it_value.tv_usec)
449 oldalarm++;
450 return oldalarm;
451} 439}
452 440
453/* Translations due to time_t size differences. Which affects all 441/* Translations due to time_t size differences. Which affects all
diff --git a/include/linux/time.h b/include/linux/time.h
index d9cdba54b789..bf0e785e2e03 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -101,6 +101,7 @@ extern long do_utimes(int dfd, char __user *filename, struct timeval *times);
101struct itimerval; 101struct itimerval;
102extern int do_setitimer(int which, struct itimerval *value, 102extern int do_setitimer(int which, struct itimerval *value,
103 struct itimerval *ovalue); 103 struct itimerval *ovalue);
104extern unsigned int alarm_setitimer(unsigned int seconds);
104extern int do_getitimer(int which, struct itimerval *value); 105extern int do_getitimer(int which, struct itimerval *value);
105extern void getnstimeofday(struct timespec *tv); 106extern void getnstimeofday(struct timespec *tv);
106 107
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 379be2f8c84c..a2dc375927d8 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -226,6 +226,43 @@ again:
226 return 0; 226 return 0;
227} 227}
228 228
229/**
230 * alarm_setitimer - set alarm in seconds
231 *
232 * @seconds: number of seconds until alarm
233 * 0 disables the alarm
234 *
235 * Returns the remaining time in seconds of a pending timer or 0 when
236 * the timer is not active.
237 *
238 * On 32 bit machines the seconds value is limited to (INT_MAX/2) to avoid
239 * negative timeval settings which would cause immediate expiry.
240 */
241unsigned int alarm_setitimer(unsigned int seconds)
242{
243 struct itimerval it_new, it_old;
244
245#if BITS_PER_LONG < 64
246 if (seconds > INT_MAX)
247 seconds = INT_MAX;
248#endif
249 it_new.it_value.tv_sec = seconds;
250 it_new.it_value.tv_usec = 0;
251 it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
252
253 do_setitimer(ITIMER_REAL, &it_new, &it_old);
254
255 /*
256 * We can't return 0 if we have an alarm pending ... And we'd
257 * better return too much than too little anyway
258 */
259 if ((!it_old.it_value.tv_sec && it_old.it_value.tv_usec) ||
260 it_old.it_value.tv_usec >= 500000)
261 it_old.it_value.tv_sec++;
262
263 return it_old.it_value.tv_sec;
264}
265
229asmlinkage long sys_setitimer(int which, 266asmlinkage long sys_setitimer(int which,
230 struct itimerval __user *value, 267 struct itimerval __user *value,
231 struct itimerval __user *ovalue) 268 struct itimerval __user *ovalue)
diff --git a/kernel/timer.c b/kernel/timer.c
index 17d956cebcb9..13fa72cac7d8 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -956,19 +956,7 @@ void do_timer(struct pt_regs *regs)
956 */ 956 */
957asmlinkage unsigned long sys_alarm(unsigned int seconds) 957asmlinkage unsigned long sys_alarm(unsigned int seconds)
958{ 958{
959 struct itimerval it_new, it_old; 959 return alarm_setitimer(seconds);
960 unsigned int oldalarm;
961
962 it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
963 it_new.it_value.tv_sec = seconds;
964 it_new.it_value.tv_usec = 0;
965 do_setitimer(ITIMER_REAL, &it_new, &it_old);
966 oldalarm = it_old.it_value.tv_sec;
967 /* ehhh.. We can't return 0 if we have an alarm pending.. */
968 /* And we'd better return too much than too little anyway */
969 if ((!oldalarm && it_old.it_value.tv_usec) || it_old.it_value.tv_usec >= 500000)
970 oldalarm++;
971 return oldalarm;
972} 960}
973 961
974#endif 962#endif