rtai_sem.h
1 /** 2 * @ingroup lxrt 3 * @file 4 * 5 * @author Paolo Mantegazza 6 * 7 * @note Copyright © 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 */