1/* $Id: semaphore.h,v 1.1.1.1 2008/10/15 03:29:02 james26_jang Exp $ */ 2 3/* On the i386 these are coded in asm, perhaps we should as well. Later.. */ 4 5#ifndef _CRIS_SEMAPHORE_H 6#define _CRIS_SEMAPHORE_H 7 8#define RW_LOCK_BIAS 0x01000000 9 10#include <linux/wait.h> 11#include <linux/spinlock.h> 12#include <linux/rwsem.h> 13 14#include <asm/system.h> 15#include <asm/atomic.h> 16 17/* 18 * CRIS semaphores, implemented in C-only so far. 19 */ 20 21int printk(const char *fmt, ...); 22 23struct semaphore { 24 int count; /* not atomic_t since we do the atomicity here already */ 25 atomic_t waking; 26 wait_queue_head_t wait; 27#if WAITQUEUE_DEBUG 28 long __magic; 29#endif 30}; 31 32#if WAITQUEUE_DEBUG 33# define __SEM_DEBUG_INIT(name) , (long)&(name).__magic 34#else 35# define __SEM_DEBUG_INIT(name) 36#endif 37 38#define __SEMAPHORE_INITIALIZER(name,count) \ 39 { count, ATOMIC_INIT(0), \ 40 __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ 41 __SEM_DEBUG_INIT(name) } 42 43#define __MUTEX_INITIALIZER(name) \ 44 __SEMAPHORE_INITIALIZER(name,1) 45 46#define __DECLARE_SEMAPHORE_GENERIC(name,count) \ 47 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) 48 49#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) 50#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) 51 52extern inline void sema_init(struct semaphore *sem, int val) 53{ 54 *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); 55} 56 57static inline void init_MUTEX (struct semaphore *sem) 58{ 59 sema_init(sem, 1); 60} 61 62static inline void init_MUTEX_LOCKED (struct semaphore *sem) 63{ 64 sema_init(sem, 0); 65} 66 67extern void __down(struct semaphore * sem); 68extern int __down_interruptible(struct semaphore * sem); 69extern int __down_trylock(struct semaphore * sem); 70extern void __up(struct semaphore * sem); 71 72/* notice - we probably can do cli/sti here instead of saving */ 73 74extern inline void down(struct semaphore * sem) 75{ 76 unsigned long flags; 77 int failed; 78 79#if WAITQUEUE_DEBUG 80 CHECK_MAGIC(sem->__magic); 81#endif 82 83 /* atomically decrement the semaphores count, and if its negative, we wait */ 84 save_flags(flags); 85 cli(); 86 failed = --(sem->count) < 0; 87 restore_flags(flags); 88 if(failed) { 89 __down(sem); 90 } 91} 92 93/* 94 * This version waits in interruptible state so that the waiting 95 * process can be killed. The down_interruptible routine 96 * returns negative for signalled and zero for semaphore acquired. 97 */ 98 99extern inline int down_interruptible(struct semaphore * sem) 100{ 101 unsigned long flags; 102 int failed; 103 104#if WAITQUEUE_DEBUG 105 CHECK_MAGIC(sem->__magic); 106#endif 107 108 /* atomically decrement the semaphores count, and if its negative, we wait */ 109 save_flags(flags); 110 cli(); 111 failed = --(sem->count) < 0; 112 restore_flags(flags); 113 if(failed) 114 failed = __down_interruptible(sem); 115 return(failed); 116} 117 118extern inline int down_trylock(struct semaphore * sem) 119{ 120 unsigned long flags; 121 int failed; 122 123#if WAITQUEUE_DEBUG 124 CHECK_MAGIC(sem->__magic); 125#endif 126 127 save_flags(flags); 128 cli(); 129 failed = --(sem->count) < 0; 130 restore_flags(flags); 131 if(failed) 132 failed = __down_trylock(sem); 133 return(failed); 134} 135 136/* 137 * Note! This is subtle. We jump to wake people up only if 138 * the semaphore was negative (== somebody was waiting on it). 139 * The default case (no contention) will result in NO 140 * jumps for both down() and up(). 141 */ 142extern inline void up(struct semaphore * sem) 143{ 144 unsigned long flags; 145 int wakeup; 146 147#if WAITQUEUE_DEBUG 148 CHECK_MAGIC(sem->__magic); 149#endif 150 151 /* atomically increment the semaphores count, and if it was negative, we wake people */ 152 save_flags(flags); 153 cli(); 154 wakeup = ++(sem->count) <= 0; 155 restore_flags(flags); 156 if(wakeup) { 157 __up(sem); 158 } 159} 160 161static inline int sem_getcount(struct semaphore *sem) 162{ 163 return sem->count; 164} 165 166#endif 167