| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593 |
- /*
- * Copyright (C) 2008 Philippe Gerum <rpm@xenomai.org>.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
- #ifndef _COPPERPLATE_THREADOBJ_H
- #define _COPPERPLATE_THREADOBJ_H
- #include <time.h>
- #include <semaphore.h>
- #include <signal.h>
- #include <pthread.h>
- #include <stdint.h>
- #include <boilerplate/list.h>
- #include <boilerplate/lock.h>
- #include <boilerplate/sched.h>
- #include <copperplate/clockobj.h>
- #include <copperplate/heapobj.h>
- #ifdef CONFIG_XENO_COBALT
- #include <cobalt/uapi/kernel/types.h>
- struct xnthread_user_window;
- struct threadobj_corespec {
- xnhandle_t handle;
- union {
- __u32 u_winoff;
- struct xnthread_user_window *u_window;
- };
- };
- struct threadobj_stat {
- /** Execution time in primary mode (ns). */
- ticks_t xtime;
- /** Current timeout value (ns). */
- ticks_t timeout;
- /** Number of primary->secondary mode switches. */
- uint64_t msw;
- /** Number of context switches. */
- uint64_t csw;
- /** Number of Xenomai syscalls. */
- uint64_t xsc;
- /** Current CPU for thread. */
- int cpu;
- /** Scheduler lock nesting count. */
- int schedlock;
- /** Cobalt thread status bits. */
- unsigned int status;
- /** Number of page faults. */
- uint32_t pf;
- };
- #define SCHED_CORE SCHED_COBALT
- static inline
- void threadobj_save_timeout(struct threadobj_corespec *corespec,
- const struct timespec *timeout)
- {
- /*
- * We retrieve this information from the nucleus directly via
- * cobalt_thread_stat().
- */
- }
- #ifdef CONFIG_XENO_PSHARED
- static inline struct xnthread_user_window *
- threadobj_get_window(struct threadobj_corespec *corespec)
- {
- extern void *cobalt_umm_shared;
- return (struct xnthread_user_window *)
- ((caddr_t)cobalt_umm_shared + corespec->u_winoff);
- }
- #else /* !CONFIG_XENO_PSHARED */
- static inline struct xnthread_user_window *
- threadobj_get_window(struct threadobj_corespec *corespec)
- {
- return corespec->u_window;
- }
- #endif /* !CONFIG_XENO_PSHARED */
- #else /* CONFIG_XENO_MERCURY */
- #include <sys/time.h>
- struct threadobj_corespec {
- pthread_cond_t grant_sync;
- int policy_unlocked;
- struct sched_param_ex schedparam_unlocked;
- timer_t rr_timer;
- /** Timeout reported by sysregd. */
- struct timespec timeout;
- #ifdef CONFIG_XENO_WORKAROUND_CONDVAR_PI
- int policy_unboosted;
- struct sched_param_ex schedparam_unboosted;
- #endif
- };
- struct threadobj_stat {
- /** Current timeout value (ns). */
- ticks_t timeout;
- /** Current CPU for thread. */
- int cpu;
- /** Scheduler lock nesting count. */
- int schedlock;
- /** Mercury thread status bits. */
- unsigned int status;
- };
- #define SCHED_CORE SCHED_FIFO
- static inline
- void threadobj_save_timeout(struct threadobj_corespec *corespec,
- const struct timespec *timeout)
- {
- if (timeout)
- corespec->timeout = *timeout;
- }
- #endif /* CONFIG_XENO_MERCURY */
- /*
- * threadobj->status, updated with ->lock held.
- */
- #define __THREAD_S_STARTED (1 << 0) /* threadobj_start() called. */
- #define __THREAD_S_WARMUP (1 << 1) /* threadobj_prologue() not called yet. */
- #define __THREAD_S_ABORTED (1 << 2) /* Cancelled before start. */
- #define __THREAD_S_LOCKED (1 << 3) /* threadobj_lock() granted (debug only). */
- #define __THREAD_S_ACTIVE (1 << 4) /* Running user code. */
- #define __THREAD_S_SUSPENDED (1 << 5) /* Suspended via threadobj_suspend(). */
- #define __THREAD_S_SAFE (1 << 6) /* TCB release deferred. */
- #define __THREAD_S_PERIODIC (1 << 7) /* Periodic timer set. */
- #define __THREAD_S_DEBUG (1 << 31) /* Debug mode enabled. */
- /*
- * threadobj->run_state, locklessly updated by "current", merged
- * with ->status bits by threadobj_get_status().
- */
- #define __THREAD_S_RUNNING 0
- #define __THREAD_S_DORMANT (1 << 16)
- #define __THREAD_S_WAIT (1 << 17)
- #define __THREAD_S_TIMEDWAIT (1 << 18)
- #define __THREAD_S_DELAYED (1 << 19)
- #define __THREAD_S_BREAK (__THREAD_S_DELAYED|(1 << 20))
- /* threadobj mode bits */
- #define __THREAD_M_LOCK (1 << 0) /* Toggle scheduler lock. */
- #define __THREAD_M_WARNSW (1 << 1) /* Toggle switch warning bit. */
- #define __THREAD_M_CONFORMING (1 << 2) /* Switch to conforming mode. */
- #define __THREAD_M_SPARE0 (1 << 16)
- #define __THREAD_M_SPARE1 (1 << 17)
- #define __THREAD_M_SPARE2 (1 << 18)
- #define __THREAD_M_SPARE3 (1 << 19)
- #define __THREAD_M_SPARE4 (1 << 20)
- #define __THREAD_M_SPARE5 (1 << 21)
- #define __THREAD_M_SPARE6 (1 << 22)
- #define __THREAD_M_SPARE7 (1 << 23)
- /*
- * We need to use a valid address here. The object will never be dereferenced
- * when it is identified as IRQ context, so the pthread key itself is fine.
- */
- #define THREADOBJ_IRQCONTEXT ((struct threadobj *)&threadobj_tskey)
- struct traceobj;
- struct syncobj;
- struct threadobj {
- unsigned int magic; /* Must be first. */
- pthread_t ptid;
- pthread_mutex_t lock;
- int schedlock_depth;
- int cancel_state;
- int status;
- int run_state;
- int policy;
- struct sched_param_ex schedparam;
- int global_priority;
- pid_t cnode;
- pid_t pid;
- char name[32];
- void (*finalizer)(struct threadobj *thobj);
- int core_offset;
- int *errno_pointer;
- /* Those members belong exclusively to the syncobj code. */
- struct syncobj *wait_sobj;
- struct holder wait_link;
- int wait_status;
- int wait_prio;
- dref_type(void *) wait_union;
- size_t wait_size;
- timer_t periodic_timer;
- struct threadobj_corespec core;
- struct timespec tslice;
- pthread_cond_t barrier;
- struct traceobj *tracer;
- sem_t *cancel_sem;
- struct sysgroup_memspec memspec;
- struct backtrace_data btd;
- };
- struct threadobj_init_data {
- unsigned int magic;
- cpu_set_t affinity;
- int policy;
- struct sched_param_ex param_ex;
- void (*finalizer)(struct threadobj *thobj);
- };
- extern int threadobj_high_prio;
- extern int threadobj_irq_prio;
- extern pthread_key_t threadobj_tskey;
- #ifdef HAVE_TLS
- extern __thread __attribute__ ((tls_model (CONFIG_XENO_TLS_MODEL)))
- struct threadobj *__threadobj_current;
- static inline void threadobj_set_current(struct threadobj *thobj)
- {
- __threadobj_current = thobj;
- pthread_setspecific(threadobj_tskey, thobj);
- }
- static inline struct threadobj *__threadobj_get_current(void)
- {
- return __threadobj_current;
- }
- #else /* !HAVE_TLS */
- static inline void threadobj_set_current(struct threadobj *thobj)
- {
- pthread_setspecific(threadobj_tskey, thobj);
- }
- static inline struct threadobj *__threadobj_get_current(void)
- {
- return (struct threadobj *)pthread_getspecific(threadobj_tskey);
- }
- #endif /* !HAVE_TLS */
- static inline struct threadobj *threadobj_current(void)
- {
- struct threadobj *thobj = __threadobj_get_current();
- return thobj == NULL || thobj == THREADOBJ_IRQCONTEXT ? NULL : thobj;
- }
- #ifdef CONFIG_XENO_DEBUG
- static inline void __threadobj_tag_locked(struct threadobj *thobj)
- {
- thobj->status |= __THREAD_S_LOCKED;
- }
- static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
- {
- assert(thobj->status & __THREAD_S_LOCKED);
- thobj->status &= ~__THREAD_S_LOCKED;
- }
- static inline void __threadobj_check_locked(struct threadobj *thobj)
- {
- assert(thobj->status & __THREAD_S_LOCKED);
- }
- #else /* !CONFIG_XENO_DEBUG */
- static inline void __threadobj_tag_locked(struct threadobj *thobj)
- {
- }
- static inline void __threadobj_tag_unlocked(struct threadobj *thobj)
- {
- }
- static inline void __threadobj_check_locked(struct threadobj *thobj)
- {
- }
- #endif /* !CONFIG_XENO_DEBUG */
- #ifdef __cplusplus
- extern "C" {
- #endif
- void *__threadobj_alloc(size_t tcb_struct_size,
- size_t wait_union_size,
- int thobj_offset);
- static inline void __threadobj_free(void *p)
- {
- xnfree(p);
- }
- static inline void threadobj_free(struct threadobj *thobj)
- {
- __threadobj_free((unsigned char *)thobj - thobj->core_offset);
- }
- int threadobj_init(struct threadobj *thobj,
- struct threadobj_init_data *idata) __must_check;
- int threadobj_start(struct threadobj *thobj) __must_check;
- int threadobj_shadow(struct threadobj *thobj,
- const char *name);
- int threadobj_prologue(struct threadobj *thobj,
- const char *name);
- void threadobj_wait_start(void);
- void threadobj_notify_entry(void);
- int threadobj_cancel(struct threadobj *thobj);
- void threadobj_uninit(struct threadobj *thobj);
- int threadobj_suspend(struct threadobj *thobj);
- int threadobj_resume(struct threadobj *thobj);
- int threadobj_unblock(struct threadobj *thobj);
- int __threadobj_lock_sched(struct threadobj *current);
- int threadobj_lock_sched(void);
- int __threadobj_unlock_sched(struct threadobj *current);
- int threadobj_unlock_sched(void);
- int threadobj_set_schedparam(struct threadobj *thobj, int policy,
- const struct sched_param_ex *param_ex);
- int threadobj_set_schedprio(struct threadobj *thobj, int priority);
- int threadobj_set_mode(int clrmask, int setmask, int *mode_r);
- int threadobj_set_periodic(struct threadobj *thobj,
- const struct timespec *__restrict__ idate,
- const struct timespec *__restrict__ period);
- int threadobj_get_periodic(struct threadobj *thobj,
- struct timespec *__restrict__ idate,
- struct timespec *__restrict__ period);
- int threadobj_wait_period(unsigned long *overruns_r) __must_check;
- void threadobj_spin(ticks_t ns);
- int threadobj_stat(struct threadobj *thobj,
- struct threadobj_stat *stat);
- int threadobj_sleep(const struct timespec *ts);
- void threadobj_set_current_name(const char *name);
- #ifdef CONFIG_XENO_PSHARED
- static inline int threadobj_local_p(struct threadobj *thobj)
- {
- extern pid_t __node_id;
- return thobj->cnode == __node_id;
- }
- #else /* !CONFIG_XENO_PSHARED */
- static inline int threadobj_local_p(struct threadobj *thobj)
- {
- return 1;
- }
- #endif /* !CONFIG_XENO_PSHARED */
- void threadobj_init_key(void);
- int threadobj_pkg_init(int anon_session);
- #ifdef __cplusplus
- }
- #endif
- #define threadobj_alloc(T, __mptr, W) \
- ({ \
- void *__p; \
- __p = __threadobj_alloc(sizeof(T), sizeof(W), offsetof(T, __mptr)); \
- __p; \
- })
- static inline int threadobj_get_policy(struct threadobj *thobj)
- {
- return thobj->policy;
- }
- static inline int threadobj_get_priority(struct threadobj *thobj)
- {
- return thobj->schedparam.sched_priority;
- }
- static inline void threadobj_copy_schedparam(struct sched_param_ex *param_ex,
- const struct threadobj *thobj)
- {
- *param_ex = thobj->schedparam;
- }
- static inline int threadobj_lock(struct threadobj *thobj)
- {
- int ret;
- ret = write_lock_safe(&thobj->lock, thobj->cancel_state);
- if (ret)
- return ret;
- __threadobj_tag_locked(thobj);
- return 0;
- }
- static inline int threadobj_trylock(struct threadobj *thobj)
- {
- int ret;
- ret = write_trylock_safe(&thobj->lock, thobj->cancel_state);
- if (ret)
- return ret;
- __threadobj_tag_locked(thobj);
- return 0;
- }
- static inline int threadobj_unlock(struct threadobj *thobj)
- {
- __threadobj_check_locked(thobj);
- __threadobj_tag_unlocked(thobj);
- return write_unlock_safe(&thobj->lock, thobj->cancel_state);
- }
- static inline int threadobj_irq_p(void)
- {
- struct threadobj *current = __threadobj_get_current();
- return current == THREADOBJ_IRQCONTEXT;
- }
- static inline int threadobj_current_p(void)
- {
- return threadobj_current() != NULL;
- }
- static inline int __threadobj_lock_sched_once(struct threadobj *current)
- {
- if (current->schedlock_depth == 0)
- return __threadobj_lock_sched(current);
- return -EBUSY;
- }
- static inline int threadobj_lock_sched_once(void)
- {
- struct threadobj *current = threadobj_current();
- if (current->schedlock_depth == 0)
- return threadobj_lock_sched();
- return -EBUSY;
- }
- static inline void threadobj_yield(void)
- {
- __RT(sched_yield());
- }
- static inline unsigned int threadobj_get_magic(struct threadobj *thobj)
- {
- return thobj->magic;
- }
- static inline void threadobj_set_magic(struct threadobj *thobj,
- unsigned int magic)
- {
- thobj->magic = magic;
- }
- static inline int threadobj_get_lockdepth(struct threadobj *thobj)
- {
- return thobj->schedlock_depth;
- }
- static inline int threadobj_get_status(struct threadobj *thobj)
- {
- return thobj->status | thobj->run_state;
- }
- static inline int threadobj_get_errno(struct threadobj *thobj)
- {
- return *thobj->errno_pointer;
- }
- #define threadobj_prepare_wait(T) \
- ({ \
- struct threadobj *__thobj = threadobj_current(); \
- assert(__thobj != NULL); \
- assert(sizeof(typeof(T)) <= __thobj->wait_size); \
- __mptr(__thobj->wait_union); \
- })
- #define threadobj_finish_wait() do { } while (0)
- static inline void *threadobj_get_wait(struct threadobj *thobj)
- {
- return __mptr(thobj->wait_union);
- }
- static inline const char *threadobj_get_name(struct threadobj *thobj)
- {
- return thobj->name;
- }
- static inline pid_t threadobj_get_pid(struct threadobj *thobj)
- {
- return thobj->pid;
- }
- #ifdef CONFIG_XENO_WORKAROUND_CONDVAR_PI
- int threadobj_cond_timedwait(pthread_cond_t *cond,
- pthread_mutex_t *lock,
- const struct timespec *timeout);
- int threadobj_cond_wait(pthread_cond_t *cond,
- pthread_mutex_t *lock);
- int threadobj_cond_signal(pthread_cond_t *cond);
- int threadobj_cond_broadcast(pthread_cond_t *cond);
- #else
- static inline
- int threadobj_cond_timedwait(pthread_cond_t *cond,
- pthread_mutex_t *lock,
- const struct timespec *timeout)
- {
- return __RT(pthread_cond_timedwait(cond, lock, timeout));
- }
- static inline
- int threadobj_cond_wait(pthread_cond_t *cond,
- pthread_mutex_t *lock)
- {
- return __RT(pthread_cond_wait(cond, lock));
- }
- static inline
- int threadobj_cond_signal(pthread_cond_t *cond)
- {
- return __RT(pthread_cond_signal(cond));
- }
- static inline
- int threadobj_cond_broadcast(pthread_cond_t *cond)
- {
- return __RT(pthread_cond_broadcast(cond));
- }
- #endif /* !CONFIG_XENO_WORKAROUND_CONDVAR_PI */
- #endif /* _COPPERPLATE_THREADOBJ_H */
|