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> 114e6045f1SJohannes Berg #include <linux/lockdep.h> 12a08727baSLinus Torvalds #include <asm/atomic.h> 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds struct workqueue_struct; 151da177e4SLinus Torvalds 1665f27f38SDavid Howells struct work_struct; 1765f27f38SDavid Howells typedef void (*work_func_t)(struct work_struct *work); 186bb49e59SDavid Howells 19a08727baSLinus Torvalds /* 20a08727baSLinus Torvalds * The first word is the work queue pointer and the flags rolled into 21a08727baSLinus Torvalds * one 22a08727baSLinus Torvalds */ 23a08727baSLinus Torvalds #define work_data_bits(work) ((unsigned long *)(&(work)->data)) 24a08727baSLinus Torvalds 251da177e4SLinus Torvalds struct work_struct { 26a08727baSLinus Torvalds atomic_long_t data; 27365970a1SDavid Howells #define WORK_STRUCT_PENDING 0 /* T if work item pending execution */ 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; 324e6045f1SJohannes Berg #ifdef CONFIG_LOCKDEP 334e6045f1SJohannes Berg struct lockdep_map lockdep_map; 344e6045f1SJohannes Berg #endif 3552bad64dSDavid Howells }; 3652bad64dSDavid Howells 3723b2e599SOleg Nesterov #define WORK_DATA_INIT() ATOMIC_LONG_INIT(0) 38a08727baSLinus Torvalds 3952bad64dSDavid Howells struct delayed_work { 4052bad64dSDavid Howells struct work_struct work; 411da177e4SLinus Torvalds struct timer_list timer; 421da177e4SLinus Torvalds }; 431da177e4SLinus Torvalds 441fa44ecaSJames Bottomley struct execute_work { 451fa44ecaSJames Bottomley struct work_struct work; 461fa44ecaSJames Bottomley }; 471fa44ecaSJames Bottomley 484e6045f1SJohannes Berg #ifdef CONFIG_LOCKDEP 494e6045f1SJohannes Berg /* 504e6045f1SJohannes Berg * NB: because we have to copy the lockdep_map, setting _key 514e6045f1SJohannes Berg * here is required, otherwise it could get initialised to the 524e6045f1SJohannes Berg * copy of the lockdep_map! 534e6045f1SJohannes Berg */ 544e6045f1SJohannes Berg #define __WORK_INIT_LOCKDEP_MAP(n, k) \ 554e6045f1SJohannes Berg .lockdep_map = STATIC_LOCKDEP_MAP_INIT(n, k), 564e6045f1SJohannes Berg #else 574e6045f1SJohannes Berg #define __WORK_INIT_LOCKDEP_MAP(n, k) 584e6045f1SJohannes Berg #endif 594e6045f1SJohannes Berg 6065f27f38SDavid Howells #define __WORK_INITIALIZER(n, f) { \ 6123b2e599SOleg Nesterov .data = WORK_DATA_INIT(), \ 6265f27f38SDavid Howells .entry = { &(n).entry, &(n).entry }, \ 6365f27f38SDavid Howells .func = (f), \ 644e6045f1SJohannes Berg __WORK_INIT_LOCKDEP_MAP(#n, &(n)) \ 6565f27f38SDavid Howells } 6665f27f38SDavid Howells 6765f27f38SDavid Howells #define __DELAYED_WORK_INITIALIZER(n, f) { \ 6865f27f38SDavid Howells .work = __WORK_INITIALIZER((n).work, (f)), \ 691da177e4SLinus Torvalds .timer = TIMER_INITIALIZER(NULL, 0, 0), \ 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds 7265f27f38SDavid Howells #define DECLARE_WORK(n, f) \ 7365f27f38SDavid Howells struct work_struct n = __WORK_INITIALIZER(n, f) 7465f27f38SDavid Howells 7565f27f38SDavid Howells #define DECLARE_DELAYED_WORK(n, f) \ 7665f27f38SDavid Howells struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f) 7765f27f38SDavid Howells 781da177e4SLinus Torvalds /* 7965f27f38SDavid Howells * initialize a work item's function pointer 801da177e4SLinus Torvalds */ 8165f27f38SDavid Howells #define PREPARE_WORK(_work, _func) \ 821da177e4SLinus Torvalds do { \ 8352bad64dSDavid Howells (_work)->func = (_func); \ 841da177e4SLinus Torvalds } while (0) 851da177e4SLinus Torvalds 8665f27f38SDavid Howells #define PREPARE_DELAYED_WORK(_work, _func) \ 8765f27f38SDavid Howells PREPARE_WORK(&(_work)->work, (_func)) 8852bad64dSDavid Howells 891da177e4SLinus Torvalds /* 9052bad64dSDavid Howells * initialize all of a work item in one go 91a08727baSLinus Torvalds * 92a08727baSLinus Torvalds * NOTE! No point in using "atomic_long_set()": useing a direct 93a08727baSLinus Torvalds * assignment of the work data initializer allows the compiler 94a08727baSLinus Torvalds * to generate better code. 951da177e4SLinus Torvalds */ 964e6045f1SJohannes Berg #ifdef CONFIG_LOCKDEP 974e6045f1SJohannes Berg #define INIT_WORK(_work, _func) \ 984e6045f1SJohannes Berg do { \ 994e6045f1SJohannes Berg static struct lock_class_key __key; \ 1004e6045f1SJohannes Berg \ 1014e6045f1SJohannes Berg (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \ 1024e6045f1SJohannes Berg lockdep_init_map(&(_work)->lockdep_map, #_work, &__key, 0);\ 1034e6045f1SJohannes Berg INIT_LIST_HEAD(&(_work)->entry); \ 1044e6045f1SJohannes Berg PREPARE_WORK((_work), (_func)); \ 1054e6045f1SJohannes Berg } while (0) 1064e6045f1SJohannes Berg #else 10765f27f38SDavid Howells #define INIT_WORK(_work, _func) \ 1081da177e4SLinus Torvalds do { \ 10923b2e599SOleg Nesterov (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \ 11065f27f38SDavid Howells INIT_LIST_HEAD(&(_work)->entry); \ 11165f27f38SDavid Howells PREPARE_WORK((_work), (_func)); \ 11265f27f38SDavid Howells } while (0) 1134e6045f1SJohannes Berg #endif 11465f27f38SDavid Howells 11565f27f38SDavid Howells #define INIT_DELAYED_WORK(_work, _func) \ 11665f27f38SDavid Howells do { \ 11765f27f38SDavid Howells INIT_WORK(&(_work)->work, (_func)); \ 11865f27f38SDavid Howells init_timer(&(_work)->timer); \ 11965f27f38SDavid Howells } while (0) 12065f27f38SDavid Howells 1216d612b0fSPeter Zijlstra #define INIT_DELAYED_WORK_ON_STACK(_work, _func) \ 1226d612b0fSPeter Zijlstra do { \ 1236d612b0fSPeter Zijlstra INIT_WORK(&(_work)->work, (_func)); \ 1246d612b0fSPeter Zijlstra init_timer_on_stack(&(_work)->timer); \ 1256d612b0fSPeter Zijlstra } while (0) 1266d612b0fSPeter Zijlstra 12728287033SVenki Pallipadi #define INIT_DELAYED_WORK_DEFERRABLE(_work, _func) \ 12828287033SVenki Pallipadi do { \ 12928287033SVenki Pallipadi INIT_WORK(&(_work)->work, (_func)); \ 13028287033SVenki Pallipadi init_timer_deferrable(&(_work)->timer); \ 13128287033SVenki Pallipadi } while (0) 13228287033SVenki Pallipadi 133365970a1SDavid Howells /** 134365970a1SDavid Howells * work_pending - Find out whether a work item is currently pending 135365970a1SDavid Howells * @work: The work item in question 136365970a1SDavid Howells */ 137365970a1SDavid Howells #define work_pending(work) \ 138a08727baSLinus Torvalds test_bit(WORK_STRUCT_PENDING, work_data_bits(work)) 139365970a1SDavid Howells 140365970a1SDavid Howells /** 141365970a1SDavid Howells * delayed_work_pending - Find out whether a delayable work item is currently 142365970a1SDavid Howells * pending 143365970a1SDavid Howells * @work: The work item in question 144365970a1SDavid Howells */ 1450221872aSLinus Torvalds #define delayed_work_pending(w) \ 1460221872aSLinus Torvalds work_pending(&(w)->work) 147365970a1SDavid Howells 14865f27f38SDavid Howells /** 14923b2e599SOleg Nesterov * work_clear_pending - for internal use only, mark a work item as not pending 15023b2e599SOleg Nesterov * @work: The work item in question 15165f27f38SDavid Howells */ 15223b2e599SOleg Nesterov #define work_clear_pending(work) \ 153a08727baSLinus Torvalds clear_bit(WORK_STRUCT_PENDING, work_data_bits(work)) 15465f27f38SDavid Howells 15552bad64dSDavid Howells 1564e6045f1SJohannes Berg extern struct workqueue_struct * 1574e6045f1SJohannes Berg __create_workqueue_key(const char *name, int singlethread, 1580d557dc9SHeiko Carstens int freezeable, int rt, struct lock_class_key *key, 159eb13ba87SJohannes Berg const char *lock_name); 1604e6045f1SJohannes Berg 1614e6045f1SJohannes Berg #ifdef CONFIG_LOCKDEP 1620d557dc9SHeiko Carstens #define __create_workqueue(name, singlethread, freezeable, rt) \ 1634e6045f1SJohannes Berg ({ \ 1644e6045f1SJohannes Berg static struct lock_class_key __key; \ 165eb13ba87SJohannes Berg const char *__lock_name; \ 166eb13ba87SJohannes Berg \ 167eb13ba87SJohannes Berg if (__builtin_constant_p(name)) \ 168eb13ba87SJohannes Berg __lock_name = (name); \ 169eb13ba87SJohannes Berg else \ 170eb13ba87SJohannes Berg __lock_name = #name; \ 1714e6045f1SJohannes Berg \ 1724e6045f1SJohannes Berg __create_workqueue_key((name), (singlethread), \ 1730d557dc9SHeiko Carstens (freezeable), (rt), &__key, \ 174eb13ba87SJohannes Berg __lock_name); \ 1754e6045f1SJohannes Berg }) 1764e6045f1SJohannes Berg #else 1770d557dc9SHeiko Carstens #define __create_workqueue(name, singlethread, freezeable, rt) \ 1780d557dc9SHeiko Carstens __create_workqueue_key((name), (singlethread), (freezeable), (rt), \ 1790d557dc9SHeiko Carstens NULL, NULL) 1804e6045f1SJohannes Berg #endif 1814e6045f1SJohannes Berg 1820d557dc9SHeiko Carstens #define create_workqueue(name) __create_workqueue((name), 0, 0, 0) 1830d557dc9SHeiko Carstens #define create_rt_workqueue(name) __create_workqueue((name), 0, 0, 1) 1840d557dc9SHeiko Carstens #define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1, 0) 1850d557dc9SHeiko Carstens #define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0, 0) 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds extern void destroy_workqueue(struct workqueue_struct *wq); 1881da177e4SLinus Torvalds 189b3c97528SHarvey Harrison extern int queue_work(struct workqueue_struct *wq, struct work_struct *work); 190c1a220e7SZhang Rui extern int queue_work_on(int cpu, struct workqueue_struct *wq, 191c1a220e7SZhang Rui struct work_struct *work); 192b3c97528SHarvey Harrison extern int queue_delayed_work(struct workqueue_struct *wq, 193b3c97528SHarvey Harrison struct delayed_work *work, unsigned long delay); 1947a6bc1cdSVenkatesh Pallipadi extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, 19552bad64dSDavid Howells struct delayed_work *work, unsigned long delay); 19628e53bddSOleg Nesterov 197b3c97528SHarvey Harrison extern void flush_workqueue(struct workqueue_struct *wq); 19828e53bddSOleg Nesterov extern void flush_scheduled_work(void); 1991da177e4SLinus Torvalds 200b3c97528SHarvey Harrison extern int schedule_work(struct work_struct *work); 201c1a220e7SZhang Rui extern int schedule_work_on(int cpu, struct work_struct *work); 202b3c97528SHarvey Harrison extern int schedule_delayed_work(struct delayed_work *work, unsigned long delay); 20328e53bddSOleg Nesterov extern int schedule_delayed_work_on(int cpu, struct delayed_work *work, 20428e53bddSOleg Nesterov unsigned long delay); 20565f27f38SDavid Howells extern int schedule_on_each_cpu(work_func_t func); 2061da177e4SLinus Torvalds extern int current_is_keventd(void); 2071da177e4SLinus Torvalds extern int keventd_up(void); 2081da177e4SLinus Torvalds 2091da177e4SLinus Torvalds extern void init_workqueues(void); 21065f27f38SDavid Howells int execute_in_process_context(work_func_t fn, struct execute_work *); 2111da177e4SLinus Torvalds 212db700897SOleg Nesterov extern int flush_work(struct work_struct *work); 213db700897SOleg Nesterov 2141f1f642eSOleg Nesterov extern int cancel_work_sync(struct work_struct *work); 21528e53bddSOleg Nesterov 2161da177e4SLinus Torvalds /* 2171da177e4SLinus Torvalds * Kill off a pending schedule_delayed_work(). Note that the work callback 218071b6386SOleg Nesterov * function may still be running on return from cancel_delayed_work(), unless 219071b6386SOleg Nesterov * it returns 1 and the work doesn't re-arm itself. Run flush_workqueue() or 22028e53bddSOleg Nesterov * cancel_work_sync() to wait on it. 2211da177e4SLinus Torvalds */ 22252bad64dSDavid Howells static inline int cancel_delayed_work(struct delayed_work *work) 2231da177e4SLinus Torvalds { 2241da177e4SLinus Torvalds int ret; 2251da177e4SLinus Torvalds 226223a10a9SOleg Nesterov ret = del_timer_sync(&work->timer); 2271da177e4SLinus Torvalds if (ret) 22823b2e599SOleg Nesterov work_clear_pending(&work->work); 2291da177e4SLinus Torvalds return ret; 2301da177e4SLinus Torvalds } 2311da177e4SLinus Torvalds 2321f1f642eSOleg Nesterov extern int cancel_delayed_work_sync(struct delayed_work *work); 2331634c48fSOleg Nesterov 234f5a421a4SOleg Nesterov /* Obsolete. use cancel_delayed_work_sync() */ 2351634c48fSOleg Nesterov static inline 2361634c48fSOleg Nesterov void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq, 2371634c48fSOleg Nesterov struct delayed_work *work) 2381634c48fSOleg Nesterov { 239f5a421a4SOleg Nesterov cancel_delayed_work_sync(work); 240f5a421a4SOleg Nesterov } 241f5a421a4SOleg Nesterov 242f5a421a4SOleg Nesterov /* Obsolete. use cancel_delayed_work_sync() */ 243f5a421a4SOleg Nesterov static inline 244f5a421a4SOleg Nesterov void cancel_rearming_delayed_work(struct delayed_work *work) 245f5a421a4SOleg Nesterov { 246f5a421a4SOleg Nesterov cancel_delayed_work_sync(work); 2471634c48fSOleg Nesterov } 2481634c48fSOleg Nesterov 2492d3854a3SRusty Russell #ifndef CONFIG_SMP 2502d3854a3SRusty Russell static inline long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) 2512d3854a3SRusty Russell { 2522d3854a3SRusty Russell return fn(arg); 2532d3854a3SRusty Russell } 2542d3854a3SRusty Russell #else 2552d3854a3SRusty Russell long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg); 2562d3854a3SRusty Russell #endif /* CONFIG_SMP */ 2571da177e4SLinus Torvalds #endif 258