1/* semaphore.h: semaphores for the FR-V 2 * 3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11#ifndef _ASM_SEMAPHORE_H 12#define _ASM_SEMAPHORE_H 13 14#define RW_LOCK_BIAS 0x01000000 15 16#ifndef __ASSEMBLY__ 17 18#include <linux/linkage.h> 19#include <linux/wait.h> 20#include <linux/spinlock.h> 21#include <linux/rwsem.h> 22 23/* 24 * the semaphore definition 25 * - if counter is >0 then there are tokens available on the semaphore for down to collect 26 * - if counter is <=0 then there are no spare tokens, and anyone that wants one must wait 27 * - if wait_list is not empty, then there are processes waiting for the semaphore 28 */ 29struct semaphore { 30 unsigned counter; 31 spinlock_t wait_lock; 32 struct list_head wait_list; 33#ifdef CONFIG_DEBUG_SEMAPHORE 34 unsigned __magic; 35#endif 36}; 37 38#ifdef CONFIG_DEBUG_SEMAPHORE 39# define __SEM_DEBUG_INIT(name) , (long)&(name).__magic 40#else 41# define __SEM_DEBUG_INIT(name) 42#endif 43 44 45#define __SEMAPHORE_INITIALIZER(name,count) \ 46{ count, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) __SEM_DEBUG_INIT(name) } 47 48#define __DECLARE_SEMAPHORE_GENERIC(name,count) \ 49 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) 50 51#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) 52#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) 53 54static inline void sema_init (struct semaphore *sem, int val) 55{ 56 *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val); 57} 58 59static inline void init_MUTEX (struct semaphore *sem) 60{ 61 sema_init(sem, 1); 62} 63 64static inline void init_MUTEX_LOCKED (struct semaphore *sem) 65{ 66 sema_init(sem, 0); 67} 68 69extern void __down(struct semaphore *sem, unsigned long flags); 70extern int __down_interruptible(struct semaphore *sem, unsigned long flags); 71extern void __up(struct semaphore *sem); 72 73static inline void down(struct semaphore *sem) 74{ 75 unsigned long flags; 76 77#ifdef CONFIG_DEBUG_SEMAPHORE 78 CHECK_MAGIC(sem->__magic); 79#endif 80 81 spin_lock_irqsave(&sem->wait_lock, flags); 82 if (likely(sem->counter > 0)) { 83 sem->counter--; 84 spin_unlock_irqrestore(&sem->wait_lock, flags); 85 } 86 else { 87 __down(sem, flags); 88 } 89} 90 91static inline int down_interruptible(struct semaphore *sem) 92{ 93 unsigned long flags; 94 int ret = 0; 95 96#ifdef CONFIG_DEBUG_SEMAPHORE 97 CHECK_MAGIC(sem->__magic); 98#endif 99 100 spin_lock_irqsave(&sem->wait_lock, flags); 101 if (likely(sem->counter > 0)) { 102 sem->counter--; 103 spin_unlock_irqrestore(&sem->wait_lock, flags); 104 } 105 else { 106 ret = __down_interruptible(sem, flags); 107 } 108 return ret; 109} 110 111/* 112 * non-blockingly attempt to down() a semaphore. 113 * - returns zero if we acquired it 114 */ 115static inline int down_trylock(struct semaphore *sem) 116{ 117 unsigned long flags; 118 int success = 0; 119 120#ifdef CONFIG_DEBUG_SEMAPHORE 121 CHECK_MAGIC(sem->__magic); 122#endif 123 124 spin_lock_irqsave(&sem->wait_lock, flags); 125 if (sem->counter > 0) { 126 sem->counter--; 127 success = 1; 128 } 129 spin_unlock_irqrestore(&sem->wait_lock, flags); 130 return !success; 131} 132 133static inline void up(struct semaphore *sem) 134{ 135 unsigned long flags; 136 137#ifdef CONFIG_DEBUG_SEMAPHORE 138 CHECK_MAGIC(sem->__magic); 139#endif 140 141 spin_lock_irqsave(&sem->wait_lock, flags); 142 if (!list_empty(&sem->wait_list)) 143 __up(sem); 144 else 145 sem->counter++; 146 spin_unlock_irqrestore(&sem->wait_lock, flags); 147} 148 149static inline int sem_getcount(struct semaphore *sem) 150{ 151 return sem->counter; 152} 153 154#endif /* __ASSEMBLY__ */ 155 156#endif 157