1 /* $Id: semaphore.h,v 1.6 1999/06/17 13:30:38 ralf Exp $
3 * SMP- and interrupt-safe semaphores..
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file "COPYING" in the main directory of this archive
9 * (C) Copyright 1996 Linus Torvalds
10 * (C) Copyright 1998, 1999 Ralf Baechle
12 #ifndef __ASM_MIPS_SEMAPHORE_H
13 #define __ASM_MIPS_SEMAPHORE_H
15 #include <asm/system.h>
16 #include <asm/atomic.h>
17 #include <linux/spinlock.h>
18 #include <linux/wait.h>
23 wait_queue_head_t wait
;
30 # define __SEM_DEBUG_INIT(name) \
31 , (long)&(name).__magic
33 # define __SEM_DEBUG_INIT(name)
36 #define __SEMAPHORE_INITIALIZER(name,count) \
37 { ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
38 __SEM_DEBUG_INIT(name) }
40 #define __MUTEX_INITIALIZER(name) \
41 __SEMAPHORE_INITIALIZER(name,1)
43 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
44 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
46 #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
47 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
49 extern inline void sema_init (struct semaphore
*sem
, int val
)
51 atomic_set(&sem
->count
, val
);
52 atomic_set(&sem
->waking
, 0);
53 init_waitqueue_head(&sem
->wait
);
55 sem
->__magic
= (long)&sem
->__magic
;
59 static inline void init_MUTEX (struct semaphore
*sem
)
64 static inline void init_MUTEX_LOCKED (struct semaphore
*sem
)
69 asmlinkage
void __down(struct semaphore
* sem
);
70 asmlinkage
int __down_interruptible(struct semaphore
* sem
);
71 asmlinkage
int __down_trylock(struct semaphore
* sem
);
72 asmlinkage
void __up(struct semaphore
* sem
);
74 extern inline void down(struct semaphore
* sem
)
77 CHECK_MAGIC(sem
->__magic
);
79 if (atomic_dec_return(&sem
->count
) < 0)
83 extern inline int down_interruptible(struct semaphore
* sem
)
88 CHECK_MAGIC(sem
->__magic
);
90 if (atomic_dec_return(&sem
->count
) < 0)
91 ret
= __down_interruptible(sem
);
96 * down_trylock returns 0 on success, 1 if we failed to get the lock.
98 * We must manipulate count and waking simultaneously and atomically.
99 * Do this by using ll/sc on the pair of 32-bit words.
101 extern inline int down_trylock(struct semaphore
* sem
)
103 long ret
, tmp
, tmp2
, sub
;
106 CHECK_MAGIC(sem
->__magic
);
109 __asm__
__volatile__("
112 dli %3, 0x0000000100000000
130 : "=&r"(ret
), "=&r"(tmp
), "=&r"(tmp2
), "=&r"(sub
)
136 #error "FIXME: down_trylock doesn't support little endian machines yet."
143 * Note! This is subtle. We jump to wake people up only if
144 * the semaphore was negative (== somebody was waiting on it).
146 extern inline void up(struct semaphore
* sem
)
149 CHECK_MAGIC(sem
->__magic
);
151 if (atomic_inc_return(&sem
->count
) <= 0)
155 #endif /* __ASM_MIPS_SEMAPHORE_H */