--- linux/include/linux/sched.h.orig Mon Mar 13 16:49:12 2000 +++ linux/include/linux/sched.h Mon Mar 13 17:37:32 2000 @@ -268,6 +268,7 @@ */ struct exec_domain *exec_domain; volatile long need_resched; + atomic_t may_preempt; cycles_t avg_slice; int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */ --- linux/include/asm-i386/uaccess.h.orig Mon Mar 13 16:49:12 2000 +++ linux/include/asm-i386/uaccess.h Mon Mar 13 17:38:30 2000 @@ -253,6 +253,7 @@ #define __copy_user(to,from,size) \ do { \ int __d0, __d1; \ + atomic_inc_local(¤t->may_preempt); \ __asm__ __volatile__( \ "0: rep; movsl\n" \ " movl %3,%0\n" \ @@ -270,11 +271,13 @@ : "=&c"(size), "=&D" (__d0), "=&S" (__d1) \ : "r"(size & 3), "0"(size / 4), "1"(to), "2"(from) \ : "memory"); \ + atomic_dec_local(¤t->may_preempt); \ } while (0) #define __copy_user_zeroing(to,from,size) \ do { \ int __d0, __d1; \ + atomic_inc_local(¤t->may_preempt); \ __asm__ __volatile__( \ "0: rep; movsl\n" \ " movl %3,%0\n" \ @@ -298,6 +301,7 @@ : "=&c"(size), "=&D" (__d0), "=&S" (__d1) \ : "r"(size & 3), "0"(size / 4), "1"(to), "2"(from) \ : "memory"); \ + atomic_dec_local(¤t->may_preempt); \ } while (0) /* We let the __ versions of copy_from/to_user inline, because they're often --- linux/include/asm-i386/atomic.h.orig Mon Mar 13 17:35:08 2000 +++ linux/include/asm-i386/atomic.h Mon Mar 13 17:36:36 2000 @@ -65,10 +65,30 @@ :"m" (__atomic_fool_gcc(v))); } +/* + * This variant is an _IRQ-atomic_ (and compiler-barrier) increment, + * which is a simple but LOCK-less incl on x86. + */ +static __inline__ void atomic_inc_local(volatile atomic_t *v) +{ + __asm__ __volatile__( + "incl %0" + :"=m" (__atomic_fool_gcc(v)) + :"m" (__atomic_fool_gcc(v))); +} + static __inline__ void atomic_dec(volatile atomic_t *v) { __asm__ __volatile__( LOCK "decl %0" + :"=m" (__atomic_fool_gcc(v)) + :"m" (__atomic_fool_gcc(v))); +} + +static __inline__ void atomic_dec_local(volatile atomic_t *v) +{ + __asm__ __volatile__( + "decl %0" :"=m" (__atomic_fool_gcc(v)) :"m" (__atomic_fool_gcc(v))); } --- linux/arch/i386/kernel/entry.S.orig Mon Mar 13 16:49:12 2000 +++ linux/arch/i386/kernel/entry.S Mon Mar 13 17:44:41 2000 @@ -76,7 +76,8 @@ addr_limit = 12 exec_domain = 16 need_resched = 20 -processor = 56 +may_preempt = 24 +processor = 60 ENOSYS = 38 @@ -280,6 +281,20 @@ movb CS(%esp),%al testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor? jne ret_with_reschedule + cmpl $0, need_resched(%ebx) + jnz restore_all + cmpl $0, may_preempt(%ebx) + jz restore_all + + /* + * Preempt kernel-space, but only if we return to non-IRQ context: + */ + movl processor(%ebx), %eax + shll $5,%eax + movl SYMBOL_NAME(irq_stat)(,%eax), %edx + addl SYMBOL_NAME(irq_stat)+4(,%eax), %edx + jnz restore_all + call SYMBOL_NAME(schedule) jmp restore_all ALIGN