]>
Commit | Line | Data |
---|---|---|
23b10630 GKH |
1 | From 0e8c665699e953fa58dc1b0b0d09e5dce7343cc7 Mon Sep 17 00:00:00 2001 |
2 | From: Manfred Spraul <manfred@colorfullife.com> | |
3 | Date: Mon, 30 Sep 2013 13:45:25 -0700 | |
4 | Subject: ipc/sem.c: update sem_otime for all operations | |
5 | ||
6 | From: Manfred Spraul <manfred@colorfullife.com> | |
7 | ||
8 | commit 0e8c665699e953fa58dc1b0b0d09e5dce7343cc7 upstream. | |
9 | ||
10 | In commit 0a2b9d4c7967 ("ipc/sem.c: move wake_up_process out of the | |
11 | spinlock section"), the update of semaphore's sem_otime(last semop time) | |
12 | was moved to one central position (do_smart_update). | |
13 | ||
14 | But since do_smart_update() is only called for operations that modify | |
15 | the array, this means that wait-for-zero semops do not update sem_otime | |
16 | anymore. | |
17 | ||
18 | The fix is simple: | |
19 | Non-alter operations must update sem_otime. | |
20 | ||
21 | [akpm@linux-foundation.org: coding-style fixes] | |
22 | Signed-off-by: Manfred Spraul <manfred@colorfullife.com> | |
23 | Reported-by: Jia He <jiakernel@gmail.com> | |
24 | Tested-by: Jia He <jiakernel@gmail.com> | |
25 | Cc: Davidlohr Bueso <davidlohr.bueso@hp.com> | |
26 | Cc: Mike Galbraith <efault@gmx.de> | |
27 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
28 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
29 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
30 | ||
31 | --- | |
32 | ipc/sem.c | 42 +++++++++++++++++++++++++++++------------- | |
33 | 1 file changed, 29 insertions(+), 13 deletions(-) | |
34 | ||
35 | --- a/ipc/sem.c | |
36 | +++ b/ipc/sem.c | |
37 | @@ -918,6 +918,24 @@ again: | |
38 | } | |
39 | ||
40 | /** | |
41 | + * set_semotime(sma, sops) - set sem_otime | |
42 | + * @sma: semaphore array | |
43 | + * @sops: operations that modified the array, may be NULL | |
44 | + * | |
45 | + * sem_otime is replicated to avoid cache line trashing. | |
46 | + * This function sets one instance to the current time. | |
47 | + */ | |
48 | +static void set_semotime(struct sem_array *sma, struct sembuf *sops) | |
49 | +{ | |
50 | + if (sops == NULL) { | |
51 | + sma->sem_base[0].sem_otime = get_seconds(); | |
52 | + } else { | |
53 | + sma->sem_base[sops[0].sem_num].sem_otime = | |
54 | + get_seconds(); | |
55 | + } | |
56 | +} | |
57 | + | |
58 | +/** | |
59 | * do_smart_update(sma, sops, nsops, otime, pt) - optimized update_queue | |
60 | * @sma: semaphore array | |
61 | * @sops: operations that were performed | |
62 | @@ -967,17 +985,10 @@ static void do_smart_update(struct sem_a | |
63 | } | |
64 | } | |
65 | } | |
66 | - if (otime) { | |
67 | - if (sops == NULL) { | |
68 | - sma->sem_base[0].sem_otime = get_seconds(); | |
69 | - } else { | |
70 | - sma->sem_base[sops[0].sem_num].sem_otime = | |
71 | - get_seconds(); | |
72 | - } | |
73 | - } | |
74 | + if (otime) | |
75 | + set_semotime(sma, sops); | |
76 | } | |
77 | ||
78 | - | |
79 | /* The following counts are associated to each semaphore: | |
80 | * semncnt number of tasks waiting on semval being nonzero | |
81 | * semzcnt number of tasks waiting on semval being zero | |
82 | @@ -1839,12 +1850,17 @@ SYSCALL_DEFINE4(semtimedop, int, semid, | |
83 | ||
84 | error = perform_atomic_semop(sma, sops, nsops, un, | |
85 | task_tgid_vnr(current)); | |
86 | - if (error <= 0) { | |
87 | - if (alter && error == 0) | |
88 | + if (error == 0) { | |
89 | + /* If the operation was successful, then do | |
90 | + * the required updates. | |
91 | + */ | |
92 | + if (alter) | |
93 | do_smart_update(sma, sops, nsops, 1, &tasks); | |
94 | - | |
95 | - goto out_unlock_free; | |
96 | + else | |
97 | + set_semotime(sma, sops); | |
98 | } | |
99 | + if (error <= 0) | |
100 | + goto out_unlock_free; | |
101 | ||
102 | /* We need to sleep on this operation, so we put the current | |
103 | * task into the pending queue and go to sleep. |