semaphore.h 3.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
/* $Id: semaphore.h,v 1.3 2001/05/08 13:54:09 bjornw Exp $ */

/* On the i386 these are coded in asm, perhaps we should as well. Later.. */

#ifndef _CRIS_SEMAPHORE_H
#define _CRIS_SEMAPHORE_H

#define RW_LOCK_BIAS             0x01000000

#include <linux/wait.h>
#include <linux/spinlock.h>
#include <linux/rwsem.h>

#include <asm/system.h>
#include <asm/atomic.h>

/*
 * CRIS semaphores, implemented in C-only so far. 
 */

int printk(const char *fmt, ...);

struct semaphore {
	atomic_t count;
	atomic_t waking;
	wait_queue_head_t wait;
};

#define __SEMAPHORE_INITIALIZER(name, n)				\
{									\
	.count		= ATOMIC_INIT(n),				\
	.waking		= ATOMIC_INIT(0),				\
	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
}

#define __MUTEX_INITIALIZER(name) \
        __SEMAPHORE_INITIALIZER(name,1)

#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
        struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)

#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)

extern inline void sema_init(struct semaphore *sem, int val)
{
	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
}

extern inline void init_MUTEX (struct semaphore *sem)
{
        sema_init(sem, 1);
}

extern inline void init_MUTEX_LOCKED (struct semaphore *sem)
{
        sema_init(sem, 0);
}

extern void __down(struct semaphore * sem);
extern int __down_interruptible(struct semaphore * sem);
extern int __down_trylock(struct semaphore * sem);
extern void __up(struct semaphore * sem);

/* notice - we probably can do cli/sti here instead of saving */

extern inline void down(struct semaphore * sem)
{
	unsigned long flags;
	int failed;

	might_sleep();

	/* atomically decrement the semaphores count, and if its negative, we wait */
	local_save_flags(flags);
	local_irq_disable();
	failed = --(sem->count.counter) < 0;
	local_irq_restore(flags);
	if(failed) {
		__down(sem);
	}
}

/*
 * This version waits in interruptible state so that the waiting
 * process can be killed.  The down_interruptible routine
 * returns negative for signalled and zero for semaphore acquired.
 */

extern inline int down_interruptible(struct semaphore * sem)
{
	unsigned long flags;
	int failed;

	might_sleep();

	/* atomically decrement the semaphores count, and if its negative, we wait */
	local_save_flags(flags);
	local_irq_disable();
	failed = --(sem->count.counter) < 0;
	local_irq_restore(flags);
	if(failed)
		failed = __down_interruptible(sem);
	return(failed);
}

extern inline int down_trylock(struct semaphore * sem)
{
	unsigned long flags;
	int failed;

	local_save_flags(flags);
	local_irq_disable();
	failed = --(sem->count.counter) < 0;
	local_irq_restore(flags);
	if(failed)
		failed = __down_trylock(sem);
	return(failed);
}

/*
 * Note! This is subtle. We jump to wake people up only if
 * the semaphore was negative (== somebody was waiting on it).
 * The default case (no contention) will result in NO
 * jumps for both down() and up().
 */
extern inline void up(struct semaphore * sem)
{  
	unsigned long flags;
	int wakeup;

	/* atomically increment the semaphores count, and if it was negative, we wake people */
	local_save_flags(flags);
	local_irq_disable();
	wakeup = ++(sem->count.counter) <= 0;
	local_irq_restore(flags);
	if(wakeup) {
		__up(sem);
	}
}

#endif