diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-06-20 08:13:53 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-06-20 08:13:53 -0700 |
| commit | 1327ca85e19e5ea19c9fcab0b54f093ddaaca31a (patch) | |
| tree | eb468430b12517233fb32fac4e4ef9032f810a22 /kernel/fork.c | |
| parent | 0d5ff9d0ca5801ccc5dd8f1f6023629bbc6090da (diff) | |
[PATCH] sysv semundo fixes
From: Manfred Spraul <manfred@colorfullife.com>
The CLONE_SYSVSEM implementation is racy: it does an (atomic_read(->refcnt)
==1) instead of atomic_dec_and_test calls in the exit handling. The patch
fixes that.
Additionally, the patch contains the following changes:
- lock_undo() locks the list of undo structures. The lock is held
throughout the semop() syscall, but that's unnecessary - we can drop it
immediately after the lookup.
- undo structures are only allocated when necessary. The need for undo
structures is only noticed in the middle of the semop operation, while
holding the semaphore array spinlock. The result is a convoluted
unlock&revalidate implementation. I've reordered the code, and now the
undo allocation can happen before acquiring the semaphore array spinlock.
As a bonus, less code runs under the semaphore array spinlock.
- sysvsem.sleep_list looks like code to handle oopses: if an oops kills a
thread that sleeps in sys_timedsemop(), then sem_exit tries to recover.
I've removed that - too fragile.
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 0fe154adc3ef..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) @@ -1032,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: |
