| /* $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 */ | |