Xenomai  3.1.2
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 /*
177  * We need to use a valid address here. The object will never be dereferenced
178  * when it is identified as IRQ context, so the pthread key itself is fine.
179  */
180 #define THREADOBJ_IRQCONTEXT ((struct threadobj *)&threadobj_tskey)
181 
182 struct traceobj;
183 struct syncobj;
184 
185 struct threadobj {
186  unsigned int magic; /* Must be first. */
187  pthread_t ptid;
188  pthread_mutex_t lock;
189 
190  int schedlock_depth;
191  int cancel_state;
192  int status;
193  int run_state;
194  int policy;
195  struct sched_param_ex schedparam;
196  int global_priority;
197  pid_t cnode;
198  pid_t pid;
199  char name[32];
200 
201  void (*finalizer)(struct threadobj *thobj);
202  int core_offset;
203  int *errno_pointer;
204  /* Those members belong exclusively to the syncobj code. */
205  struct syncobj *wait_sobj;
206  struct holder wait_link;
207  int wait_status;
208  int wait_prio;
209  dref_type(void *) wait_union;
210  size_t wait_size;
211  timer_t periodic_timer;
212 
213  struct threadobj_corespec core;
214  struct timespec tslice;
215  pthread_cond_t barrier;
216  struct traceobj *tracer;
217  sem_t *cancel_sem;
218  struct sysgroup_memspec memspec;
219  struct backtrace_data btd;
220 };
221 
222 struct threadobj_init_data {
223  unsigned int magic;
224  cpu_set_t affinity;
225  int policy;
226  struct sched_param_ex param_ex;
227  void (*finalizer)(struct threadobj *thobj);
228 };
229 
230 extern int threadobj_high_prio;
231 
232 extern int threadobj_irq_prio;
233 
234 extern pthread_key_t threadobj_tskey;
235 
236 #ifdef HAVE_TLS
237 
238 extern __thread __attribute__ ((tls_model (CONFIG_XENO_TLS_MODEL)))
239 struct threadobj *__threadobj_current;
240 
241 static inline void threadobj_set_current(struct threadobj *thobj)
242 {
243  __threadobj_current = thobj;
244  pthread_setspecific(threadobj_tskey, thobj);
245 }
246 
247 static inline struct threadobj *__threadobj_get_current(void)
248 {
249  return __threadobj_current;
250 }
251 
252 #else /* !HAVE_TLS */
253 
254 static inline void threadobj_set_current(struct threadobj *thobj)
255 {
256  pthread_setspecific(threadobj_tskey, thobj);
257 }
258 
259 static inline struct threadobj *__threadobj_get_current(void)
260 {
261  return (struct threadobj *)pthread_getspecific(threadobj_tskey);
262 }
263 
264 #endif /* !HAVE_TLS */
265 
266 static inline struct threadobj *threadobj_current(void)
267 {
268  struct threadobj *thobj = __threadobj_get_current();
269  return thobj == NULL || thobj == THREADOBJ_IRQCONTEXT ? NULL : thobj;
270 }
271 
272 #ifdef CONFIG_XENO_DEBUG
273 
274 static inline void __threadobj_tag_locked(struct threadobj *thobj)
275 {
276  thobj->status |= __THREAD_S_LOCKED;
277 }
278 
279 static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
280 {
281  assert(thobj->status & __THREAD_S_LOCKED);
282  thobj->status &= ~__THREAD_S_LOCKED;
283 }
284 
285 static inline void __threadobj_check_locked(struct threadobj *thobj)
286 {
287  assert(thobj->status & __THREAD_S_LOCKED);
288 }
289 
290 #else /* !CONFIG_XENO_DEBUG */
291 
292 static inline void __threadobj_tag_locked(struct threadobj *thobj)
293 {
294 }
295 
296 static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
297 {
298 }
299 
300 static inline void __threadobj_check_locked(struct threadobj *thobj)
301 {
302 }
303 
304 #endif /* !CONFIG_XENO_DEBUG */
305 
306 #ifdef __cplusplus
307 extern "C" {
308 #endif
309 
310 void *__threadobj_alloc(size_t tcb_struct_size,
311  size_t wait_union_size,
312  int thobj_offset);
313 
314 static inline void __threadobj_free(void *p)
315 {
316  xnfree(p);
317 }
318 
319 static inline void threadobj_free(struct threadobj *thobj)
320 {
321  __threadobj_free((unsigned char *)thobj - thobj->core_offset);
322 }
323 
324 int threadobj_init(struct threadobj *thobj,
325  struct threadobj_init_data *idata) __must_check;
326 
327 int threadobj_start(struct threadobj *thobj) __must_check;
328 
329 int threadobj_shadow(struct threadobj *thobj,
330  const char *name);
331 
332 int threadobj_prologue(struct threadobj *thobj,
333  const char *name);
334 
335 void threadobj_wait_start(void);
336 
337 void threadobj_notify_entry(void);
338 
339 int threadobj_cancel(struct threadobj *thobj);
340 
341 void threadobj_uninit(struct threadobj *thobj);
342 
343 int threadobj_suspend(struct threadobj *thobj);
344 
345 int threadobj_resume(struct threadobj *thobj);
346 
347 int threadobj_unblock(struct threadobj *thobj);
348 
349 int __threadobj_lock_sched(struct threadobj *current);
350 
351 int threadobj_lock_sched(void);
352 
353 int __threadobj_unlock_sched(struct threadobj *current);
354 
355 int threadobj_unlock_sched(void);
356 
357 int threadobj_set_schedparam(struct threadobj *thobj, int policy,
358  const struct sched_param_ex *param_ex);
359 
360 int threadobj_set_schedprio(struct threadobj *thobj, int priority);
361 
362 int threadobj_set_mode(int clrmask, int setmask, int *mode_r);
363 
364 int threadobj_set_periodic(struct threadobj *thobj,
365  const struct timespec *__restrict__ idate,
366  const struct timespec *__restrict__ period);
367 
368 int threadobj_wait_period(unsigned long *overruns_r) __must_check;
369 
370 void threadobj_spin(ticks_t ns);
371 
372 int threadobj_stat(struct threadobj *thobj,
373  struct threadobj_stat *stat);
374 
375 int threadobj_sleep(const struct timespec *ts);
376 
377 void threadobj_set_current_name(const char *name);
378 
379 #ifdef CONFIG_XENO_PSHARED
380 
381 static inline int threadobj_local_p(struct threadobj *thobj)
382 {
383  extern pid_t __node_id;
384  return thobj->cnode == __node_id;
385 }
386 
387 #else /* !CONFIG_XENO_PSHARED */
388 
389 static inline int threadobj_local_p(struct threadobj *thobj)
390 {
391  return 1;
392 }
393 
394 #endif /* !CONFIG_XENO_PSHARED */
395 
396 void threadobj_init_key(void);
397 
398 int threadobj_pkg_init(int anon_session);
399 
400 #ifdef __cplusplus
401 }
402 #endif
403 
404 #define threadobj_alloc(T, __mptr, W) \
405  ({ \
406  void *__p; \
407  __p = __threadobj_alloc(sizeof(T), sizeof(W), offsetof(T, __mptr)); \
408  __p; \
409  })
410 
411 static inline int threadobj_get_policy(struct threadobj *thobj)
412 {
413  return thobj->policy;
414 }
415 
416 static inline int threadobj_get_priority(struct threadobj *thobj)
417 {
418  return thobj->schedparam.sched_priority;
419 }
420 
421 static inline void threadobj_copy_schedparam(struct sched_param_ex *param_ex,
422  const struct threadobj *thobj)
423 {
424  *param_ex = thobj->schedparam;
425 }
426 
427 static inline int threadobj_lock(struct threadobj *thobj)
428 {
429  int ret;
430 
431  ret = write_lock_safe(&thobj->lock, thobj->cancel_state);
432  if (ret)
433  return ret;
434 
435  __threadobj_tag_locked(thobj);
436 
437  return 0;
438 }
439 
440 static inline int threadobj_trylock(struct threadobj *thobj)
441 {
442  int ret;
443 
444  ret = write_trylock_safe(&thobj->lock, thobj->cancel_state);
445  if (ret)
446  return ret;
447 
448  __threadobj_tag_locked(thobj);
449 
450  return 0;
451 }
452 
453 static inline int threadobj_unlock(struct threadobj *thobj)
454 {
455  __threadobj_check_locked(thobj);
456  __threadobj_tag_unlocked(thobj);
457  return write_unlock_safe(&thobj->lock, thobj->cancel_state);
458 }
459 
460 static inline int threadobj_irq_p(void)
461 {
462  struct threadobj *current = __threadobj_get_current();
463  return current == THREADOBJ_IRQCONTEXT;
464 }
465 
466 static inline int threadobj_current_p(void)
467 {
468  return threadobj_current() != NULL;
469 }
470 
471 static inline int __threadobj_lock_sched_once(struct threadobj *current)
472 {
473  if (current->schedlock_depth == 0)
474  return __threadobj_lock_sched(current);
475 
476  return -EBUSY;
477 }
478 
479 static inline int threadobj_lock_sched_once(void)
480 {
481  struct threadobj *current = threadobj_current();
482 
483  if (current->schedlock_depth == 0)
484  return threadobj_lock_sched();
485 
486  return -EBUSY;
487 }
488 
489 static inline void threadobj_yield(void)
490 {
491  __RT(sched_yield());
492 }
493 
494 static inline unsigned int threadobj_get_magic(struct threadobj *thobj)
495 {
496  return thobj->magic;
497 }
498 
499 static inline void threadobj_set_magic(struct threadobj *thobj,
500  unsigned int magic)
501 {
502  thobj->magic = magic;
503 }
504 
505 static inline int threadobj_get_lockdepth(struct threadobj *thobj)
506 {
507  return thobj->schedlock_depth;
508 }
509 
510 static inline int threadobj_get_status(struct threadobj *thobj)
511 {
512  return thobj->status | thobj->run_state;
513 }
514 
515 static inline int threadobj_get_errno(struct threadobj *thobj)
516 {
517  return *thobj->errno_pointer;
518 }
519 
520 #define threadobj_prepare_wait(T) \
521  ({ \
522  struct threadobj *__thobj = threadobj_current(); \
523  assert(__thobj != NULL); \
524  assert(sizeof(typeof(T)) <= __thobj->wait_size); \
525  __mptr(__thobj->wait_union); \
526  })
527 
528 #define threadobj_finish_wait() do { } while (0)
529 
530 static inline void *threadobj_get_wait(struct threadobj *thobj)
531 {
532  return __mptr(thobj->wait_union);
533 }
534 
535 static inline const char *threadobj_get_name(struct threadobj *thobj)
536 {
537  return thobj->name;
538 }
539 
540 static inline pid_t threadobj_get_pid(struct threadobj *thobj)
541 {
542  return thobj->pid;
543 }
544 
545 #ifdef CONFIG_XENO_WORKAROUND_CONDVAR_PI
546 
547 int threadobj_cond_timedwait(pthread_cond_t *cond,
548  pthread_mutex_t *lock,
549  const struct timespec *timeout);
550 
551 int threadobj_cond_wait(pthread_cond_t *cond,
552  pthread_mutex_t *lock);
553 
554 int threadobj_cond_signal(pthread_cond_t *cond);
555 
556 int threadobj_cond_broadcast(pthread_cond_t *cond);
557 
558 #else
559 
560 static inline
561 int threadobj_cond_timedwait(pthread_cond_t *cond,
562  pthread_mutex_t *lock,
563  const struct timespec *timeout)
564 {
565  return __RT(pthread_cond_timedwait(cond, lock, timeout));
566 }
567 
568 static inline
569 int threadobj_cond_wait(pthread_cond_t *cond,
570  pthread_mutex_t *lock)
571 {
572  return __RT(pthread_cond_wait(cond, lock));
573 }
574 
575 static inline
576 int threadobj_cond_signal(pthread_cond_t *cond)
577 {
578  return __RT(pthread_cond_signal(cond));
579 }
580 
581 static inline
582 int threadobj_cond_broadcast(pthread_cond_t *cond)
583 {
584  return __RT(pthread_cond_broadcast(cond));
585 }
586 
587 #endif /* !CONFIG_XENO_WORKAROUND_CONDVAR_PI */
588 
589 #endif /* _COPPERPLATE_THREADOBJ_H */
int pthread_cond_signal(pthread_cond_t *cond)
Signal a condition variable.
Definition: cond.c:440
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Wait on a condition variable.
Definition: cond.c:277
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:367
int pthread_cond_broadcast(pthread_cond_t *cond)
Broadcast a condition variable.
Definition: cond.c:495
static int __attribute__((cold))
Test if a mutex structure contains a valid autoinitializer.
Definition: mutex.c:176
int sched_yield(void)
Yield the processor.
Definition: sched.c:57