Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / include / linux / workqueue.h
index edef8d5..d555f31 100644 (file)
@@ -8,24 +8,30 @@
 #include <linux/timer.h>
 #include <linux/linkage.h>
 #include <linux/bitops.h>
+#include <asm/atomic.h>
 
 struct workqueue_struct;
 
 struct work_struct;
 typedef void (*work_func_t)(struct work_struct *work);
 
+/*
+ * The first word is the work queue pointer and the flags rolled into
+ * one
+ */
+#define work_data_bits(work) ((unsigned long *)(&(work)->data))
+
 struct work_struct {
-       /* the first word is the work queue pointer and the flags rolled into
-        * one */
-       unsigned long management;
+       atomic_long_t data;
 #define WORK_STRUCT_PENDING 0          /* T if work item pending execution */
-#define WORK_STRUCT_NOAUTOREL 1                /* F if work item automatically released on exec */
 #define WORK_STRUCT_FLAG_MASK (3UL)
 #define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
        struct list_head entry;
        work_func_t func;
 };
 
+#define WORK_DATA_INIT()       ATOMIC_LONG_INIT(0)
+
 struct delayed_work {
        struct work_struct work;
        struct timer_list timer;
@@ -36,14 +42,8 @@ struct execute_work {
 };
 
 #define __WORK_INITIALIZER(n, f) {                             \
-       .management = 0,                                        \
-        .entry = { &(n).entry, &(n).entry },                   \
-       .func = (f),                                            \
-       }
-
-#define __WORK_INITIALIZER_NAR(n, f) {                         \
-       .management = (1 << WORK_STRUCT_NOAUTOREL),             \
-        .entry = { &(n).entry, &(n).entry },                   \
+       .data = WORK_DATA_INIT(),                               \
+       .entry  = { &(n).entry, &(n).entry },                   \
        .func = (f),                                            \
        }
 
@@ -52,23 +52,12 @@ struct execute_work {
        .timer = TIMER_INITIALIZER(NULL, 0, 0),                 \
        }
 
-#define __DELAYED_WORK_INITIALIZER_NAR(n, f) {                 \
-       .work = __WORK_INITIALIZER_NAR((n).work, (f)),          \
-       .timer = TIMER_INITIALIZER(NULL, 0, 0),                 \
-       }
-
 #define DECLARE_WORK(n, f)                                     \
        struct work_struct n = __WORK_INITIALIZER(n, f)
 
-#define DECLARE_WORK_NAR(n, f)                                 \
-       struct work_struct n = __WORK_INITIALIZER_NAR(n, f)
-
 #define DECLARE_DELAYED_WORK(n, f)                             \
        struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f)
 
-#define DECLARE_DELAYED_WORK_NAR(n, f)                 \
-       struct dwork_struct n = __DELAYED_WORK_INITIALIZER_NAR(n, f)
-
 /*
  * initialize a work item's function pointer
  */
@@ -82,17 +71,14 @@ struct execute_work {
 
 /*
  * initialize all of a work item in one go
+ *
+ * NOTE! No point in using "atomic_long_set()": useing a direct
+ * assignment of the work data initializer allows the compiler
+ * to generate better code.
  */
-#define INIT_WORK(_work, _func)                                        \
-       do {                                                    \
-               (_work)->management = 0;                        \
-               INIT_LIST_HEAD(&(_work)->entry);                \
-               PREPARE_WORK((_work), (_func));                 \
-       } while (0)
-
-#define INIT_WORK_NAR(_work, _func)                                    \
+#define INIT_WORK(_work, _func)                                                \
        do {                                                            \
-               (_work)->management = (1 << WORK_STRUCT_NOAUTOREL);     \
+               (_work)->data = (atomic_long_t) WORK_DATA_INIT();       \
                INIT_LIST_HEAD(&(_work)->entry);                        \
                PREPARE_WORK((_work), (_func));                         \
        } while (0)
@@ -103,10 +89,10 @@ struct execute_work {
                init_timer(&(_work)->timer);                    \
        } while (0)
 
-#define INIT_DELAYED_WORK_NAR(_work, _func)                    \
+#define INIT_DELAYED_WORK_DEFERRABLE(_work, _func)                     \
        do {                                                    \
-               INIT_WORK_NAR(&(_work)->work, (_func));         \
-               init_timer(&(_work)->timer);                    \
+               INIT_WORK(&(_work)->work, (_func));             \
+               init_timer_deferrable(&(_work)->timer);         \
        } while (0)
 
 /**
@@ -114,36 +100,22 @@ struct execute_work {
  * @work: The work item in question
  */
 #define work_pending(work) \
-       test_bit(WORK_STRUCT_PENDING, &(work)->management)
+       test_bit(WORK_STRUCT_PENDING, work_data_bits(work))
 
 /**
  * delayed_work_pending - Find out whether a delayable work item is currently
  * pending
  * @work: The work item in question
  */
-#define delayed_work_pending(work) \
-       test_bit(WORK_STRUCT_PENDING, &(work)->work.management)
+#define delayed_work_pending(w) \
+       work_pending(&(w)->work)
 
 /**
- * work_release - Release a work item under execution
- * @work: The work item to release
- *
- * This is used to release a work item that has been initialised with automatic
- * release mode disabled (WORK_STRUCT_NOAUTOREL is set).  This gives the work
- * function the opportunity to grab auxiliary data from the container of the
- * work_struct before clearing the pending bit as the work_struct may be
- * subject to deallocation the moment the pending bit is cleared.
- *
- * In such a case, this should be called in the work function after it has
- * fetched any data it may require from the containter of the work_struct.
- * After this function has been called, the work_struct may be scheduled for
- * further execution or it may be deallocated unless other precautions are
- * taken.
- *
- * This should also be used to release a delayed work item.
+ * work_clear_pending - for internal use only, mark a work item as not pending
+ * @work: The work item in question
  */
-#define work_release(work) \
-       clear_bit(WORK_STRUCT_PENDING, &(work)->management)
+#define work_clear_pending(work) \
+       clear_bit(WORK_STRUCT_PENDING, work_data_bits(work))
 
 
 extern struct workqueue_struct *__create_workqueue(const char *name,
@@ -156,40 +128,52 @@ extern struct workqueue_struct *__create_workqueue(const char *name,
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
 extern int FASTCALL(queue_work(struct workqueue_struct *wq, struct work_struct *work));
-extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay));
+extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq,
+                       struct delayed_work *work, unsigned long delay));
 extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
-       struct delayed_work *work, unsigned long delay);
+                       struct delayed_work *work, unsigned long delay);
+
 extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq));
+extern void flush_scheduled_work(void);
 
 extern int FASTCALL(schedule_work(struct work_struct *work));
-extern int FASTCALL(run_scheduled_work(struct work_struct *work));
-extern int FASTCALL(schedule_delayed_work(struct delayed_work *work, unsigned long delay));
-
-extern int schedule_delayed_work_on(int cpu, struct delayed_work *work, unsigned long delay);
+extern int FASTCALL(schedule_delayed_work(struct delayed_work *work,
+                                       unsigned long delay));
+extern int schedule_delayed_work_on(int cpu, struct delayed_work *work,
+                                       unsigned long delay);
 extern int schedule_on_each_cpu(work_func_t func);
-extern void flush_scheduled_work(void);
 extern int current_is_keventd(void);
 extern int keventd_up(void);
 
 extern void init_workqueues(void);
-void cancel_rearming_delayed_work(struct delayed_work *work);
-void cancel_rearming_delayed_workqueue(struct workqueue_struct *,
-                                      struct delayed_work *);
 int execute_in_process_context(work_func_t fn, struct execute_work *);
 
+extern void cancel_work_sync(struct work_struct *work);
+
 /*
  * Kill off a pending schedule_delayed_work().  Note that the work callback
- * function may still be running on return from cancel_delayed_work().  Run
- * flush_scheduled_work() to wait on it.
+ * function may still be running on return from cancel_delayed_work(), unless
+ * it returns 1 and the work doesn't re-arm itself. Run flush_workqueue() or
+ * cancel_work_sync() to wait on it.
  */
 static inline int cancel_delayed_work(struct delayed_work *work)
 {
        int ret;
 
-       ret = del_timer_sync(&work->timer);
+       ret = del_timer(&work->timer);
        if (ret)
-               clear_bit(WORK_STRUCT_PENDING, &work->work.management);
+               work_clear_pending(&work->work);
        return ret;
 }
 
+extern void cancel_rearming_delayed_work(struct delayed_work *work);
+
+/* Obsolete. use cancel_rearming_delayed_work() */
+static inline
+void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
+                                       struct delayed_work *work)
+{
+       cancel_rearming_delayed_work(work);
+}
+
 #endif