aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-11-22 09:55:48 -0500
committerDavid Howells <dhowells@redhat.com>2006-11-22 09:55:48 -0500
commit65f27f38446e1976cc98fd3004b110fedcddd189 (patch)
tree68f8be93feae31dfa018c22db392a05546b63ee1 /drivers/char
parent365970a1ea76d81cb1ad2f652acb605f06dae256 (diff)
WorkStruct: Pass the work_struct pointer instead of context data
Pass the work_struct pointer to the work function rather than context data. The work function can use container_of() to work out the data. For the cases where the container of the work_struct may go away the moment the pending bit is cleared, it is made possible to defer the release of the structure by deferring the clearing of the pending bit. To make this work, an extra flag is introduced into the management side of the work_struct. This governs auto-release of the structure upon execution. Ordinarily, the work queue executor would release the work_struct for further scheduling or deallocation by clearing the pending bit prior to jumping to the work function. This means that, unless the driver makes some guarantee itself that the work_struct won't go away, the work function may not access anything else in the work_struct or its container lest they be deallocated.. This is a problem if the auxiliary data is taken away (as done by the last patch). However, if the pending bit is *not* cleared before jumping to the work function, then the work function *may* access the work_struct and its container with no problems. But then the work function must itself release the work_struct by calling work_release(). In most cases, automatic release is fine, so this is the default. Special initiators exist for the non-auto-release case (ending in _NAR). Signed-Off-By: David Howells <dhowells@redhat.com>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/random.c6
-rw-r--r--drivers/char/sysrq.c4
-rw-r--r--drivers/char/tty_io.c31
-rw-r--r--drivers/char/vt.c6
4 files changed, 25 insertions, 22 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index f2ab61f3e8ae..fa764688cad1 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1422,9 +1422,9 @@ static struct keydata {
1422 1422
1423static unsigned int ip_cnt; 1423static unsigned int ip_cnt;
1424 1424
1425static void rekey_seq_generator(void *private_); 1425static void rekey_seq_generator(struct work_struct *work);
1426 1426
1427static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator, NULL); 1427static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator);
1428 1428
1429/* 1429/*
1430 * Lock avoidance: 1430 * Lock avoidance:
@@ -1438,7 +1438,7 @@ static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator, NULL);
1438 * happen, and even if that happens only a not perfectly compliant 1438 * happen, and even if that happens only a not perfectly compliant
1439 * ISN is generated, nothing fatal. 1439 * ISN is generated, nothing fatal.
1440 */ 1440 */
1441static void rekey_seq_generator(void *private_) 1441static void rekey_seq_generator(struct work_struct *work)
1442{ 1442{
1443 struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)]; 1443 struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)];
1444 1444
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 5f49280779fb..c64f5bcff947 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -219,13 +219,13 @@ static struct sysrq_key_op sysrq_term_op = {
219 .enable_mask = SYSRQ_ENABLE_SIGNAL, 219 .enable_mask = SYSRQ_ENABLE_SIGNAL,
220}; 220};
221 221
222static void moom_callback(void *ignored) 222static void moom_callback(struct work_struct *ignored)
223{ 223{
224 out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], 224 out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL],
225 GFP_KERNEL, 0); 225 GFP_KERNEL, 0);
226} 226}
227 227
228static DECLARE_WORK(moom_work, moom_callback, NULL); 228static DECLARE_WORK(moom_work, moom_callback);
229 229
230static void sysrq_handle_moom(int key, struct tty_struct *tty) 230static void sysrq_handle_moom(int key, struct tty_struct *tty)
231{ 231{
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 7297acfe520c..83e9e7d9b58c 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1254,7 +1254,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
1254 1254
1255/** 1255/**
1256 * do_tty_hangup - actual handler for hangup events 1256 * do_tty_hangup - actual handler for hangup events
1257 * @data: tty device 1257 * @work: tty device
1258 * 1258 *
1259 * This can be called by the "eventd" kernel thread. That is process 1259 * This can be called by the "eventd" kernel thread. That is process
1260 * synchronous but doesn't hold any locks, so we need to make sure we 1260 * synchronous but doesn't hold any locks, so we need to make sure we
@@ -1274,9 +1274,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
1274 * tasklist_lock to walk task list for hangup event 1274 * tasklist_lock to walk task list for hangup event
1275 * 1275 *
1276 */ 1276 */
1277static void do_tty_hangup(void *data) 1277static void do_tty_hangup(struct work_struct *work)
1278{ 1278{
1279 struct tty_struct *tty = (struct tty_struct *) data; 1279 struct tty_struct *tty =
1280 container_of(work, struct tty_struct, hangup_work);
1280 struct file * cons_filp = NULL; 1281 struct file * cons_filp = NULL;
1281 struct file *filp, *f = NULL; 1282 struct file *filp, *f = NULL;
1282 struct task_struct *p; 1283 struct task_struct *p;
@@ -1433,7 +1434,7 @@ void tty_vhangup(struct tty_struct * tty)
1433 1434
1434 printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); 1435 printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
1435#endif 1436#endif
1436 do_tty_hangup((void *) tty); 1437 do_tty_hangup(&tty->hangup_work);
1437} 1438}
1438EXPORT_SYMBOL(tty_vhangup); 1439EXPORT_SYMBOL(tty_vhangup);
1439 1440
@@ -3304,12 +3305,13 @@ int tty_ioctl(struct inode * inode, struct file * file,
3304 * Nasty bug: do_SAK is being called in interrupt context. This can 3305 * Nasty bug: do_SAK is being called in interrupt context. This can
3305 * deadlock. We punt it up to process context. AKPM - 16Mar2001 3306 * deadlock. We punt it up to process context. AKPM - 16Mar2001
3306 */ 3307 */
3307static void __do_SAK(void *arg) 3308static void __do_SAK(struct work_struct *work)
3308{ 3309{
3310 struct tty_struct *tty =
3311 container_of(work, struct tty_struct, SAK_work);
3309#ifdef TTY_SOFT_SAK 3312#ifdef TTY_SOFT_SAK
3310 tty_hangup(tty); 3313 tty_hangup(tty);
3311#else 3314#else
3312 struct tty_struct *tty = arg;
3313 struct task_struct *g, *p; 3315 struct task_struct *g, *p;
3314 int session; 3316 int session;
3315 int i; 3317 int i;
@@ -3388,7 +3390,7 @@ void do_SAK(struct tty_struct *tty)
3388{ 3390{
3389 if (!tty) 3391 if (!tty)
3390 return; 3392 return;
3391 PREPARE_WORK(&tty->SAK_work, __do_SAK, tty); 3393 PREPARE_WORK(&tty->SAK_work, __do_SAK);
3392 schedule_work(&tty->SAK_work); 3394 schedule_work(&tty->SAK_work);
3393} 3395}
3394 3396
@@ -3396,7 +3398,7 @@ EXPORT_SYMBOL(do_SAK);
3396 3398
3397/** 3399/**
3398 * flush_to_ldisc 3400 * flush_to_ldisc
3399 * @private_: tty structure passed from work queue. 3401 * @work: tty structure passed from work queue.
3400 * 3402 *
3401 * This routine is called out of the software interrupt to flush data 3403 * This routine is called out of the software interrupt to flush data
3402 * from the buffer chain to the line discipline. 3404 * from the buffer chain to the line discipline.
@@ -3406,9 +3408,10 @@ EXPORT_SYMBOL(do_SAK);
3406 * receive_buf method is single threaded for each tty instance. 3408 * receive_buf method is single threaded for each tty instance.
3407 */ 3409 */
3408 3410
3409static void flush_to_ldisc(void *private_) 3411static void flush_to_ldisc(struct work_struct *work)
3410{ 3412{
3411 struct tty_struct *tty = (struct tty_struct *) private_; 3413 struct tty_struct *tty =
3414 container_of(work, struct tty_struct, buf.work.work);
3412 unsigned long flags; 3415 unsigned long flags;
3413 struct tty_ldisc *disc; 3416 struct tty_ldisc *disc;
3414 struct tty_buffer *tbuf, *head; 3417 struct tty_buffer *tbuf, *head;
@@ -3553,7 +3556,7 @@ void tty_flip_buffer_push(struct tty_struct *tty)
3553 spin_unlock_irqrestore(&tty->buf.lock, flags); 3556 spin_unlock_irqrestore(&tty->buf.lock, flags);
3554 3557
3555 if (tty->low_latency) 3558 if (tty->low_latency)
3556 flush_to_ldisc((void *) tty); 3559 flush_to_ldisc(&tty->buf.work.work);
3557 else 3560 else
3558 schedule_delayed_work(&tty->buf.work, 1); 3561 schedule_delayed_work(&tty->buf.work, 1);
3559} 3562}
@@ -3580,17 +3583,17 @@ static void initialize_tty_struct(struct tty_struct *tty)
3580 tty->overrun_time = jiffies; 3583 tty->overrun_time = jiffies;
3581 tty->buf.head = tty->buf.tail = NULL; 3584 tty->buf.head = tty->buf.tail = NULL;
3582 tty_buffer_init(tty); 3585 tty_buffer_init(tty);
3583 INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc, tty); 3586 INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
3584 init_MUTEX(&tty->buf.pty_sem); 3587 init_MUTEX(&tty->buf.pty_sem);
3585 mutex_init(&tty->termios_mutex); 3588 mutex_init(&tty->termios_mutex);
3586 init_waitqueue_head(&tty->write_wait); 3589 init_waitqueue_head(&tty->write_wait);
3587 init_waitqueue_head(&tty->read_wait); 3590 init_waitqueue_head(&tty->read_wait);
3588 INIT_WORK(&tty->hangup_work, do_tty_hangup, tty); 3591 INIT_WORK(&tty->hangup_work, do_tty_hangup);
3589 mutex_init(&tty->atomic_read_lock); 3592 mutex_init(&tty->atomic_read_lock);
3590 mutex_init(&tty->atomic_write_lock); 3593 mutex_init(&tty->atomic_write_lock);
3591 spin_lock_init(&tty->read_lock); 3594 spin_lock_init(&tty->read_lock);
3592 INIT_LIST_HEAD(&tty->tty_files); 3595 INIT_LIST_HEAD(&tty->tty_files);
3593 INIT_WORK(&tty->SAK_work, NULL, NULL); 3596 INIT_WORK(&tty->SAK_work, NULL);
3594} 3597}
3595 3598
3596/* 3599/*
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 8e4413f6fbaf..8ee04adc37f0 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -155,7 +155,7 @@ static void con_flush_chars(struct tty_struct *tty);
155static void set_vesa_blanking(char __user *p); 155static void set_vesa_blanking(char __user *p);
156static void set_cursor(struct vc_data *vc); 156static void set_cursor(struct vc_data *vc);
157static void hide_cursor(struct vc_data *vc); 157static void hide_cursor(struct vc_data *vc);
158static void console_callback(void *ignored); 158static void console_callback(struct work_struct *ignored);
159static void blank_screen_t(unsigned long dummy); 159static void blank_screen_t(unsigned long dummy);
160static void set_palette(struct vc_data *vc); 160static void set_palette(struct vc_data *vc);
161 161
@@ -174,7 +174,7 @@ static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
174static int blankinterval = 10*60*HZ; 174static int blankinterval = 10*60*HZ;
175static int vesa_off_interval; 175static int vesa_off_interval;
176 176
177static DECLARE_WORK(console_work, console_callback, NULL); 177static DECLARE_WORK(console_work, console_callback);
178 178
179/* 179/*
180 * fg_console is the current virtual console, 180 * fg_console is the current virtual console,
@@ -2154,7 +2154,7 @@ out:
2154 * with other console code and prevention of re-entrancy is 2154 * with other console code and prevention of re-entrancy is
2155 * ensured with console_sem. 2155 * ensured with console_sem.
2156 */ 2156 */
2157static void console_callback(void *ignored) 2157static void console_callback(struct work_struct *ignored)
2158{ 2158{
2159 acquire_console_sem(); 2159 acquire_console_sem();
2160 2160