Dear RT Folks,

I'm pleased to announce the 3.6.9-rt21 release. 3.6.7-rt18, 3.6.8-rt19
and 3.6.9-rt20 are not announced updates to the respective 3.6.y
stable releases without any RT changes

Changes since 3.6.9-rt20:

   * Fix the PREEMPT_LAZY implementation on ARM

   * Fix the RCUTINY issues

   * Fix a long standing scheduler bug (See commit log of
     sched-enqueue-to-head.patch)


Known issues:

   * There is still a possibility to get false positives from the NOHZ
     idle softirq pending detector. It's rather complex to fix and I
     have postponed it for a separate release. The warnings are
     harmless and can be ignored for now.

The delta patch against 3.6.9-rt20 is appended below and can be found
here:

  
http://www.kernel.org/pub/linux/kernel/projects/rt/3.6/incr/patch-3.6.9-rt20-rt21.patch.xz

The RT patch against 3.6.9 can be found here:

  
http://www.kernel.org/pub/linux/kernel/projects/rt/3.6/patch-3.6.9-rt21.patch.xz

The split quilt queue is available at:

  
http://www.kernel.org/pub/linux/kernel/projects/rt/3.6/patches-3.6.9-rt21.tar.xz

Enjoy,

        tglx

------------->
Index: linux-stable/arch/arm/kernel/entry-armv.S
===================================================================
--- linux-stable.orig/arch/arm/kernel/entry-armv.S
+++ linux-stable/arch/arm/kernel/entry-armv.S
@@ -216,17 +216,18 @@ __irq_svc:
 #ifdef CONFIG_PREEMPT
        get_thread_info tsk
        ldr     r8, [tsk, #TI_PREEMPT]          @ get preempt count
-       ldr     r0, [tsk, #TI_FLAGS]            @ get flags
        teq     r8, #0                          @ if preempt count != 0
-       movne   r0, #0                          @ force flags to 0
-       tst     r0, #_TIF_NEED_RESCHED
-       blne    svc_preempt
-       ldr     r8, [tsk, #TI_PREEMPT_LAZY]     @ get preempt lazy count
+       bne     1f                              @ return from exeption
        ldr     r0, [tsk, #TI_FLAGS]            @ get flags
+       tst     r0, #_TIF_NEED_RESCHED          @ if NEED_RESCHED is set
+       blne    svc_preempt                     @ preempt!
+
+       ldr     r8, [tsk, #TI_PREEMPT_LAZY]     @ get preempt lazy count
        teq     r8, #0                          @ if preempt lazy count != 0
        movne   r0, #0                          @ force flags to 0
        tst     r0, #_TIF_NEED_RESCHED_LAZY
        blne    svc_preempt
+1:
 #endif
 
 #ifdef CONFIG_TRACE_IRQFLAGS
Index: linux-stable/kernel/Makefile
===================================================================
--- linux-stable.orig/kernel/Makefile
+++ linux-stable/kernel/Makefile
@@ -10,7 +10,7 @@ obj-y     = fork.o exec_domain.o panic.o
            kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o \
            hrtimer.o nsproxy.o srcu.o semaphore.o \
            notifier.o ksysfs.o cred.o \
-           async.o range.o groups.o lglock.o
+           async.o range.o groups.o lglock.o wait-simple.o
 
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace debug files and internal ftrace files
Index: linux-stable/kernel/rcutiny_plugin.h
===================================================================
--- linux-stable.orig/kernel/rcutiny_plugin.h
+++ linux-stable/kernel/rcutiny_plugin.h
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/wait-simple.h>
 
 /* Global control variables for rcupdate callback mechanism. */
 struct rcu_ctrlblk {
@@ -260,7 +261,7 @@ static void show_tiny_preempt_stats(stru
 
 /* Controls for rcu_kthread() kthread. */
 static struct task_struct *rcu_kthread_task;
-static DECLARE_WAIT_QUEUE_HEAD(rcu_kthread_wq);
+static DEFINE_SWAIT_HEAD(rcu_kthread_wq);
 static unsigned long have_rcu_kthread_work;
 
 /*
@@ -710,7 +711,7 @@ void synchronize_rcu(void)
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu);
 
-static DECLARE_WAIT_QUEUE_HEAD(sync_rcu_preempt_exp_wq);
+static DEFINE_SWAIT_HEAD(sync_rcu_preempt_exp_wq);
 static unsigned long sync_rcu_preempt_exp_count;
 static DEFINE_MUTEX(sync_rcu_preempt_exp_mutex);
 
@@ -732,7 +733,7 @@ static int rcu_preempted_readers_exp(voi
  */
 static void rcu_report_exp_done(void)
 {
-       wake_up(&sync_rcu_preempt_exp_wq);
+       swait_wake(&sync_rcu_preempt_exp_wq);
 }
 
 /*
@@ -784,8 +785,8 @@ void synchronize_rcu_expedited(void)
        } else {
                rcu_initiate_boost();
                local_irq_restore(flags);
-               wait_event(sync_rcu_preempt_exp_wq,
-                          !rcu_preempted_readers_exp());
+               swait_event(sync_rcu_preempt_exp_wq,
+                           !rcu_preempted_readers_exp());
        }
 
        /* Clean up and exit. */
@@ -855,7 +856,7 @@ static void invoke_rcu_callbacks(void)
 {
        have_rcu_kthread_work = 1;
        if (rcu_kthread_task != NULL)
-               wake_up(&rcu_kthread_wq);
+               swait_wake(&rcu_kthread_wq);
 }
 
 #ifdef CONFIG_RCU_TRACE
@@ -885,8 +886,8 @@ static int rcu_kthread(void *arg)
        unsigned long flags;
 
        for (;;) {
-               wait_event_interruptible(rcu_kthread_wq,
-                                        have_rcu_kthread_work != 0);
+               swait_event_interruptible(rcu_kthread_wq,
+                                         have_rcu_kthread_work != 0);
                morework = rcu_boost();
                local_irq_save(flags);
                work = have_rcu_kthread_work;
Index: linux-stable/kernel/sched/core.c
===================================================================
--- linux-stable.orig/kernel/sched/core.c
+++ linux-stable/kernel/sched/core.c
@@ -4268,6 +4268,8 @@ void rt_mutex_setprio(struct task_struct
 
        trace_sched_pi_setprio(p, prio);
        oldprio = p->prio;
+       if (oldprio == prio)
+               goto out_unlock;
        prev_class = p->sched_class;
        on_rq = p->on_rq;
        running = task_current(rq, p);
@@ -4618,6 +4620,13 @@ recheck:
                task_rq_unlock(rq, p, &flags);
                goto recheck;
        }
+
+       p->sched_reset_on_fork = reset_on_fork;
+
+       oldprio = p->prio;
+       if (oldprio == param->sched_priority)
+               goto out;
+
        on_rq = p->on_rq;
        running = task_current(rq, p);
        if (on_rq)
@@ -4625,18 +4634,17 @@ recheck:
        if (running)
                p->sched_class->put_prev_task(rq, p);
 
-       p->sched_reset_on_fork = reset_on_fork;
-
-       oldprio = p->prio;
        prev_class = p->sched_class;
        __setscheduler(rq, p, policy, param->sched_priority);
 
        if (running)
                p->sched_class->set_curr_task(rq);
        if (on_rq)
-               enqueue_task(rq, p, 0);
+               enqueue_task(rq, p, oldprio < param->sched_priority ?
+                            ENQUEUE_HEAD : 0);
 
        check_class_changed(rq, p, prev_class, oldprio);
+out:
        task_rq_unlock(rq, p, &flags);
 
        rt_mutex_adjust_pi(p);
Index: linux-stable/localversion-rt
===================================================================
--- linux-stable.orig/localversion-rt
+++ linux-stable/localversion-rt
@@ -1 +1 @@
--rt20
+-rt21
Index: linux-stable/include/linux/wait-simple.h
===================================================================
--- /dev/null
+++ linux-stable/include/linux/wait-simple.h
@@ -0,0 +1,204 @@
+#ifndef _LINUX_WAIT_SIMPLE_H
+#define _LINUX_WAIT_SIMPLE_H
+
+#include <linux/spinlock.h>
+#include <linux/list.h>
+
+#include <asm/current.h>
+
+struct swaiter {
+       struct task_struct      *task;
+       struct list_head        node;
+};
+
+#define DEFINE_SWAITER(name)                                   \
+       struct swaiter name = {                                 \
+               .task   = current,                              \
+               .node   = LIST_HEAD_INIT((name).node),          \
+       }
+
+struct swait_head {
+       raw_spinlock_t          lock;
+       struct list_head        list;
+};
+
+#define DEFINE_SWAIT_HEAD(name)                                        \
+       struct swait_head name = {                              \
+               .lock   = __RAW_SPIN_LOCK_UNLOCKED(name.lock),  \
+               .list   = LIST_HEAD_INIT((name).list),          \
+       }
+
+extern void __init_swait_head(struct swait_head *h, struct lock_class_key 
*key);
+
+#define init_swait_head(swh)                                   \
+       do {                                                    \
+               static struct lock_class_key __key;             \
+                                                               \
+               __init_swait_head((swh), &__key);               \
+       } while (0)
+
+/*
+ * Waiter functions
+ */
+static inline bool swaiter_enqueued(struct swaiter *w)
+{
+       return w->task != NULL;
+}
+
+extern void swait_prepare(struct swait_head *head, struct swaiter *w, int 
state);
+extern void swait_finish(struct swait_head *head, struct swaiter *w);
+
+/*
+ * Adds w to head->list. Must be called with head->lock locked.
+ */
+static inline void __swait_enqueue(struct swait_head *head, struct swaiter *w)
+{
+       list_add(&w->node, &head->list);
+}
+
+/*
+ * Removes w from head->list. Must be called with head->lock locked.
+ */
+static inline void __swait_dequeue(struct swaiter *w)
+{
+       list_del_init(&w->node);
+}
+
+/*
+ * Check whether a head has waiters enqueued
+ */
+static inline bool swait_head_has_waiters(struct swait_head *h)
+{
+       return !list_empty(&h->list);
+}
+
+/*
+ * Wakeup functions
+ */
+extern int __swait_wake(struct swait_head *head, unsigned int state);
+
+static inline int swait_wake(struct swait_head *head)
+{
+       return swait_head_has_waiters(head) ?
+               __swait_wake(head, TASK_NORMAL) : 0;
+}
+
+static inline int swait_wake_interruptible(struct swait_head *head)
+{
+       return swait_head_has_waiters(head) ?
+               __swait_wake(head, TASK_INTERRUPTIBLE) : 0;
+}
+
+/*
+ * Event API
+ */
+
+#define __swait_event(wq, condition)                                   \
+do {                                                                   \
+       DEFINE_SWAITER(__wait);                                         \
+                                                                       \
+       for (;;) {                                                      \
+               swait_prepare(&wq, &__wait, TASK_UNINTERRUPTIBLE);      \
+               if (condition)                                          \
+                       break;                                          \
+               schedule();                                             \
+       }                                                               \
+       swait_finish(&wq, &__wait);                                     \
+} while (0)
+
+/**
+ * swait_event - sleep until a condition gets true
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ *
+ * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
+ * @condition evaluates to true. The @condition is checked each time
+ * the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ */
+#define swait_event(wq, condition)                                     \
+do {                                                                   \
+       if (condition)                                                  \
+               break;                                                  \
+       __swait_event(wq, condition);                                   \
+} while (0)
+
+#define __swait_event_interruptible(wq, condition, ret)                        
\
+do {                                                                   \
+       DEFINE_SWAITER(__wait);                                         \
+                                                                       \
+       for (;;) {                                                      \
+               swait_prepare(&wq, &__wait, TASK_INTERRUPTIBLE);        \
+               if (condition)                                          \
+                       break;                                          \
+               if (signal_pending(current)) {                          \
+                       ret = -ERESTARTSYS;                             \
+                       break;                                          \
+               }                                                       \
+               schedule();                                             \
+       }                                                               \
+       swait_finish(&wq, &__wait);                                     \
+} while (0)
+
+/**
+ * swait_event_interruptible - sleep until a condition gets true
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true. The @condition is checked each time
+ * the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ */
+#define swait_event_interruptible(wq, condition)                       \
+({                                                                     \
+       int __ret = 0;                                                  \
+       if (!(condition))                                               \
+               __swait_event_interruptible(wq, condition, __ret);      \
+       __ret;                                                          \
+})
+
+#define __swait_event_timeout(wq, condition, ret)                      \
+do {                                                                   \
+       DEFINE_SWAITER(__wait);                                         \
+                                                                       \
+       for (;;) {                                                      \
+               swait_prepare(&wq, &__wait, TASK_UNINTERRUPTIBLE);      \
+               if (condition)                                          \
+                       break;                                          \
+               ret = schedule_timeout(ret);                            \
+               if (!ret)                                               \
+                       break;                                          \
+       }                                                               \
+       swait_finish(&wq, &__wait);                                     \
+} while (0)
+
+/**
+ * swait_event_timeout - sleep until a condition gets true or a timeout elapses
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ * @timeout: timeout, in jiffies
+ *
+ * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
+ * @condition evaluates to true. The @condition is checked each time
+ * the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * The function returns 0 if the @timeout elapsed, and the remaining
+ * jiffies if the condition evaluated to true before the timeout elapsed.
+ */
+#define swait_event_timeout(wq, condition, timeout)                    \
+({                                                                     \
+       long __ret = timeout;                                           \
+       if (!(condition))                                               \
+               __swait_event_timeout(wq, condition, __ret);            \
+       __ret;                                                          \
+})
+
+#endif
Index: linux-stable/kernel/wait-simple.c
===================================================================
--- /dev/null
+++ linux-stable/kernel/wait-simple.c
@@ -0,0 +1,68 @@
+/*
+ * Simple waitqueues without fancy flags and callbacks
+ *
+ * (C) 2011 Thomas Gleixner <t...@linutronix.de>
+ *
+ * Based on kernel/wait.c
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/wait-simple.h>
+
+void __init_swait_head(struct swait_head *head, struct lock_class_key *key)
+{
+       raw_spin_lock_init(&head->lock);
+       lockdep_set_class(&head->lock, key);
+       INIT_LIST_HEAD(&head->list);
+}
+EXPORT_SYMBOL_GPL(__init_swait_head);
+
+void swait_prepare(struct swait_head *head, struct swaiter *w, int state)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&head->lock, flags);
+       w->task = current;
+       if (list_empty(&w->node))
+               __swait_enqueue(head, w);
+       set_current_state(state);
+       raw_spin_unlock_irqrestore(&head->lock, flags);
+}
+EXPORT_SYMBOL_GPL(swait_prepare);
+
+void swait_finish(struct swait_head *head, struct swaiter *w)
+{
+       unsigned long flags;
+
+       __set_current_state(TASK_RUNNING);
+       if (w->task) {
+               raw_spin_lock_irqsave(&head->lock, flags);
+               __swait_dequeue(w);
+               raw_spin_unlock_irqrestore(&head->lock, flags);
+       }
+}
+EXPORT_SYMBOL_GPL(swait_finish);
+
+int __swait_wake(struct swait_head *head, unsigned int state)
+{
+       struct swaiter *curr, *next;
+       unsigned long flags;
+       int woken = 0;
+
+       raw_spin_lock_irqsave(&head->lock, flags);
+
+       list_for_each_entry_safe(curr, next, &head->list, node) {
+               if (wake_up_state(curr->task, state)) {
+                       __swait_dequeue(curr);
+                       curr->task = NULL;
+                       woken++;
+               }
+       }
+
+       raw_spin_unlock_irqrestore(&head->lock, flags);
+       return woken;
+}
+EXPORT_SYMBOL_GPL(__swait_wake);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to