|  | /* $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. | 
|  | */ | 
|  | static inline void wake_one_more(struct semaphore * sem) | 
|  | { | 
|  | atomic_inc(&sem->waking); | 
|  | } | 
|  |  | 
|  | static inline int waking_non_zero(struct semaphore *sem) | 
|  | { | 
|  | unsigned long flags; | 
|  | int ret = 0; | 
|  |  | 
|  | local_irq_save(flags); | 
|  | if (read(&sem->waking) > 0) { | 
|  | dec(&sem->waking); | 
|  | ret = 1; | 
|  | } | 
|  | local_irq_restore(flags); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static inline int waking_non_zero_interruptible(struct semaphore *sem, | 
|  | struct task_struct *tsk) | 
|  | { | 
|  | int ret = 0; | 
|  | unsigned long flags; | 
|  |  | 
|  | local_irq_save(flags); | 
|  | 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; | 
|  | } | 
|  |  | 
|  | static inline int waking_non_zero_trylock(struct semaphore *sem) | 
|  | { | 
|  | int ret = 1; | 
|  | unsigned long flags; | 
|  |  | 
|  | local_irq_save(flags); | 
|  | 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 */ | 
|  |  | 
|  |  |