diff options
author | deischen <deischen@FreeBSD.org> | 2003-08-05 22:46:00 +0000 |
---|---|---|
committer | deischen <deischen@FreeBSD.org> | 2003-08-05 22:46:00 +0000 |
commit | 73db9e759e57e01346011c961658790abf22719c (patch) | |
tree | 72d4a76c0fc38dbe53f86f2219914d854a838dbb /lib/libpthread/arch/i386/include/pthread_md.h | |
parent | e6b31b28140188d90a9dd49e4543af529f64843f (diff) | |
download | FreeBSD-src-73db9e759e57e01346011c961658790abf22719c.zip FreeBSD-src-73db9e759e57e01346011c961658790abf22719c.tar.gz |
Rethink the MD interfaces for libpthread to account for
archs that can (or are required to) have per-thread registers.
Tested on i386, amd64; marcel is testing on ia64 and will
have some follow-up commits.
Reviewed by: davidxu
Diffstat (limited to 'lib/libpthread/arch/i386/include/pthread_md.h')
-rw-r--r-- | lib/libpthread/arch/i386/include/pthread_md.h | 204 |
1 files changed, 185 insertions, 19 deletions
diff --git a/lib/libpthread/arch/i386/include/pthread_md.h b/lib/libpthread/arch/i386/include/pthread_md.h index 980680a..9718562 100644 --- a/lib/libpthread/arch/i386/include/pthread_md.h +++ b/lib/libpthread/arch/i386/include/pthread_md.h @@ -37,34 +37,193 @@ extern int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *); extern int _thr_getcontext(mcontext_t *); -#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext); -#define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, NULL, NULL); +#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext) +#define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL) -#define THR_ALIGNBYTES 15 -#define THR_ALIGN(td) (((unsigned)(td) + THR_ALIGNBYTES) & ~THR_ALIGNBYTES) +#define PER_KSE +#undef PER_THREAD + +struct kse; +struct pthread; +struct tdv; /* - * KSE Specific Data. + * %gs points to a struct kcb. */ -struct ksd { - int ldt; -#define KSDF_INITIALIZED 0x01 - long flags; - void *base; - long size; +struct kcb { + struct tcb *kcb_curtcb; + struct kcb *kcb_self; /* self reference */ + int kcb_ldt; + struct kse *kcb_kse; + struct kse_mailbox kcb_kmbx; +}; + +struct tcb { + struct tdv *tcb_tdv; + struct pthread *tcb_thread; + void *tcb_addr; /* allocated tcb address */ + void *tcb_spare; /* align tcb_tmbx to 16 bytes */ + struct kse_thr_mailbox tcb_tmbx; }; -extern void _i386_enter_uts(struct kse_mailbox *, kse_func_t, void *, long); +/* + * Evaluates to the byte offset of the per-kse variable name. + */ +#define __kcb_offset(name) __offsetof(struct kcb, name) + +/* + * Evaluates to the type of the per-kse variable name. + */ +#define __kcb_type(name) __typeof(((struct kcb *)0)->name) + +/* + * Evaluates to the value of the per-kse variable name. + */ +#define KCB_GET32(name) ({ \ + __kcb_type(name) __result; \ + \ + u_int __i; \ + __asm __volatile("movl %%gs:%1, %0" \ + : "=r" (__i) \ + : "m" (*(u_int *)(__kcb_offset(name)))); \ + __result = *(__kcb_type(name) *)&__i; \ + \ + __result; \ +}) + +/* + * Sets the value of the per-kse variable name to value val. + */ +#define KCB_SET32(name, val) ({ \ + __kcb_type(name) __val = (val); \ + \ + u_int __i; \ + __i = *(u_int *)&__val; \ + __asm __volatile("movl %1,%%gs:%0" \ + : "=m" (*(u_int *)(__kcb_offset(name))) \ + : "r" (__i)); \ +}) + +static __inline u_long +__kcb_readandclear32(volatile u_long *addr) +{ + u_long result; + + __asm __volatile ( + " xorl %0, %0;" + " xchgl %%gs:%1, %0;" + "# __kcb_readandclear32" + : "=&r" (result) + : "m" (*addr)); + return (result); +} + +#define KCB_READANDCLEAR32(name) ({ \ + __kcb_type(name) __result; \ + \ + __result = (__kcb_type(name)) \ + __kcb_readandclear32((u_long *)__kcb_offset(name)); \ + __result; \ +}) + + +#define _kcb_curkcb() KCB_GET32(kcb_self) +#define _kcb_curtcb() KCB_GET32(kcb_curtcb) +#define _kcb_curkse() ((struct kse *)KCB_GET32(kcb_kmbx.km_udata)) +#define _kcb_get_tmbx() KCB_GET32(kcb_kmbx.km_curthread) +#define _kcb_set_tmbx(value) KCB_SET32(kcb_kmbx.km_curthread, (void *)value) +#define _kcb_readandclear_tmbx() KCB_READANDCLEAR32(kcb_kmbx.km_curthread) + + +/* + * The constructors. + */ +struct tcb *_tcb_ctor(struct pthread *); +void _tcb_dtor(struct tcb *tcb); +struct kcb *_kcb_ctor(struct kse *); +void _kcb_dtor(struct kcb *); + +/* Called from the KSE to set its private data. */ +static __inline void +_kcb_set(struct kcb *kcb) +{ + int val; + + val = (kcb->kcb_ldt << 3) | 7; + __asm __volatile("movl %0, %%gs" : : "r" (val)); +} + +/* Get the current kcb. */ +static __inline struct kcb * +_kcb_get(void) +{ + return (_kcb_curkcb()); +} + +static __inline struct kse_thr_mailbox * +_kcb_critical_enter(void) +{ + struct kse_thr_mailbox *crit; + + crit = _kcb_readandclear_tmbx(); + return (crit); +} + +static __inline void +_kcb_critical_leave(struct kse_thr_mailbox *crit) +{ + _kcb_set_tmbx(crit); +} static __inline int -_thread_enter_uts(struct kse_thr_mailbox *tmbx, struct kse_mailbox *kmbx) +_kcb_in_critical(void) +{ + return (_kcb_get_tmbx() == NULL); +} + +static __inline void +_tcb_set(struct kcb *kcb, struct tcb *tcb) +{ + kcb->kcb_curtcb = tcb; +} + +static __inline struct tcb * +_tcb_get(void) +{ + return (_kcb_curtcb()); +} + +static __inline struct pthread * +_get_curthread(void) +{ + struct tcb *tcb; + + tcb = _kcb_curtcb(); + if (tcb != NULL) + return (tcb->tcb_thread); + else + return (NULL); +} + +static __inline struct kse * +_get_curkse(void) +{ + return ((struct kse *)_kcb_curkse()); +} + +void _i386_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack, + size_t stacksz); + +static __inline int +_thread_enter_uts(struct tcb *tcb, struct kcb *kcb) { int ret; - ret = _thr_getcontext(&tmbx->tm_context.uc_mcontext); + ret = _thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext); if (ret == 0) { - _i386_enter_uts(kmbx, kmbx->km_func, - kmbx->km_stack.ss_sp, kmbx->km_stack.ss_size); + _i386_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, + kcb->kcb_kmbx.km_stack.ss_sp, + kcb->kcb_kmbx.km_stack.ss_size); /* We should not reach here. */ return (-1); } @@ -74,10 +233,17 @@ _thread_enter_uts(struct kse_thr_mailbox *tmbx, struct kse_mailbox *kmbx) } static __inline int -_thread_switch(struct kse_thr_mailbox *tmbx, struct kse_thr_mailbox **loc) +_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) { - _thr_setcontext(&tmbx->tm_context.uc_mcontext, - (intptr_t)tmbx, (intptr_t *)loc); + if ((kcb == NULL) || (tcb == NULL)) + return (-1); + kcb->kcb_curtcb = tcb; + if (setmbox != 0) + _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, + (intptr_t)&tcb->tcb_tmbx, + (intptr_t *)&kcb->kcb_kmbx.km_curthread); + else + _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 0, NULL); /* We should not reach here. */ return (-1); } |