Blame view

include/asm-cris/semaphore.h 3.23 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  /* $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 */
8d20a541b   Mikael Starvik   [PATCH] CRIS upda...
75
  	cris_atomic_save(sem, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
  	failed = --(sem->count.counter) < 0;
8d20a541b   Mikael Starvik   [PATCH] CRIS upda...
77
  	cris_atomic_restore(sem, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  	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 */
8d20a541b   Mikael Starvik   [PATCH] CRIS upda...
97
  	cris_atomic_save(sem, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  	failed = --(sem->count.counter) < 0;
8d20a541b   Mikael Starvik   [PATCH] CRIS upda...
99
  	cris_atomic_restore(sem, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
104
105
106
107
108
  	if(failed)
  		failed = __down_interruptible(sem);
  	return(failed);
  }
  
  extern inline int down_trylock(struct semaphore * sem)
  {
  	unsigned long flags;
  	int failed;
8d20a541b   Mikael Starvik   [PATCH] CRIS upda...
109
  	cris_atomic_save(sem, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  	failed = --(sem->count.counter) < 0;
8d20a541b   Mikael Starvik   [PATCH] CRIS upda...
111
  	cris_atomic_restore(sem, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
  	if(failed)
  		failed = __down_trylock(sem);
  	return(failed);
8d20a541b   Mikael Starvik   [PATCH] CRIS upda...
115

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  }
  
  /*
   * 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 */
8d20a541b   Mikael Starvik   [PATCH] CRIS upda...
130
  	cris_atomic_save(sem, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  	wakeup = ++(sem->count.counter) <= 0;
8d20a541b   Mikael Starvik   [PATCH] CRIS upda...
132
  	cris_atomic_restore(sem, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
136
137
138
  	if(wakeup) {
  		__up(sem);
  	}
  }
  
  #endif