diff options
| author | Ingo Molnar <mingo@elte.hu> | 2002-09-30 22:17:42 -0700 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2002-09-30 22:17:42 -0700 |
| commit | 6ed12ff83c765aeda7d38d3bf9df7d46d24bfb11 (patch) | |
| tree | d2dd4a9cefd38743d3e51fbbab3d79920bb19ae1 /include | |
| parent | 7570df54ef8cc5b42500d26562ff50fcbe265aa2 (diff) | |
[PATCH] Workqueue Abstraction
This is the next iteration of the workqueue abstraction.
The framework includes:
- per-CPU queueing support.
on SMP there is a per-CPU worker thread (bound to its CPU) and per-CPU
work queues - this feature is completely transparent to workqueue-users.
keventd automatically uses this feature. XFS can now update to work-queues
and have the same per-CPU performance as it had with its per-CPU worker
threads.
- delayed work submission
there's a new queue_delayed_work(wq, work, delay) function and a new
schedule_delayed_work(work, delay) function. The later one is used to
correctly fix former tq_timer users. I've reverted those changes in 2.5.40
that changed tq_timer uses to schedule_work() - eg. in the case of
random.c or the tty flip queue it was definitely the wrong thing to do.
delayed work means a timer embedded in struct work_struct. I considered
using split struct work_struct and delayed_work_struct types, but lots
of code actively uses task-queues in both delayed and non-delayed mode,
so i went for the more generic approach that allows both methods of work
submission. Delayed timers do not cause any other overhead in the
normal submission path otherwise.
- multithreaded run_workqueue() implementation
the run_workqueue() function can now be called from multiple contexts, and
a worker thread will only use up a single entryy - this property is used
by the flushing code, and can potentially be used in the future to extend
the number of per-CPU worker threads.
- more reliable flushing
there's now a 'pending work' counter, which is used to accurately detect
when the last work-function has finished execution. It's also used to
correctly flush against timed requests. I'm not convinced whether the old
keventd implementation got this detail right.
- i switched the arguments of the queueing function(s) per Jeff's
suggestion, it's more straightforward this way.
Driver fixes:
i have converted almost every affected driver to the new framework. This
cleaned up tons of code. I also fixed a number of drivers that were still
using BHs (these drivers did not compile in 2.5.40).
while this means lots of changes, it might ease the QA decision whether to
put this patch into 2.5.
The pach converts roughly 80% of all tqueue-using code to workqueues - and
all the places that are not converted to workqueues yet are places that do
not compile in vanilla 2.5.40 anyway, due to unrelated changes. I've
converted a fair number of drivers that do not compile in 2.5.40, and i
think i've managed to convert every driver that compiles under 2.5.40.
Diffstat (limited to 'include')
28 files changed, 101 insertions, 97 deletions
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index ee1171a3ae67..55e0742783ed 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -4,7 +4,6 @@ #include <linux/major.h> #include <linux/sched.h> #include <linux/genhd.h> -#include <linux/tqueue.h> #include <linux/list.h> #include <linux/pagemap.h> #include <linux/backing-dev.h> diff --git a/include/linux/compatmac.h b/include/linux/compatmac.h index 1e28380cabb7..5ae68a6b58e7 100644 --- a/include/linux/compatmac.h +++ b/include/linux/compatmac.h @@ -102,7 +102,7 @@ static inline void *ioremap(unsigned long base, long length) #define my_iounmap(x, b) (((long)x<0x100000)?0:vfree ((void*)x)) -#define tty_flip_buffer_push(tty) queue_task(&tty->flip.tqueue, &tq_timer) +#define tty_flip_buffer_push(tty) schedule_delayed_work(&tty->flip.work, 1) #define signal_pending(current) (current->signal & ~current->blocked) #define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0) #define time_after(t1,t2) (((long)t1-t2) > 0) diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h index 0fe53b96a2e4..4d6235fb96cf 100644 --- a/include/linux/cyclades.h +++ b/include/linux/cyclades.h @@ -605,7 +605,7 @@ struct cyclades_port { struct cyclades_monitor mon; struct cyclades_idle_stats idle_stats; struct cyclades_icount icount; - struct tq_struct tqueue; + struct work_struct tqueue; wait_queue_head_t open_wait; wait_queue_head_t close_wait; wait_queue_head_t shutdown_wait; diff --git a/include/linux/hayesesp.h b/include/linux/hayesesp.h index 7efc5e31dc11..00774e5d4550 100644 --- a/include/linux/hayesesp.h +++ b/include/linux/hayesesp.h @@ -102,8 +102,8 @@ struct esp_struct { int xmit_head; int xmit_tail; int xmit_cnt; - struct tq_struct tqueue; - struct tq_struct tqueue_hangup; + struct work_struct tqueue; + struct work_struct tqueue_hangup; struct termios normal_termios; struct termios callout_termios; wait_queue_head_t open_wait; diff --git a/include/linux/if_wanpipe_common.h b/include/linux/if_wanpipe_common.h index e1c95b5d4cda..a5cab08d6990 100644 --- a/include/linux/if_wanpipe_common.h +++ b/include/linux/if_wanpipe_common.h @@ -39,7 +39,7 @@ typedef struct { int (*func) (struct sk_buff *, netdevice_t *, struct sock *); - struct tq_struct wanpipe_task; /* Immediate BH handler task */ + struct work_struct wanpipe_work; /* deferred keventd work */ unsigned char rw_bind; /* Sock bind state */ unsigned char usedby; unsigned char state; diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 9bcc7e3dba80..7de3324606ee 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -362,7 +362,7 @@ typedef struct isdn_net_local_s { char cisco_line_state; /* state of line according to keepalive packets */ char cisco_debserint; /* debugging flag of cisco hdlc with slarp */ struct timer_list cisco_timer; - struct tq_struct tqueue; + struct work_struct tqueue; struct isdn_netif_ops *ops; } isdn_net_local; diff --git a/include/linux/isicom.h b/include/linux/isicom.h index 6b0fc14f83e5..72114196a2fc 100644 --- a/include/linux/isicom.h +++ b/include/linux/isicom.h @@ -154,8 +154,8 @@ struct isi_port { struct tty_struct * tty; wait_queue_head_t close_wait; wait_queue_head_t open_wait; - struct tq_struct hangup_tq; - struct tq_struct bh_tqueue; + struct work_struct hangup_tq; + struct work_struct bh_tqueue; unsigned char * xmit_buf; int xmit_head; int xmit_tail; diff --git a/include/linux/istallion.h b/include/linux/istallion.h index e8a2709f66fb..c93624048244 100644 --- a/include/linux/istallion.h +++ b/include/linux/istallion.h @@ -79,7 +79,7 @@ typedef struct { wait_queue_head_t close_wait; wait_queue_head_t raw_wait; #endif - struct tq_struct tqhangup; + struct work_struct tqhangup; struct termios normaltermios; struct termios callouttermios; asysigs_t asig; diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index cab82ddbddc5..611aa1b5b129 100644 --- a/include/linux/jffs2_fs_sb.h +++ b/include/linux/jffs2_fs_sb.h @@ -5,7 +5,7 @@ #include <linux/types.h> #include <linux/spinlock.h> -#include <linux/tqueue.h> +#include <linux/workqueue.h> #include <linux/completion.h> #include <asm/semaphore.h> #include <linux/list.h> @@ -82,7 +82,7 @@ struct jffs2_sb_info { uint32_t wbuf_ofs; uint32_t wbuf_len; uint32_t wbuf_pagesize; - struct tq_struct wbuf_task; /* task for timed wbuf flush */ + struct work_struct wbuf_task; /* task for timed wbuf flush */ struct timer_list wbuf_timer; /* timer for flushing wbuf */ /* OS-private pointer for getting back to master superblock info */ diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h index abc0c3e7bad2..8e6d600dc534 100644 --- a/include/linux/kbd_kern.h +++ b/include/linux/kbd_kern.h @@ -150,7 +150,7 @@ extern unsigned int keymap_count; static inline void con_schedule_flip(struct tty_struct *t) { - schedule_task(&t->flip.tqueue); + schedule_work(&t->flip.work); } #endif diff --git a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h index 02ef9bb50b51..9febc18c6a85 100644 --- a/include/linux/ncp_fs_sb.h +++ b/include/linux/ncp_fs_sb.h @@ -13,7 +13,7 @@ #ifdef __KERNEL__ -#include <linux/tqueue.h> +#include <linux/workqueue.h> #define NCP_DEFAULT_OPTIONS 0 /* 2 for packet signatures */ @@ -91,7 +91,7 @@ struct ncp_server { void (*error_report)(struct sock* sk); void (*write_space)(struct sock* sk); /* STREAM mode only */ struct { - struct tq_struct tq; /* STREAM/DGRAM: data/error ready */ + struct work_struct tq; /* STREAM/DGRAM: data/error ready */ struct ncp_request_reply* creq; /* STREAM/DGRAM: awaiting reply from this request */ struct semaphore creq_sem; /* DGRAM only: lock accesses to rcv.creq */ @@ -110,11 +110,11 @@ struct ncp_server { } rcv; struct { struct list_head requests; /* STREAM only: queued requests */ - struct tq_struct tq; /* STREAM only: transmitter ready */ + struct work_struct tq; /* STREAM only: transmitter ready */ struct ncp_request_reply* creq; /* STREAM only: currently transmitted entry */ } tx; struct timer_list timeout_tm; /* DGRAM only: timeout timer */ - struct tq_struct timeout_tq; /* DGRAM only: associated queue, we run timers from process context */ + struct work_struct timeout_tq; /* DGRAM only: associated queue, we run timers from process context */ int timeout_last; /* DGRAM only: current timeout length */ int timeout_retries; /* DGRAM only: retries left */ struct { diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 0deab78dea6b..ee20abf5bb6c 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -16,7 +16,7 @@ #ifdef __KERNEL__ #include <linux/slab.h> #include <linux/interrupt.h> -#include <linux/tqueue.h> +#include <linux/workqueue.h> #include <asm/unaligned.h> #include <linux/bitops.h> #include <linux/proc_fs.h> diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 74bd8e0a1d3e..28b31edd08dc 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h @@ -5,7 +5,7 @@ #define _LINUX_REISER_FS_SB #ifdef __KERNEL__ -#include <linux/tqueue.h> +#include <linux/workqueue.h> #endif diff --git a/include/linux/sched.h b/include/linux/sched.h index 8a361b76cf43..850a01b4455c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -172,9 +172,6 @@ extern unsigned long cache_decay_ticks; extern signed long FASTCALL(schedule_timeout(signed long timeout)); asmlinkage void schedule(void); -extern int start_context_thread(void); -extern int current_is_keventd(void); - struct namespace; /* Maximum number of active map areas.. This is a random (large) number */ diff --git a/include/linux/serial167.h b/include/linux/serial167.h index 2c805a1791cf..1683e8941c04 100644 --- a/include/linux/serial167.h +++ b/include/linux/serial167.h @@ -51,7 +51,7 @@ struct cyclades_port { int xmit_cnt; int default_threshold; int default_timeout; - struct tq_struct tqueue; + struct work_struct tqueue; struct termios normal_termios; struct termios callout_termios; wait_queue_head_t open_wait; diff --git a/include/linux/serialP.h b/include/linux/serialP.h index 40c5b938472c..6fcb341a8776 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -21,7 +21,7 @@ #include <linux/config.h> #include <linux/termios.h> -#include <linux/tqueue.h> +#include <linux/workqueue.h> #include <linux/circ_buf.h> #include <linux/wait.h> #if (LINUX_VERSION_CODE < 0x020300) @@ -86,7 +86,7 @@ struct async_struct { u8 *iomem_base; u16 iomem_reg_shift; int io_type; - struct tq_struct tqueue; + struct work_struct work; #ifdef DECLARE_WAITQUEUE wait_queue_head_t open_wait; wait_queue_head_t close_wait; diff --git a/include/linux/stallion.h b/include/linux/stallion.h index 072f89508a13..50cc96401196 100644 --- a/include/linux/stallion.h +++ b/include/linux/stallion.h @@ -104,7 +104,7 @@ typedef struct stlport { #endif struct termios normaltermios; struct termios callouttermios; - struct tq_struct tqueue; + struct work_struct tqueue; comstats_t stats; stlrq_t tx; } stlport_t; diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h index 5d1f842c8512..b338aa49201e 100644 --- a/include/linux/sunrpc/debug.h +++ b/include/linux/sunrpc/debug.h @@ -12,7 +12,7 @@ #include <linux/config.h> #include <linux/timer.h> -#include <linux/tqueue.h> +#include <linux/workqueue.h> /* * Enable RPC debugging/profiling. diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index ff3a4ad22a13..601899c6ed87 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h @@ -10,7 +10,6 @@ #define _LINUX_SUNRPC_SCHED_H_ #include <linux/timer.h> -#include <linux/tqueue.h> #include <linux/sunrpc/types.h> #include <linux/wait.h> diff --git a/include/linux/sunrpc/types.h b/include/linux/sunrpc/types.h index d524016fb4ba..d222f47550af 100644 --- a/include/linux/sunrpc/types.h +++ b/include/linux/sunrpc/types.h @@ -10,7 +10,7 @@ #define _LINUX_SUNRPC_TYPES_H_ #include <linux/timer.h> -#include <linux/tqueue.h> +#include <linux/workqueue.h> #include <linux/sunrpc/debug.h> #include <linux/list.h> diff --git a/include/linux/suspend.h b/include/linux/suspend.h index ccc76b9ba88b..23e0ccdab015 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -43,7 +43,7 @@ struct suspend_header { #define SUSPEND_PD_PAGES(x) (((x)*sizeof(struct pbe))/PAGE_SIZE+1) -extern struct tq_struct suspend_tq; +extern struct work_struct suspend_tq; /* mm/vmscan.c */ extern int shrink_mem(void); diff --git a/include/linux/tqueue.h b/include/linux/tqueue.h deleted file mode 100644 index cca0b193617b..000000000000 --- a/include/linux/tqueue.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * tqueue.h --- task queue handling for Linux. - * - * Modified version of previous incarnations of task-queues, - * written by: - * - * (C) 1994 Kai Petzke, wpp@marie.physik.tu-berlin.de - * Modified for use in the Linux kernel by Theodore Ts'o, - * tytso@mit.edu. - */ - -#ifndef _LINUX_TQUEUE_H -#define _LINUX_TQUEUE_H - -#include <linux/spinlock.h> -#include <linux/list.h> -#include <linux/bitops.h> -#include <asm/system.h> - -struct tq_struct { - struct list_head list; /* linked list of active tq's */ - unsigned long sync; /* must be initialized to zero */ - void (*routine)(void *); /* function to call */ - void *data; /* argument to function */ -}; - -/* - * Emit code to initialise a tq_struct's routine and data pointers - */ -#define PREPARE_TQUEUE(_tq, _routine, _data) \ - do { \ - (_tq)->routine = _routine; \ - (_tq)->data = _data; \ - } while (0) - -/* - * Emit code to initialise all of a tq_struct - */ -#define INIT_TQUEUE(_tq, _routine, _data) \ - do { \ - INIT_LIST_HEAD(&(_tq)->list); \ - (_tq)->sync = 0; \ - PREPARE_TQUEUE((_tq), (_routine), (_data)); \ - } while (0) - -#define DECLARE_TASK_QUEUE(q) LIST_HEAD(q) - -/* Schedule a tq to run in process context */ -extern int schedule_task(struct tq_struct *task); - -/* finish all currently pending tasks - do not call from irq context */ -extern void flush_scheduled_tasks(void); - -#endif - diff --git a/include/linux/tty.h b/include/linux/tty.h index 3474a7dba9c2..81c8d745f708 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -20,7 +20,7 @@ #include <linux/fs.h> #include <linux/major.h> #include <linux/termios.h> -#include <linux/tqueue.h> +#include <linux/workqueue.h> #include <linux/tty_driver.h> #include <linux/tty_ldisc.h> @@ -138,7 +138,7 @@ extern struct screen_info screen_info; #define TTY_FLIPBUF_SIZE 512 struct tty_flip_buffer { - struct tq_struct tqueue; + struct work_struct work; struct semaphore pty_sem; char *char_buf_ptr; unsigned char *flag_buf_ptr; @@ -279,7 +279,7 @@ struct tty_struct { int alt_speed; /* For magic substitution of 38400 bps */ wait_queue_head_t write_wait; wait_queue_head_t read_wait; - struct tq_struct tq_hangup; + struct work_struct hangup_work; void *disc_data; void *driver_data; struct list_head tty_files; @@ -309,7 +309,7 @@ struct tty_struct { struct semaphore atomic_write; spinlock_t read_lock; /* If the tty has a pending do_SAK, queue it here - akpm */ - struct tq_struct SAK_tq; + struct work_struct SAK_work; }; /* tty magic number */ diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 738ffcd53264..abe9bfcf226c 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -19,7 +19,7 @@ _INLINE_ void tty_insert_flip_char(struct tty_struct *tty, _INLINE_ void tty_schedule_flip(struct tty_struct *tty) { - schedule_task(&tty->flip.tqueue); + schedule_delayed_work(&tty->flip.work, 1); } #undef _INLINE_ diff --git a/include/linux/wanpipe.h b/include/linux/wanpipe.h index 061090a368f8..74b35ec9099c 100644 --- a/include/linux/wanpipe.h +++ b/include/linux/wanpipe.h @@ -320,7 +320,7 @@ typedef struct { #include <linux/sdladrv.h> /* SDLA support module API definitions */ #include <linux/sdlasfm.h> /* SDLA firmware module definitions */ -#include <linux/tqueue.h> +#include <linux/workqueue.h> #ifdef LINUX_2_4 #include <linux/serial.h> #include <linux/serialP.h> @@ -389,7 +389,7 @@ typedef struct sdla unsigned int tty_open; unsigned char *tty_buf; unsigned char *tty_rx; - struct tq_struct tty_task_queue; + struct work_struct tty_work; union { @@ -422,7 +422,7 @@ typedef struct sdla u8 oob_on_modem; /* Option to send modem status to the api */ u16 num_of_ch; /* Number of channels configured by the user */ - struct tq_struct x25_poll_task; + struct work_struct x25_poll_work; struct timer_list x25_timer; } x; struct @@ -545,7 +545,7 @@ int wsppp_init (sdla_t* card, wandev_conf_t* conf); /* Sync PPP on top of RAW CH extern sdla_t * wanpipe_find_card(char *); extern sdla_t * wanpipe_find_card_num (int); -extern void wanpipe_queue_tq (struct tq_struct *); +extern void wanpipe_queue_work (struct work_struct *); extern void wanpipe_mark_bh (void); extern void wakeup_sk_bh (netdevice_t *); extern int change_dev_flags (netdevice_t *, unsigned); diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h new file mode 100644 index 000000000000..7828c7bef55f --- /dev/null +++ b/include/linux/workqueue.h @@ -0,0 +1,64 @@ +/* + * workqueue.h --- work queue handling for Linux. + */ + +#ifndef _LINUX_WORKQUEUE_H +#define _LINUX_WORKQUEUE_H + +#include <linux/timer.h> + +struct workqueue_struct; + +struct work_struct { + unsigned long pending; + struct list_head entry; + void (*func)(void *); + void *data; + void *wq_data; + timer_t timer; +}; + +#define __WORK_INITIALIZER(n, f, d) { \ + .entry = { &(n).entry, &(n).entry }, \ + .func = (f), \ + .data = (d) } + +#define DECLARE_WORK(n, f, d) \ + struct work_struct n = __WORK_INITIALIZER(n, f, d) + +/* + * initialize a work-struct's func and data pointers: + */ +#define PREPARE_WORK(_work, _func, _data) \ + do { \ + (_work)->func = _func; \ + (_work)->data = _data; \ + } while (0) + +/* + * initialize all of a work-struct: + */ +#define INIT_WORK(_work, _func, _data) \ + do { \ + INIT_LIST_HEAD(&(_work)->entry); \ + (_work)->pending = 0; \ + PREPARE_WORK((_work), (_func), (_data)); \ + init_timer(&(_work)->timer); \ + } while (0) + +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 work_struct *work, unsigned long delay)); +extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq)); + +extern int FASTCALL(schedule_work(struct work_struct *work)); +extern int FASTCALL(schedule_delayed_work(struct work_struct *work, unsigned long delay)); +extern void flush_scheduled_work(void); +extern int current_is_keventd(void); + +extern void init_workqueues(void); + +#endif + diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h index e5985f9ea68a..7f9659cc4239 100644 --- a/include/net/irda/ircomm_tty.h +++ b/include/net/irda/ircomm_tty.h @@ -95,7 +95,7 @@ struct ircomm_tty_cb { wait_queue_head_t open_wait; wait_queue_head_t close_wait; struct timer_list watchdog_timer; - struct tq_struct tqueue; + struct work_struct tqueue; unsigned short close_delay; unsigned short closing_wait; /* time to wait before closing */ diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 69f99bba1d9b..a405d9b517d8 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -57,7 +57,7 @@ #include <asm/param.h> /* We get MAXHOSTNAMELEN. */ #include <asm/atomic.h> /* This gets us atomic counters. */ #include <linux/skbuff.h> /* We need sk_buff_head. */ -#include <linux/tqueue.h> /* We need tq_struct. */ +#include <linux/workqueue.h> /* We need tq_struct. */ #include <linux/sctp.h> /* We need sctp* header structs. */ /* @@ -761,7 +761,7 @@ struct SCTP_inqueue { /* This is the delayed task to finish delivering inbound * messages. */ - struct tq_struct immediate; + struct work_struct immediate; int malloced; /* Is this structure kfree()able? */ }; |
