diff options
author | Jiri Slaby <jslaby@suse.cz> | 2012-03-05 08:51:58 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-03-08 14:42:21 -0500 |
commit | ee024d494ab75426bc77e0c053700915f0a1a16d (patch) | |
tree | f679d17f39f8dc46836bdc72a6d74703943e121f /arch/alpha | |
parent | 5e88e6c4e8b044a1d275f1a599128b95046d2968 (diff) |
ALPHA: srmcons, fix racy singleton structure
The test and the assignment were racy. Make it really a singleton.
This is achieved by one global variable initialized at the module
init.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/alpha')
-rw-r--r-- | arch/alpha/kernel/srmcons.c | 40 |
1 files changed, 5 insertions, 35 deletions
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c index f1fdf178bcb4..2c89ce5c9ab6 100644 --- a/arch/alpha/kernel/srmcons.c +++ b/arch/alpha/kernel/srmcons.c | |||
@@ -33,7 +33,7 @@ struct srmcons_private { | |||
33 | struct tty_struct *tty; | 33 | struct tty_struct *tty; |
34 | struct timer_list timer; | 34 | struct timer_list timer; |
35 | spinlock_t lock; | 35 | spinlock_t lock; |
36 | }; | 36 | } srmcons_singleton; |
37 | 37 | ||
38 | typedef union _srmcons_result { | 38 | typedef union _srmcons_result { |
39 | struct { | 39 | struct { |
@@ -154,43 +154,10 @@ srmcons_chars_in_buffer(struct tty_struct *tty) | |||
154 | } | 154 | } |
155 | 155 | ||
156 | static int | 156 | static int |
157 | srmcons_get_private_struct(struct srmcons_private **ps) | ||
158 | { | ||
159 | static struct srmcons_private *srmconsp = NULL; | ||
160 | static DEFINE_SPINLOCK(srmconsp_lock); | ||
161 | unsigned long flags; | ||
162 | int retval = 0; | ||
163 | |||
164 | if (srmconsp == NULL) { | ||
165 | srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL); | ||
166 | spin_lock_irqsave(&srmconsp_lock, flags); | ||
167 | |||
168 | if (srmconsp == NULL) | ||
169 | retval = -ENOMEM; | ||
170 | else { | ||
171 | srmconsp->tty = NULL; | ||
172 | spin_lock_init(&srmconsp->lock); | ||
173 | setup_timer(&srmconsp->timer, srmcons_receive_chars, | ||
174 | (unsigned long)srmconsp); | ||
175 | } | ||
176 | |||
177 | spin_unlock_irqrestore(&srmconsp_lock, flags); | ||
178 | } | ||
179 | |||
180 | *ps = srmconsp; | ||
181 | return retval; | ||
182 | } | ||
183 | |||
184 | static int | ||
185 | srmcons_open(struct tty_struct *tty, struct file *filp) | 157 | srmcons_open(struct tty_struct *tty, struct file *filp) |
186 | { | 158 | { |
187 | struct srmcons_private *srmconsp; | 159 | struct srmcons_private *srmconsp = &srmcons_singleton; |
188 | unsigned long flags; | 160 | unsigned long flags; |
189 | int retval; | ||
190 | |||
191 | retval = srmcons_get_private_struct(&srmconsp); | ||
192 | if (retval) | ||
193 | return retval; | ||
194 | 161 | ||
195 | spin_lock_irqsave(&srmconsp->lock, flags); | 162 | spin_lock_irqsave(&srmconsp->lock, flags); |
196 | 163 | ||
@@ -236,6 +203,9 @@ static const struct tty_operations srmcons_ops = { | |||
236 | static int __init | 203 | static int __init |
237 | srmcons_init(void) | 204 | srmcons_init(void) |
238 | { | 205 | { |
206 | spin_lock_init(&srmcons_singleton.lock); | ||
207 | setup_timer(&srmcons_singleton.timer, srmcons_receive_chars, | ||
208 | (unsigned long)&srmcons_singleton); | ||
239 | if (srm_is_registered_console) { | 209 | if (srm_is_registered_console) { |
240 | struct tty_driver *driver; | 210 | struct tty_driver *driver; |
241 | int err; | 211 | int err; |