| /* $Id: semaphore-helper.h,v 1.3 2001/03/26 15:00:33 orjanf Exp $ |
| * |
| * SMP- and interrupt-safe semaphores helper functions. Generic versions, no |
| * optimizations whatsoever... |
| * |
| */ |
| |
| #ifndef _ASM_SEMAPHORE_HELPER_H |
| #define _ASM_SEMAPHORE_HELPER_H |
| |
| #include <asm/atomic.h> |
| #include <linux/errno.h> |
| |
| #define read(a) ((a)->counter) |
| #define inc(a) (((a)->counter)++) |
| #define dec(a) (((a)->counter)--) |
| |
| #define count_inc(a) ((*(a))++) |
| |
| /* |
| * These two _must_ execute atomically wrt each other. |
| */ |
| extern inline void wake_one_more(struct semaphore * sem) |
| { |
| atomic_inc(&sem->waking); |
| } |
| |
| extern inline int waking_non_zero(struct semaphore *sem) |
| { |
| unsigned long flags; |
| int ret = 0; |
| |
| local_save_flags(flags); |
| local_irq_disable(); |
| if (read(&sem->waking) > 0) { |
| dec(&sem->waking); |
| ret = 1; |
| } |
| local_irq_restore(flags); |
| return ret; |
| } |
| |
| extern inline int waking_non_zero_interruptible(struct semaphore *sem, |
| struct task_struct *tsk) |
| { |
| int ret = 0; |
| unsigned long flags; |
| |
| local_save_flags(flags); |
| local_irq_disable(); |
| if (read(&sem->waking) > 0) { |
| dec(&sem->waking); |
| ret = 1; |
| } else if (signal_pending(tsk)) { |
| inc(&sem->count); |
| ret = -EINTR; |
| } |
| local_irq_restore(flags); |
| return ret; |
| } |
| |
| extern inline int waking_non_zero_trylock(struct semaphore *sem) |
| { |
| int ret = 1; |
| unsigned long flags; |
| |
| local_save_flags(flags); |
| local_irq_disable(); |
| if (read(&sem->waking) <= 0) |
| inc(&sem->count); |
| else { |
| dec(&sem->waking); |
| ret = 0; |
| } |
| local_irq_restore(flags); |
| return ret; |
| } |
| |
| #endif /* _ASM_SEMAPHORE_HELPER_H */ |
| |
| |