diff options
author | Ivo Sieben <meltedpianoman@gmail.com> | 2012-10-17 08:03:14 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-24 14:37:02 -0400 |
commit | c97399418a25b18943c9910fb28e0ee5ecc3c316 (patch) | |
tree | 0c4d711eae09998e4b4fe4b7efe6036d0cdf896c /drivers/tty/tty_ldisc.c | |
parent | ad3d1e5fc94e1d617298cf9b8fb522e2d219521a (diff) |
tty: Use raw spin lock to protect TTY ldisc administration
The global "normal" spin lock that guards the line discipline
administration is replaced by a raw spin lock. On a PREEMPT_RT system this
prevents unwanted scheduling overhead around the line discipline administration.
On a 200 MHz AT91SAM9261 processor setup this fixes about 100us of scheduling
overhead on a TTY read or write call.
Signed-off-by: Ivo Sieben <meltedpianoman@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/tty_ldisc.c')
-rw-r--r-- | drivers/tty/tty_ldisc.c | 32 |
1 files changed, 16 insertions, 16 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index f4e6754525dc..c5782294e532 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * callers who will do ldisc lookups and cannot sleep. | 26 | * callers who will do ldisc lookups and cannot sleep. |
27 | */ | 27 | */ |
28 | 28 | ||
29 | static DEFINE_SPINLOCK(tty_ldisc_lock); | 29 | static DEFINE_RAW_SPINLOCK(tty_ldisc_lock); |
30 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | 30 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); |
31 | /* Line disc dispatch table */ | 31 | /* Line disc dispatch table */ |
32 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; | 32 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; |
@@ -49,21 +49,21 @@ static void put_ldisc(struct tty_ldisc *ld) | |||
49 | * If this is the last user, free the ldisc, and | 49 | * If this is the last user, free the ldisc, and |
50 | * release the ldisc ops. | 50 | * release the ldisc ops. |
51 | * | 51 | * |
52 | * We really want an "atomic_dec_and_lock_irqsave()", | 52 | * We really want an "atomic_dec_and_raw_lock_irqsave()", |
53 | * but we don't have it, so this does it by hand. | 53 | * but we don't have it, so this does it by hand. |
54 | */ | 54 | */ |
55 | local_irq_save(flags); | 55 | raw_spin_lock_irqsave(&tty_ldisc_lock, flags); |
56 | if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) { | 56 | if (atomic_dec_and_test(&ld->users)) { |
57 | struct tty_ldisc_ops *ldo = ld->ops; | 57 | struct tty_ldisc_ops *ldo = ld->ops; |
58 | 58 | ||
59 | ldo->refcount--; | 59 | ldo->refcount--; |
60 | module_put(ldo->owner); | 60 | module_put(ldo->owner); |
61 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 61 | raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
62 | 62 | ||
63 | kfree(ld); | 63 | kfree(ld); |
64 | return; | 64 | return; |
65 | } | 65 | } |
66 | local_irq_restore(flags); | 66 | raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
67 | wake_up(&ld->wq_idle); | 67 | wake_up(&ld->wq_idle); |
68 | } | 68 | } |
69 | 69 | ||
@@ -88,11 +88,11 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) | |||
88 | if (disc < N_TTY || disc >= NR_LDISCS) | 88 | if (disc < N_TTY || disc >= NR_LDISCS) |
89 | return -EINVAL; | 89 | return -EINVAL; |
90 | 90 | ||
91 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 91 | raw_spin_lock_irqsave(&tty_ldisc_lock, flags); |
92 | tty_ldiscs[disc] = new_ldisc; | 92 | tty_ldiscs[disc] = new_ldisc; |
93 | new_ldisc->num = disc; | 93 | new_ldisc->num = disc; |
94 | new_ldisc->refcount = 0; | 94 | new_ldisc->refcount = 0; |
95 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 95 | raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
96 | 96 | ||
97 | return ret; | 97 | return ret; |
98 | } | 98 | } |
@@ -118,12 +118,12 @@ int tty_unregister_ldisc(int disc) | |||
118 | if (disc < N_TTY || disc >= NR_LDISCS) | 118 | if (disc < N_TTY || disc >= NR_LDISCS) |
119 | return -EINVAL; | 119 | return -EINVAL; |
120 | 120 | ||
121 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 121 | raw_spin_lock_irqsave(&tty_ldisc_lock, flags); |
122 | if (tty_ldiscs[disc]->refcount) | 122 | if (tty_ldiscs[disc]->refcount) |
123 | ret = -EBUSY; | 123 | ret = -EBUSY; |
124 | else | 124 | else |
125 | tty_ldiscs[disc] = NULL; | 125 | tty_ldiscs[disc] = NULL; |
126 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 126 | raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
127 | 127 | ||
128 | return ret; | 128 | return ret; |
129 | } | 129 | } |
@@ -134,7 +134,7 @@ static struct tty_ldisc_ops *get_ldops(int disc) | |||
134 | unsigned long flags; | 134 | unsigned long flags; |
135 | struct tty_ldisc_ops *ldops, *ret; | 135 | struct tty_ldisc_ops *ldops, *ret; |
136 | 136 | ||
137 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 137 | raw_spin_lock_irqsave(&tty_ldisc_lock, flags); |
138 | ret = ERR_PTR(-EINVAL); | 138 | ret = ERR_PTR(-EINVAL); |
139 | ldops = tty_ldiscs[disc]; | 139 | ldops = tty_ldiscs[disc]; |
140 | if (ldops) { | 140 | if (ldops) { |
@@ -144,7 +144,7 @@ static struct tty_ldisc_ops *get_ldops(int disc) | |||
144 | ret = ldops; | 144 | ret = ldops; |
145 | } | 145 | } |
146 | } | 146 | } |
147 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 147 | raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
148 | return ret; | 148 | return ret; |
149 | } | 149 | } |
150 | 150 | ||
@@ -152,10 +152,10 @@ static void put_ldops(struct tty_ldisc_ops *ldops) | |||
152 | { | 152 | { |
153 | unsigned long flags; | 153 | unsigned long flags; |
154 | 154 | ||
155 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 155 | raw_spin_lock_irqsave(&tty_ldisc_lock, flags); |
156 | ldops->refcount--; | 156 | ldops->refcount--; |
157 | module_put(ldops->owner); | 157 | module_put(ldops->owner); |
158 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 158 | raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
159 | } | 159 | } |
160 | 160 | ||
161 | /** | 161 | /** |
@@ -287,11 +287,11 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty) | |||
287 | unsigned long flags; | 287 | unsigned long flags; |
288 | struct tty_ldisc *ld; | 288 | struct tty_ldisc *ld; |
289 | 289 | ||
290 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 290 | raw_spin_lock_irqsave(&tty_ldisc_lock, flags); |
291 | ld = NULL; | 291 | ld = NULL; |
292 | if (test_bit(TTY_LDISC, &tty->flags)) | 292 | if (test_bit(TTY_LDISC, &tty->flags)) |
293 | ld = get_ldisc(tty->ldisc); | 293 | ld = get_ldisc(tty->ldisc); |
294 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 294 | raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
295 | return ld; | 295 | return ld; |
296 | } | 296 | } |
297 | 297 | ||