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