1/* 2 * include/asm-s390/semaphore.h 3 * 4 * S390 version 5 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * 7 * Derived from "include/asm-i386/semaphore.h" 8 * (C) Copyright 1996 Linus Torvalds 9 */ 10 11#ifndef _S390_SEMAPHORE_H 12#define _S390_SEMAPHORE_H 13 14#include <asm/system.h> 15#include <asm/atomic.h> 16#include <linux/wait.h> 17#include <linux/rwsem.h> 18 19struct semaphore { 20 /* 21 * Note that any negative value of count is equivalent to 0, 22 * but additionally indicates that some process(es) might be 23 * sleeping on `wait'. 24 */ 25 atomic_t count; 26 wait_queue_head_t wait; 27}; 28 29#define __SEMAPHORE_INITIALIZER(name,count) \ 30 { ATOMIC_INIT(count), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) } 31 32#define __DECLARE_SEMAPHORE_GENERIC(name,count) \ 33 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) 34 35#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) 36#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0) 37 38static inline void sema_init (struct semaphore *sem, int val) 39{ 40 atomic_set(&sem->count, val); 41 init_waitqueue_head(&sem->wait); 42} 43 44static inline void init_MUTEX (struct semaphore *sem) 45{ 46 sema_init(sem, 1); 47} 48 49static inline void init_MUTEX_LOCKED (struct semaphore *sem) 50{ 51 sema_init(sem, 0); 52} 53 54asmlinkage void __down(struct semaphore * sem); 55asmlinkage int __down_interruptible(struct semaphore * sem); 56asmlinkage int __down_trylock(struct semaphore * sem); 57asmlinkage void __up(struct semaphore * sem); 58 59static inline void down(struct semaphore * sem) 60{ 61 might_sleep(); 62 if (atomic_dec_return(&sem->count) < 0) 63 __down(sem); 64} 65 66static inline int down_interruptible(struct semaphore * sem) 67{ 68 int ret = 0; 69 70 might_sleep(); 71 if (atomic_dec_return(&sem->count) < 0) 72 ret = __down_interruptible(sem); 73 return ret; 74} 75 76static inline int down_trylock(struct semaphore * sem) 77{ 78 int old_val, new_val; 79 80 /* 81 * This inline assembly atomically implements the equivalent 82 * to the following C code: 83 * old_val = sem->count.counter; 84 * if ((new_val = old_val) > 0) 85 * sem->count.counter = --new_val; 86 * In the ppc code this is called atomic_dec_if_positive. 87 */ 88 asm volatile( 89 " l %0,0(%3)\n" 90 "0: ltr %1,%0\n" 91 " jle 1f\n" 92 " ahi %1,-1\n" 93 " cs %0,%1,0(%3)\n" 94 " jl 0b\n" 95 "1:" 96 : "=&d" (old_val), "=&d" (new_val), "=m" (sem->count.counter) 97 : "a" (&sem->count.counter), "m" (sem->count.counter) 98 : "cc", "memory"); 99 return old_val <= 0; 100} 101 102static inline void up(struct semaphore * sem) 103{ 104 if (atomic_inc_return(&sem->count) <= 0) 105 __up(sem); 106} 107 108#endif 109