diff options
| author | Marcel Moolenaar <marcel@FreeBSD.org> | 2006-09-02 19:41:21 +0000 |
|---|---|---|
| committer | Marcel Moolenaar <marcel@FreeBSD.org> | 2006-09-02 19:41:21 +0000 |
| commit | 7f17908103490007d6f1eec234adff7a6fad56b1 (patch) | |
| tree | 20a48ab00033bbc0c88d5486ce15cd8f0331ca85 /lib | |
| parent | efc075fdfc1af3e4160c7f3f6997a0d336098afd (diff) | |
Notes
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libpthread/arch/ia64/ia64/pthread_md.c | 33 | ||||
| -rw-r--r-- | lib/libpthread/arch/ia64/include/pthread_md.h | 90 | ||||
| -rw-r--r-- | lib/libpthread/arch/powerpc/include/pthread_md.h | 100 | ||||
| -rw-r--r-- | lib/libpthread/arch/powerpc/powerpc/pthread_md.c | 31 |
4 files changed, 156 insertions, 98 deletions
diff --git a/lib/libpthread/arch/ia64/ia64/pthread_md.c b/lib/libpthread/arch/ia64/ia64/pthread_md.c index 00e9a40fe5df..dc59b0e87f8f 100644 --- a/lib/libpthread/arch/ia64/ia64/pthread_md.c +++ b/lib/libpthread/arch/ia64/ia64/pthread_md.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org> + * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,6 +29,8 @@ #include <stdlib.h> #include <strings.h> + +#include "rtld_tls.h" #include "pthread_md.h" /* @@ -36,21 +39,22 @@ struct tcb * _tcb_ctor(struct pthread *thread, int initial) { + register char *tp __asm("%r13"); struct tcb *tcb; - if ((tcb = malloc(sizeof(struct tcb))) != NULL) { - bzero(tcb, sizeof(struct tcb)); - tcb->tcb_thread = thread; - /* Allocate TDV */ - } + tcb = _rtld_allocate_tls((initial) ? tp : NULL, + sizeof(struct tcb), 16); + if (tcb == NULL) + return (NULL); + tcb->tcb_thread = thread; return (tcb); } void _tcb_dtor(struct tcb *tcb) { - /* Free TDV */ - free(tcb); + + _rtld_free_tls(tcb, sizeof(struct tcb), 16); } struct kcb * @@ -58,13 +62,14 @@ _kcb_ctor(struct kse *kse) { struct kcb *kcb; - if ((kcb = malloc(sizeof(struct kcb))) != NULL) { - bzero(kcb, sizeof(struct kcb)); - kcb->kcb_faketcb.tcb_isfake = 1; - kcb->kcb_faketcb.tcb_tmbx.tm_flags = TMF_NOUPCALL; - kcb->kcb_curtcb = &kcb->kcb_faketcb; - kcb->kcb_kse = kse; - } + kcb = malloc(sizeof(struct kcb)); + if (kcb == NULL) + return (NULL); + bzero(kcb, sizeof(struct kcb)); + kcb->kcb_kse = kse; + kcb->kcb_faketcb.tcb_isfake = 1; + kcb->kcb_faketcb.tcb_tmbx.tm_flags = TMF_NOUPCALL; + kcb->kcb_curtcb = &kcb->kcb_faketcb; return (kcb); } diff --git a/lib/libpthread/arch/ia64/include/pthread_md.h b/lib/libpthread/arch/ia64/include/pthread_md.h index 1df5046287f2..c5fef187f584 100644 --- a/lib/libpthread/arch/ia64/include/pthread_md.h +++ b/lib/libpthread/arch/ia64/include/pthread_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2003-2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,7 +34,7 @@ #include <ucontext.h> #define KSE_STACKSIZE 16384 -#define DTV_OFFSET offsetof(struct tcb, tcb_tp.tp_tdv) +#define DTV_OFFSET offsetof(struct tcb, tcb_tp.tp_dtv) #define THR_GETCONTEXT(ucp) _ia64_save_context(&(ucp)->uc_mcontext) #define THR_SETCONTEXT(ucp) PANIC("THR_SETCONTEXT() now in use!\n") @@ -45,19 +45,16 @@ struct kcb; struct kse; struct pthread; struct tcb; -struct tdv; /* We don't know what this is yet? */ /* - * tp points to one of these. We define the static TLS as an array - * of long double to enforce 16-byte alignment of the TLS memory, - * struct ia64_tp, struct tcb and also struct kcb. Both static and - * dynamic allocation of any of these structures will result in a - * valid, well-aligned thread pointer. + * tp points to one of these. We define the TLS structure as a union + * containing a long double to enforce 16-byte alignment. This makes + * sure that there will not be any padding in struct tcb after the + * TLS structure. */ -struct ia64_tp { - struct tdv *tp_tdv; /* dynamic TLS */ - uint64_t _reserved_; - long double tp_tls[0]; /* static TLS */ +union ia64_tp { + void *tp_dtv; + long double _align_; }; struct tcb { @@ -65,19 +62,31 @@ struct tcb { struct pthread *tcb_thread; struct kcb *tcb_curkcb; long tcb_isfake; - struct ia64_tp tcb_tp; + union ia64_tp tcb_tp; }; struct kcb { struct kse_mailbox kcb_kmbx; - struct tcb kcb_faketcb; - struct tcb *kcb_curtcb; struct kse *kcb_kse; + struct tcb *kcb_curtcb; + struct tcb kcb_faketcb; }; -register struct ia64_tp *_tp __asm("%r13"); +static __inline struct tcb * +ia64_get_tcb() +{ + register char *tp __asm("%r13"); -#define _tcb ((struct tcb*)((char*)(_tp) - offsetof(struct tcb, tcb_tp))) + return ((struct tcb *)(tp - offsetof(struct tcb, tcb_tp))); +} + +static __inline void +ia64_set_tcb(struct tcb *tcb) +{ + register char *tp __asm("%r13"); + + __asm __volatile("mov %0 = %1;;" : "=r"(tp) : "r"(&tcb->tcb_tp)); +} /* * The kcb and tcb constructors. @@ -92,7 +101,7 @@ static __inline void _kcb_set(struct kcb *kcb) { /* There is no thread yet; use the fake tcb. */ - _tp = &kcb->kcb_faketcb.tcb_tp; + ia64_set_tcb(&kcb->kcb_faketcb); } /* @@ -104,7 +113,7 @@ _kcb_set(struct kcb *kcb) static __inline struct kcb * _kcb_get(void) { - return (_tcb->tcb_curkcb); + return (ia64_get_tcb()->tcb_curkcb); } /* @@ -115,21 +124,23 @@ _kcb_get(void) static __inline struct kse_thr_mailbox * _kcb_critical_enter(void) { + struct tcb *tcb; struct kse_thr_mailbox *crit; uint32_t flags; - if (_tcb->tcb_isfake != 0) { + tcb = ia64_get_tcb(); + if (tcb->tcb_isfake != 0) { /* * We already are in a critical region since * there is no current thread. */ crit = NULL; } else { - flags = _tcb->tcb_tmbx.tm_flags; - _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; - crit = _tcb->tcb_curkcb->kcb_kmbx.km_curthread; - _tcb->tcb_curkcb->kcb_kmbx.km_curthread = NULL; - _tcb->tcb_tmbx.tm_flags = flags; + flags = tcb->tcb_tmbx.tm_flags; + tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; + crit = tcb->tcb_curkcb->kcb_kmbx.km_curthread; + tcb->tcb_curkcb->kcb_kmbx.km_curthread = NULL; + tcb->tcb_tmbx.tm_flags = flags; } return (crit); } @@ -137,28 +148,33 @@ _kcb_critical_enter(void) static __inline void _kcb_critical_leave(struct kse_thr_mailbox *crit) { + struct tcb *tcb; + + tcb = ia64_get_tcb(); /* No need to do anything if this is a fake tcb. */ - if (_tcb->tcb_isfake == 0) - _tcb->tcb_curkcb->kcb_kmbx.km_curthread = crit; + if (tcb->tcb_isfake == 0) + tcb->tcb_curkcb->kcb_kmbx.km_curthread = crit; } static __inline int _kcb_in_critical(void) { + struct tcb *tcb; uint32_t flags; int ret; - if (_tcb->tcb_isfake != 0) { + tcb = ia64_get_tcb(); + if (tcb->tcb_isfake != 0) { /* * We are in a critical region since there is no * current thread. */ ret = 1; } else { - flags = _tcb->tcb_tmbx.tm_flags; - _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; - ret = (_tcb->tcb_curkcb->kcb_kmbx.km_curthread == NULL); - _tcb->tcb_tmbx.tm_flags = flags; + flags = tcb->tcb_tmbx.tm_flags; + tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; + ret = (tcb->tcb_curkcb->kcb_kmbx.km_curthread == NULL); + tcb->tcb_tmbx.tm_flags = flags; } return (ret); } @@ -170,19 +186,19 @@ _tcb_set(struct kcb *kcb, struct tcb *tcb) tcb = &kcb->kcb_faketcb; kcb->kcb_curtcb = tcb; tcb->tcb_curkcb = kcb; - _tp = &tcb->tcb_tp; + ia64_set_tcb(tcb); } static __inline struct tcb * _tcb_get(void) { - return (_tcb); + return (ia64_get_tcb()); } static __inline struct pthread * _get_curthread(void) { - return (_tcb->tcb_thread); + return (ia64_get_tcb()->tcb_thread); } /* @@ -193,7 +209,7 @@ _get_curthread(void) static __inline struct kse * _get_curkse(void) { - return (_tcb->tcb_curkcb->kcb_kse); + return (ia64_get_tcb()->tcb_curkcb->kcb_kse); } void _ia64_break_setcontext(mcontext_t *mc); @@ -208,7 +224,7 @@ _thread_enter_uts(struct tcb *tcb, struct kcb *kcb) if (_ia64_save_context(&tcb->tcb_tmbx.tm_context.uc_mcontext) == 0) { /* Make the fake tcb the current thread. */ kcb->kcb_curtcb = &kcb->kcb_faketcb; - _tp = &kcb->kcb_faketcb.tcb_tp; + ia64_set_tcb(&kcb->kcb_faketcb); _ia64_enter_uts(kcb->kcb_kmbx.km_func, &kcb->kcb_kmbx, kcb->kcb_kmbx.km_stack.ss_sp, kcb->kcb_kmbx.km_stack.ss_size); diff --git a/lib/libpthread/arch/powerpc/include/pthread_md.h b/lib/libpthread/arch/powerpc/include/pthread_md.h index 33a58b55af99..2b13e4bc11cd 100644 --- a/lib/libpthread/arch/powerpc/include/pthread_md.h +++ b/lib/libpthread/arch/powerpc/include/pthread_md.h @@ -1,5 +1,7 @@ /* - * Copyright 2004 by Peter Grehan. All rights reserved. + * Copyright 2004 by Peter Grehan. + * Copyright 2006 Marcel Moolenaar + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,7 +44,7 @@ extern int _ppc32_setcontext(mcontext_t *, intptr_t, intptr_t *); extern int _ppc32_getcontext(mcontext_t *); #define KSE_STACKSIZE 16384 -#define DTV_OFFSET offsetof(struct tcb, tcb_tp.tp_tdv) +#define DTV_OFFSET offsetof(struct tcb, tcb_tp.tp_dtv) #define THR_GETCONTEXT(ucp) _ppc32_getcontext(&(ucp)->uc_mcontext) #define THR_SETCONTEXT(ucp) _ppc32_setcontext(&(ucp)->uc_mcontext, 0, NULL) @@ -53,15 +55,14 @@ struct kcb; struct kse; struct pthread; struct tcb; -struct tdv; /* - * %r2 points to a struct kcb. + * %r2 points to the following. */ struct ppc32_tp { - struct tdv *tp_tdv; /* dynamic TLS */ + void *tp_dtv; /* dynamic thread vector */ uint32_t _reserved_; - long double tp_tls[0]; /* static TLS */ + double tp_tls[0]; /* static TLS */ }; struct tcb { @@ -69,14 +70,15 @@ struct tcb { struct pthread *tcb_thread; struct kcb *tcb_curkcb; long tcb_isfake; + long tcb_spare[3]; struct ppc32_tp tcb_tp; }; struct kcb { struct kse_mailbox kcb_kmbx; - struct tcb kcb_faketcb; - struct tcb *kcb_curtcb; struct kse *kcb_kse; + struct tcb *kcb_curtcb; + struct tcb kcb_faketcb; }; /* @@ -86,9 +88,33 @@ struct kcb { * thread control block." Or, 0x7008 past the start of the 8-byte tcb */ #define TP_OFFSET 0x7008 -register uint8_t *_tpr __asm("%r2"); -#define _tcb ((struct tcb *)(_tpr - TP_OFFSET - offsetof(struct tcb, tcb_tp))) +static __inline char * +ppc_get_tp() +{ + register char *r2 __asm__("%r2"); + + return (r2 - TP_OFFSET); +} + +static __inline void +ppc_set_tp(char *tp) +{ + register char *r2 __asm__("%r2"); + __asm __volatile("mr %0,%1" : "=r"(r2) : "r"(tp + TP_OFFSET)); +} + +static __inline struct tcb * +ppc_get_tcb() +{ + return ((struct tcb *)(ppc_get_tp() - offsetof(struct tcb, tcb_tp))); +} + +static __inline void +ppc_set_tcb(struct tcb *tcb) +{ + ppc_set_tp((char*)&tcb->tcb_tp); +} /* * The kcb and tcb constructors. @@ -103,7 +129,7 @@ static __inline void _kcb_set(struct kcb *kcb) { /* There is no thread yet; use the fake tcb. */ - _tpr = (uint8_t *)&kcb->kcb_faketcb.tcb_tp + TP_OFFSET; + ppc_set_tcb(&kcb->kcb_faketcb); } /* @@ -115,7 +141,7 @@ _kcb_set(struct kcb *kcb) static __inline struct kcb * _kcb_get(void) { - return (_tcb->tcb_curkcb); + return (ppc_get_tcb()->tcb_curkcb); } /* @@ -127,20 +153,22 @@ static __inline struct kse_thr_mailbox * _kcb_critical_enter(void) { struct kse_thr_mailbox *crit; + struct tcb *tcb; uint32_t flags; - if (_tcb->tcb_isfake != 0) { + tcb = ppc_get_tcb(); + if (tcb->tcb_isfake != 0) { /* * We already are in a critical region since * there is no current thread. */ crit = NULL; } else { - flags = _tcb->tcb_tmbx.tm_flags; - _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; - crit = _tcb->tcb_curkcb->kcb_kmbx.km_curthread; - _tcb->tcb_curkcb->kcb_kmbx.km_curthread = NULL; - _tcb->tcb_tmbx.tm_flags = flags; + flags = tcb->tcb_tmbx.tm_flags; + tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; + crit = tcb->tcb_curkcb->kcb_kmbx.km_curthread; + tcb->tcb_curkcb->kcb_kmbx.km_curthread = NULL; + tcb->tcb_tmbx.tm_flags = flags; } return (crit); } @@ -148,28 +176,34 @@ _kcb_critical_enter(void) static __inline void _kcb_critical_leave(struct kse_thr_mailbox *crit) { - /* No need to do anything if this is a fake tcb. */ - if (_tcb->tcb_isfake == 0) - _tcb->tcb_curkcb->kcb_kmbx.km_curthread = crit; + struct tcb *tcb; + + tcb = ppc_get_tcb(); + + /* No need to do anything if this is a fake tcb. */ + if (tcb->tcb_isfake == 0) + tcb->tcb_curkcb->kcb_kmbx.km_curthread = crit; } static __inline int _kcb_in_critical(void) { + struct tcb *tcb; uint32_t flags; int ret; - if (_tcb->tcb_isfake != 0) { + tcb = ppc_get_tcb(); + if (tcb->tcb_isfake != 0) { /* * We are in a critical region since there is no * current thread. */ ret = 1; } else { - flags = _tcb->tcb_tmbx.tm_flags; - _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; - ret = (_tcb->tcb_curkcb->kcb_kmbx.km_curthread == NULL); - _tcb->tcb_tmbx.tm_flags = flags; + flags = tcb->tcb_tmbx.tm_flags; + tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; + ret = (tcb->tcb_curkcb->kcb_kmbx.km_curthread == NULL); + tcb->tcb_tmbx.tm_flags = flags; } return (ret); } @@ -181,19 +215,19 @@ _tcb_set(struct kcb *kcb, struct tcb *tcb) tcb = &kcb->kcb_faketcb; kcb->kcb_curtcb = tcb; tcb->tcb_curkcb = kcb; - _tpr = (uint8_t *)&tcb->tcb_tp + TP_OFFSET; + ppc_set_tcb(tcb); } static __inline struct tcb * _tcb_get(void) { - return (_tcb); + return (ppc_get_tcb()); } static __inline struct pthread * _get_curthread(void) { - return (_tcb->tcb_thread); + return (ppc_get_tcb()->tcb_thread); } /* @@ -204,7 +238,7 @@ _get_curthread(void) static __inline struct kse * _get_curkse(void) { - return (_tcb->tcb_curkcb->kcb_kse); + return (ppc_get_tcb()->tcb_curkcb->kcb_kse); } static __inline int @@ -213,7 +247,7 @@ _thread_enter_uts(struct tcb *tcb, struct kcb *kcb) if (_ppc32_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext) == 0) { /* Make the fake tcb the current thread. */ kcb->kcb_curtcb = &kcb->kcb_faketcb; - _tpr = (uint8_t *)&kcb->kcb_faketcb.tcb_tp + TP_OFFSET; + ppc_set_tcb(&kcb->kcb_faketcb); _ppc32_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, kcb->kcb_kmbx.km_stack.ss_sp, kcb->kcb_kmbx.km_stack.ss_size - 32); @@ -240,8 +274,8 @@ _thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) if (mc->mc_vers != _MC_VERSION_KSE && _libkse_debug != 0) { if (setmbox) kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX); - else - kse_switchin(&tcb->tcb_tmbx, 0); + else + kse_switchin(&tcb->tcb_tmbx, 0); } else { tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp; if (setmbox) diff --git a/lib/libpthread/arch/powerpc/powerpc/pthread_md.c b/lib/libpthread/arch/powerpc/powerpc/pthread_md.c index c8445b177c54..7aa5ee90f186 100644 --- a/lib/libpthread/arch/powerpc/powerpc/pthread_md.c +++ b/lib/libpthread/arch/powerpc/powerpc/pthread_md.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org> + * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,6 +30,8 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <strings.h> + +#include "rtld_tls.h" #include "pthread_md.h" /* @@ -39,19 +42,18 @@ _tcb_ctor(struct pthread *thread, int initial) { struct tcb *tcb; - if ((tcb = malloc(sizeof(struct tcb))) != NULL) { - bzero(tcb, sizeof(struct tcb)); - tcb->tcb_thread = thread; - /* Allocate TDV */ - } + tcb = _rtld_allocate_tls((initial) ? ppc_get_tp() : NULL, + sizeof(struct tcb), 8); + if (tcb == NULL) + return (NULL); + tcb->tcb_thread = thread; return (tcb); } void _tcb_dtor(struct tcb *tcb) { - /* Free TDV */ - free(tcb); + _rtld_free_tls(tcb, sizeof(struct tcb), 8); } struct kcb * @@ -59,13 +61,14 @@ _kcb_ctor(struct kse *kse) { struct kcb *kcb; - if ((kcb = malloc(sizeof(struct kcb))) != NULL) { - bzero(kcb, sizeof(struct kcb)); - kcb->kcb_faketcb.tcb_isfake = 1; - kcb->kcb_faketcb.tcb_tmbx.tm_flags = TMF_NOUPCALL; - kcb->kcb_curtcb = &kcb->kcb_faketcb; - kcb->kcb_kse = kse; - } + kcb = malloc(sizeof(struct kcb)); + if (kcb == NULL) + return (NULL); + bzero(kcb, sizeof(struct kcb)); + kcb->kcb_kse = kse; + kcb->kcb_faketcb.tcb_isfake = 1; + kcb->kcb_faketcb.tcb_tmbx.tm_flags = TMF_NOUPCALL; + kcb->kcb_curtcb = &kcb->kcb_faketcb; return (kcb); } |
