diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2003-06-22 22:01:51 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-06-22 22:01:51 -0700 |
| commit | 2e7f53ec14475d56559bcdd07acfb737b7bff1e9 (patch) | |
| tree | 964fee6f7bfc40bae796fe137e293c6831103919 /kernel | |
| parent | 5cb7db89366c7c64c5476bec0a2939c7c75af4c9 (diff) | |
| parent | 8514206eb4e65262f50d6f18293dc3175ab05693 (diff) | |
Merge home.transmeta.com:/home/torvalds/v2.5/xfs
into home.transmeta.com:/home/torvalds/v2.5/linux
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/acct.c | 14 | ||||
| -rw-r--r-- | kernel/exit.c | 2 | ||||
| -rw-r--r-- | kernel/fork.c | 10 | ||||
| -rw-r--r-- | kernel/kmod.c | 12 | ||||
| -rw-r--r-- | kernel/ksyms.c | 1 | ||||
| -rw-r--r-- | kernel/sched.c | 26 | ||||
| -rw-r--r-- | kernel/timer.c | 4 | ||||
| -rw-r--r-- | kernel/workqueue.c | 85 |
8 files changed, 80 insertions, 74 deletions
diff --git a/kernel/acct.c b/kernel/acct.c index 9f7cdf9a826b..e63095525ac2 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -54,6 +54,7 @@ #include <linux/jiffies.h> #include <asm/uaccess.h> #include <asm/div64.h> +#include <linux/blkdev.h> /* sector_div */ /* * These constants control the amount of freespace that suspend and @@ -100,9 +101,11 @@ static void acct_timeout(unsigned long unused) */ static int check_free_space(struct file *file) { - struct statfs sbuf; + struct kstatfs sbuf; int res; int act; + sector_t resume; + sector_t suspend; spin_lock(&acct_globals.lock); res = acct_globals.active; @@ -113,10 +116,15 @@ static int check_free_space(struct file *file) /* May block */ if (vfs_statfs(file->f_dentry->d_inode->i_sb, &sbuf)) return res; + suspend = sbuf.f_blocks * SUSPEND; + resume = sbuf.f_blocks * RESUME; - if (sbuf.f_bavail <= SUSPEND * sbuf.f_blocks / 100) + sector_div(suspend, 100); + sector_div(resume, 100); + + if (sbuf.f_bavail <= suspend) act = -1; - else if (sbuf.f_bavail >= RESUME * sbuf.f_blocks / 100) + else if (sbuf.f_bavail >= resume) act = 1; else act = 0; diff --git a/kernel/exit.c b/kernel/exit.c index c5b8ec241a83..7dee095b31bd 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -698,7 +698,7 @@ NORET_TYPE void do_exit(long code) acct_process(code); __exit_mm(tsk); - sem_exit(); + exit_sem(tsk); __exit_files(tsk); __exit_fs(tsk); exit_namespace(tsk); diff --git a/kernel/fork.c b/kernel/fork.c index fba722be316e..5ef2dca02354 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -39,7 +39,7 @@ #include <asm/tlbflush.h> extern int copy_semundo(unsigned long clone_flags, struct task_struct *tsk); -extern void exit_semundo(struct task_struct *tsk); +extern void exit_sem(struct task_struct *tsk); /* The idle threads do not count.. * Protected by write_lock_irq(&tasklist_lock) @@ -887,13 +887,11 @@ struct task_struct *copy_process(unsigned long clone_flags, if (retval) goto bad_fork_cleanup_namespace; - if (clone_flags & CLONE_CHILD_SETTID) - p->set_child_tid = child_tidptr; + p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; /* * Clear TID on mm_release()? */ - if (clone_flags & CLONE_CHILD_CLEARTID) - p->clear_child_tid = child_tidptr; + p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; /* * Syscall tracing should be turned off in the child regardless @@ -1034,7 +1032,7 @@ bad_fork_cleanup_fs: bad_fork_cleanup_files: exit_files(p); /* blocking */ bad_fork_cleanup_semundo: - exit_semundo(p); + exit_sem(p); bad_fork_cleanup_security: security_task_free(p); bad_fork_cleanup: diff --git a/kernel/kmod.c b/kernel/kmod.c index d9e4299a8765..e011611afb7d 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -183,12 +183,15 @@ static int wait_for_helper(void *data) struct subprocess_info *sub_info = data; pid_t pid; - pid = kernel_thread(____call_usermodehelper, sub_info, - CLONE_VFORK | SIGCHLD); + sub_info->retval = 0; + pid = kernel_thread(____call_usermodehelper, sub_info, SIGCHLD); if (pid < 0) sub_info->retval = pid; else - sys_wait4(pid, (unsigned int *)&sub_info->retval, 0, NULL); + /* We don't have a SIGCHLD signal handler, so this + * always returns -ECHILD, but the important thing is + * that it blocks. */ + sys_wait4(pid, NULL, 0, NULL); complete(sub_info->complete); return 0; @@ -231,8 +234,7 @@ static void __call_usermodehelper(void *data) * (ie. it runs with full root capabilities). * * Must be called from process context. Returns a negative error code - * if program was not execed successfully, or (exitcode << 8 + signal) - * of the application (0 if wait is not set). + * if program was not execed successfully, or 0. */ int call_usermodehelper(char *path, char **argv, char **envp, int wait) { diff --git a/kernel/ksyms.c b/kernel/ksyms.c index ab547345372e..cbb2313433ce 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -592,7 +592,6 @@ EXPORT_SYMBOL(__tasklet_hi_schedule); /* init task, for moving kthread roots - ought to export a function ?? */ EXPORT_SYMBOL(init_task); -EXPORT_SYMBOL(init_thread_union); EXPORT_SYMBOL(tasklist_lock); EXPORT_SYMBOL(find_task_by_pid); diff --git a/kernel/sched.c b/kernel/sched.c index c603aaa67790..9566cd11de18 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1880,10 +1880,6 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask))) return -EFAULT; - new_mask &= cpu_online_map; - if (!new_mask) - return -EINVAL; - read_lock(&tasklist_lock); p = find_process_by_pid(pid); @@ -1905,8 +1901,7 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, !capable(CAP_SYS_NICE)) goto out_unlock; - retval = 0; - set_cpus_allowed(p, new_mask); + retval = set_cpus_allowed(p, new_mask); out_unlock: put_task_struct(p); @@ -2182,10 +2177,7 @@ static void show_task(task_t * p) else printk(" (NOTLB)\n"); - { - extern void show_trace_task(task_t *tsk); - show_trace_task(p); - } + show_stack(p, NULL); } void show_state(void) @@ -2272,17 +2264,14 @@ typedef struct { * task must not exit() & deallocate itself prematurely. The * call is not atomic; no spinlocks may be held. */ -void set_cpus_allowed(task_t *p, unsigned long new_mask) +int set_cpus_allowed(task_t *p, unsigned long new_mask) { unsigned long flags; migration_req_t req; runqueue_t *rq; -#if 0 /* FIXME: Grab cpu_lock, return error on this case. --RR */ - new_mask &= cpu_online_map; - if (!new_mask) - BUG(); -#endif + if (any_online_cpu(new_mask) == NR_CPUS) + return -EINVAL; rq = task_rq_lock(p, &flags); p->cpus_allowed = new_mask; @@ -2292,7 +2281,7 @@ void set_cpus_allowed(task_t *p, unsigned long new_mask) */ if (new_mask & (1UL << task_cpu(p))) { task_rq_unlock(rq, &flags); - return; + return 0; } /* * If the task is not on a runqueue (and not running), then @@ -2301,7 +2290,7 @@ void set_cpus_allowed(task_t *p, unsigned long new_mask) if (!p->array && !task_running(rq, p)) { set_task_cpu(p, any_online_cpu(p->cpus_allowed)); task_rq_unlock(rq, &flags); - return; + return 0; } init_completion(&req.done); req.task = p; @@ -2311,6 +2300,7 @@ void set_cpus_allowed(task_t *p, unsigned long new_mask) wake_up_process(rq->migration_thread); wait_for_completion(&req.done); + return 0; } /* Move (not current) task off this cpu, onto dest cpu. */ diff --git a/kernel/timer.c b/kernel/timer.c index 5136630693b4..ad3758c663d4 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -439,8 +439,8 @@ repeat: /* * Timekeeping variables */ -unsigned long tick_usec = TICK_USEC; /* ACTHZ period (usec) */ -unsigned long tick_nsec = TICK_NSEC; /* USER_HZ period (nsec) */ +unsigned long tick_usec = TICK_USEC; /* USER_HZ period (usec) */ +unsigned long tick_nsec = TICK_NSEC; /* ACTHZ period (nsec) */ /* * The current time diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 968837218657..efeaaa4f0274 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -259,15 +259,41 @@ void flush_workqueue(struct workqueue_struct *wq) } } -struct workqueue_struct *create_workqueue(const char *name) +static int create_workqueue_thread(struct workqueue_struct *wq, + const char *name, + int cpu) { - int ret, cpu, destroy = 0; - struct cpu_workqueue_struct *cwq; startup_t startup; + struct cpu_workqueue_struct *cwq = wq->cpu_wq + cpu; + int ret; + + spin_lock_init(&cwq->lock); + cwq->wq = wq; + cwq->thread = NULL; + cwq->insert_sequence = 0; + cwq->remove_sequence = 0; + INIT_LIST_HEAD(&cwq->worklist); + init_waitqueue_head(&cwq->more_work); + init_waitqueue_head(&cwq->work_done); + init_completion(&cwq->exit); + + init_completion(&startup.done); + startup.cwq = cwq; + startup.name = name; + ret = kernel_thread(worker_thread, &startup, CLONE_FS | CLONE_FILES); + if (ret >= 0) { + wait_for_completion(&startup.done); + BUG_ON(!cwq->thread); + } + return ret; +} + +struct workqueue_struct *create_workqueue(const char *name) +{ + int cpu, destroy = 0; struct workqueue_struct *wq; BUG_ON(strlen(name) > 10); - startup.name = name; wq = kmalloc(sizeof(*wq), GFP_KERNEL); if (!wq) @@ -276,27 +302,8 @@ struct workqueue_struct *create_workqueue(const char *name) for (cpu = 0; cpu < NR_CPUS; cpu++) { if (!cpu_online(cpu)) continue; - cwq = wq->cpu_wq + cpu; - - spin_lock_init(&cwq->lock); - cwq->wq = wq; - cwq->thread = NULL; - cwq->insert_sequence = 0; - cwq->remove_sequence = 0; - INIT_LIST_HEAD(&cwq->worklist); - init_waitqueue_head(&cwq->more_work); - init_waitqueue_head(&cwq->work_done); - - init_completion(&startup.done); - startup.cwq = cwq; - ret = kernel_thread(worker_thread, &startup, - CLONE_FS | CLONE_FILES); - if (ret < 0) + if (create_workqueue_thread(wq, name, cpu) < 0) destroy = 1; - else { - wait_for_completion(&startup.done); - BUG_ON(!cwq->thread); - } } /* * Was there any error during startup? If yes then clean up: @@ -308,28 +315,30 @@ struct workqueue_struct *create_workqueue(const char *name) return wq; } -void destroy_workqueue(struct workqueue_struct *wq) +static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu) { struct cpu_workqueue_struct *cwq; - int cpu; - flush_workqueue(wq); - - for (cpu = 0; cpu < NR_CPUS; cpu++) { - if (!cpu_online(cpu)) - continue; - cwq = wq->cpu_wq + cpu; - if (!cwq->thread) - continue; - /* - * Initiate an exit and wait for it: - */ - init_completion(&cwq->exit); + cwq = wq->cpu_wq + cpu; + if (cwq->thread) { + /* Tell thread to exit and wait for it. */ cwq->thread = NULL; wake_up(&cwq->more_work); wait_for_completion(&cwq->exit); } +} + +void destroy_workqueue(struct workqueue_struct *wq) +{ + int cpu; + + flush_workqueue(wq); + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + if (cpu_online(cpu)) + cleanup_workqueue_thread(wq, cpu); + } kfree(wq); } |
