Xenomai 3.3.2
Loading...
Searching...
No Matches
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
37struct xnthread_user_window;
38
39struct threadobj_corespec {
40 xnhandle_t handle;
41 union {
42 __u32 u_winoff;
43 struct xnthread_user_window *u_window;
44 };
45};
46
47struct 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
70static inline
71void 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
82static inline struct xnthread_user_window *
83threadobj_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
92static inline struct xnthread_user_window *
93threadobj_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
104struct 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
117struct 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
130static inline
131void 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
182struct traceobj;
183struct syncobj;
184
185struct 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
222struct 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
230extern int threadobj_high_prio;
231
232extern int threadobj_irq_prio;
233
234extern pthread_key_t threadobj_tskey;
235
236#ifdef HAVE_TLS
237
238extern __thread __attribute__ ((tls_model (CONFIG_XENO_TLS_MODEL)))
239struct threadobj *__threadobj_current;
240
241static inline void threadobj_set_current(struct threadobj *thobj)
242{
243 __threadobj_current = thobj;
244 pthread_setspecific(threadobj_tskey, thobj);
245}
246
247static inline struct threadobj *__threadobj_get_current(void)
248{
249 return __threadobj_current;
250}
251
252#else /* !HAVE_TLS */
253
254static inline void threadobj_set_current(struct threadobj *thobj)
255{
256 pthread_setspecific(threadobj_tskey, thobj);
257}
258
259static inline struct threadobj *__threadobj_get_current(void)
260{
261 return (struct threadobj *)pthread_getspecific(threadobj_tskey);
262}
263
264#endif /* !HAVE_TLS */
265
266static 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
274static inline void __threadobj_tag_locked(struct threadobj *thobj)
275{
276 thobj->status |= __THREAD_S_LOCKED;
277}
278
279static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
280{
281 assert(thobj->status & __THREAD_S_LOCKED);
282 thobj->status &= ~__THREAD_S_LOCKED;
283}
284
285static inline void __threadobj_check_locked(struct threadobj *thobj)
286{
287 assert(thobj->status & __THREAD_S_LOCKED);
288}
289
290#else /* !CONFIG_XENO_DEBUG */
291
292static inline void __threadobj_tag_locked(struct threadobj *thobj)
293{
294}
295
296static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
297{
298}
299
300static inline void __threadobj_check_locked(struct threadobj *thobj)
301{
302}
303
304#endif /* !CONFIG_XENO_DEBUG */
305
306#ifdef __cplusplus
307extern "C" {
308#endif
309
310void *__threadobj_alloc(size_t tcb_struct_size,
311 size_t wait_union_size,
312 int thobj_offset);
313
314static inline void __threadobj_free(void *p)
315{
316 xnfree(p);
317}
318
319static inline void threadobj_free(struct threadobj *thobj)
320{
321 __threadobj_free((unsigned char *)thobj - thobj->core_offset);
322}
323
324int threadobj_init(struct threadobj *thobj,
325 struct threadobj_init_data *idata) __must_check;
326
327int threadobj_start(struct threadobj *thobj) __must_check;
328
329int threadobj_shadow(struct threadobj *thobj,
330 const char *name);
331
332int threadobj_prologue(struct threadobj *thobj,
333 const char *name);
334
335void threadobj_wait_start(void);
336
337void threadobj_notify_entry(void);
338
339int threadobj_cancel(struct threadobj *thobj);
340
341void threadobj_uninit(struct threadobj *thobj);
342
343int threadobj_suspend(struct threadobj *thobj);
344
345int threadobj_resume(struct threadobj *thobj);
346
347int threadobj_unblock(struct threadobj *thobj);
348
349int __threadobj_lock_sched(struct threadobj *current);
350
351int threadobj_lock_sched(void);
352
353int __threadobj_unlock_sched(struct threadobj *current);
354
355int threadobj_unlock_sched(void);
356
357int threadobj_set_schedparam(struct threadobj *thobj, int policy,
358 const struct sched_param_ex *param_ex);
359
360int threadobj_set_schedprio(struct threadobj *thobj, int priority);
361
362int threadobj_set_mode(int clrmask, int setmask, int *mode_r);
363
364int threadobj_set_periodic(struct threadobj *thobj,
365 const struct timespec *__restrict__ idate,
366 const struct timespec *__restrict__ period);
367
368int threadobj_get_periodic(struct threadobj *thobj,
369 struct timespec *__restrict__ idate,
370 struct timespec *__restrict__ period);
371
372int threadobj_wait_period(unsigned long *overruns_r) __must_check;
373
374void threadobj_spin(ticks_t ns);
375
376int threadobj_stat(struct threadobj *thobj,
377 struct threadobj_stat *stat);
378
379int threadobj_sleep(const struct timespec *ts);
380
381void threadobj_set_current_name(const char *name);
382
383#ifdef CONFIG_XENO_PSHARED
384
385static inline int threadobj_local_p(struct threadobj *thobj)
386{
387 extern pid_t __node_id;
388 return thobj->cnode == __node_id;
389}
390
391#else /* !CONFIG_XENO_PSHARED */
392
393static inline int threadobj_local_p(struct threadobj *thobj)
394{
395 return 1;
396}
397
398#endif /* !CONFIG_XENO_PSHARED */
399
400void threadobj_init_key(void);
401
402int threadobj_pkg_init(int anon_session);
403
404#ifdef __cplusplus
405}
406#endif
407
408#define threadobj_alloc(T, __mptr, W) \
409 ({ \
410 void *__p; \
411 __p = __threadobj_alloc(sizeof(T), sizeof(W), offsetof(T, __mptr)); \
412 __p; \
413 })
414
415static inline int threadobj_get_policy(struct threadobj *thobj)
416{
417 return thobj->policy;
418}
419
420static inline int threadobj_get_priority(struct threadobj *thobj)
421{
422 return thobj->schedparam.sched_priority;
423}
424
425static inline void threadobj_copy_schedparam(struct sched_param_ex *param_ex,
426 const struct threadobj *thobj)
427{
428 *param_ex = thobj->schedparam;
429}
430
431static inline int threadobj_lock(struct threadobj *thobj)
432{
433 int ret;
434
435 ret = write_lock_safe(&thobj->lock, thobj->cancel_state);
436 if (ret)
437 return ret;
438
439 __threadobj_tag_locked(thobj);
440
441 return 0;
442}
443
444static inline int threadobj_trylock(struct threadobj *thobj)
445{
446 int ret;
447
448 ret = write_trylock_safe(&thobj->lock, thobj->cancel_state);
449 if (ret)
450 return ret;
451
452 __threadobj_tag_locked(thobj);
453
454 return 0;
455}
456
457static inline int threadobj_unlock(struct threadobj *thobj)
458{
459 __threadobj_check_locked(thobj);
460 __threadobj_tag_unlocked(thobj);
461 return write_unlock_safe(&thobj->lock, thobj->cancel_state);
462}
463
464static inline int threadobj_irq_p(void)
465{
466 struct threadobj *current = __threadobj_get_current();
467 return current == THREADOBJ_IRQCONTEXT;
468}
469
470static inline int threadobj_current_p(void)
471{
472 return threadobj_current() != NULL;
473}
474
475static inline int __threadobj_lock_sched_once(struct threadobj *current)
476{
477 if (current->schedlock_depth == 0)
478 return __threadobj_lock_sched(current);
479
480 return -EBUSY;
481}
482
483static inline int threadobj_lock_sched_once(void)
484{
485 struct threadobj *current = threadobj_current();
486
487 if (current->schedlock_depth == 0)
488 return threadobj_lock_sched();
489
490 return -EBUSY;
491}
492
493static inline void threadobj_yield(void)
494{
495 __RT(sched_yield());
496}
497
498static inline unsigned int threadobj_get_magic(struct threadobj *thobj)
499{
500 return thobj->magic;
501}
502
503static inline void threadobj_set_magic(struct threadobj *thobj,
504 unsigned int magic)
505{
506 thobj->magic = magic;
507}
508
509static inline int threadobj_get_lockdepth(struct threadobj *thobj)
510{
511 return thobj->schedlock_depth;
512}
513
514static inline int threadobj_get_status(struct threadobj *thobj)
515{
516 return thobj->status | thobj->run_state;
517}
518
519static inline int threadobj_get_errno(struct threadobj *thobj)
520{
521 return *thobj->errno_pointer;
522}
523
524#define threadobj_prepare_wait(T) \
525 ({ \
526 struct threadobj *__thobj = threadobj_current(); \
527 assert(__thobj != NULL); \
528 assert(sizeof(typeof(T)) <= __thobj->wait_size); \
529 __mptr(__thobj->wait_union); \
530 })
531
532#define threadobj_finish_wait() do { } while (0)
533
534static inline void *threadobj_get_wait(struct threadobj *thobj)
535{
536 return __mptr(thobj->wait_union);
537}
538
539static inline const char *threadobj_get_name(struct threadobj *thobj)
540{
541 return thobj->name;
542}
543
544static inline pid_t threadobj_get_pid(struct threadobj *thobj)
545{
546 return thobj->pid;
547}
548
549#ifdef CONFIG_XENO_WORKAROUND_CONDVAR_PI
550
551int threadobj_cond_timedwait(pthread_cond_t *cond,
552 pthread_mutex_t *lock,
553 const struct timespec *timeout);
554
555int threadobj_cond_wait(pthread_cond_t *cond,
556 pthread_mutex_t *lock);
557
558int threadobj_cond_signal(pthread_cond_t *cond);
559
560int threadobj_cond_broadcast(pthread_cond_t *cond);
561
562#else
563
564static inline
565int threadobj_cond_timedwait(pthread_cond_t *cond,
566 pthread_mutex_t *lock,
567 const struct timespec *timeout)
568{
569 return __RT(pthread_cond_timedwait(cond, lock, timeout));
570}
571
572static inline
573int threadobj_cond_wait(pthread_cond_t *cond,
574 pthread_mutex_t *lock)
575{
576 return __RT(pthread_cond_wait(cond, lock));
577}
578
579static inline
580int threadobj_cond_signal(pthread_cond_t *cond)
581{
582 return __RT(pthread_cond_signal(cond));
583}
584
585static inline
586int threadobj_cond_broadcast(pthread_cond_t *cond)
587{
588 return __RT(pthread_cond_broadcast(cond));
589}
590
591#endif /* !CONFIG_XENO_WORKAROUND_CONDVAR_PI */
592
593#endif /* _COPPERPLATE_THREADOBJ_H */
int pthread_cond_signal(pthread_cond_t *cond))
Signal a condition variable.
Definition cond.c:457
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex))
Wait on a condition variable.
Definition cond.c:297
int pthread_cond_broadcast(pthread_cond_t *cond))
Broadcast a condition variable.
Definition cond.c:512
int sched_yield(void))
Yield the processor.
Definition sched.c:52