diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 21:05:59 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 21:05:59 +0000 |
commit | ba2dacab305c598cd4c34a604f8e276bf5bab5ff (patch) | |
tree | 78670a0139bf4d5ace617b29b7eba82bbc74d602 /kernel/exit.c | |
parent | b77bf69998121e689c5e86cc5630d39a0a9ee6ca (diff) |
Merge with Linux 2.3.99-pre7 and various other bits.
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index b38b067dd..8617b9d36 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -182,24 +182,32 @@ static inline void close_files(struct files_struct * files) extern kmem_cache_t *files_cachep; +void put_files_struct(struct files_struct *files) +{ + if (atomic_dec_and_test(&files->count)) { + close_files(files); + /* + * Free the fd and fdset arrays if we expanded them. + */ + if (files->fd != &files->fd_array[0]) + free_fd_array(files->fd, files->max_fds); + if (files->max_fdset > __FD_SETSIZE) { + free_fdset(files->open_fds, files->max_fdset); + free_fdset(files->close_on_exec, files->max_fdset); + } + kmem_cache_free(files_cachep, files); + } +} + static inline void __exit_files(struct task_struct *tsk) { - struct files_struct * files = xchg(&tsk->files, NULL); + struct files_struct * files = tsk->files; if (files) { - if (atomic_dec_and_test(&files->count)) { - close_files(files); - /* - * Free the fd and fdset arrays if we expanded them. - */ - if (files->fd != &files->fd_array[0]) - free_fd_array(files->fd, files->max_fds); - if (files->max_fdset > __FD_SETSIZE) { - free_fdset(files->open_fds, files->max_fdset); - free_fdset(files->close_on_exec, files->max_fdset); - } - kmem_cache_free(files_cachep, files); - } + task_lock(tsk); + tsk->files = NULL; + task_unlock(tsk); + put_files_struct(files); } } @@ -232,7 +240,9 @@ static inline void __exit_fs(struct task_struct *tsk) struct fs_struct * fs = tsk->fs; if (fs) { + task_lock(tsk); tsk->fs = NULL; + task_unlock(tsk); __put_fs_struct(fs); } } @@ -247,11 +257,9 @@ static inline void __exit_sighand(struct task_struct *tsk) struct signal_struct * sig = tsk->sig; if (sig) { - unsigned long flags; - - spin_lock_irqsave(&tsk->sigmask_lock, flags); + spin_lock_irq(&tsk->sigmask_lock); tsk->sig = NULL; - spin_unlock_irqrestore(&tsk->sigmask_lock, flags); + spin_unlock_irq(&tsk->sigmask_lock); if (atomic_dec_and_test(&sig->count)) kfree(sig); } @@ -302,7 +310,10 @@ static inline void __exit_mm(struct task_struct * tsk) atomic_inc(&mm->mm_count); mm_release(); if (mm != tsk->active_mm) BUG(); + /* more a memory barrier than a real lock */ + task_lock(tsk); tsk->mm = NULL; + task_unlock(tsk); enter_lazy_tlb(mm, current, smp_processor_id()); mmput(mm); } @@ -434,12 +445,10 @@ fake_volatile: __exit_files(tsk); __exit_fs(tsk); __exit_sighand(tsk); - task_lock(tsk); exit_thread(); tsk->state = TASK_ZOMBIE; tsk->exit_code = code; exit_notify(); - task_unlock(tsk); put_exec_domain(tsk->exec_domain); if (tsk->binfmt && tsk->binfmt->module) __MOD_DEC_USE_COUNT(tsk->binfmt->module); |