diff options
author | Jiri Slaby <jslaby@suse.cz> | 2012-03-05 14:51:58 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-03-08 11:42:21 -0800 |
commit | ee024d494ab75426bc77e0c053700915f0a1a16d (patch) | |
tree | f679d17f39f8dc46836bdc72a6d74703943e121f /arch/alpha/kernel/srmcons.c | |
parent | 5e88e6c4e8b044a1d275f1a599128b95046d2968 (diff) | |
download | blackbird-op-linux-ee024d494ab75426bc77e0c053700915f0a1a16d.tar.gz blackbird-op-linux-ee024d494ab75426bc77e0c053700915f0a1a16d.zip |
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/kernel/srmcons.c')
-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 { struct tty_struct *tty; struct timer_list timer; spinlock_t lock; -}; +} srmcons_singleton; typedef union _srmcons_result { struct { @@ -154,43 +154,10 @@ srmcons_chars_in_buffer(struct tty_struct *tty) } static int -srmcons_get_private_struct(struct srmcons_private **ps) -{ - static struct srmcons_private *srmconsp = NULL; - static DEFINE_SPINLOCK(srmconsp_lock); - unsigned long flags; - int retval = 0; - - if (srmconsp == NULL) { - srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL); - spin_lock_irqsave(&srmconsp_lock, flags); - - if (srmconsp == NULL) - retval = -ENOMEM; - else { - srmconsp->tty = NULL; - spin_lock_init(&srmconsp->lock); - setup_timer(&srmconsp->timer, srmcons_receive_chars, - (unsigned long)srmconsp); - } - - spin_unlock_irqrestore(&srmconsp_lock, flags); - } - - *ps = srmconsp; - return retval; -} - -static int srmcons_open(struct tty_struct *tty, struct file *filp) { - struct srmcons_private *srmconsp; + struct srmcons_private *srmconsp = &srmcons_singleton; unsigned long flags; - int retval; - - retval = srmcons_get_private_struct(&srmconsp); - if (retval) - return retval; spin_lock_irqsave(&srmconsp->lock, flags); @@ -236,6 +203,9 @@ static const struct tty_operations srmcons_ops = { static int __init srmcons_init(void) { + spin_lock_init(&srmcons_singleton.lock); + setup_timer(&srmcons_singleton.timer, srmcons_receive_chars, + (unsigned long)&srmcons_singleton); if (srm_is_registered_console) { struct tty_driver *driver; int err; |