2.4, maintenance mode, and workqueues
Subsystems (2)
RFC PATCH 1/1 2.4, maintenance mode, and workqueues
One thing that would make my life a lot easier, before 2.4 goes into "deep maintenance" mode, would be the addition of workqueues (kthread.c and workqueue.c).
Doing so would go a long way towards making drivers more portable, since the kthread/wq stuff eliminates a lot of the task/signal mess that a driver really shouldn't have to care about.
The interfaces are pretty self-contained, as is shown by the attached patch (_not_ for application).
Jeff
# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/10/21 21:15:43-04:00 [email protected]
# Add kthread/workqueue APIs.
#
# kernel/workqueue.c # 2004/10/21 21:15:41-04:00 [email protected] +528 -0 # # kernel/kthread.c # 2004/10/21 21:15:41-04:00 [email protected] +184 -0 # # include/linux/workqueue.h # 2004/10/21 21:15:41-04:00 [email protected] +89 -0 # # include/linux/kthread.h # 2004/10/21 21:15:41-04:00 [email protected] +81 -0 # # kernel/workqueue.c # 2004/10/21 21:15:41-04:00 [email protected] +0 -0 # BitKeeper file /garz/repo/kthread-2.4/kernel/workqueue.c # # kernel/sched.c # 2004/10/21 21:15:41-04:00 [email protected] +11 -0 # Add kthread/workqueue APIs. # # kernel/kthread.c # 2004/10/21 21:15:41-04:00 [email protected] +0 -0 # BitKeeper file /garz/repo/kthread-2.4/kernel/kthread.c # # kernel/ksyms.c # 2004/10/21 21:15:41-04:00 [email protected] +1 -0 # Add kthread/workqueue APIs. # # kernel/Makefile # 2004/10/21 21:15:41-04:00 [email protected] +3 -2 # Add kthread/workqueue APIs. # # include/linux/workqueue.h # 2004/10/21 21:15:41-04:00 [email protected] +0 -0 # BitKeeper file /garz/repo/kthread-2.4/include/linux/workqueue.h # # include/linux/timer.h # 2004/10/21 21:15:41-04:00 [email protected] +12 -0 # Add kthread/workqueue APIs. # # include/linux/smp.h # 2004/10/21 21:15:41-04:00 [email protected] +11 -3 # Add kthread/workqueue APIs. # # include/linux/sched.h # 2004/10/21 21:15:41-04:00 [email protected] +3 -1 # Add kthread/workqueue APIs. # # include/linux/kthread.h # 2004/10/21 21:15:41-04:00 [email protected] +0 -0 # BitKeeper file /garz/repo/kthread-2.4/include/linux/kthread.h # diff -Nru a/include/linux/kthread.h b/include/linux/kthread.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/linux/kthread.h 2004-10-21 21:15:58 -04:00 @@ -0,0 +1,81 @@ +#ifndef _LINUX_KTHREAD_H +#define _LINUX_KTHREAD_H +/* Simple interface for creating and stopping kernel threads without mess. */ +#include <linux/fs.h> +#include <linux/sched.h> + +/** + * kthread_create: create a kthread. + * @threadfn: the function to run until signal_pending(current). + * @data: data ptr for @threadfn. + * @namefmt: printf-style name for the thread. + * + * Description: This helper function creates and names a kernel + * thread. The thread will be stopped: use wake_up_process() to start + * it. See also kthread_run(), kthread_create_on_cpu(). + * + * When woken, the thread will run @threadfn() with @data as its + * argument. @threadfn can either call do_exit() directly if it is a + * standalone thread for which noone will call kthread_stop(), or + * return when 'kthread_should_stop()' is true (which means + * kthread_stop() has been called). The return value should be zero + * or a negative error number: it will be passed to kthread_stop(). + * + * Returns a task_struct or ERR_PTR(-ENOMEM). + */ +struct task_struct *kthread_create(int (*threadfn)(void *data), + void *data, + const char namefmt[], ...); + +/** + * kthread_run: create and wake a thread. + * @threadfn: the function to run until signal_pending(current). + * @data: data ptr for @threadfn. + * @namefmt: printf-style name for the thread. + * + * Description: Convenient wrapper for kthread_create() followed by + * wake_up_process(). Returns the kthread, or ERR_PTR(-ENOMEM). */ +#define kthread_run(threadfn, data, namefmt, ...) \ +({ \ + struct task_struct *__k \ + = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \ + if (!IS_ERR(__k)) \ + wake_up_process(__k); \ + __k; \ +}) + +/** + * kthread_bind: bind a just-created kthread to a cpu. + * @k: thread created by kthread_create(). + * @cpu: cpu (might not be online, must be possible) for @k to run on. + * + * Description: This function is equivalent to set_cpus_allowed(), + * except that @cpu doesn't need to be online, and the thread must be + * stopped (ie. just returned from kthread_create(). + */ +void kthread_bind(struct task_struct *k, unsigned int cpu); + +/** + * kthread_stop: stop a thread created by kthread_create(). + * @k: thread created by kthread_create(). + * + * Sets kthread_should_stop() for @k to return true, wakes it, and + * waits for it to exit. Your threadfn() must not call do_exit() + * itself if you use this function! This can also be called after + * kthread_create() instead of calling wake_up_process(): the thread + * will exit without calling threadfn(). + * + * Returns the result of threadfn(), or -EINTR if wake_up_process() + * was never called. */ +int kthread_stop(struct task_struct *k); + +/** + * kthread_should_stop: should this kthread return now? + * + * When someone calls kthread_stop on your kthread, it will be woken + * and this will return true. You should then return, and your return + * value will be passed through to kthread_stop(). + */ +int kthread_should_stop(void); + +#endif /* _LINUX_KTHREAD_H */ diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h 2004-10-21 21:15:58 -04:00 +++ b/include/linux/sched.h 2004-10-21 21:15:58 -04:00 @@ -135,6 +135,8 @@ extern spinlock_t runqueue_lock; extern spinlock_t mmlist_lock;
+typedef struct task_struct task_t;
+
extern void sched_init(void);
extern void init_idle(void);
extern void show_state(void);
@@ -143,7 +145,7 @@
extern void update_process_times(int user);
extern void update_one_process(struct task_struct *p, unsigned long user,
unsigned long system, int cpu);
-
+extern void set_user_nice(struct task_struct *p, long nice);
#define MAX_SCHEDULE_TIMEOUT LONG_MAX
extern signed long FASTCALL(schedule_timeout(signed long timeout)); asmlinkage void schedule(void);
include/linux/smp.h +11 -3
@@ -71,7 +71,7 @@#define MSG_RESCHEDULE 0x0003/* Reschedule request from master CPU*/ #define MSG_CALL_FUNCTION 0x0004/* Call function on all other CPUs */ -#else +#else /* !SMP */ /* * These macros fold the SMP functionality into a single CPU system
@@ -87,5 +87,13 @@#define smp_call_function (func,info,retry,wait) ({ 0; })#define cpu_online_map 1 -#endif -#endif +#endif /* !SMP */ + +#define get_cpu () ({ smp_processor_id(); }) +#define put_cpu () do {} while (0) +#define lock_cpu_hotplug () do {} while (0) +#define unlock_cpu_hotplug () do {} while (0) +#define for_each_online_cpu (cpu) \ + for ((cpu) = 0; (cpu) < smp_num_cpus; (cpu)++) + +#endif /* __LINUX_SMP_H */
include/linux/timer.h +12 -0
@@ -20,8 +20,20 @@void (*function)(unsigned long ); }; +#define TIMER_INITIALIZER (_function, _expires, _data) { \ + .function = (_function), \ + .expires = (_expires), \ + .data = (_data), \ + .list = { NULL, NULL }, \ + } +extern void add_timer (struct timer_list * timer);extern int del_timer (struct timer_list * timer); + +static inline void add_timer_on (struct timer_list *timer,int cpu) +{ +add_timer (timer); +}#ifdef CONFIG_SMP extern int del_timer_sync (struct timer_list * timer);
include/linux/workqueue.h new file +89 -0
89 lines not on this page · raw message
kernel/Makefile +3 -2
@@ -9,12 +9,13 @@ O_TARGET := kernel.o -export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o +export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \ + printk.o kthread.o workqueue.o obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \ module.o exit.o itimer.o info.o time.o softirq.o resource.o \ sysctl.o acct.o capability.o ptrace.o timer.o user.o \ - signal.o sys.o kmod.o context.o + signal.o sys.o kmod.o context.o kthread.o workqueue.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += ksyms.o
kernel/ksyms.c +1 -0
@@ -478,6 +478,7 @@EXPORT_SYMBOL (xtime);EXPORT_SYMBOL (do_gettimeofday);EXPORT_SYMBOL (do_settimeofday); +EXPORT_SYMBOL (set_user_nice);#if !defined(__ia64__)EXPORT_SYMBOL (loops_per_jiffy);
kernel/kthread.c new file +184 -0
184 lines not on this page · raw message
kernel/sched.c +11 -0
@@ -1350,6 +1350,17 @@atomic_inc (¤t->files->count); } +void set_user_nice (struct task_struct *p,long nice) +{ +if (nice <-20 ) + nice =-20 ; +if (nice >19 ) + nice =19 ; +write_lock (&tasklist_lock); + p->nice = nice; +write_unlock (&tasklist_lock); +} +extern unsigned long wait_init_idle;void __init init_idle (void )
kernel/workqueue.c new file +528 -0
528 lines not on this page · raw message