Merge branch 'tip/perf/urgent-3' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / include / linux / workqueue.h
index d0f7c81..4f9d277 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/linkage.h>
 #include <linux/bitops.h>
 #include <linux/lockdep.h>
+#include <linux/threads.h>
 #include <asm/atomic.h>
 
 struct workqueue_struct;
@@ -22,12 +23,59 @@ typedef void (*work_func_t)(struct work_struct *work);
  */
 #define work_data_bits(work) ((unsigned long *)(&(work)->data))
 
+enum {
+       WORK_STRUCT_PENDING_BIT = 0,    /* work item is pending execution */
+       WORK_STRUCT_CWQ_BIT     = 1,    /* data points to cwq */
+       WORK_STRUCT_LINKED_BIT  = 2,    /* next work is linked to this one */
+#ifdef CONFIG_DEBUG_OBJECTS_WORK
+       WORK_STRUCT_STATIC_BIT  = 3,    /* static initializer (debugobjects) */
+       WORK_STRUCT_COLOR_SHIFT = 4,    /* color for workqueue flushing */
+#else
+       WORK_STRUCT_COLOR_SHIFT = 3,    /* color for workqueue flushing */
+#endif
+
+       WORK_STRUCT_COLOR_BITS  = 4,
+
+       WORK_STRUCT_PENDING     = 1 << WORK_STRUCT_PENDING_BIT,
+       WORK_STRUCT_CWQ         = 1 << WORK_STRUCT_CWQ_BIT,
+       WORK_STRUCT_LINKED      = 1 << WORK_STRUCT_LINKED_BIT,
+#ifdef CONFIG_DEBUG_OBJECTS_WORK
+       WORK_STRUCT_STATIC      = 1 << WORK_STRUCT_STATIC_BIT,
+#else
+       WORK_STRUCT_STATIC      = 0,
+#endif
+
+       /*
+        * The last color is no color used for works which don't
+        * participate in workqueue flushing.
+        */
+       WORK_NR_COLORS          = (1 << WORK_STRUCT_COLOR_BITS) - 1,
+       WORK_NO_COLOR           = WORK_NR_COLORS,
+
+       /* special cpu IDs */
+       WORK_CPU_UNBOUND        = NR_CPUS,
+       WORK_CPU_NONE           = NR_CPUS + 1,
+       WORK_CPU_LAST           = WORK_CPU_NONE,
+
+       /*
+        * Reserve 7 bits off of cwq pointer w/ debugobjects turned
+        * off.  This makes cwqs aligned to 128 bytes which isn't too
+        * excessive while allowing 15 workqueue flush colors.
+        */
+       WORK_STRUCT_FLAG_BITS   = WORK_STRUCT_COLOR_SHIFT +
+                                 WORK_STRUCT_COLOR_BITS,
+
+       WORK_STRUCT_FLAG_MASK   = (1UL << WORK_STRUCT_FLAG_BITS) - 1,
+       WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK,
+       WORK_STRUCT_NO_CPU      = WORK_CPU_NONE << WORK_STRUCT_FLAG_BITS,
+
+       /* bit mask for work_busy() return values */
+       WORK_BUSY_PENDING       = 1 << 0,
+       WORK_BUSY_RUNNING       = 1 << 1,
+};
+
 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;
        work_func_t func;
 #ifdef CONFIG_LOCKDEP
@@ -35,8 +83,9 @@ struct work_struct {
 #endif
 };
 
-#define WORK_DATA_INIT()       ATOMIC_LONG_INIT(0)
-#define WORK_DATA_STATIC_INIT()        ATOMIC_LONG_INIT(2)
+#define WORK_DATA_INIT()       ATOMIC_LONG_INIT(WORK_STRUCT_NO_CPU)
+#define WORK_DATA_STATIC_INIT()        \
+       ATOMIC_LONG_INIT(WORK_STRUCT_NO_CPU | WORK_STRUCT_STATIC)
 
 struct delayed_work {
        struct work_struct work;
@@ -96,9 +145,14 @@ struct execute_work {
 #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);
+static inline unsigned int work_static(struct work_struct *work)
+{
+       return *work_data_bits(work) & WORK_STRUCT_STATIC;
+}
 #else
 static inline void __init_work(struct work_struct *work, int onstack) { }
 static inline void destroy_work_on_stack(struct work_struct *work) { }
+static inline unsigned int work_static(struct work_struct *work) { return 0; }
 #endif
 
 /*
@@ -162,7 +216,7 @@ static inline void destroy_work_on_stack(struct work_struct *work) { }
  * @work: The work item in question
  */
 #define work_pending(work) \
-       test_bit(WORK_STRUCT_PENDING, work_data_bits(work))
+       test_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))
 
 /**
  * delayed_work_pending - Find out whether a delayable work item is currently
@@ -177,16 +231,56 @@ static inline void destroy_work_on_stack(struct work_struct *work) { }
  * @work: The work item in question
  */
 #define work_clear_pending(work) \
-       clear_bit(WORK_STRUCT_PENDING, work_data_bits(work))
+       clear_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))
+
+enum {
+       WQ_NON_REENTRANT        = 1 << 0, /* guarantee non-reentrance */
+       WQ_UNBOUND              = 1 << 1, /* not bound to any cpu */
+       WQ_FREEZEABLE           = 1 << 2, /* freeze during suspend */
+       WQ_RESCUER              = 1 << 3, /* has an rescue worker */
+       WQ_HIGHPRI              = 1 << 4, /* high priority */
+       WQ_CPU_INTENSIVE        = 1 << 5, /* cpu instensive workqueue */
+
+       WQ_MAX_ACTIVE           = 512,    /* I like 512, better ideas? */
+       WQ_MAX_UNBOUND_PER_CPU  = 4,      /* 4 * #cpus for unbound wq */
+       WQ_DFL_ACTIVE           = WQ_MAX_ACTIVE / 2,
+};
+
+/* unbound wq's aren't per-cpu, scale max_active according to #cpus */
+#define WQ_UNBOUND_MAX_ACTIVE  \
+       max_t(int, WQ_MAX_ACTIVE, num_possible_cpus() * WQ_MAX_UNBOUND_PER_CPU)
 
+/*
+ * System-wide workqueues which are always present.
+ *
+ * system_wq is the one used by schedule[_delayed]_work[_on]().
+ * Multi-CPU multi-threaded.  There are users which expect relatively
+ * short queue flush time.  Don't queue works which can run for too
+ * long.
+ *
+ * system_long_wq is similar to system_wq but may host long running
+ * works.  Queue flushing might take relatively long.
+ *
+ * system_nrt_wq is non-reentrant and guarantees that any given work
+ * item is never executed in parallel by multiple CPUs.  Queue
+ * flushing might take relatively long.
+ *
+ * system_unbound_wq is unbound workqueue.  Workers are not bound to
+ * any specific CPU, not concurrency managed, and all queued works are
+ * executed immediately as long as max_active limit is not reached and
+ * resources are available.
+ */
+extern struct workqueue_struct *system_wq;
+extern struct workqueue_struct *system_long_wq;
+extern struct workqueue_struct *system_nrt_wq;
+extern struct workqueue_struct *system_unbound_wq;
 
 extern struct workqueue_struct *
-__create_workqueue_key(const char *name, int singlethread,
-                      int freezeable, int rt, struct lock_class_key *key,
-                      const char *lock_name);
+__alloc_workqueue_key(const char *name, unsigned int flags, int max_active,
+                     struct lock_class_key *key, const char *lock_name);
 
 #ifdef CONFIG_LOCKDEP
-#define __create_workqueue(name, singlethread, freezeable, rt) \
+#define alloc_workqueue(name, flags, max_active)               \
 ({                                                             \
        static struct lock_class_key __key;                     \
        const char *__lock_name;                                \
@@ -196,20 +290,20 @@ __create_workqueue_key(const char *name, int singlethread,
        else                                                    \
                __lock_name = #name;                            \
                                                                \
-       __create_workqueue_key((name), (singlethread),          \
-                              (freezeable), (rt), &__key,      \
-                              __lock_name);                    \
+       __alloc_workqueue_key((name), (flags), (max_active),    \
+                             &__key, __lock_name);             \
 })
 #else
-#define __create_workqueue(name, singlethread, freezeable, rt) \
-       __create_workqueue_key((name), (singlethread), (freezeable), (rt), \
-                              NULL, NULL)
+#define alloc_workqueue(name, flags, max_active)               \
+       __alloc_workqueue_key((name), (flags), (max_active), NULL, NULL)
 #endif
 
-#define create_workqueue(name) __create_workqueue((name), 0, 0, 0)
-#define create_rt_workqueue(name) __create_workqueue((name), 0, 0, 1)
-#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1, 0)
-#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0, 0)
+#define create_workqueue(name)                                 \
+       alloc_workqueue((name), WQ_RESCUER, 1)
+#define create_freezeable_workqueue(name)                      \
+       alloc_workqueue((name), WQ_FREEZEABLE | WQ_UNBOUND | WQ_RESCUER, 1)
+#define create_singlethread_workqueue(name)                    \
+       alloc_workqueue((name), WQ_UNBOUND | WQ_RESCUER, 1)
 
 extern void destroy_workqueue(struct workqueue_struct *wq);
 
@@ -231,16 +325,19 @@ extern int 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 int current_is_keventd(void);
 extern int keventd_up(void);
 
-extern void init_workqueues(void);
 int execute_in_process_context(work_func_t fn, struct execute_work *);
 
 extern int flush_work(struct work_struct *work);
-
 extern int cancel_work_sync(struct work_struct *work);
 
+extern void workqueue_set_max_active(struct workqueue_struct *wq,
+                                    int max_active);
+extern bool workqueue_congested(unsigned int cpu, struct workqueue_struct *wq);
+extern unsigned int work_cpu(struct work_struct *work);
+extern unsigned int work_busy(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(), unless
@@ -298,7 +395,14 @@ static inline long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
 long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg);
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_FREEZER
+extern void freeze_workqueues_begin(void);
+extern bool freeze_workqueues_busy(void);
+extern void thaw_workqueues(void);
+#endif /* CONFIG_FREEZER */
+
 #ifdef CONFIG_LOCKDEP
 int in_workqueue_context(struct workqueue_struct *wq);
 #endif
+
 #endif