aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2006-02-23 13:43:43 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-02-28 00:34:40 -0500
commit1fa44ecad2b86475e038aed81b0bf333fa484f8b (patch)
tree62e9e9aac0aaf64e6f8e69809d8ab513e22346a1 /kernel
parentba3af0aff042caa1f41b5f7164cab37c717b8811 (diff)
[SCSI] add execute_in_process_context() API
We have several points in the SCSI stack (primarily for our device functions) where we need to guarantee process context, but (given the place where the last reference was released) we cannot guarantee this. This API gets around the issue by executing the function directly if the caller has process context, but scheduling a workqueue to execute in process context if the caller doesn't have it. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/workqueue.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index b052e2c4c710..e9e464a90376 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -27,6 +27,7 @@
27#include <linux/cpu.h> 27#include <linux/cpu.h>
28#include <linux/notifier.h> 28#include <linux/notifier.h>
29#include <linux/kthread.h> 29#include <linux/kthread.h>
30#include <linux/hardirq.h>
30 31
31/* 32/*
32 * The per-CPU workqueue (if single thread, we always use the first 33 * The per-CPU workqueue (if single thread, we always use the first
@@ -476,6 +477,34 @@ void cancel_rearming_delayed_work(struct work_struct *work)
476} 477}
477EXPORT_SYMBOL(cancel_rearming_delayed_work); 478EXPORT_SYMBOL(cancel_rearming_delayed_work);
478 479
480/**
481 * execute_in_process_context - reliably execute the routine with user context
482 * @fn: the function to execute
483 * @data: data to pass to the function
484 * @ew: guaranteed storage for the execute work structure (must
485 * be available when the work executes)
486 *
487 * Executes the function immediately if process context is available,
488 * otherwise schedules the function for delayed execution.
489 *
490 * Returns: 0 - function was executed
491 * 1 - function was scheduled for execution
492 */
493int execute_in_process_context(void (*fn)(void *data), void *data,
494 struct execute_work *ew)
495{
496 if (!in_interrupt()) {
497 fn(data);
498 return 0;
499 }
500
501 INIT_WORK(&ew->work, fn, data);
502 schedule_work(&ew->work);
503
504 return 1;
505}
506EXPORT_SYMBOL_GPL(execute_in_process_context);
507
479int keventd_up(void) 508int keventd_up(void)
480{ 509{
481 return keventd_wq != NULL; 510 return keventd_wq != NULL;