[PATCH] misc. kernel preemption bits

From: Robert Love (rml@tech9.net)
Date: Thu Aug 29 2002 - 10:33:01 EST


Linus,

Misc. kernel preemption-related bits. Specifically,

        - update to Documentation/preempt-locking.txt (me)

        - preempt-safe arch/i386/kernel/ioport.c :: sys_ioperm()
          (George Anzinger)

        - remove "kernel_lock()" cruft in include/linux/smp.h
          (Andrew Morton)

        - we have a debug check in preempt_schedule that, even
          on detecting a schedule with irqs disabled, still goes
          ahead and reschedules. We should return. (me)

        - preempt-safe net/core/dev.c :: netif_rx() (George Anzinger)

All fairly trivial and/or simple. Patch is against 2.5.32-bk. Please,
apply.

        Robert Love

diff -urN linux-2.5.32/Documentation/preempt-locking.txt linux/Documentation/preempt-locking.txt
--- linux-2.5.32/Documentation/preempt-locking.txt Tue Aug 27 15:26:32 2002
+++ linux/Documentation/preempt-locking.txt Wed Aug 28 23:23:30 2002
@@ -1,7 +1,7 @@
                   Proper Locking Under a Preemptible Kernel:
                        Keeping Kernel Code Preempt-Safe
- Robert Love <rml@tech9.net>
- Last Updated: 22 Jan 2002
+ Robert Love <rml@tech9.net>
+ Last Updated: 28 Aug 2002
 

 INTRODUCTION
@@ -112,3 +112,24 @@
 
 This code is not preempt-safe, but see how easily we can fix it by simply
 moving the spin_lock up two lines.
+
+
+PREVENTING PREEMPTION USING INTERRUPT DISABLING
+
+
+It is possible to prevent a preemption event using local_irq_disable and
+local_irq_save. Note, when doing so, you must be very careful to not cause
+an event that would set need_resched and result in a preemption check. When
+in doubt, rely on locking or explicit preemption disabling.
+
+Note in 2.5 interrupt disabling is now only per-CPU (e.g. local).
+
+An additional concern is proper usage of local_irq_disable and local_irq_save.
+These may be used to protect from preemption, however, on exit, if preemption
+may be enabled, a test to see if preemption is required should be done. If
+these are called from the spin_lock and read/write lock macros, the right thing
+is done. They may also be called within a spin-lock protected region, however,
+if they are ever called outside of this context, a test for preemption should
+be made. Do note that calls from interrupt context or bottom half/ tasklets
+are also protected by preemption locks and so may use the versions which do
+not check preemption.
diff -urN linux-2.5.32/arch/i386/kernel/ioport.c linux/arch/i386/kernel/ioport.c
--- linux-2.5.32/arch/i386/kernel/ioport.c Tue Aug 27 15:26:42 2002
+++ linux/arch/i386/kernel/ioport.c Wed Aug 28 23:23:30 2002
@@ -55,12 +55,16 @@
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
         struct thread_struct * t = &current->thread;
- struct tss_struct * tss = init_tss + smp_processor_id();
+ struct tss_struct * tss;
+ int ret = 0;
 
         if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32))
                 return -EINVAL;
         if (turn_on && !capable(CAP_SYS_RAWIO))
                 return -EPERM;
+
+ tss = init_tss + get_cpu();
+
         /*
          * If it's the first ioperm() call in this thread's lifetime, set the
          * IO bitmap up. ioperm() is much less timing critical than clone(),
@@ -69,8 +73,11 @@
         if (!t->ts_io_bitmap) {
                 unsigned long *bitmap;
                 bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
- if (!bitmap)
- return -ENOMEM;
+ if (!bitmap) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
                 /*
                  * just in case ...
                  */
@@ -88,7 +95,9 @@
         set_bitmap(t->ts_io_bitmap, from, num, !turn_on);
         set_bitmap(tss->io_bitmap, from, num, !turn_on);
 
- return 0;
+out:
+ put_cpu();
+ return ret;
 }
 
 /*
diff -urN linux-2.5.32/include/linux/smp.h linux/include/linux/smp.h
--- linux-2.5.32/include/linux/smp.h Tue Aug 27 15:26:43 2002
+++ linux/include/linux/smp.h Wed Aug 28 23:23:30 2002
@@ -87,9 +87,6 @@
 #define smp_processor_id() 0
 #define hard_smp_processor_id() 0
 #define smp_threads_ready 1
-#ifndef CONFIG_PREEMPT
-#define kernel_lock()
-#endif
 #define smp_call_function(func,info,retry,wait) ({ 0; })
 static inline void smp_send_reschedule(int cpu) { }
 static inline void smp_send_reschedule_all(void) { }
diff -urN linux-2.5.32/kernel/sched.c linux/kernel/sched.c
--- linux-2.5.32/kernel/sched.c Tue Aug 27 15:26:37 2002
+++ linux/kernel/sched.c Wed Aug 28 23:23:24 2002
@@ -1039,6 +1039,7 @@
                 printk("bad: schedule() with irqs disabled!\n");
                 show_stack(NULL);
                 preempt_enable_no_resched();
+ return;
         }
 
 need_resched:
diff -urN linux-2.5.32/net/core/dev.c linux/net/core/dev.c
--- linux-2.5.32/net/core/dev.c Tue Aug 27 15:26:43 2002
+++ linux/net/core/dev.c Wed Aug 28 23:23:30 2002
@@ -1229,19 +1229,20 @@
 
 int netif_rx(struct sk_buff *skb)
 {
- int this_cpu = smp_processor_id();
+ int this_cpu;
         struct softnet_data *queue;
         unsigned long flags;
 
         if (!skb->stamp.tv_sec)
                 do_gettimeofday(&skb->stamp);
 
- /* The code is rearranged so that the path is the most
- short when CPU is congested, but is still operating.
+ /*
+ * The code is rearranged so that the path is the most
+ * short when CPU is congested, but is still operating.
          */
- queue = &softnet_data[this_cpu];
-
         local_irq_save(flags);
+ this_cpu = smp_processor_id();
+ queue = &softnet_data[this_cpu];
 
         netdev_rx_stat[this_cpu].total++;
         if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
@@ -1252,10 +1253,10 @@
 enqueue:
                         dev_hold(skb->dev);
                         __skb_queue_tail(&queue->input_pkt_queue, skb);
- local_irq_restore(flags);
 #ifndef OFFLINE_SAMPLE
                         get_sample_stats(this_cpu);
 #endif
+ local_irq_restore(flags);
                         return queue->cng_level;
                 }
 

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



This archive was generated by hypermail 2b29 : Sat Aug 31 2002 - 22:00:26 EST