/ base / include / rtai_sem.h
rtai_sem.h
  1  /**
  2   * @ingroup lxrt
  3   * @file
  4   *
  5   * @author Paolo Mantegazza
  6   *
  7   * @note Copyright &copy; 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
  8   *
  9   * This program is free software; you can redistribute it and/or
 10   * modify it under the terms of the GNU General Public License as
 11   * published by the Free Software Foundation; either version 2 of the
 12   * License, or (at your option) any later version.
 13   *
 14   * This program is distributed in the hope that it will be useful,
 15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17   * GNU General Public License for more details.
 18   *
 19   * You should have received a copy of the GNU General Public License
 20   * along with this program; if not, write to the Free Software
 21   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 22   */
 23  
 24  #ifndef _RTAI_SEM_H
 25  #define _RTAI_SEM_H
 26  
 27  #include <rtai_types.h>
 28  #include <rtai_nam2num.h>
 29  #include <rtai_sched.h>
 30  
 31  #define RT_SEM_MAGIC 0x3f83ebb  // nam2num("rtsem")
 32  
 33  #define SEM_ERR     (RTE_OBJINV)
 34  #define SEM_TIMOUT  (RTE_TIMOUT)
 35  
 36  struct rt_poll_s { void *what; unsigned long forwhat; };
 37  
 38  // do not use 0 for any "forwhat" below
 39  #define RT_POLL_NOT_TO_USE    0
 40  #define RT_POLL_MBX_RECV      1
 41  #define RT_POLL_MBX_SEND      2
 42  #define RT_POLL_SEM_WAIT_ALL  3
 43  #define RT_POLL_SEM_WAIT_ONE  4
 44  
 45  #if defined(__KERNEL__) && !defined(__cplusplus)
 46  
 47  struct rt_poll_ql { QUEUE pollq; spinlock_t pollock; };
 48  struct rt_poll_enc { unsigned long offset; int (*topoll)(void *); };
 49  extern struct rt_poll_enc rt_poll_ofstfun[];
 50  
 51  typedef struct rt_semaphore {
 52  	struct rt_queue queue; /* <= Must be first in struct. */
 53  	int magic;
 54  	int type, restype;
 55  	int count;
 56  	struct rt_task_struct *owndby;
 57  	int qtype;
 58  	struct rt_queue resq;
 59  #ifdef CONFIG_RTAI_RT_POLL
 60  	struct rt_poll_ql poll_wait_all;
 61  	struct rt_poll_ql poll_wait_one;
 62  #endif
 63  } SEM;
 64  
 65  #ifdef CONFIG_RTAI_RT_POLL
 66  
 67  RTAI_SYSCALL_MODE int _rt_poll(struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout, int space);
 68  static inline int rt_poll(struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout)
 69  {
 70  	return _rt_poll(pdsa, nr, timeout, 1);
 71  }
 72  
 73  void rt_wakeup_pollers(struct rt_poll_ql *ql, int reason);
 74  
 75  #else
 76  
 77  static inline int rt_poll(struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout)
 78  {
 79  	return RTE_OBJINV;
 80  }
 81  
 82  #define rt_wakeup_pollers(ql, reason)
 83  
 84  #endif
 85  
 86  #else /* !__KERNEL__ || __cplusplus */
 87  
 88  typedef struct rt_semaphore {
 89      int opaque;
 90  } SEM;
 91  
 92  #endif /* __KERNEL__ && !__cplusplus */
 93  
 94  typedef SEM CND;
 95  
 96  #ifdef __KERNEL__
 97  
 98  #include <linux/errno.h>
 99  
100  typedef SEM psem_t;
101  
102  typedef SEM pmutex_t;
103  
104  #ifdef __cplusplus
105  extern "C" {
106  #endif /* __cplusplus */
107  
108  int __rtai_sem_init(void);
109  
110  void __rtai_sem_exit(void);
111  
112  RTAI_SYSCALL_MODE void rt_typed_sem_init(SEM *sem,
113  		       int value,
114  		       int type);
115  
116  RTAI_SYSCALL_MODE int rt_sem_delete(SEM *sem);
117  
118  RTAI_SYSCALL_MODE SEM *_rt_typed_named_sem_init(unsigned long sem_name,
119  			     int value,
120  			     int type,
121  			     unsigned long *handle);
122  
123  static inline SEM *rt_typed_named_sem_init(const char *sem_name,
124  					   int value,
125  					   int type) {
126      return _rt_typed_named_sem_init(nam2num(sem_name), value, type, NULL);
127  }
128  
129  RTAI_SYSCALL_MODE int rt_named_sem_delete(SEM *sem);
130  
131  void rt_sem_init(SEM *sem,
132  		 int value);
133  
134  RTAI_SYSCALL_MODE int rt_sem_signal(SEM *sem);
135  
136  RTAI_SYSCALL_MODE int rt_sem_broadcast(SEM *sem);
137  
138  RTAI_SYSCALL_MODE int rt_sem_wait(SEM *sem);
139  
140  RTAI_SYSCALL_MODE int rt_sem_wait_if(SEM *sem);
141  
142  int rt_cntsem_wait_if_and_lock(SEM *sem);
143  
144  RTAI_SYSCALL_MODE int rt_sem_wait_until(SEM *sem,
145  		      RTIME time);
146  
147  RTAI_SYSCALL_MODE int rt_sem_wait_timed(SEM *sem,
148  		      RTIME delay);
149  
150  RTAI_SYSCALL_MODE int rt_sem_wait_barrier(SEM *sem);
151  
152  RTAI_SYSCALL_MODE int rt_sem_count(SEM *sem);
153  
154  RTAI_SYSCALL_MODE int rt_cond_signal(CND *cnd);
155  
156  RTAI_SYSCALL_MODE int rt_cond_wait(CND *cnd,
157  		 SEM *mtx);
158  
159  RTAI_SYSCALL_MODE int rt_cond_wait_until(CND *cnd,
160  		       SEM *mtx,
161  		       RTIME time);
162  
163  RTAI_SYSCALL_MODE int rt_cond_wait_timed(CND *cnd,
164  		       SEM *mtx,
165  		       RTIME delay);
166  
167  #define rt_named_sem_init(sem_name, value)  rt_typed_named_sem_init(sem_name, value, CNT_SEM)
168  
169  static inline int rt_psem_init(psem_t *sem, int pshared, unsigned int value)
170  {
171  	if (value < SEM_TIMOUT) {
172  		rt_typed_sem_init(sem, value, pshared | PRIO_Q);
173  		return 0;
174  	}
175  	return -EINVAL;
176  }
177  
178  static inline int rt_psem_destroy(psem_t *sem)
179  {
180  	if (rt_sem_wait_if(sem) >= 0) {
181  		rt_sem_signal(sem);
182  		return rt_sem_delete(sem);
183  	}
184  	return -EBUSY;
185  }
186  
187  static inline int rt_psem_wait(psem_t *sem) {
188      return rt_sem_wait(sem) < SEM_TIMOUT ? 0 : -1;
189  }
190  
191  static inline int rt_psem_timedwait(psem_t *sem, struct timespec *abstime) {
192      return rt_sem_wait_until(sem, timespec2count(abstime)) < SEM_TIMOUT ? 0 : -1;
193  }
194  
195  static inline int rt_psem_trywait(psem_t *sem) {
196      return rt_sem_wait_if(sem) > 0 ? 0 : -EAGAIN;
197  }
198  
199  static inline int rt_psem_post(psem_t *sem) {
200      return rt_sem_signal(sem);
201  }
202  
203  static inline int rt_psem_getvalue(psem_t *sem, int *sval)
204  {
205  	if ((*sval = rt_sem_wait_if(sem)) > 0) {
206  		rt_sem_signal(sem);
207  	}
208  	return 0;
209  }
210  
211  static inline int rt_pmutex_init(pmutex_t *mutex, void *mutexattr)
212  {
213  	rt_typed_sem_init(mutex, 1, RES_SEM);
214  	return 0;
215  }
216  
217  static inline int rt_pmutex_destroy(pmutex_t *mutex)
218  {
219  	if (rt_sem_wait_if(mutex) > 0) {
220  		rt_sem_signal(mutex);
221  		return rt_sem_delete(mutex);
222  	}
223  	return -EBUSY;
224  }
225  
226  static inline int rt_pmutex_lock(pmutex_t *mutex) {
227      return rt_sem_wait(mutex) < SEM_TIMOUT ? 0 : -EINVAL;
228  }
229  
230  static inline int rt_pmutex_trylock(pmutex_t *mutex) {
231      return rt_sem_wait_if(mutex) > 0 ? 0 : -EBUSY;
232  }
233  
234  static inline int rt_pmutex_timedlock(pmutex_t *sem, struct timespec *abstime) {
235      return rt_sem_wait_until(sem, timespec2count(abstime)) < SEM_TIMOUT ? 0 : -1;
236  }
237  
238  static inline int rt_pmutex_unlock(pmutex_t *mutex) {
239      return rt_sem_signal(mutex);
240  }
241  
242  #undef rt_mutex_init
243  #define rt_mutex_init(mtx)             rt_typed_sem_init(mtx, 1, RES_SEM)
244  #define rt_mutex_delete(mtx)           rt_sem_delete(mtx)
245  #define rt_mutex_destroy(mtx)          rt_sem_delete(mtx)
246  #define rt_mutex_trylock(mtx)          rt_sem_wait_if(mtx)
247  #define rt_mutex_lock(mtx)             rt_sem_wait(mtx)
248  #define rt_mutex_timedlock(mtx, time)  rt_sem_wait_until(mtx, time)
249  #define rt_mutex_unlock(mtx)           rt_sem_signal(mtx)
250  
251  #define rt_cond_init(cnd)                  rt_typed_sem_init(cnd, 0, BIN_SEM | PRIO_Q)
252  #define rt_cond_delete(cnd)                rt_sem_delete(cnd)
253  #define rt_cond_destroy(cnd)               rt_sem_delete(cnd)
254  #define rt_cond_broadcast(cnd)             rt_sem_broadcast(cnd)
255  
256  static inline int rt_cond_timedwait(CND *cnd, SEM *mtx, RTIME time) {
257      return rt_cond_wait_until(cnd, mtx, time) < SEM_TIMOUT ? 0 : -1;
258  }
259  
260  #ifdef __cplusplus
261  }
262  #endif /* __cplusplus */
263  
264  #else /* !__KERNEL__ */
265  
266  #include <rtai_lxrt.h>
267  
268  #ifdef __cplusplus
269  extern "C" {
270  #endif /* __cplusplus */
271  
272  RTAI_PROTO(SEM *, rt_typed_sem_init,(unsigned long name, int value, int type))
273  {
274  	struct { unsigned long name; long value, type; } arg = { name ? name : rt_get_name(NULL), value, type };
275  	return (SEM *)rtai_lxrt(BIDX, SIZARG, LXRT_SEM_INIT, &arg).v[LOW];
276  }
277  
278  /**
279   * @ingroup lxrt
280   * Initialize a counting semaphore.
281   *
282   * Allocates and initializes a semaphore to be referred by @a name.
283   *
284   * @param name name of the semaphore.
285   *
286   * @param value is the initial value of the semaphore
287   *
288   * It is important to remark that the returned task pointer cannot be used
289   * directly, they are for kernel space data, but just passed as arguments when
290   * needed.
291   *
292   * @return a pointer to the semaphore to be used in related calls or 0 if an
293   * error has occured.
294   */ 
295  #define rt_sem_init(name, value) rt_typed_sem_init(name, value, CNT_SEM)
296  
297  #define rt_named_sem_init(sem_name, value) \
298  	rt_typed_named_sem_init(sem_name, value, CNT_SEM)
299  
300  RTAI_PROTO(int, rt_sem_delete,(SEM *sem))
301  {
302  	struct { SEM *sem; } arg = { sem };
303  	return rtai_lxrt(BIDX, SIZARG, LXRT_SEM_DELETE, &arg).i[LOW];
304  }
305  
306  RTAI_PROTO(SEM *, rt_typed_named_sem_init,(const char *name, int value, int type))
307  {
308  	struct { unsigned long name; long value, type; unsigned long *handle; } arg = { nam2num(name), value, type, NULL };
309  	return (SEM *)rtai_lxrt(BIDX, SIZARG, NAMED_SEM_INIT, &arg).v[LOW];
310  }
311  
312  RTAI_PROTO(int, rt_named_sem_delete,(SEM *sem))
313  {
314  	struct { SEM *sem; } arg = { sem };
315  	return rtai_lxrt(BIDX, SIZARG, NAMED_SEM_DELETE, &arg).i[LOW];
316  }
317  
318  RTAI_PROTO(int, rt_sem_signal,(SEM *sem))
319  {
320  	struct { SEM *sem; } arg = { sem };
321  	return rtai_lxrt(BIDX, SIZARG, SEM_SIGNAL, &arg).i[LOW];
322  }
323  
324  RTAI_PROTO(int, rt_sem_broadcast,(SEM *sem))
325  {
326  	struct { SEM *sem; } arg = { sem };
327  	return rtai_lxrt(BIDX, SIZARG, SEM_BROADCAST, &arg).i[LOW];
328  }
329  
330  RTAI_PROTO(int, rt_sem_wait,(SEM *sem))
331  {
332  	struct { SEM *sem; } arg = { sem };
333  	return rtai_lxrt(BIDX, SIZARG, SEM_WAIT, &arg).i[LOW];
334  }
335  
336  RTAI_PROTO(int, rt_sem_wait_if,(SEM *sem))
337  {
338  	struct { SEM *sem; } arg = { sem };
339  	return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_IF, &arg).i[LOW];
340  }
341  
342  RTAI_PROTO(int, rt_sem_wait_until,(SEM *sem, RTIME time))
343  {
344  	struct { SEM *sem; RTIME time; } arg = { sem, time };
345  	return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_UNTIL, &arg).i[LOW];
346  }
347  
348  RTAI_PROTO(int, rt_sem_wait_timed,(SEM *sem, RTIME delay))
349  {
350  	struct { SEM *sem; RTIME delay; } arg = { sem, delay };
351  	return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_TIMED, &arg).i[LOW];
352  }
353  
354  RTAI_PROTO(int, rt_sem_wait_barrier,(SEM *sem))
355  {
356  	struct { SEM *sem; } arg = { sem };
357  	return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_BARRIER, &arg).i[LOW];
358  }
359  
360  RTAI_PROTO(int, rt_sem_count,(SEM *sem))
361  {
362  	struct { SEM *sem; } arg = { sem };
363  	return rtai_lxrt(BIDX, SIZARG, SEM_COUNT, &arg).i[LOW];
364  }
365  
366  /**
367   * @ingroup lxrt
368   * Initialize a condition variable.
369   *
370   * Allocates and initializes a condition variable to be referred by @a name.
371   *
372   * @param name name of the condition variable.
373   *
374   * It is important to remark that the returned pointer cannot be used
375   * directly, it is for kernel space data, but just passed as arguments when
376   * needed.
377   *
378   * @return a pointer to the condition variable to be used in related calls or 0
379   * if an error has occured.
380   */ 
381  #define rt_cond_init(name)                 rt_typed_sem_init(name, 0, BIN_SEM)
382  #define rt_cond_delete(cnd)                rt_sem_delete(cnd)
383  #define rt_cond_destroy(cnd)               rt_sem_delete(cnd)
384  #define rt_cond_broadcast(cnd)             rt_sem_broadcast(cnd)
385  #define rt_cond_timedwait(cnd, mtx, time)  rt_cond_wait_until(cnd, mtx, time)
386  
387  RTAI_PROTO(int, rt_cond_signal,(CND *cnd))
388  {
389  	struct { CND *cnd; } arg = { cnd };
390  	return rtai_lxrt(BIDX, SIZARG, COND_SIGNAL, &arg).i[LOW];
391  }
392  
393  RTAI_PROTO(int, rt_cond_wait,(CND *cnd, SEM  *mutex))
394  {
395  	struct { CND *cnd; SEM *mutex; } arg = { cnd, mutex };
396  	return rtai_lxrt(BIDX, SIZARG, COND_WAIT, &arg).i[LOW];
397  }
398  
399  RTAI_PROTO(int, rt_cond_wait_until,(CND *cnd, SEM *mutex, RTIME time))
400  {
401  	struct { CND *cnd; SEM *mutex; RTIME time; } arg = { cnd, mutex, time };
402  	return rtai_lxrt(BIDX, SIZARG, COND_WAIT_UNTIL, &arg).i[LOW];
403  }
404  
405  RTAI_PROTO(int, rt_cond_wait_timed,(CND *cnd, SEM *mutex, RTIME delay))
406  {
407  	struct { CND *cnd; SEM *mutex; RTIME delay; } arg = { cnd, mutex, delay };
408  	return rtai_lxrt(BIDX, SIZARG, COND_WAIT_TIMED, &arg).i[LOW];
409  }
410  
411  RTAI_PROTO(int, rt_poll, (struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout))
412  {
413  #ifdef CONFIG_RTAI_RT_POLL
414  	struct { struct rt_poll_s *pdsa; unsigned long nr; RTIME timeout; long space; } arg = { pdsa, nr, timeout, 0 };
415  	return rtai_lxrt(BIDX, SIZARG, SEM_RT_POLL, &arg).i[LOW];
416  #else
417  	return RTE_OBJINV;
418  #endif
419  }
420  
421  #ifdef __cplusplus
422  }
423  #endif /* __cplusplus */
424  
425  #endif /* __KERNEL__ */
426  
427  #endif /* !_RTAI_SEM_H */