From 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Apr 2005 15:20:36 -0700 Subject: Linux-2.6.12-rc2 Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip! --- arch/parisc/kernel/semaphore.c | 102 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 arch/parisc/kernel/semaphore.c (limited to 'arch/parisc/kernel/semaphore.c') diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c new file mode 100644 index 00000000000..ee806bcc372 --- /dev/null +++ b/arch/parisc/kernel/semaphore.c @@ -0,0 +1,102 @@ +/* + * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard + */ + +#include +#include +#include +#include + +/* + * Semaphores are complex as we wish to avoid using two variables. + * `count' has multiple roles, depending on its value. If it is positive + * or zero, there are no waiters. The functions here will never be + * called; see + * + * When count is -1 it indicates there is at least one task waiting + * for the semaphore. + * + * When count is less than that, there are '- count - 1' wakeups + * pending. ie if it has value -3, there are 2 wakeups pending. + * + * Note that these functions are only called when there is contention + * on the lock, and as such all this is the "non-critical" part of the + * whole semaphore business. The critical part is the inline stuff in + * where we want to avoid any extra jumps and calls. + */ +void __up(struct semaphore *sem) +{ + sem->count--; + wake_up(&sem->wait); +} + +#define wakers(count) (-1 - count) + +#define DOWN_HEAD \ + int ret = 0; \ + DECLARE_WAITQUEUE(wait, current); \ + \ + /* Note that someone is waiting */ \ + if (sem->count == 0) \ + sem->count = -1; \ + \ + /* protected by the sentry still -- use unlocked version */ \ + wait.flags = WQ_FLAG_EXCLUSIVE; \ + __add_wait_queue_tail(&sem->wait, &wait); \ + lost_race: \ + spin_unlock_irq(&sem->sentry); \ + +#define DOWN_TAIL \ + spin_lock_irq(&sem->sentry); \ + if (wakers(sem->count) == 0 && ret == 0) \ + goto lost_race; /* Someone stole our wakeup */ \ + __remove_wait_queue(&sem->wait, &wait); \ + current->state = TASK_RUNNING; \ + if (!waitqueue_active(&sem->wait) && (sem->count < 0)) \ + sem->count = wakers(sem->count); + +#define UPDATE_COUNT \ + sem->count += (sem->count < 0) ? 1 : - 1; + + +void __sched __down(struct semaphore * sem) +{ + DOWN_HEAD + + for(;;) { + set_task_state(current, TASK_UNINTERRUPTIBLE); + /* we can _read_ this without the sentry */ + if (sem->count != -1) + break; + schedule(); + } + + DOWN_TAIL + UPDATE_COUNT +} + +int __sched __down_interruptible(struct semaphore * sem) +{ + DOWN_HEAD + + for(;;) { + set_task_state(current, TASK_INTERRUPTIBLE); + /* we can _read_ this without the sentry */ + if (sem->count != -1) + break; + + if (signal_pending(current)) { + ret = -EINTR; + break; + } + schedule(); + } + + DOWN_TAIL + + if (!ret) { + UPDATE_COUNT + } + + return ret; +} -- cgit v1.2.3