Commit 1791f881435fab951939ad700e947b66c062e083

Authored by Richard Cochran
Committed by Thomas Gleixner
1 parent a1b49cb7e2

posix clocks: Replace mutex with reader/writer semaphore

A dynamic posix clock is protected from asynchronous removal by a mutex.
However, using a mutex has the unwanted effect that a long running clock
operation in one process will unnecessarily block other processes.

For example, one process might call read() to get an external time stamp
coming in at one pulse per second. A second process calling clock_gettime
would have to wait for almost a whole second.

This patch fixes the issue by using a reader/writer semaphore instead of
a mutex.

Signed-off-by: Richard Cochran <richard.cochran@omicron.at>
Cc: John Stultz <john.stultz@linaro.org>
Link: http://lkml.kernel.org/r/%3C20110330132421.GA31771%40riccoc20.at.omicron.at%3E
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Showing 2 changed files with 12 additions and 17 deletions Side-by-side Diff

include/linux/posix-clock.h
... ... @@ -24,6 +24,7 @@
24 24 #include <linux/fs.h>
25 25 #include <linux/poll.h>
26 26 #include <linux/posix-timers.h>
  27 +#include <linux/rwsem.h>
27 28  
28 29 struct posix_clock;
29 30  
... ... @@ -104,7 +105,7 @@
104 105 * @ops: Functional interface to the clock
105 106 * @cdev: Character device instance for this clock
106 107 * @kref: Reference count.
107   - * @mutex: Protects the 'zombie' field from concurrent access.
  108 + * @rwsem: Protects the 'zombie' field from concurrent access.
108 109 * @zombie: If 'zombie' is true, then the hardware has disappeared.
109 110 * @release: A function to free the structure when the reference count reaches
110 111 * zero. May be NULL if structure is statically allocated.
... ... @@ -117,7 +118,7 @@
117 118 struct posix_clock_operations ops;
118 119 struct cdev cdev;
119 120 struct kref kref;
120   - struct mutex mutex;
  121 + struct rw_semaphore rwsem;
121 122 bool zombie;
122 123 void (*release)(struct posix_clock *clk);
123 124 };
kernel/time/posix-clock.c
... ... @@ -19,7 +19,6 @@
19 19 */
20 20 #include <linux/device.h>
21 21 #include <linux/file.h>
22   -#include <linux/mutex.h>
23 22 #include <linux/posix-clock.h>
24 23 #include <linux/slab.h>
25 24 #include <linux/syscalls.h>
26 25  
27 26  
... ... @@ -34,19 +33,19 @@
34 33 {
35 34 struct posix_clock *clk = fp->private_data;
36 35  
37   - mutex_lock(&clk->mutex);
  36 + down_read(&clk->rwsem);
38 37  
39 38 if (!clk->zombie)
40 39 return clk;
41 40  
42   - mutex_unlock(&clk->mutex);
  41 + up_read(&clk->rwsem);
43 42  
44 43 return NULL;
45 44 }
46 45  
47 46 static void put_posix_clock(struct posix_clock *clk)
48 47 {
49   - mutex_unlock(&clk->mutex);
  48 + up_read(&clk->rwsem);
50 49 }
51 50  
52 51 static ssize_t posix_clock_read(struct file *fp, char __user *buf,
... ... @@ -156,7 +155,7 @@
156 155 struct posix_clock *clk =
157 156 container_of(inode->i_cdev, struct posix_clock, cdev);
158 157  
159   - mutex_lock(&clk->mutex);
  158 + down_read(&clk->rwsem);
160 159  
161 160 if (clk->zombie) {
162 161 err = -ENODEV;
... ... @@ -172,7 +171,7 @@
172 171 fp->private_data = clk;
173 172 }
174 173 out:
175   - mutex_unlock(&clk->mutex);
  174 + up_read(&clk->rwsem);
176 175 return err;
177 176 }
178 177  
179 178  
180 179  
181 180  
... ... @@ -211,25 +210,20 @@
211 210 int err;
212 211  
213 212 kref_init(&clk->kref);
214   - mutex_init(&clk->mutex);
  213 + init_rwsem(&clk->rwsem);
215 214  
216 215 cdev_init(&clk->cdev, &posix_clock_file_operations);
217 216 clk->cdev.owner = clk->ops.owner;
218 217 err = cdev_add(&clk->cdev, devid, 1);
219   - if (err)
220   - goto no_cdev;
221 218  
222 219 return err;
223   -no_cdev:
224   - mutex_destroy(&clk->mutex);
225   - return err;
226 220 }
227 221 EXPORT_SYMBOL_GPL(posix_clock_register);
228 222  
229 223 static void delete_clock(struct kref *kref)
230 224 {
231 225 struct posix_clock *clk = container_of(kref, struct posix_clock, kref);
232   - mutex_destroy(&clk->mutex);
  226 +
233 227 if (clk->release)
234 228 clk->release(clk);
235 229 }
236 230  
... ... @@ -238,9 +232,9 @@
238 232 {
239 233 cdev_del(&clk->cdev);
240 234  
241   - mutex_lock(&clk->mutex);
  235 + down_write(&clk->rwsem);
242 236 clk->zombie = true;
243   - mutex_unlock(&clk->mutex);
  237 + up_write(&clk->rwsem);
244 238  
245 239 kref_put(&clk->kref, delete_clock);
246 240 }