]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/blob - rt-patches/0205-ipc-sem-Rework-semaphore-wakeups.patch
rt_patches: required rebase due to printk change
[hercules2020/nv-tegra/linux-4.4.git] / rt-patches / 0205-ipc-sem-Rework-semaphore-wakeups.patch
1 From ab3b7df5658a5fdaa17d183eeab4acfe26f2f935 Mon Sep 17 00:00:00 2001
2 From: Peter Zijlstra <peterz@infradead.org>
3 Date: Wed, 14 Sep 2011 11:57:04 +0200
4 Subject: [PATCH 205/366] ipc/sem: Rework semaphore wakeups
5
6 Current sysv sems have a weird ass wakeup scheme that involves keeping
7 preemption disabled over a potential O(n^2) loop and busy waiting on
8 that on other CPUs.
9
10 Kill this and simply wake the task directly from under the sem_lock.
11
12 This was discovered by a migrate_disable() debug feature that
13 disallows:
14
15   spin_lock();
16   preempt_disable();
17   spin_unlock()
18   preempt_enable();
19
20 Cc: Manfred Spraul <manfred@colorfullife.com>
21 Suggested-by: Thomas Gleixner <tglx@linutronix.de>
22 Reported-by: Mike Galbraith <efault@gmx.de>
23 Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
24 Cc: Manfred Spraul <manfred@colorfullife.com>
25 Link: http://lkml.kernel.org/r/1315994224.5040.1.camel@twins
26 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
27 ---
28  ipc/sem.c | 10 ++++++++++
29  1 file changed, 10 insertions(+)
30
31 diff --git a/ipc/sem.c b/ipc/sem.c
32 index 9862c3d..ef34d73 100644
33 --- a/ipc/sem.c
34 +++ b/ipc/sem.c
35 @@ -708,6 +708,13 @@ undo:
36  static void wake_up_sem_queue_prepare(struct list_head *pt,
37                                 struct sem_queue *q, int error)
38  {
39 +#ifdef CONFIG_PREEMPT_RT_BASE
40 +       struct task_struct *p = q->sleeper;
41 +       get_task_struct(p);
42 +       q->status = error;
43 +       wake_up_process(p);
44 +       put_task_struct(p);
45 +#else
46         if (list_empty(pt)) {
47                 /*
48                  * Hold preempt off so that we don't get preempted and have the
49 @@ -719,6 +726,7 @@ static void wake_up_sem_queue_prepare(struct list_head *pt,
50         q->pid = error;
51  
52         list_add_tail(&q->list, pt);
53 +#endif
54  }
55  
56  /**
57 @@ -732,6 +740,7 @@ static void wake_up_sem_queue_prepare(struct list_head *pt,
58   */
59  static void wake_up_sem_queue_do(struct list_head *pt)
60  {
61 +#ifndef CONFIG_PREEMPT_RT_BASE
62         struct sem_queue *q, *t;
63         int did_something;
64  
65 @@ -744,6 +753,7 @@ static void wake_up_sem_queue_do(struct list_head *pt)
66         }
67         if (did_something)
68                 preempt_enable();
69 +#endif
70  }
71  
72  static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
73 -- 
74 1.9.1
75