diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-29 12:00:57 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-29 12:00:57 -0400 |
commit | ca364d8388602b5c0d607c5452774833cc1ad667 (patch) | |
tree | 4c6aa0a71c89b813c73c112391005fc00e44841a /include/linux/percpu-rwsem.h | |
parent | 84fd7bdf1266ee6228319903af7e58702745024d (diff) | |
parent | 8f0d8163b50e01f398b14bcd4dc039ac5ab18d64 (diff) |
Merge 3.7-rc3 into tty-next
This merges the tty changes in 3.7-rc3 into tty-next
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/linux/percpu-rwsem.h')
-rw-r--r-- | include/linux/percpu-rwsem.h | 28 |
1 files changed, 11 insertions, 17 deletions
diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h index cf80f7e5277f..250a4acddb2b 100644 --- a/include/linux/percpu-rwsem.h +++ b/include/linux/percpu-rwsem.h | |||
@@ -12,34 +12,27 @@ struct percpu_rw_semaphore { | |||
12 | struct mutex mtx; | 12 | struct mutex mtx; |
13 | }; | 13 | }; |
14 | 14 | ||
15 | #define light_mb() barrier() | ||
16 | #define heavy_mb() synchronize_sched() | ||
17 | |||
15 | static inline void percpu_down_read(struct percpu_rw_semaphore *p) | 18 | static inline void percpu_down_read(struct percpu_rw_semaphore *p) |
16 | { | 19 | { |
17 | rcu_read_lock(); | 20 | rcu_read_lock_sched(); |
18 | if (unlikely(p->locked)) { | 21 | if (unlikely(p->locked)) { |
19 | rcu_read_unlock(); | 22 | rcu_read_unlock_sched(); |
20 | mutex_lock(&p->mtx); | 23 | mutex_lock(&p->mtx); |
21 | this_cpu_inc(*p->counters); | 24 | this_cpu_inc(*p->counters); |
22 | mutex_unlock(&p->mtx); | 25 | mutex_unlock(&p->mtx); |
23 | return; | 26 | return; |
24 | } | 27 | } |
25 | this_cpu_inc(*p->counters); | 28 | this_cpu_inc(*p->counters); |
26 | rcu_read_unlock(); | 29 | rcu_read_unlock_sched(); |
30 | light_mb(); /* A, between read of p->locked and read of data, paired with D */ | ||
27 | } | 31 | } |
28 | 32 | ||
29 | static inline void percpu_up_read(struct percpu_rw_semaphore *p) | 33 | static inline void percpu_up_read(struct percpu_rw_semaphore *p) |
30 | { | 34 | { |
31 | /* | 35 | light_mb(); /* B, between read of the data and write to p->counter, paired with C */ |
32 | * On X86, write operation in this_cpu_dec serves as a memory unlock | ||
33 | * barrier (i.e. memory accesses may be moved before the write, but | ||
34 | * no memory accesses are moved past the write). | ||
35 | * On other architectures this may not be the case, so we need smp_mb() | ||
36 | * there. | ||
37 | */ | ||
38 | #if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE)) | ||
39 | barrier(); | ||
40 | #else | ||
41 | smp_mb(); | ||
42 | #endif | ||
43 | this_cpu_dec(*p->counters); | 36 | this_cpu_dec(*p->counters); |
44 | } | 37 | } |
45 | 38 | ||
@@ -58,14 +51,15 @@ static inline void percpu_down_write(struct percpu_rw_semaphore *p) | |||
58 | { | 51 | { |
59 | mutex_lock(&p->mtx); | 52 | mutex_lock(&p->mtx); |
60 | p->locked = true; | 53 | p->locked = true; |
61 | synchronize_rcu(); | 54 | synchronize_sched(); /* make sure that all readers exit the rcu_read_lock_sched region */ |
62 | while (__percpu_count(p->counters)) | 55 | while (__percpu_count(p->counters)) |
63 | msleep(1); | 56 | msleep(1); |
64 | smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */ | 57 | heavy_mb(); /* C, between read of p->counter and write to data, paired with B */ |
65 | } | 58 | } |
66 | 59 | ||
67 | static inline void percpu_up_write(struct percpu_rw_semaphore *p) | 60 | static inline void percpu_up_write(struct percpu_rw_semaphore *p) |
68 | { | 61 | { |
62 | heavy_mb(); /* D, between write to data and write to p->locked, paired with A */ | ||
69 | p->locked = false; | 63 | p->locked = false; |
70 | mutex_unlock(&p->mtx); | 64 | mutex_unlock(&p->mtx); |
71 | } | 65 | } |