serial: fix NULL pointer dereference
[safe/jmp/linux-2.6] / include / linux / workqueue.h
index 47151c8..9466e86 100644 (file)
@@ -25,6 +25,7 @@ typedef void (*work_func_t)(struct work_struct *work);
 struct work_struct {
        atomic_long_t data;
 #define WORK_STRUCT_PENDING 0          /* T if work item pending execution */
+#define WORK_STRUCT_STATIC  1          /* static initializer (debugobjects) */
 #define WORK_STRUCT_FLAG_MASK (3UL)
 #define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
        struct list_head entry;
@@ -35,12 +36,18 @@ struct work_struct {
 };
 
 #define WORK_DATA_INIT()       ATOMIC_LONG_INIT(0)
+#define WORK_DATA_STATIC_INIT()        ATOMIC_LONG_INIT(2)
 
 struct delayed_work {
        struct work_struct work;
        struct timer_list timer;
 };
 
+static inline struct delayed_work *to_delayed_work(struct work_struct *work)
+{
+       return container_of(work, struct delayed_work, work);
+}
+
 struct execute_work {
        struct work_struct work;
 };
@@ -58,7 +65,7 @@ struct execute_work {
 #endif
 
 #define __WORK_INITIALIZER(n, f) {                             \
-       .data = WORK_DATA_INIT(),                               \
+       .data = WORK_DATA_STATIC_INIT(),                        \
        .entry  = { &(n).entry, &(n).entry },                   \
        .func = (f),                                            \
        __WORK_INIT_LOCKDEP_MAP(#n, &(n))                       \
@@ -86,32 +93,52 @@ struct execute_work {
 #define PREPARE_DELAYED_WORK(_work, _func)                     \
        PREPARE_WORK(&(_work)->work, (_func))
 
+#ifdef CONFIG_DEBUG_OBJECTS_WORK
+extern void __init_work(struct work_struct *work, int onstack);
+extern void destroy_work_on_stack(struct work_struct *work);
+#else
+static inline void __init_work(struct work_struct *work, int onstack) { }
+static inline void destroy_work_on_stack(struct work_struct *work) { }
+#endif
+
 /*
  * initialize all of a work item in one go
  *
- * NOTE! No point in using "atomic_long_set()": useing a direct
+ * NOTE! No point in using "atomic_long_set()": using a direct
  * assignment of the work data initializer allows the compiler
  * to generate better code.
  */
 #ifdef CONFIG_LOCKDEP
-#define INIT_WORK(_work, _func)                                                \
+#define __INIT_WORK(_work, _func, _onstack)                            \
        do {                                                            \
                static struct lock_class_key __key;                     \
                                                                        \
+               __init_work((_work), _onstack);                         \
                (_work)->data = (atomic_long_t) WORK_DATA_INIT();       \
                lockdep_init_map(&(_work)->lockdep_map, #_work, &__key, 0);\
                INIT_LIST_HEAD(&(_work)->entry);                        \
                PREPARE_WORK((_work), (_func));                         \
        } while (0)
 #else
-#define INIT_WORK(_work, _func)                                                \
+#define __INIT_WORK(_work, _func, _onstack)                            \
        do {                                                            \
+               __init_work((_work), _onstack);                         \
                (_work)->data = (atomic_long_t) WORK_DATA_INIT();       \
                INIT_LIST_HEAD(&(_work)->entry);                        \
                PREPARE_WORK((_work), (_func));                         \
        } while (0)
 #endif
 
+#define INIT_WORK(_work, _func)                                        \
+       do {                                                    \
+               __INIT_WORK((_work), (_func), 0);               \
+       } while (0)
+
+#define INIT_WORK_ON_STACK(_work, _func)                       \
+       do {                                                    \
+               __INIT_WORK((_work), (_func), 1);               \
+       } while (0)
+
 #define INIT_DELAYED_WORK(_work, _func)                                \
        do {                                                    \
                INIT_WORK(&(_work)->work, (_func));             \
@@ -120,11 +147,11 @@ struct execute_work {
 
 #define INIT_DELAYED_WORK_ON_STACK(_work, _func)               \
        do {                                                    \
-               INIT_WORK(&(_work)->work, (_func));             \
+               INIT_WORK_ON_STACK(&(_work)->work, (_func));    \
                init_timer_on_stack(&(_work)->timer);           \
        } while (0)
 
-#define INIT_DELAYED_WORK_DEFERRABLE(_work, _func)                     \
+#define INIT_DELAYED_WORK_DEFERRABLE(_work, _func)             \
        do {                                                    \
                INIT_WORK(&(_work)->work, (_func));             \
                init_timer_deferrable(&(_work)->timer);         \
@@ -196,6 +223,7 @@ extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
 
 extern void flush_workqueue(struct workqueue_struct *wq);
 extern void flush_scheduled_work(void);
+extern void flush_delayed_work(struct delayed_work *work);
 
 extern int schedule_work(struct work_struct *work);
 extern int schedule_work_on(int cpu, struct work_struct *work);
@@ -229,6 +257,21 @@ static inline int cancel_delayed_work(struct delayed_work *work)
        return ret;
 }
 
+/*
+ * Like above, but uses del_timer() instead of del_timer_sync(). This means,
+ * if it returns 0 the timer function may be running and the queueing is in
+ * progress.
+ */
+static inline int __cancel_delayed_work(struct delayed_work *work)
+{
+       int ret;
+
+       ret = del_timer(&work->timer);
+       if (ret)
+               work_clear_pending(&work->work);
+       return ret;
+}
+
 extern int cancel_delayed_work_sync(struct delayed_work *work);
 
 /* Obsolete. use cancel_delayed_work_sync() */