Xenomai  3.0-rc7
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 #include <copperplate/debug.h>
33 
34 #ifdef CONFIG_XENO_COBALT
35 
36 #include <cobalt/uapi/kernel/types.h>
37 
38 struct xnthread_user_window;
39 
40 struct threadobj_corespec {
41  xnhandle_t handle;
42  union {
43  __u32 u_winoff;
44  struct xnthread_user_window *u_window;
45  };
46 };
47 
48 struct threadobj_stat {
50  ticks_t xtime;
52  ticks_t timeout;
54  uint64_t msw;
56  uint64_t csw;
58  uint64_t xsc;
60  int cpu;
62  int schedlock;
64  unsigned int status;
66  uint32_t pf;
67 };
68 
69 #define SCHED_CORE SCHED_COBALT
70 
71 static inline
72 void threadobj_save_timeout(struct threadobj_corespec *corespec,
73  const struct timespec *timeout)
74 {
75  /*
76  * We retrieve this information from the nucleus directly via
77  * cobalt_thread_stat().
78  */
79 }
80 
81 #ifdef CONFIG_XENO_PSHARED
82 
83 static inline struct xnthread_user_window *
84 threadobj_get_window(struct threadobj_corespec *corespec)
85 {
86  extern void *cobalt_umm_shared;
87  return (struct xnthread_user_window *)
88  ((caddr_t)cobalt_umm_shared + corespec->u_winoff);
89 }
90 
91 #else /* !CONFIG_XENO_PSHARED */
92 
93 static inline struct xnthread_user_window *
94 threadobj_get_window(struct threadobj_corespec *corespec)
95 {
96  return corespec->u_window;
97 }
98 
99 #endif /* !CONFIG_XENO_PSHARED */
100 
101 #else /* CONFIG_XENO_MERCURY */
102 
103 #include <sys/time.h>
104 
105 struct threadobj_corespec {
106  pthread_cond_t grant_sync;
107  int policy_unlocked;
108  struct sched_param_ex schedparam_unlocked;
109  timer_t rr_timer;
111  struct timespec timeout;
112 #ifdef CONFIG_XENO_WORKAROUND_CONDVAR_PI
113  int policy_unboosted;
114  struct sched_param_ex schedparam_unboosted;
115 #endif
116 };
117 
118 struct threadobj_stat {
120  ticks_t timeout;
122  int cpu;
124  int schedlock;
126  unsigned int status;
127 };
128 
129 #define SCHED_CORE SCHED_FIFO
130 
131 static inline
132 void threadobj_save_timeout(struct threadobj_corespec *corespec,
133  const struct timespec *timeout)
134 {
135  if (timeout)
136  corespec->timeout = *timeout;
137 }
138 
139 #endif /* CONFIG_XENO_MERCURY */
140 
141 /*
142  * threadobj->status, updated with ->lock held.
143  */
144 #define __THREAD_S_STARTED (1 << 0) /* threadobj_start() called. */
145 #define __THREAD_S_WARMUP (1 << 1) /* threadobj_prologue() not called yet. */
146 #define __THREAD_S_ABORTED (1 << 2) /* Cancelled before start. */
147 #define __THREAD_S_LOCKED (1 << 3) /* threadobj_lock() granted (debug only). */
148 #define __THREAD_S_ACTIVE (1 << 4) /* Running user code. */
149 #define __THREAD_S_SUSPENDED (1 << 5) /* Suspended via threadobj_suspend(). */
150 #define __THREAD_S_SAFE (1 << 6) /* TCB release deferred. */
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 agent_memspec agent;
216  struct backtrace_data btd;
217 };
218 
219 struct threadobj_init_data {
220  unsigned int magic;
221  cpu_set_t affinity;
222  int policy;
223  struct sched_param_ex param_ex;
224  void (*finalizer)(struct threadobj *thobj);
225 };
226 
227 extern int threadobj_high_prio;
228 
229 extern int threadobj_irq_prio;
230 
231 extern pthread_key_t threadobj_tskey;
232 
233 #ifdef HAVE_TLS
234 
235 extern __thread __attribute__ ((tls_model (CONFIG_XENO_TLS_MODEL)))
236 struct threadobj *__threadobj_current;
237 
238 static inline void threadobj_set_current(struct threadobj *thobj)
239 {
240  __threadobj_current = thobj;
241  pthread_setspecific(threadobj_tskey, thobj);
242 }
243 
244 static inline struct threadobj *__threadobj_get_current(void)
245 {
246  return __threadobj_current;
247 }
248 
249 #else /* !HAVE_TLS */
250 
251 static inline void threadobj_set_current(struct threadobj *thobj)
252 {
253  pthread_setspecific(threadobj_tskey, thobj);
254 }
255 
256 static inline struct threadobj *__threadobj_get_current(void)
257 {
258  return (struct threadobj *)pthread_getspecific(threadobj_tskey);
259 }
260 
261 #endif /* !HAVE_TLS */
262 
263 static inline struct threadobj *threadobj_current(void)
264 {
265  struct threadobj *thobj = __threadobj_get_current();
266  return thobj == NULL || thobj == THREADOBJ_IRQCONTEXT ? NULL : thobj;
267 }
268 
269 #ifdef CONFIG_XENO_DEBUG
270 
271 static inline void __threadobj_tag_locked(struct threadobj *thobj)
272 {
273  thobj->status |= __THREAD_S_LOCKED;
274 }
275 
276 static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
277 {
278  assert(thobj->status & __THREAD_S_LOCKED);
279  thobj->status &= ~__THREAD_S_LOCKED;
280 }
281 
282 static inline void __threadobj_check_locked(struct threadobj *thobj)
283 {
284  assert(thobj->status & __THREAD_S_LOCKED);
285 }
286 
287 #else /* !CONFIG_XENO_DEBUG */
288 
289 static inline void __threadobj_tag_locked(struct threadobj *thobj)
290 {
291 }
292 
293 static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
294 {
295 }
296 
297 static inline void __threadobj_check_locked(struct threadobj *thobj)
298 {
299 }
300 
301 #endif /* !CONFIG_XENO_DEBUG */
302 
303 #ifdef __cplusplus
304 extern "C" {
305 #endif
306 
307 void *__threadobj_alloc(size_t tcb_struct_size,
308  size_t wait_union_size,
309  int thobj_offset);
310 
311 static inline void __threadobj_free(void *p)
312 {
313  xnfree(p);
314 }
315 
316 static inline void threadobj_free(struct threadobj *thobj)
317 {
318  __threadobj_free((unsigned char *)thobj - thobj->core_offset);
319 }
320 
321 int threadobj_init(struct threadobj *thobj,
322  struct threadobj_init_data *idata) __must_check;
323 
324 int threadobj_start(struct threadobj *thobj) __must_check;
325 
326 int threadobj_shadow(struct threadobj *thobj,
327  const char *name);
328 
329 int threadobj_prologue(struct threadobj *thobj,
330  const char *name);
331 
332 void threadobj_wait_start(void);
333 
334 void threadobj_notify_entry(void);
335 
336 int threadobj_cancel(struct threadobj *thobj);
337 
338 void threadobj_uninit(struct threadobj *thobj);
339 
340 int threadobj_suspend(struct threadobj *thobj);
341 
342 int threadobj_resume(struct threadobj *thobj);
343 
344 int threadobj_unblock(struct threadobj *thobj);
345 
346 int __threadobj_lock_sched(struct threadobj *current);
347 
348 int threadobj_lock_sched(void);
349 
350 int __threadobj_unlock_sched(struct threadobj *current);
351 
352 int threadobj_unlock_sched(void);
353 
354 int threadobj_set_schedparam(struct threadobj *thobj, int policy,
355  const struct sched_param_ex *param_ex);
356 
357 int threadobj_set_schedprio(struct threadobj *thobj, int priority);
358 
359 int threadobj_set_mode(int clrmask, int setmask, int *mode_r);
360 
361 int threadobj_set_periodic(struct threadobj *thobj,
362  const struct timespec *__restrict__ idate,
363  const struct timespec *__restrict__ period);
364 
365 int threadobj_wait_period(unsigned long *overruns_r) __must_check;
366 
367 void threadobj_spin(ticks_t ns);
368 
369 int threadobj_stat(struct threadobj *thobj,
370  struct threadobj_stat *stat);
371 
372 int threadobj_sleep(const struct timespec *ts);
373 
374 void threadobj_set_current_name(const char *name);
375 
376 #ifdef CONFIG_XENO_PSHARED
377 
378 static inline int threadobj_local_p(struct threadobj *thobj)
379 {
380  extern pid_t __node_id;
381  return thobj->cnode == __node_id;
382 }
383 
384 #else /* !CONFIG_XENO_PSHARED */
385 
386 static inline int threadobj_local_p(struct threadobj *thobj)
387 {
388  return 1;
389 }
390 
391 #endif /* !CONFIG_XENO_PSHARED */
392 
393 void threadobj_init_key(void);
394 
395 int threadobj_pkg_init(void);
396 
397 #ifdef __cplusplus
398 }
399 #endif
400 
401 #define threadobj_alloc(T, __mptr, W) \
402  ({ \
403  void *__p; \
404  __p = __threadobj_alloc(sizeof(T), sizeof(W), offsetof(T, __mptr)); \
405  __p; \
406  })
407 
408 static inline int threadobj_get_policy(struct threadobj *thobj)
409 {
410  return thobj->policy;
411 }
412 
413 static inline int threadobj_get_priority(struct threadobj *thobj)
414 {
415  return thobj->schedparam.sched_priority;
416 }
417 
418 static inline void threadobj_copy_schedparam(struct sched_param_ex *param_ex,
419  const struct threadobj *thobj)
420 {
421  *param_ex = thobj->schedparam;
422 }
423 
424 static inline int threadobj_lock(struct threadobj *thobj)
425 {
426  int ret;
427 
428  ret = write_lock_safe(&thobj->lock, thobj->cancel_state);
429  if (ret)
430  return ret;
431 
432  __threadobj_tag_locked(thobj);
433 
434  return 0;
435 }
436 
437 static inline int threadobj_trylock(struct threadobj *thobj)
438 {
439  int ret;
440 
441  ret = write_trylock_safe(&thobj->lock, thobj->cancel_state);
442  if (ret)
443  return ret;
444 
445  __threadobj_tag_locked(thobj);
446 
447  return 0;
448 }
449 
450 static inline int threadobj_unlock(struct threadobj *thobj)
451 {
452  __threadobj_check_locked(thobj);
453  __threadobj_tag_unlocked(thobj);
454  return write_unlock_safe(&thobj->lock, thobj->cancel_state);
455 }
456 
457 static inline int threadobj_irq_p(void)
458 {
459  struct threadobj *current = __threadobj_get_current();
460  return current == THREADOBJ_IRQCONTEXT;
461 }
462 
463 static inline int threadobj_current_p(void)
464 {
465  return threadobj_current() != NULL;
466 }
467 
468 static inline int __threadobj_lock_sched_once(struct threadobj *current)
469 {
470  if (current->schedlock_depth == 0)
471  return __threadobj_lock_sched(current);
472 
473  return -EBUSY;
474 }
475 
476 static inline int threadobj_lock_sched_once(void)
477 {
478  struct threadobj *current = threadobj_current();
479 
480  if (current->schedlock_depth == 0)
481  return threadobj_lock_sched();
482 
483  return -EBUSY;
484 }
485 
486 static inline void threadobj_yield(void)
487 {
488  __RT(sched_yield());
489 }
490 
491 static inline unsigned int threadobj_get_magic(struct threadobj *thobj)
492 {
493  return thobj->magic;
494 }
495 
496 static inline void threadobj_set_magic(struct threadobj *thobj,
497  unsigned int magic)
498 {
499  thobj->magic = magic;
500 }
501 
502 static inline int threadobj_get_lockdepth(struct threadobj *thobj)
503 {
504  return thobj->schedlock_depth;
505 }
506 
507 static inline int threadobj_get_status(struct threadobj *thobj)
508 {
509  return thobj->status | thobj->run_state;
510 }
511 
512 static inline int threadobj_get_errno(struct threadobj *thobj)
513 {
514  return *thobj->errno_pointer;
515 }
516 
517 #define threadobj_prepare_wait(T) \
518  ({ \
519  struct threadobj *__thobj = threadobj_current(); \
520  assert(__thobj != NULL); \
521  assert(sizeof(typeof(T)) <= __thobj->wait_size); \
522  __mptr(__thobj->wait_union); \
523  })
524 
525 #define threadobj_finish_wait() do { } while (0)
526 
527 static inline void *threadobj_get_wait(struct threadobj *thobj)
528 {
529  return __mptr(thobj->wait_union);
530 }
531 
532 static inline const char *threadobj_get_name(struct threadobj *thobj)
533 {
534  return thobj->name;
535 }
536 
537 static inline pid_t threadobj_get_pid(struct threadobj *thobj)
538 {
539  return thobj->pid;
540 }
541 
542 #ifdef CONFIG_XENO_WORKAROUND_CONDVAR_PI
543 
544 int threadobj_cond_timedwait(pthread_cond_t *cond,
545  pthread_mutex_t *lock,
546  const struct timespec *timeout);
547 
548 int threadobj_cond_wait(pthread_cond_t *cond,
549  pthread_mutex_t *lock);
550 
551 int threadobj_cond_signal(pthread_cond_t *cond);
552 
553 int threadobj_cond_broadcast(pthread_cond_t *cond);
554 
555 #else
556 
557 static inline
558 int threadobj_cond_timedwait(pthread_cond_t *cond,
559  pthread_mutex_t *lock,
560  const struct timespec *timeout)
561 {
562  return __RT(pthread_cond_timedwait(cond, lock, timeout));
563 }
564 
565 static inline
566 int threadobj_cond_wait(pthread_cond_t *cond,
567  pthread_mutex_t *lock)
568 {
569  return __RT(pthread_cond_wait(cond, lock));
570 }
571 
572 static inline
573 int threadobj_cond_signal(pthread_cond_t *cond)
574 {
575  return __RT(pthread_cond_signal(cond));
576 }
577 
578 static inline
579 int threadobj_cond_broadcast(pthread_cond_t *cond)
580 {
581  return __RT(pthread_cond_broadcast(cond));
582 }
583 
584 #endif /* !CONFIG_XENO_WORKAROUND_CONDVAR_PI */
585 
586 #endif /* _COPPERPLATE_THREADOBJ_H */
int pthread_cond_signal(pthread_cond_t *cond)
Signal a condition variable.
Definition: cond.c:423
int pthread_cond_broadcast(pthread_cond_t *cond)
Broadcast a condition variable.
Definition: cond.c:483
int sched_yield(void)
Yield the processor.
Definition: thread.c:800
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Wait on a condition variable.
Definition: cond.c:250
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:345