lkml.org 
[lkml]   [1998]   [Nov]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Date
From
Subjectarca-26
Arca 26 is out:

ftp://e-mind.com/pub/linux/kernel-patches/arca-26...

The differences between arca-25 ares:

o fixed timespec_to_jiffies() wraps, I include the new code here too
to allow more people to complain about:

Index: linux/include/linux/time.h
diff -u linux/include/linux/time.h:1.1.1.1 linux/include/linux/time.h:1.1.1.1.2.3
--- linux/include/linux/time.h:1.1.1.1 Fri Nov 20 00:01:14 1998
+++ linux/include/linux/time.h Sat Nov 21 01:38:33 1998
@@ -3,6 +3,7 @@

#include <asm/param.h>
#include <linux/types.h>
+#include <linux/kernel.h>

#ifndef _STRUCT_TIMESPEC
#define _STRUCT_TIMESPEC
@@ -15,22 +16,58 @@
/*
* change timeval to jiffies, trying to avoid the
* most obvious overflows..
+ * Added some overflow fix by Andrea Arcangeli
*/
-static __inline__ unsigned long
-timespec_to_jiffies(struct timespec *value)
+static __inline__ long timespec_to_jiffies(struct timespec *value)
{
- unsigned long sec = value->tv_sec;
- long nsec = value->tv_nsec;
+ unsigned long sec = value->tv_sec, nsec = value->tv_nsec, nsec_tmp;
+ long retval;

- if (sec > ((long)(~0UL >> 1) / HZ))
- return ~0UL >> 1;
- nsec += 1000000000L / HZ - 1;
- nsec /= 1000000000L / HZ;
- return HZ * sec + nsec;
+ if (sec >= LONG_MAX / HZ)
+ return LONG_MAX;
+ sec *= HZ;
+
+ nsec_tmp = nsec + 1000000000UL/HZ - 1;
+ if (nsec_tmp > nsec)
+ nsec = nsec_tmp;
+ nsec /= 1000000000UL/HZ;
+ if (nsec >= LONG_MAX)
+ return LONG_MAX;
+
+ retval = nsec + sec;
+ if (retval < 0)
+ return LONG_MAX;
+ return retval;
+}
+
+/*
+ * change timeval to jiffies plus one if the timespec struct is not null
+ * by Andrea Arcangeli
+ */
+static __inline__ long timespec_to_jiffies_plus_one(struct timespec *value)
+{
+ unsigned long sec = value->tv_sec, nsec = value->tv_nsec, nsec_tmp;
+ long retval;
+
+ if (sec >= (LONG_MAX-1) / HZ)
+ return LONG_MAX;
+ sec *= HZ;
+
+ nsec_tmp = nsec + 1000000000UL/HZ - 1;
+ if (nsec_tmp > nsec)
+ nsec = nsec_tmp;
+ nsec /= 1000000000UL/HZ;
+ if (nsec >= LONG_MAX-1)
+ return LONG_MAX;
+
+ retval = nsec + sec + (value->tv_sec || value->tv_nsec);
+ if (retval < 0)
+ return LONG_MAX;
+ return retval;
}

static __inline__ void
-jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
+jiffies_to_timespec(long jiffies, struct timespec *value)
{
value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
value->tv_sec = jiffies / HZ;
Index: linux/kernel/signal.c
diff -u linux/kernel/signal.c:1.1.1.1 linux/kernel/signal.c:1.1.1.1.2.2
--- linux/kernel/signal.c:1.1.1.1 Fri Nov 20 00:01:12 1998
+++ linux/kernel/signal.c Fri Nov 20 11:39:11 1998
@@ -742,8 +742,7 @@

timeout = MAX_SCHEDULE_TIMEOUT;
if (uts)
- timeout = (timespec_to_jiffies(&ts)
- + (ts.tv_sec || ts.tv_nsec));
+ timeout = timespec_to_jiffies_plus_one(&ts);

current->state = TASK_INTERRUPTIBLE;
timeout = schedule_timeout(timeout);
Index: linux/kernel/sched.c
diff -u linux/kernel/sched.c:1.1.1.1 linux/kernel/sched.c:1.1.1.1.2.9
--- linux/kernel/sched.c:1.1.1.1 Fri Nov 20 00:01:12 1998
+++ linux/kernel/sched.c Sat Nov 21 01:43:35 1998
@@ -1604,7 +1619,7 @@
asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
{
struct timespec t;
- unsigned long expire;
+ long expire;

if(copy_from_user(&t, rqtp, sizeof(struct timespec)))
return -EFAULT;
@@ -1626,7 +1641,7 @@
return 0;
}

- expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
+ expire = timespec_to_jiffies_plus_one(&t);

current->state = TASK_INTERRUPTIBLE;
expire = schedule_timeout(expire);
o restored the official timer code and fixed the SMP race in itimer
using bh_atomic contexts (SMP bug discovered by Linus)

Index: linux/kernel/exit.c
diff -u linux/kernel/exit.c:1.1.1.1 linux/kernel/exit.c:1.1.1.1.2.1
--- linux/kernel/exit.c:1.1.1.1 Fri Nov 20 00:01:12 1998
+++ linux/kernel/exit.c Fri Nov 20 00:15:38 1998
@@ -358,7 +358,9 @@
if (!tsk->pid)
panic("Attempted to kill the idle task!");
tsk->flags |= PF_EXITING;
+ start_bh_atomic();
del_timer(&tsk->real_timer);
+ end_bh_atomic();

lock_kernel();
fake_volatile:
Index: linux/kernel/itimer.c
diff -u linux/kernel/itimer.c:1.1.1.1 linux/kernel/itimer.c:1.1.1.1.2.3
--- linux/kernel/itimer.c:1.1.1.1 Fri Nov 20 00:01:12 1998
+++ linux/kernel/itimer.c Sat Nov 21 02:05:59 1998
@@ -11,6 +11,7 @@
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
+#include <linux/interrupt.h>

#include <asm/uaccess.h>

@@ -47,15 +48,19 @@
register unsigned long val, interval;

switch (which) {
+ int timer_pending;
case ITIMER_REAL:
interval = current->it_real_incr;
val = 0;
- if (del_timer(&current->real_timer)) {
+ start_bh_atomic();
+ timer_pending = del_timer(&current->real_timer);
+ end_bh_atomic();
+ if (timer_pending) {
unsigned long now = jiffies;
val = current->real_timer.expires;
add_timer(&current->real_timer);
/* look out for negative/zero itimer.. */
- if (val <= now)
+ if (time_before_eq(val, now))
val = now+1;
val -= now;
}
@@ -117,7 +122,9 @@
return k;
switch (which) {
case ITIMER_REAL:
+ start_bh_atomic();
del_timer(&current->real_timer);
+ end_bh_atomic();
current->it_real_value = j;
current->it_real_incr = i;
if (!j)
o wchan compile on alpha (and i386 ;-).

Andrea Arcangeli


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:45    [W:0.030 / U:0.668 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site