1#ifndef __ASM_SH_SEMAPHORE_H 2#define __ASM_SH_SEMAPHORE_H 3 4#include <linux/linkage.h> 5 6#ifdef __KERNEL__ 7/* 8 * SMP- and interrupt-safe semaphores. 9 * 10 * (C) Copyright 1996 Linus Torvalds 11 * 12 * SuperH verison by Niibe Yutaka 13 * (Currently no asm implementation but generic C code...) 14 */ 15 16#include <linux/spinlock.h> 17#include <linux/rwsem.h> 18 19#include <asm/system.h> 20#include <asm/atomic.h> 21 22struct semaphore { 23 atomic_t count; 24 int sleepers; 25 wait_queue_head_t wait; 26#if WAITQUEUE_DEBUG 27 long __magic; 28#endif 29}; 30 31#if WAITQUEUE_DEBUG 32# define __SEM_DEBUG_INIT(name) \ 33 , (int)&(name).__magic 34#else 35# define __SEM_DEBUG_INIT(name) 36#endif 37 38#define __SEMAPHORE_INITIALIZER(name,count) \ 39{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ 40 __SEM_DEBUG_INIT(name) } 41 42#define __MUTEX_INITIALIZER(name) \ 43 __SEMAPHORE_INITIALIZER(name,1) 44 45#define __DECLARE_SEMAPHORE_GENERIC(name,count) \ 46 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) 47 48#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) 49#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) 50 51static inline void sema_init (struct semaphore *sem, int val) 52{ 53/* 54 * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); 55 * 56 * i'd rather use the more flexible initialization above, but sadly 57 * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well. 58 */ 59 atomic_set(&sem->count, val); 60 sem->sleepers = 0; 61 init_waitqueue_head(&sem->wait); 62#if WAITQUEUE_DEBUG 63 sem->__magic = (int)&sem->__magic; 64#endif 65} 66 67static inline void init_MUTEX (struct semaphore *sem) 68{ 69 sema_init(sem, 1); 70} 71 72static inline void init_MUTEX_LOCKED (struct semaphore *sem) 73{ 74 sema_init(sem, 0); 75} 76 77 78asmlinkage void __down(struct semaphore * sem); 79asmlinkage int __down_interruptible(struct semaphore * sem); 80asmlinkage int __down_trylock(struct semaphore * sem); 81asmlinkage void __up(struct semaphore * sem); 82 83extern spinlock_t semaphore_wake_lock; 84 85static inline void down(struct semaphore * sem) 86{ 87#if WAITQUEUE_DEBUG 88 CHECK_MAGIC(sem->__magic); 89#endif 90 91 if (atomic_dec_return(&sem->count) < 0) 92 __down(sem); 93} 94 95static inline int down_interruptible(struct semaphore * sem) 96{ 97 int ret = 0; 98#if WAITQUEUE_DEBUG 99 CHECK_MAGIC(sem->__magic); 100#endif 101 102 if (atomic_dec_return(&sem->count) < 0) 103 ret = __down_interruptible(sem); 104 return ret; 105} 106 107static inline int down_trylock(struct semaphore * sem) 108{ 109 int ret = 0; 110#if WAITQUEUE_DEBUG 111 CHECK_MAGIC(sem->__magic); 112#endif 113 114 if (atomic_dec_return(&sem->count) < 0) 115 ret = __down_trylock(sem); 116 return ret; 117} 118 119/* 120 * Note! This is subtle. We jump to wake people up only if 121 * the semaphore was negative (== somebody was waiting on it). 122 */ 123static inline void up(struct semaphore * sem) 124{ 125#if WAITQUEUE_DEBUG 126 CHECK_MAGIC(sem->__magic); 127#endif 128 if (atomic_inc_return(&sem->count) <= 0) 129 __up(sem); 130} 131 132static inline int sem_getcount(struct semaphore *sem) 133{ 134 return atomic_read(&sem->count); 135} 136 137#endif 138#endif /* __ASM_SH_SEMAPHORE_H */ 139