Xenomai  3.1
threadobj.h
1 /*
2  * Copyright (C) 2008 Philippe Gerum <rpm@xenomai.org>.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13 
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18 
19 #ifndef _COPPERPLATE_THREADOBJ_H
20 #define _COPPERPLATE_THREADOBJ_H
21 
22 #include <time.h>
23 #include <semaphore.h>
24 #include <signal.h>
25 #include <pthread.h>
26 #include <stdint.h>
27 #include <boilerplate/list.h>
28 #include <boilerplate/lock.h>
29 #include <boilerplate/sched.h>
30 #include <copperplate/clockobj.h>
31 #include <copperplate/heapobj.h>
32 
33 #ifdef CONFIG_XENO_COBALT
34 
35 #include <cobalt/uapi/kernel/types.h>
36 
37 struct xnthread_user_window;
38 
39 struct threadobj_corespec {
40  xnhandle_t handle;
41  union {
42  __u32 u_winoff;
43  struct xnthread_user_window *u_window;
44  };
45 };
46 
47 struct threadobj_stat {
49  ticks_t xtime;
51  ticks_t timeout;
53  uint64_t msw;
55  uint64_t csw;
57  uint64_t xsc;
59  int cpu;
61  int schedlock;
63  unsigned int status;
65  uint32_t pf;
66 };
67 
68 #define SCHED_CORE SCHED_COBALT
69 
70 static inline
71 void threadobj_save_timeout(struct threadobj_corespec *corespec,
72  const struct timespec *timeout)
73 {
74  /*
75  * We retrieve this information from the nucleus directly via
76  * cobalt_thread_stat().
77  */
78 }
79 
80 #ifdef CONFIG_XENO_PSHARED
81 
82 static inline struct xnthread_user_window *
83 threadobj_get_window(struct threadobj_corespec *corespec)
84 {
85  extern void *cobalt_umm_shared;
86  return (struct xnthread_user_window *)
87  ((caddr_t)cobalt_umm_shared + corespec->u_winoff);
88 }
89 
90 #else /* !CONFIG_XENO_PSHARED */
91 
92 static inline struct xnthread_user_window *
93 threadobj_get_window(struct threadobj_corespec *corespec)
94 {
95  return corespec->u_window;
96 }
97 
98 #endif /* !CONFIG_XENO_PSHARED */
99 
100 #else /* CONFIG_XENO_MERCURY */
101 
102 #include <sys/time.h>
103 
104 struct threadobj_corespec {
105  pthread_cond_t grant_sync;
106  int policy_unlocked;
107  struct sched_param_ex schedparam_unlocked;
108  timer_t rr_timer;
110  struct timespec timeout;
111 #ifdef CONFIG_XENO_WORKAROUND_CONDVAR_PI
112  int policy_unboosted;
113  struct sched_param_ex schedparam_unboosted;
114 #endif
115 };
116 
117 struct threadobj_stat {
119  ticks_t timeout;
121  int cpu;
123  int schedlock;
125  unsigned int status;
126 };
127 
128 #define SCHED_CORE SCHED_FIFO
129 
130 static inline
131 void threadobj_save_timeout(struct threadobj_corespec *corespec,
132  const struct timespec *timeout)
133 {
134  if (timeout)
135  corespec->timeout = *timeout;
136 }
137 
138 #endif /* CONFIG_XENO_MERCURY */
139 
140 /*
141  * threadobj->status, updated with ->lock held.
142  */
143 #define __THREAD_S_STARTED (1 << 0) /* threadobj_start() called. */
144 #define __THREAD_S_WARMUP (1 << 1) /* threadobj_prologue() not called yet. */
145 #define __THREAD_S_ABORTED (1 << 2) /* Cancelled before start. */
146 #define __THREAD_S_LOCKED (1 << 3) /* threadobj_lock() granted (debug only). */
147 #define __THREAD_S_ACTIVE (1 << 4) /* Running user code. */
148 #define __THREAD_S_SUSPENDED (1 << 5) /* Suspended via threadobj_suspend(). */
149 #define __THREAD_S_SAFE (1 << 6) /* TCB release deferred. */
150 #define __THREAD_S_PERIODIC (1 << 7) /* Periodic timer set. */
151 #define __THREAD_S_DEBUG (1 << 31) /* Debug mode enabled. */
152 /*
153  * threadobj->run_state, locklessly updated by "current", merged
154  * with ->status bits by threadobj_get_status().
155  */
156 #define __THREAD_S_RUNNING 0
157 #define __THREAD_S_DORMANT (1 << 16)
158 #define __THREAD_S_WAIT (1 << 17)
159 #define __THREAD_S_TIMEDWAIT (1 << 18)
160 #define __THREAD_S_DELAYED (1 << 19)
161 #define __THREAD_S_BREAK (__THREAD_S_DELAYED|(1 << 20))
162 
163 /* threadobj mode bits */
164 #define __THREAD_M_LOCK (1 << 0) /* Toggle scheduler lock. */
165 #define __THREAD_M_WARNSW (1 << 1) /* Toggle switch warning bit. */
166 #define __THREAD_M_CONFORMING (1 << 2) /* Switch to conforming mode. */
167 #define __THREAD_M_SPARE0 (1 << 16)
168 #define __THREAD_M_SPARE1 (1 << 17)
169 #define __THREAD_M_SPARE2 (1 << 18)
170 #define __THREAD_M_SPARE3 (1 << 19)
171 #define __THREAD_M_SPARE4 (1 << 20)
172 #define __THREAD_M_SPARE5 (1 << 21)
173 #define __THREAD_M_SPARE6 (1 << 22)
174 #define __THREAD_M_SPARE7 (1 << 23)
175 
176 #define THREADOBJ_IRQCONTEXT ((struct threadobj *)-2UL)
177 
178 struct traceobj;
179 struct syncobj;
180 
181 struct threadobj {
182  unsigned int magic; /* Must be first. */
183  pthread_t ptid;
184  pthread_mutex_t lock;
185 
186  int schedlock_depth;
187  int cancel_state;
188  int status;
189  int run_state;
190  int policy;
191  struct sched_param_ex schedparam;
192  int global_priority;
193  pid_t cnode;
194  pid_t pid;
195  char name[32];
196 
197  void (*finalizer)(struct threadobj *thobj);
198  int core_offset;
199  int *errno_pointer;
200  /* Those members belong exclusively to the syncobj code. */
201  struct syncobj *wait_sobj;
202  struct holder wait_link;
203  int wait_status;
204  int wait_prio;
205  dref_type(void *) wait_union;
206  size_t wait_size;
207  timer_t periodic_timer;
208 
209  struct threadobj_corespec core;
210  struct timespec tslice;
211  pthread_cond_t barrier;
212  struct traceobj *tracer;
213  sem_t *cancel_sem;
214  struct sysgroup_memspec memspec;
215  struct backtrace_data btd;
216 };
217 
218 struct threadobj_init_data {
219  unsigned int magic;
220  cpu_set_t affinity;
221  int policy;
222  struct sched_param_ex param_ex;
223  void (*finalizer)(struct threadobj *thobj);
224 };
225 
226 extern int threadobj_high_prio;
227 
228 extern int threadobj_irq_prio;
229 
230 extern pthread_key_t threadobj_tskey;
231 
232 #ifdef HAVE_TLS
233 
234 extern __thread __attribute__ ((tls_model (CONFIG_XENO_TLS_MODEL)))
235 struct threadobj *__threadobj_current;
236 
237 static inline void threadobj_set_current(struct threadobj *thobj)
238 {
239  __threadobj_current = thobj;
240  pthread_setspecific(threadobj_tskey, thobj);
241 }
242 
243 static inline struct threadobj *__threadobj_get_current(void)
244 {
245  return __threadobj_current;
246 }
247 
248 #else /* !HAVE_TLS */
249 
250 static inline void threadobj_set_current(struct threadobj *thobj)
251 {
252  pthread_setspecific(threadobj_tskey, thobj);
253 }
254 
255 static inline struct threadobj *__threadobj_get_current(void)
256 {
257  return (struct threadobj *)pthread_getspecific(threadobj_tskey);
258 }
259 
260 #endif /* !HAVE_TLS */
261 
262 static inline struct threadobj *threadobj_current(void)
263 {
264  struct threadobj *thobj = __threadobj_get_current();
265  return thobj == NULL || thobj == THREADOBJ_IRQCONTEXT ? NULL : thobj;
266 }
267 
268 #ifdef CONFIG_XENO_DEBUG
269 
270 static inline void __threadobj_tag_locked(struct threadobj *thobj)
271 {
272  thobj->status |= __THREAD_S_LOCKED;
273 }
274 
275 static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
276 {
277  assert(thobj->status & __THREAD_S_LOCKED);
278  thobj->status &= ~__THREAD_S_LOCKED;
279 }
280 
281 static inline void __threadobj_check_locked(struct threadobj *thobj)
282 {
283  assert(thobj->status & __THREAD_S_LOCKED);
284 }
285 
286 #else /* !CONFIG_XENO_DEBUG */
287 
288 static inline void __threadobj_tag_locked(struct threadobj *thobj)
289 {
290 }
291 
292 static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
293 {
294 }
295 
296 static inline void __threadobj_check_locked(struct threadobj *thobj)
297 {
298 }
299 
300 #endif /* !CONFIG_XENO_DEBUG */
301 
302 #ifdef __cplusplus
303 extern "C" {
304 #endif
305 
306 void *__threadobj_alloc(size_t tcb_struct_size,
307  size_t wait_union_size,
308  int thobj_offset);
309 
310 static inline void __threadobj_free(void *p)
311 {
312  xnfree(p);
313 }
314 
315 static inline void threadobj_free(struct threadobj *thobj)
316 {
317  __threadobj_free((unsigned char *)thobj - thobj->core_offset);
318 }
319 
320 int threadobj_init(struct threadobj *thobj,
321  struct threadobj_init_data *idata) __must_check;
322 
323 int threadobj_start(struct threadobj *thobj) __must_check;
324 
325 int threadobj_shadow(struct threadobj *thobj,
326  const char *name);
327 
328 int threadobj_prologue(struct threadobj *thobj,
329  const char *name);
330 
331 void threadobj_wait_start(void);
332 
333 void threadobj_notify_entry(void);
334 
335 int threadobj_cancel(struct threadobj *thobj);
336 
337 void threadobj_uninit(struct threadobj *thobj);
338 
339 int threadobj_suspend(struct threadobj *thobj);
340 
341 int threadobj_resume(struct threadobj *thobj);
342 
343 int threadobj_unblock(struct threadobj *thobj);
344 
345 int __threadobj_lock_sched(struct threadobj *current);
346 
347 int threadobj_lock_sched(void);
348 
349 int __threadobj_unlock_sched(struct threadobj *current);
350 
351 int threadobj_unlock_sched(void);
352 
353 int threadobj_set_schedparam(struct threadobj *thobj, int policy,
354  const struct sched_param_ex *param_ex);
355 
356 int threadobj_set_schedprio(struct threadobj *thobj, int priority);
357 
358 int threadobj_set_mode(int clrmask, int setmask, int *mode_r);
359 
360 int threadobj_set_periodic(struct threadobj *thobj,
361  const struct timespec *__restrict__ idate,
362  const struct timespec *__restrict__ period);
363 
364 int threadobj_wait_period(unsigned long *overruns_r) __must_check;
365 
366 void threadobj_spin(ticks_t ns);
367 
368 int threadobj_stat(struct threadobj *thobj,
369  struct threadobj_stat *stat);
370 
371 int threadobj_sleep(const struct timespec *ts);
372 
373 void threadobj_set_current_name(const char *name);
374 
375 #ifdef CONFIG_XENO_PSHARED
376 
377 static inline int threadobj_local_p(struct threadobj *thobj)
378 {
379  extern pid_t __node_id;
380  return thobj->cnode == __node_id;
381 }
382 
383 #else /* !CONFIG_XENO_PSHARED */
384 
385 static inline int threadobj_local_p(struct threadobj *thobj)
386 {
387  return 1;
388 }
389 
390 #endif /* !CONFIG_XENO_PSHARED */
391 
392 void threadobj_init_key(void);
393 
394 int threadobj_pkg_init(int anon_session);
395 
396 #ifdef __cplusplus
397 }
398 #endif
399 
400 #define threadobj_alloc(T, __mptr, W) \
401  ({ \
402  void *__p; \
403  __p = __threadobj_alloc(sizeof(T), sizeof(W), offsetof(T, __mptr)); \
404  __p; \
405  })
406 
407 static inline int threadobj_get_policy(struct threadobj *thobj)
408 {
409  return thobj->policy;
410 }
411 
412 static inline int threadobj_get_priority(struct threadobj *thobj)
413 {
414  return thobj->schedparam.sched_priority;
415 }
416 
417 static inline void threadobj_copy_schedparam(struct sched_param_ex *param_ex,
418  const struct threadobj *thobj)
419 {
420  *param_ex = thobj->schedparam;
421 }
422 
423 static inline int threadobj_lock(struct threadobj *thobj)
424 {
425  int ret;
426 
427  ret = write_lock_safe(&thobj->lock, thobj->cancel_state);
428  if (ret)
429  return ret;
430 
431  __threadobj_tag_locked(thobj);
432 
433  return 0;
434 }
435 
436 static inline int threadobj_trylock(struct threadobj *thobj)
437 {
438  int ret;
439 
440  ret = write_trylock_safe(&thobj->lock, thobj->cancel_state);
441  if (ret)
442  return ret;
443 
444  __threadobj_tag_locked(thobj);
445 
446  return 0;
447 }
448 
449 static inline int threadobj_unlock(struct threadobj *thobj)
450 {
451  __threadobj_check_locked(thobj);
452  __threadobj_tag_unlocked(thobj);
453  return write_unlock_safe(&thobj->lock, thobj->cancel_state);
454 }
455 
456 static inline int threadobj_irq_p(void)
457 {
458  struct threadobj *current = __threadobj_get_current();
459  return current == THREADOBJ_IRQCONTEXT;
460 }
461 
462 static inline int threadobj_current_p(void)
463 {
464  return threadobj_current() != NULL;
465 }
466 
467 static inline int __threadobj_lock_sched_once(struct threadobj *current)
468 {
469  if (current->schedlock_depth == 0)
470  return __threadobj_lock_sched(current);
471 
472  return -EBUSY;
473 }
474 
475 static inline int threadobj_lock_sched_once(void)
476 {
477  struct threadobj *current = threadobj_current();
478 
479  if (current->schedlock_depth == 0)
480  return threadobj_lock_sched();
481 
482  return -EBUSY;
483 }
484 
485 static inline void threadobj_yield(void)
486 {
487  __RT(sched_yield());
488 }
489 
490 static inline unsigned int threadobj_get_magic(struct threadobj *thobj)
491 {
492  return thobj->magic;
493 }
494 
495 static inline void threadobj_set_magic(struct threadobj *thobj,
496  unsigned int magic)
497 {
498  thobj->magic = magic;
499 }
500 
501 static inline int threadobj_get_lockdepth(struct threadobj *thobj)
502 {
503  return thobj->schedlock_depth;
504 }
505 
506 static inline int threadobj_get_status(struct threadobj *thobj)
507 {
508  return thobj->status | thobj->run_state;
509 }
510 
511 static inline int threadobj_get_errno(struct threadobj *thobj)
512 {
513  return *thobj->errno_pointer;
514 }
515 
516 #define threadobj_prepare_wait(T) \
517  ({ \
518  struct threadobj *__thobj = threadobj_current(); \
519  assert(__thobj != NULL); \
520  assert(sizeof(typeof(T)) <= __thobj->wait_size); \
521  __mptr(__thobj->wait_union); \
522  })
523 
524 #define threadobj_finish_wait() do { } while (0)
525 
526 static inline void *threadobj_get_wait(struct threadobj *thobj)
527 {
528  return __mptr(thobj->wait_union);
529 }
530 
531 static inline const char *threadobj_get_name(struct threadobj *thobj)
532 {
533  return thobj->name;
534 }
535 
536 static inline pid_t threadobj_get_pid(struct threadobj *thobj)
537 {
538  return thobj->pid;
539 }
540 
541 #ifdef CONFIG_XENO_WORKAROUND_CONDVAR_PI
542 
543 int threadobj_cond_timedwait(pthread_cond_t *cond,
544  pthread_mutex_t *lock,
545  const struct timespec *timeout);
546 
547 int threadobj_cond_wait(pthread_cond_t *cond,
548  pthread_mutex_t *lock);
549 
550 int threadobj_cond_signal(pthread_cond_t *cond);
551 
552 int threadobj_cond_broadcast(pthread_cond_t *cond);
553 
554 #else
555 
556 static inline
557 int threadobj_cond_timedwait(pthread_cond_t *cond,
558  pthread_mutex_t *lock,
559  const struct timespec *timeout)
560 {
561  return __RT(pthread_cond_timedwait(cond, lock, timeout));
562 }
563 
564 static inline
565 int threadobj_cond_wait(pthread_cond_t *cond,
566  pthread_mutex_t *lock)
567 {
568  return __RT(pthread_cond_wait(cond, lock));
569 }
570 
571 static inline
572 int threadobj_cond_signal(pthread_cond_t *cond)
573 {
574  return __RT(pthread_cond_signal(cond));
575 }
576 
577 static inline
578 int threadobj_cond_broadcast(pthread_cond_t *cond)
579 {
580  return __RT(pthread_cond_broadcast(cond));
581 }
582 
583 #endif /* !CONFIG_XENO_WORKAROUND_CONDVAR_PI */
584 
585 #endif /* _COPPERPLATE_THREADOBJ_H */
int pthread_cond_signal(pthread_cond_t *cond)
Signal a condition variable.
Definition: cond.c:445
int pthread_cond_broadcast(pthread_cond_t *cond)
Broadcast a condition variable.
Definition: cond.c:501
int sched_yield(void)
Yield the processor.
Definition: sched.c:58
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Wait on a condition variable.
Definition: cond.c:280
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
Wait a bounded time on a condition variable.
Definition: cond.c:371
static int __attribute__((cold))
Test if a mutex structure contains a valid autoinitializer.
Definition: mutex.c:177