Re: [patch] Real-Time Preemption, -RT-2.6.10-rc2-mm2-V0.7.29-0

From: Ingo Molnar
Date: Sat Nov 20 2004 - 07:22:58 EST



* Peter Zijlstra <a.p.zijlstra@xxxxxxxxx> wrote:

> Hi Ingo,
>
> in 29-4 I get a lot of these lines in my log:
>
> drivers/usb/input/hid-core.c: input irq status -71 received
>
> 29-0 didn't do that.

weird. I've attached the diff between -0 and -4 - nothing should affect
USB, except perhaps the manage.c bits. Could you try to revert the
smaller plaintext patch below, does that solve this problem?

Ingo

--- linux.old/kernel/irq/manage.c
+++ linux.new/kernel/irq/manage.c
@@ -509,9 +509,7 @@ static int start_irq_thread(int irq, str
* such a case:
*/
smp_mb();
-
- if (desc->status & IRQ_INPROGRESS)
- wake_up_process(desc->thread);
+ wake_up_process(desc->thread);

return 0;
}
--- linux.old/Makefile
+++ linux.new/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 10
-EXTRAVERSION =-rc2-mm2-V0.7.29-0
+EXTRAVERSION =-rc2-mm2-V0.7.29-5
NAME=Woozy Numbat

# *DOCUMENTATION*
--- linux.old/arch/i386/kernel/io_apic.c
+++ linux.new/arch/i386/kernel/io_apic.c
@@ -1956,7 +1956,7 @@ static void end_level_ioapic_irq(unsigne
unmask_IO_APIC_irq(irq);
}

-#else /* !CONFIG_PREEMPT_HARDIRQS */
+#else /* !CONFIG_PREEMPT_HARDIRQS || !CONFIG_SMP */

static void mask_and_ack_level_ioapic_irq(unsigned int irq)
{
--- linux.old/drivers/base/bus.c
+++ linux.new/drivers/base/bus.c
@@ -65,7 +65,7 @@ static struct sysfs_ops driver_sysfs_ops
static void driver_release(struct kobject * kobj)
{
struct device_driver * drv = to_driver(kobj);
- up(&drv->unload_sem);
+ complete(&drv->unload_done);
}

static struct kobj_type ktype_driver = {
--- linux.old/drivers/base/driver.c
+++ linux.new/drivers/base/driver.c
@@ -79,14 +79,13 @@ void put_driver(struct device_driver * d
* since most of the things we have to do deal with the bus
* structures.
*
- * The one interesting aspect is that we initialize @drv->unload_sem
- * to a locked state here. It will be unlocked when the driver
- * reference count reaches 0.
+ * We init the completion strcut here. When the reference
+ * count reaches zero, complete() is called from bus_release().
*/
int driver_register(struct device_driver * drv)
{
INIT_LIST_HEAD(&drv->devices);
- init_MUTEX_LOCKED(&drv->unload_sem);
+ init_completion(&drv->unload_done);
return bus_add_driver(drv);
}

@@ -97,18 +96,16 @@ int driver_register(struct device_driver
*
* Again, we pass off most of the work to the bus-level call.
*
- * Though, once that is done, we attempt to take @drv->unload_sem.
- * This will block until the driver refcount reaches 0, and it is
- * released. Only modular drivers will call this function, and we
+ * Though, once that is done, we wait until the driver refcount
+ * reaches 0, and complete() is called in bus_release().
+ * Only modular drivers will call this function, and we
* have to guarantee that it won't complete, letting the driver
* unload until all references are gone.
*/
-
void driver_unregister(struct device_driver * drv)
{
bus_remove_driver(drv);
- down(&drv->unload_sem);
- up(&drv->unload_sem);
+ wait_for_completion(&drv->unload_done);
}

/**
--- linux.old/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ linux.new/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -658,7 +658,7 @@ static void dvb_frontend_stop (struct dv
printk("dvb_frontend_stop: thread PID %d already died\n",
fe->thread_pid);
/* make sure the mutex was not held by the thread */
- init_MUTEX (&fe->sem);
+ sema_init_nocheck (&fe->sem, 1);
return;
}

@@ -1127,10 +1127,10 @@ dvb_register_frontend (int (*ioctl) (str

memset (fe, 0, sizeof (struct dvb_frontend_data));

- init_MUTEX (&fe->sem);
+ sema_init_nocheck (&fe->sem, 1);
init_waitqueue_head (&fe->wait_queue);
init_waitqueue_head (&fe->events.wait_queue);
- init_MUTEX (&fe->events.sem);
+ sema_init_nocheck (&fe->events.sem, 1);
fe->events.eventw = fe->events.eventr = 0;
fe->events.overflow = 0;
fe->module = module;
--- linux.old/fs/lockd/svc.c
+++ linux.new/fs/lockd/svc.c
@@ -49,7 +49,7 @@ static pid_t nlmsvc_pid;
int nlmsvc_grace_period;
unsigned long nlmsvc_timeout;

-static DECLARE_MUTEX_NOCHECK(lockd_start);
+static DECLARE_WAIT_QUEUE_HEAD(lockd_start);
static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);

/*
@@ -112,7 +112,7 @@ lockd(struct svc_rqst *rqstp)
* Let our maker know we're running.
*/
nlmsvc_pid = current->pid;
- up(&lockd_start);
+ wake_up(&lockd_start);

daemonize("lockd");

@@ -233,6 +233,7 @@ lockd_up(void)
printk(KERN_WARNING
"lockd_up: no pid, %d users??\n", nlmsvc_users);

+
error = -ENOMEM;
serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE);
if (!serv) {
@@ -261,8 +262,15 @@ lockd_up(void)
"lockd_up: create thread failed, error=%d\n", error);
goto destroy_and_out;
}
- down(&lockd_start);
-
+ /*
+ * Wait for the lockd process to start, but since we're holding
+ * the lockd semaphore, we can't wait around forever ...
+ */
+ if (wait_event_interruptible_timeout(lockd_start,
+ nlmsvc_pid != 0, HZ) <= 0) {
+ printk(KERN_WARNING
+ "lockd_down: lockd failed to start\n");
+ }
/*
* Note: svc_serv structures have an initial use count of 1,
* so we exit through here on both success and failure.
@@ -302,16 +310,12 @@ lockd_down(void)
* Wait for the lockd process to exit, but since we're holding
* the lockd semaphore, we can't wait around forever ...
*/
- clear_thread_flag(TIF_SIGPENDING);
- interruptible_sleep_on_timeout(&lockd_exit, HZ);
- if (nlmsvc_pid) {
+ if (wait_event_interruptible_timeout(lockd_exit,
+ nlmsvc_pid == 0, HZ) <= 0) {
printk(KERN_WARNING
"lockd_down: lockd failed to exit, clearing pid\n");
nlmsvc_pid = 0;
}
- spin_lock_irq(&current->sighand->siglock);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
out:
up(&nlmsvc_sema);
}
@@ -428,7 +432,6 @@ module_param_call(nlm_tcpport, param_set

static int __init init_nlm(void)
{
- down(&lockd_start); // initialize as locked
nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root, 0);
return nlm_sysctl_table ? 0 : -ENOMEM;
}
--- linux.old/include/linux/device.h
+++ linux.new/include/linux/device.h
@@ -102,7 +102,7 @@ struct device_driver {
char * name;
struct bus_type * bus;

- struct semaphore unload_sem;
+ struct completion unload_done;
struct kobject kobj;
struct list_head devices;

--- linux.old/include/linux/preempt.h
+++ linux.new/include/linux/preempt.h
@@ -66,6 +66,8 @@ do { \
#define preempt_enable() do { } while (0)
#define preempt_check_resched() do { } while (0)

+#define preempt_schedule_irq() do { } while (0)
+
#endif

#endif /* __LINUX_PREEMPT_H */
--- linux.old/kernel/irq/manage.c
+++ linux.new/kernel/irq/manage.c
@@ -509,9 +509,7 @@ static int start_irq_thread(int irq, str
* such a case:
*/
smp_mb();
-
- if (desc->status & IRQ_INPROGRESS)
- wake_up_process(desc->thread);
+ wake_up_process(desc->thread);

return 0;
}
--- linux.old/kernel/rt.c
+++ linux.new/kernel/rt.c
@@ -1112,7 +1112,7 @@ static void __up_mutex(struct rt_mutex *
* reschedule then do it here without enabling interrupts
* again (and lengthening latency):
*/
- while (need_resched() && !irqs_disabled_flags(flags) && !preempt_count())
+ if (need_resched() && !irqs_disabled_flags(flags) && !preempt_count())
preempt_schedule_irq();
local_irq_restore(flags);
/* no need to check for preempt here - we just handled it */
--- linux.old/kernel/sched.c
+++ linux.new/kernel/sched.c
@@ -1165,7 +1165,7 @@ out:
* reschedule then do it here without enabling interrupts
* again (and lengthening latency):
*/
- while (need_resched() && !irqs_disabled_flags(flags) && !preempt_count())
+ if (need_resched() && !irqs_disabled_flags(flags) && !preempt_count())
preempt_schedule_irq();
local_irq_restore(flags);
/* no need to check for preempt here - we just handled it */