1/* 2 * BK Id: SCCS/s.semaphore.h 1.15 05/17/01 18:14:25 cort 3 */ 4#ifndef _PPC_SEMAPHORE_H 5#define _PPC_SEMAPHORE_H 6 7/* 8 * Swiped from asm-sparc/semaphore.h and modified 9 * -- Cort (cort@cs.nmt.edu) 10 * 11 * Stole some rw spinlock-based semaphore stuff from asm-alpha/semaphore.h 12 * -- Ani Joshi (ajoshi@unixbox.com) 13 * 14 * Remove spinlock-based RW semaphores; RW semaphore definitions are 15 * now in rwsem.h and we use the the generic lib/rwsem.c implementation. 16 * Rework semaphores to use atomic_dec_if_positive. 17 * -- Paul Mackerras (paulus@samba.org) 18 */ 19 20#ifdef __KERNEL__ 21 22#include <asm/atomic.h> 23#include <asm/system.h> 24#include <linux/wait.h> 25#include <linux/rwsem.h> 26 27struct semaphore { 28 /* 29 * Note that any negative value of count is equivalent to 0, 30 * but additionally indicates that some process(es) might be 31 * sleeping on `wait'. 32 */ 33 atomic_t count; 34 wait_queue_head_t wait; 35#if WAITQUEUE_DEBUG 36 long __magic; 37#endif 38}; 39 40#if WAITQUEUE_DEBUG 41# define __SEM_DEBUG_INIT(name) \ 42 , (long)&(name).__magic 43#else 44# define __SEM_DEBUG_INIT(name) 45#endif 46 47#define __SEMAPHORE_INITIALIZER(name, count) \ 48 { ATOMIC_INIT(count), \ 49 __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ 50 __SEM_DEBUG_INIT(name) } 51 52#define __MUTEX_INITIALIZER(name) \ 53 __SEMAPHORE_INITIALIZER(name, 1) 54 55#define __DECLARE_SEMAPHORE_GENERIC(name, count) \ 56 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) 57 58#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1) 59#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0) 60 61static inline void sema_init (struct semaphore *sem, int val) 62{ 63 atomic_set(&sem->count, val); 64 init_waitqueue_head(&sem->wait); 65#if WAITQUEUE_DEBUG 66 sem->__magic = (long)&sem->__magic; 67#endif 68} 69 70static inline void init_MUTEX (struct semaphore *sem) 71{ 72 sema_init(sem, 1); 73} 74 75static inline void init_MUTEX_LOCKED (struct semaphore *sem) 76{ 77 sema_init(sem, 0); 78} 79 80extern void __down(struct semaphore * sem); 81extern int __down_interruptible(struct semaphore * sem); 82extern void __up(struct semaphore * sem); 83 84extern inline void down(struct semaphore * sem) 85{ 86#if WAITQUEUE_DEBUG 87 CHECK_MAGIC(sem->__magic); 88#endif 89 90 /* 91 * Try to get the semaphore, take the slow path if we fail. 92 */ 93 if (atomic_dec_return(&sem->count) < 0) 94 __down(sem); 95 smp_wmb(); 96} 97 98extern inline int down_interruptible(struct semaphore * sem) 99{ 100 int ret = 0; 101 102#if WAITQUEUE_DEBUG 103 CHECK_MAGIC(sem->__magic); 104#endif 105 106 if (atomic_dec_return(&sem->count) < 0) 107 ret = __down_interruptible(sem); 108 smp_wmb(); 109 return ret; 110} 111 112extern inline int down_trylock(struct semaphore * sem) 113{ 114 int ret; 115 116#if WAITQUEUE_DEBUG 117 CHECK_MAGIC(sem->__magic); 118#endif 119 120 ret = atomic_dec_if_positive(&sem->count) < 0; 121 smp_wmb(); 122 return ret; 123} 124 125extern inline void up(struct semaphore * sem) 126{ 127#if WAITQUEUE_DEBUG 128 CHECK_MAGIC(sem->__magic); 129#endif 130 131 smp_wmb(); 132 if (atomic_inc_return(&sem->count) <= 0) 133 __up(sem); 134} 135 136static inline int sem_getcount(struct semaphore *sem) 137{ 138 return atomic_read(&sem->count); 139} 140 141#endif /* __KERNEL__ */ 142 143#endif /* !(_PPC_SEMAPHORE_H) */ 144