xref: /openbmc/linux/include/linux/workqueue.h (revision a08727ba)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * workqueue.h --- work queue handling for Linux.
31da177e4SLinus Torvalds  */
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds #ifndef _LINUX_WORKQUEUE_H
61da177e4SLinus Torvalds #define _LINUX_WORKQUEUE_H
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds #include <linux/timer.h>
91da177e4SLinus Torvalds #include <linux/linkage.h>
101da177e4SLinus Torvalds #include <linux/bitops.h>
11a08727baSLinus Torvalds #include <asm/atomic.h>
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds struct workqueue_struct;
141da177e4SLinus Torvalds 
1565f27f38SDavid Howells struct work_struct;
1665f27f38SDavid Howells typedef void (*work_func_t)(struct work_struct *work);
176bb49e59SDavid Howells 
18a08727baSLinus Torvalds /*
19a08727baSLinus Torvalds  * The first word is the work queue pointer and the flags rolled into
20a08727baSLinus Torvalds  * one
21a08727baSLinus Torvalds  */
22a08727baSLinus Torvalds #define work_data_bits(work) ((unsigned long *)(&(work)->data))
23a08727baSLinus Torvalds 
241da177e4SLinus Torvalds struct work_struct {
25a08727baSLinus Torvalds 	atomic_long_t data;
26365970a1SDavid Howells #define WORK_STRUCT_PENDING 0		/* T if work item pending execution */
2765f27f38SDavid Howells #define WORK_STRUCT_NOAUTOREL 1		/* F if work item automatically released on exec */
28365970a1SDavid Howells #define WORK_STRUCT_FLAG_MASK (3UL)
29365970a1SDavid Howells #define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
301da177e4SLinus Torvalds 	struct list_head entry;
316bb49e59SDavid Howells 	work_func_t func;
3252bad64dSDavid Howells };
3352bad64dSDavid Howells 
34a08727baSLinus Torvalds #define WORK_DATA_INIT(autorelease) \
35a08727baSLinus Torvalds 	ATOMIC_LONG_INIT((autorelease) << WORK_STRUCT_NOAUTOREL)
36a08727baSLinus Torvalds 
3752bad64dSDavid Howells struct delayed_work {
3852bad64dSDavid Howells 	struct work_struct work;
391da177e4SLinus Torvalds 	struct timer_list timer;
401da177e4SLinus Torvalds };
411da177e4SLinus Torvalds 
421fa44ecaSJames Bottomley struct execute_work {
431fa44ecaSJames Bottomley 	struct work_struct work;
441fa44ecaSJames Bottomley };
451fa44ecaSJames Bottomley 
4665f27f38SDavid Howells #define __WORK_INITIALIZER(n, f) {				\
47a08727baSLinus Torvalds 	.data = WORK_DATA_INIT(0),				\
481da177e4SLinus Torvalds         .entry	= { &(n).entry, &(n).entry },			\
491da177e4SLinus Torvalds 	.func = (f),						\
5052bad64dSDavid Howells 	}
5152bad64dSDavid Howells 
5265f27f38SDavid Howells #define __WORK_INITIALIZER_NAR(n, f) {				\
53a08727baSLinus Torvalds 	.data = WORK_DATA_INIT(1),				\
5465f27f38SDavid Howells         .entry	= { &(n).entry, &(n).entry },			\
5565f27f38SDavid Howells 	.func = (f),						\
5665f27f38SDavid Howells 	}
5765f27f38SDavid Howells 
5865f27f38SDavid Howells #define __DELAYED_WORK_INITIALIZER(n, f) {			\
5965f27f38SDavid Howells 	.work = __WORK_INITIALIZER((n).work, (f)),		\
601da177e4SLinus Torvalds 	.timer = TIMER_INITIALIZER(NULL, 0, 0),			\
611da177e4SLinus Torvalds 	}
621da177e4SLinus Torvalds 
6365f27f38SDavid Howells #define __DELAYED_WORK_INITIALIZER_NAR(n, f) {			\
6465f27f38SDavid Howells 	.work = __WORK_INITIALIZER_NAR((n).work, (f)),		\
6565f27f38SDavid Howells 	.timer = TIMER_INITIALIZER(NULL, 0, 0),			\
6665f27f38SDavid Howells 	}
671da177e4SLinus Torvalds 
6865f27f38SDavid Howells #define DECLARE_WORK(n, f)					\
6965f27f38SDavid Howells 	struct work_struct n = __WORK_INITIALIZER(n, f)
7065f27f38SDavid Howells 
7165f27f38SDavid Howells #define DECLARE_WORK_NAR(n, f)					\
7265f27f38SDavid Howells 	struct work_struct n = __WORK_INITIALIZER_NAR(n, f)
7365f27f38SDavid Howells 
7465f27f38SDavid Howells #define DECLARE_DELAYED_WORK(n, f)				\
7565f27f38SDavid Howells 	struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f)
7665f27f38SDavid Howells 
7765f27f38SDavid Howells #define DECLARE_DELAYED_WORK_NAR(n, f)			\
7865f27f38SDavid Howells 	struct dwork_struct n = __DELAYED_WORK_INITIALIZER_NAR(n, f)
7952bad64dSDavid Howells 
801da177e4SLinus Torvalds /*
8165f27f38SDavid Howells  * initialize a work item's function pointer
821da177e4SLinus Torvalds  */
8365f27f38SDavid Howells #define PREPARE_WORK(_work, _func)				\
841da177e4SLinus Torvalds 	do {							\
8552bad64dSDavid Howells 		(_work)->func = (_func);			\
861da177e4SLinus Torvalds 	} while (0)
871da177e4SLinus Torvalds 
8865f27f38SDavid Howells #define PREPARE_DELAYED_WORK(_work, _func)			\
8965f27f38SDavid Howells 	PREPARE_WORK(&(_work)->work, (_func))
9052bad64dSDavid Howells 
911da177e4SLinus Torvalds /*
9252bad64dSDavid Howells  * initialize all of a work item in one go
93a08727baSLinus Torvalds  *
94a08727baSLinus Torvalds  * NOTE! No point in using "atomic_long_set()": useing a direct
95a08727baSLinus Torvalds  * assignment of the work data initializer allows the compiler
96a08727baSLinus Torvalds  * to generate better code.
971da177e4SLinus Torvalds  */
9865f27f38SDavid Howells #define INIT_WORK(_work, _func)					\
991da177e4SLinus Torvalds 	do {							\
100a08727baSLinus Torvalds 		(_work)->data = (atomic_long_t) WORK_DATA_INIT(0);	\
10165f27f38SDavid Howells 		INIT_LIST_HEAD(&(_work)->entry);		\
10265f27f38SDavid Howells 		PREPARE_WORK((_work), (_func));			\
10352bad64dSDavid Howells 	} while (0)
10452bad64dSDavid Howells 
10565f27f38SDavid Howells #define INIT_WORK_NAR(_work, _func)					\
10652bad64dSDavid Howells 	do {								\
107a08727baSLinus Torvalds 		(_work)->data = (atomic_long_t) WORK_DATA_INIT(1);	\
10865f27f38SDavid Howells 		INIT_LIST_HEAD(&(_work)->entry);			\
10965f27f38SDavid Howells 		PREPARE_WORK((_work), (_func));				\
11065f27f38SDavid Howells 	} while (0)
11165f27f38SDavid Howells 
11265f27f38SDavid Howells #define INIT_DELAYED_WORK(_work, _func)				\
11365f27f38SDavid Howells 	do {							\
11465f27f38SDavid Howells 		INIT_WORK(&(_work)->work, (_func));		\
11565f27f38SDavid Howells 		init_timer(&(_work)->timer);			\
11665f27f38SDavid Howells 	} while (0)
11765f27f38SDavid Howells 
11865f27f38SDavid Howells #define INIT_DELAYED_WORK_NAR(_work, _func)			\
11965f27f38SDavid Howells 	do {							\
12065f27f38SDavid Howells 		INIT_WORK_NAR(&(_work)->work, (_func));		\
1211da177e4SLinus Torvalds 		init_timer(&(_work)->timer);			\
1221da177e4SLinus Torvalds 	} while (0)
1231da177e4SLinus Torvalds 
124365970a1SDavid Howells /**
125365970a1SDavid Howells  * work_pending - Find out whether a work item is currently pending
126365970a1SDavid Howells  * @work: The work item in question
127365970a1SDavid Howells  */
128365970a1SDavid Howells #define work_pending(work) \
129a08727baSLinus Torvalds 	test_bit(WORK_STRUCT_PENDING, work_data_bits(work))
130365970a1SDavid Howells 
131365970a1SDavid Howells /**
132365970a1SDavid Howells  * delayed_work_pending - Find out whether a delayable work item is currently
133365970a1SDavid Howells  * pending
134365970a1SDavid Howells  * @work: The work item in question
135365970a1SDavid Howells  */
1360221872aSLinus Torvalds #define delayed_work_pending(w) \
1370221872aSLinus Torvalds 	work_pending(&(w)->work)
138365970a1SDavid Howells 
13965f27f38SDavid Howells /**
14065f27f38SDavid Howells  * work_release - Release a work item under execution
14165f27f38SDavid Howells  * @work: The work item to release
14265f27f38SDavid Howells  *
14365f27f38SDavid Howells  * This is used to release a work item that has been initialised with automatic
14465f27f38SDavid Howells  * release mode disabled (WORK_STRUCT_NOAUTOREL is set).  This gives the work
14565f27f38SDavid Howells  * function the opportunity to grab auxiliary data from the container of the
14665f27f38SDavid Howells  * work_struct before clearing the pending bit as the work_struct may be
14765f27f38SDavid Howells  * subject to deallocation the moment the pending bit is cleared.
14865f27f38SDavid Howells  *
14965f27f38SDavid Howells  * In such a case, this should be called in the work function after it has
15065f27f38SDavid Howells  * fetched any data it may require from the containter of the work_struct.
15165f27f38SDavid Howells  * After this function has been called, the work_struct may be scheduled for
15265f27f38SDavid Howells  * further execution or it may be deallocated unless other precautions are
15365f27f38SDavid Howells  * taken.
15465f27f38SDavid Howells  *
15565f27f38SDavid Howells  * This should also be used to release a delayed work item.
15665f27f38SDavid Howells  */
15765f27f38SDavid Howells #define work_release(work) \
158a08727baSLinus Torvalds 	clear_bit(WORK_STRUCT_PENDING, work_data_bits(work))
15965f27f38SDavid Howells 
16052bad64dSDavid Howells 
1611da177e4SLinus Torvalds extern struct workqueue_struct *__create_workqueue(const char *name,
162341a5958SRafael J. Wysocki 						    int singlethread,
163341a5958SRafael J. Wysocki 						    int freezeable);
164341a5958SRafael J. Wysocki #define create_workqueue(name) __create_workqueue((name), 0, 0)
165341a5958SRafael J. Wysocki #define create_freezeable_workqueue(name) __create_workqueue((name), 0, 1)
166341a5958SRafael J. Wysocki #define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0)
1671da177e4SLinus Torvalds 
1681da177e4SLinus Torvalds extern void destroy_workqueue(struct workqueue_struct *wq);
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds extern int FASTCALL(queue_work(struct workqueue_struct *wq, struct work_struct *work));
17152bad64dSDavid Howells extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay));
1727a6bc1cdSVenkatesh Pallipadi extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
17352bad64dSDavid Howells 	struct delayed_work *work, unsigned long delay);
1741da177e4SLinus Torvalds extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq));
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds extern int FASTCALL(schedule_work(struct work_struct *work));
17768380b58SLinus Torvalds extern int FASTCALL(run_scheduled_work(struct work_struct *work));
17852bad64dSDavid Howells extern int FASTCALL(schedule_delayed_work(struct delayed_work *work, unsigned long delay));
1791da177e4SLinus Torvalds 
18052bad64dSDavid Howells extern int schedule_delayed_work_on(int cpu, struct delayed_work *work, unsigned long delay);
18165f27f38SDavid Howells extern int schedule_on_each_cpu(work_func_t func);
1821da177e4SLinus Torvalds extern void flush_scheduled_work(void);
1831da177e4SLinus Torvalds extern int current_is_keventd(void);
1841da177e4SLinus Torvalds extern int keventd_up(void);
1851da177e4SLinus Torvalds 
1861da177e4SLinus Torvalds extern void init_workqueues(void);
18752bad64dSDavid Howells void cancel_rearming_delayed_work(struct delayed_work *work);
18881ddef77SJames Bottomley void cancel_rearming_delayed_workqueue(struct workqueue_struct *,
18952bad64dSDavid Howells 				       struct delayed_work *);
19065f27f38SDavid Howells int execute_in_process_context(work_func_t fn, struct execute_work *);
1911da177e4SLinus Torvalds 
1921da177e4SLinus Torvalds /*
1931da177e4SLinus Torvalds  * Kill off a pending schedule_delayed_work().  Note that the work callback
1941da177e4SLinus Torvalds  * function may still be running on return from cancel_delayed_work().  Run
1951da177e4SLinus Torvalds  * flush_scheduled_work() to wait on it.
1961da177e4SLinus Torvalds  */
19752bad64dSDavid Howells static inline int cancel_delayed_work(struct delayed_work *work)
1981da177e4SLinus Torvalds {
1991da177e4SLinus Torvalds 	int ret;
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds 	ret = del_timer_sync(&work->timer);
2021da177e4SLinus Torvalds 	if (ret)
203a08727baSLinus Torvalds 		work_release(&work->work);
2041da177e4SLinus Torvalds 	return ret;
2051da177e4SLinus Torvalds }
2061da177e4SLinus Torvalds 
2071da177e4SLinus Torvalds #endif
208