base/include/rtai_sem.h

Go to the documentation of this file.
00001 /**
00002  * @ingroup lxrt
00003  * @file
00004  *
00005  * @author Paolo Mantegazza
00006  *
00007  * @note Copyright &copy; 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License as
00011  * published by the Free Software Foundation; either version 2 of the
00012  * License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00022  */
00023 
00024 #ifndef _RTAI_SEM_H
00025 #define _RTAI_SEM_H
00026 
00027 #include <rtai_types.h>
00028 #include <rtai_nam2num.h>
00029 #include <rtai_sched.h>
00030 
00031 #define RT_SEM_MAGIC 0x3f83ebb  // nam2num("rtsem")
00032 
00033 #define SEM_ERR     (RTE_OBJINV)
00034 #define SEM_TIMOUT  (RTE_TIMOUT)
00035 
00036 struct rt_poll_s { void *what; unsigned long forwhat; };
00037 
00038 // do not use 0 for any "forwhat" below
00039 #define RT_POLL_NOT_TO_USE    0
00040 #define RT_POLL_MBX_RECV      1
00041 #define RT_POLL_MBX_SEND      2
00042 #define RT_POLL_SEM_WAIT_ALL  3
00043 #define RT_POLL_SEM_WAIT_ONE  4
00044 
00045 #if defined(__KERNEL__) && !defined(__cplusplus)
00046 
00047 struct rt_poll_ql { QUEUE pollq; spinlock_t pollock; };
00048 struct rt_poll_enc { unsigned long offset; int (*topoll)(void *); };
00049 extern struct rt_poll_enc rt_poll_ofstfun[];
00050 
00051 typedef struct rt_semaphore {
00052     struct rt_queue queue; /* <= Must be first in struct. */
00053     int magic;
00054     int type, restype;
00055     int count;
00056     struct rt_task_struct *owndby;
00057     int qtype;
00058     struct rt_queue resq;
00059 #ifdef CONFIG_RTAI_RT_POLL
00060     struct rt_poll_ql poll_wait_all;
00061     struct rt_poll_ql poll_wait_one;
00062 #endif
00063 } SEM;
00064 
00065 #ifdef CONFIG_RTAI_RT_POLL
00066 
00067 RTAI_SYSCALL_MODE int _rt_poll(struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout, int space);
00068 static inline int rt_poll(struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout)
00069 {
00070     return _rt_poll(pdsa, nr, timeout, 1);
00071 }
00072 
00073 void rt_wakeup_pollers(struct rt_poll_ql *ql, int reason);
00074 
00075 #else
00076 
00077 static inline int rt_poll(struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout)
00078 {
00079     return RTE_OBJINV;
00080 }
00081 
00082 #define rt_wakeup_pollers(ql, reason)
00083 
00084 #endif
00085 
00086 #else /* !__KERNEL__ || __cplusplus */
00087 
00088 typedef struct rt_semaphore {
00089     int opaque;
00090 } SEM;
00091 
00092 #endif /* __KERNEL__ && !__cplusplus */
00093 
00094 typedef SEM CND;
00095 
00096 #ifdef __KERNEL__
00097 
00098 #include <linux/errno.h>
00099 
00100 typedef SEM psem_t;
00101 
00102 typedef SEM pmutex_t;
00103 
00104 #ifdef __cplusplus
00105 extern "C" {
00106 #endif /* __cplusplus */
00107 
00108 int __rtai_sem_init(void);
00109 
00110 void __rtai_sem_exit(void);
00111 
00112 RTAI_SYSCALL_MODE void rt_typed_sem_init(SEM *sem,
00113                int value,
00114                int type);
00115 
00116 RTAI_SYSCALL_MODE int rt_sem_delete(SEM *sem);
00117 
00118 RTAI_SYSCALL_MODE SEM *_rt_typed_named_sem_init(unsigned long sem_name,
00119                  int value,
00120                  int type,
00121                  unsigned long *handle);
00122 
00123 static inline SEM *rt_typed_named_sem_init(const char *sem_name,
00124                        int value,
00125                        int type) {
00126     return _rt_typed_named_sem_init(nam2num(sem_name), value, type, NULL);
00127 }
00128 
00129 RTAI_SYSCALL_MODE int rt_named_sem_delete(SEM *sem);
00130 
00131 void rt_sem_init(SEM *sem,
00132          int value);
00133 
00134 RTAI_SYSCALL_MODE int rt_sem_signal(SEM *sem);
00135 
00136 RTAI_SYSCALL_MODE int rt_sem_broadcast(SEM *sem);
00137 
00138 RTAI_SYSCALL_MODE int rt_sem_wait(SEM *sem);
00139 
00140 RTAI_SYSCALL_MODE int rt_sem_wait_if(SEM *sem);
00141 
00142 int rt_cntsem_wait_if_and_lock(SEM *sem);
00143 
00144 RTAI_SYSCALL_MODE int rt_sem_wait_until(SEM *sem,
00145               RTIME time);
00146 
00147 RTAI_SYSCALL_MODE int rt_sem_wait_timed(SEM *sem,
00148               RTIME delay);
00149 
00150 RTAI_SYSCALL_MODE int rt_sem_wait_barrier(SEM *sem);
00151 
00152 RTAI_SYSCALL_MODE int rt_sem_count(SEM *sem);
00153 
00154 RTAI_SYSCALL_MODE int rt_cond_signal(CND *cnd);
00155 
00156 RTAI_SYSCALL_MODE int rt_cond_wait(CND *cnd,
00157          SEM *mtx);
00158 
00159 RTAI_SYSCALL_MODE int rt_cond_wait_until(CND *cnd,
00160                SEM *mtx,
00161                RTIME time);
00162 
00163 RTAI_SYSCALL_MODE int rt_cond_wait_timed(CND *cnd,
00164                SEM *mtx,
00165                RTIME delay);
00166 
00167 #define rt_named_sem_init(sem_name, value)  rt_typed_named_sem_init(sem_name, value, CNT_SEM)
00168 
00169 static inline int rt_psem_init(psem_t *sem, int pshared, unsigned int value)
00170 {
00171     if (value < SEM_TIMOUT) {
00172         rt_typed_sem_init(sem, value, pshared | PRIO_Q);
00173         return 0;
00174     }
00175     return -EINVAL;
00176 }
00177 
00178 static inline int rt_psem_destroy(psem_t *sem)
00179 {
00180     if (rt_sem_wait_if(sem) >= 0) {
00181         rt_sem_signal(sem);
00182         return rt_sem_delete(sem);
00183     }
00184     return -EBUSY;
00185 }
00186 
00187 static inline int rt_psem_wait(psem_t *sem) {
00188     return rt_sem_wait(sem) < SEM_TIMOUT ? 0 : -1;
00189 }
00190 
00191 static inline int rt_psem_timedwait(psem_t *sem, struct timespec *abstime) {
00192     return rt_sem_wait_until(sem, timespec2count(abstime)) < SEM_TIMOUT ? 0 : -1;
00193 }
00194 
00195 static inline int rt_psem_trywait(psem_t *sem) {
00196     return rt_sem_wait_if(sem) > 0 ? 0 : -EAGAIN;
00197 }
00198 
00199 static inline int rt_psem_post(psem_t *sem) {
00200     return rt_sem_signal(sem);
00201 }
00202 
00203 static inline int rt_psem_getvalue(psem_t *sem, int *sval)
00204 {
00205     if ((*sval = rt_sem_wait_if(sem)) > 0) {
00206         rt_sem_signal(sem);
00207     }
00208     return 0;
00209 }
00210 
00211 static inline int rt_pmutex_init(pmutex_t *mutex, void *mutexattr)
00212 {
00213     rt_typed_sem_init(mutex, 1, RES_SEM);
00214     return 0;
00215 }
00216 
00217 static inline int rt_pmutex_destroy(pmutex_t *mutex)
00218 {
00219     if (rt_sem_wait_if(mutex) > 0) {
00220         rt_sem_signal(mutex);
00221         return rt_sem_delete(mutex);
00222     }
00223     return -EBUSY;
00224 }
00225 
00226 static inline int rt_pmutex_lock(pmutex_t *mutex) {
00227     return rt_sem_wait(mutex) < SEM_TIMOUT ? 0 : -EINVAL;
00228 }
00229 
00230 static inline int rt_pmutex_trylock(pmutex_t *mutex) {
00231     return rt_sem_wait_if(mutex) > 0 ? 0 : -EBUSY;
00232 }
00233 
00234 static inline int rt_pmutex_timedlock(pmutex_t *sem, struct timespec *abstime) {
00235     return rt_sem_wait_until(sem, timespec2count(abstime)) < SEM_TIMOUT ? 0 : -1;
00236 }
00237 
00238 static inline int rt_pmutex_unlock(pmutex_t *mutex) {
00239     return rt_sem_signal(mutex);
00240 }
00241 
00242 #undef rt_mutex_init
00243 #define rt_mutex_init(mtx)             rt_typed_sem_init(mtx, 1, RES_SEM)
00244 #define rt_mutex_delete(mtx)           rt_sem_delete(mtx)
00245 #define rt_mutex_destroy(mtx)          rt_sem_delete(mtx)
00246 #define rt_mutex_trylock(mtx)          rt_sem_wait_if(mtx)
00247 #define rt_mutex_lock(mtx)             rt_sem_wait(mtx)
00248 #define rt_mutex_timedlock(mtx, time)  rt_sem_wait_until(mtx, time)
00249 #define rt_mutex_unlock(mtx)           rt_sem_signal(mtx)
00250 
00251 #define rt_cond_init(cnd)                  rt_typed_sem_init(cnd, 0, BIN_SEM | PRIO_Q)
00252 #define rt_cond_delete(cnd)                rt_sem_delete(cnd)
00253 #define rt_cond_destroy(cnd)               rt_sem_delete(cnd)
00254 #define rt_cond_broadcast(cnd)             rt_sem_broadcast(cnd)
00255 
00256 static inline int rt_cond_timedwait(CND *cnd, SEM *mtx, RTIME time) {
00257     return rt_cond_wait_until(cnd, mtx, time) < SEM_TIMOUT ? 0 : -1;
00258 }
00259 
00260 #ifdef __cplusplus
00261 }
00262 #endif /* __cplusplus */
00263 
00264 #else /* !__KERNEL__ */
00265 
00266 #include <rtai_lxrt.h>
00267 
00268 #ifdef __cplusplus
00269 extern "C" {
00270 #endif /* __cplusplus */
00271 
00272 RTAI_PROTO(SEM *, rt_typed_sem_init,(unsigned long name, int value, int type))
00273 {
00274     struct { unsigned long name; long value, type; } arg = { name ? name : rt_get_name(NULL), value, type };
00275     return (SEM *)rtai_lxrt(BIDX, SIZARG, LXRT_SEM_INIT, &arg).v[LOW];
00276 }
00277 
00278 /**
00279  * @ingroup lxrt
00280  * Initialize a counting semaphore.
00281  *
00282  * Allocates and initializes a semaphore to be referred by @a name.
00283  *
00284  * @param name name of the semaphore.
00285  *
00286  * @param value is the initial value of the semaphore
00287  *
00288  * It is important to remark that the returned task pointer cannot be used
00289  * directly, they are for kernel space data, but just passed as arguments when
00290  * needed.
00291  *
00292  * @return a pointer to the semaphore to be used in related calls or 0 if an
00293  * error has occured.
00294  */ 
00295 #define rt_sem_init(name, value) rt_typed_sem_init(name, value, CNT_SEM)
00296 
00297 #define rt_named_sem_init(sem_name, value) \
00298     rt_typed_named_sem_init(sem_name, value, CNT_SEM)
00299 
00300 RTAI_PROTO(int, rt_sem_delete,(SEM *sem))
00301 {
00302     struct { SEM *sem; } arg = { sem };
00303     return rtai_lxrt(BIDX, SIZARG, LXRT_SEM_DELETE, &arg).i[LOW];
00304 }
00305 
00306 RTAI_PROTO(SEM *, rt_typed_named_sem_init,(const char *name, int value, int type))
00307 {
00308     struct { unsigned long name; long value, type; unsigned long *handle; } arg = { nam2num(name), value, type, NULL };
00309     return (SEM *)rtai_lxrt(BIDX, SIZARG, NAMED_SEM_INIT, &arg).v[LOW];
00310 }
00311 
00312 RTAI_PROTO(int, rt_named_sem_delete,(SEM *sem))
00313 {
00314     struct { SEM *sem; } arg = { sem };
00315     return rtai_lxrt(BIDX, SIZARG, NAMED_SEM_DELETE, &arg).i[LOW];
00316 }
00317 
00318 RTAI_PROTO(int, rt_sem_signal,(SEM *sem))
00319 {
00320     struct { SEM *sem; } arg = { sem };
00321     return rtai_lxrt(BIDX, SIZARG, SEM_SIGNAL, &arg).i[LOW];
00322 }
00323 
00324 RTAI_PROTO(int, rt_sem_broadcast,(SEM *sem))
00325 {
00326     struct { SEM *sem; } arg = { sem };
00327     return rtai_lxrt(BIDX, SIZARG, SEM_BROADCAST, &arg).i[LOW];
00328 }
00329 
00330 RTAI_PROTO(int, rt_sem_wait,(SEM *sem))
00331 {
00332     struct { SEM *sem; } arg = { sem };
00333     return rtai_lxrt(BIDX, SIZARG, SEM_WAIT, &arg).i[LOW];
00334 }
00335 
00336 RTAI_PROTO(int, rt_sem_wait_if,(SEM *sem))
00337 {
00338     struct { SEM *sem; } arg = { sem };
00339     return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_IF, &arg).i[LOW];
00340 }
00341 
00342 RTAI_PROTO(int, rt_sem_wait_until,(SEM *sem, RTIME time))
00343 {
00344     struct { SEM *sem; RTIME time; } arg = { sem, time };
00345     return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_UNTIL, &arg).i[LOW];
00346 }
00347 
00348 RTAI_PROTO(int, rt_sem_wait_timed,(SEM *sem, RTIME delay))
00349 {
00350     struct { SEM *sem; RTIME delay; } arg = { sem, delay };
00351     return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_TIMED, &arg).i[LOW];
00352 }
00353 
00354 RTAI_PROTO(int, rt_sem_wait_barrier,(SEM *sem))
00355 {
00356     struct { SEM *sem; } arg = { sem };
00357     return rtai_lxrt(BIDX, SIZARG, SEM_WAIT_BARRIER, &arg).i[LOW];
00358 }
00359 
00360 RTAI_PROTO(int, rt_sem_count,(SEM *sem))
00361 {
00362     struct { SEM *sem; } arg = { sem };
00363     return rtai_lxrt(BIDX, SIZARG, SEM_COUNT, &arg).i[LOW];
00364 }
00365 
00366 /**
00367  * @ingroup lxrt
00368  * Initialize a condition variable.
00369  *
00370  * Allocates and initializes a condition variable to be referred by @a name.
00371  *
00372  * @param name name of the condition variable.
00373  *
00374  * It is important to remark that the returned pointer cannot be used
00375  * directly, it is for kernel space data, but just passed as arguments when
00376  * needed.
00377  *
00378  * @return a pointer to the condition variable to be used in related calls or 0
00379  * if an error has occured.
00380  */ 
00381 #define rt_cond_init(name)                 rt_typed_sem_init(name, 0, BIN_SEM)
00382 #define rt_cond_delete(cnd)                rt_sem_delete(cnd)
00383 #define rt_cond_destroy(cnd)               rt_sem_delete(cnd)
00384 #define rt_cond_broadcast(cnd)             rt_sem_broadcast(cnd)
00385 #define rt_cond_timedwait(cnd, mtx, time)  rt_cond_wait_until(cnd, mtx, time)
00386 
00387 RTAI_PROTO(int, rt_cond_signal,(CND *cnd))
00388 {
00389     struct { CND *cnd; } arg = { cnd };
00390     return rtai_lxrt(BIDX, SIZARG, COND_SIGNAL, &arg).i[LOW];
00391 }
00392 
00393 RTAI_PROTO(int, rt_cond_wait,(CND *cnd, SEM  *mutex))
00394 {
00395     struct { CND *cnd; SEM *mutex; } arg = { cnd, mutex };
00396     return rtai_lxrt(BIDX, SIZARG, COND_WAIT, &arg).i[LOW];
00397 }
00398 
00399 RTAI_PROTO(int, rt_cond_wait_until,(CND *cnd, SEM *mutex, RTIME time))
00400 {
00401     struct { CND *cnd; SEM *mutex; RTIME time; } arg = { cnd, mutex, time };
00402     return rtai_lxrt(BIDX, SIZARG, COND_WAIT_UNTIL, &arg).i[LOW];
00403 }
00404 
00405 RTAI_PROTO(int, rt_cond_wait_timed,(CND *cnd, SEM *mutex, RTIME delay))
00406 {
00407     struct { CND *cnd; SEM *mutex; RTIME delay; } arg = { cnd, mutex, delay };
00408     return rtai_lxrt(BIDX, SIZARG, COND_WAIT_TIMED, &arg).i[LOW];
00409 }
00410 
00411 RTAI_PROTO(int, rt_poll, (struct rt_poll_s *pdsa, unsigned long nr, RTIME timeout))
00412 {
00413 #ifdef CONFIG_RTAI_RT_POLL
00414     struct { struct rt_poll_s *pdsa; unsigned long nr; RTIME timeout; long space; } arg = { pdsa, nr, timeout, 0 };
00415     return rtai_lxrt(BIDX, SIZARG, SEM_RT_POLL, &arg).i[LOW];
00416 #else
00417     return RTE_OBJINV;
00418 #endif
00419 }
00420 
00421 #ifdef __cplusplus
00422 }
00423 #endif /* __cplusplus */
00424 
00425 #endif /* __KERNEL__ */
00426 
00427 #endif /* !_RTAI_SEM_H */

Generated on Tue Feb 2 17:46:05 2010 for RTAI API by  doxygen 1.4.7