pthread_md.h revision 133801
1272343Sngie/*- 2272343Sngie * Copyright (c) 2002 Daniel Eischen <deischen@freebsd.org>. 3272343Sngie * All rights reserved. 4272343Sngie * 5272343Sngie * Redistribution and use in source and binary forms, with or without 6272343Sngie * modification, are permitted provided that the following conditions 7272343Sngie * are met: 8272343Sngie * 1. Redistributions of source code must retain the above copyright 9272343Sngie * notice, this list of conditions and the following disclaimer. 10272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer in the 12272343Sngie * documentation and/or other materials provided with the distribution. 13272343Sngie * 14272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15272343Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17272343Sngie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20272343Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24272343Sngie * SUCH DAMAGE. 25272343Sngie * 26272343Sngie * $FreeBSD: head/lib/libkse/arch/i386/include/pthread_md.h 133801 2004-08-16 03:27:29Z davidxu $ 27272343Sngie */ 28272343Sngie/* 29272343Sngie * Machine-dependent thread prototypes/definitions for the thread kernel. 30272343Sngie */ 31272343Sngie#ifndef _PTHREAD_MD_H_ 32272343Sngie#define _PTHREAD_MD_H_ 33272343Sngie 34272343Sngie#include <stddef.h> 35272343Sngie#include <sys/kse.h> 36272343Sngie#include <ucontext.h> 37272343Sngie 38272343Sngieextern int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *); 39272343Sngieextern int _thr_getcontext(mcontext_t *); 40272343Sngie 41272343Sngie#define KSE_STACKSIZE 16384 42272343Sngie#define DTV_OFFSET offsetof(struct tcb, tcb_dtv) 43272343Sngie 44272343Sngie#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext) 45272343Sngie#define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL) 46272343Sngie 47272343Sngie#define PER_KSE 48272343Sngie#undef PER_THREAD 49272343Sngie 50272343Sngiestruct kse; 51272343Sngiestruct pthread; 52272343Sngie 53272343Sngie/* 54272343Sngie * %gs points to a struct kcb. 55272343Sngie */ 56272343Sngiestruct kcb { 57272343Sngie struct tcb *kcb_curtcb; 58272343Sngie struct kcb *kcb_self; /* self reference */ 59272343Sngie int kcb_ldt; 60272343Sngie struct kse *kcb_kse; 61272343Sngie struct kse_mailbox kcb_kmbx; 62272343Sngie}; 63272343Sngie 64272343Sngiestruct tcb { 65272343Sngie struct tcb *tcb_self; /* required by rtld */ 66272343Sngie void *tcb_dtv; /* required by rtld */ 67272343Sngie struct pthread *tcb_thread; 68272343Sngie void *tcb_spare; /* align tcb_tmbx to 16 bytes */ 69272343Sngie struct kse_thr_mailbox tcb_tmbx; 70272343Sngie}; 71272343Sngie 72272343Sngie/* 73272343Sngie * Evaluates to the byte offset of the per-kse variable name. 74272343Sngie */ 75272343Sngie#define __kcb_offset(name) __offsetof(struct kcb, name) 76272343Sngie 77272343Sngie/* 78272343Sngie * Evaluates to the type of the per-kse variable name. 79272343Sngie */ 80272343Sngie#define __kcb_type(name) __typeof(((struct kcb *)0)->name) 81272343Sngie 82272343Sngie/* 83272343Sngie * Evaluates to the value of the per-kse variable name. 84272343Sngie */ 85272343Sngie#define KCB_GET32(name) ({ \ 86272343Sngie __kcb_type(name) __result; \ 87272343Sngie \ 88272343Sngie u_int __i; \ 89272343Sngie __asm __volatile("movl %%gs:%1, %0" \ 90272343Sngie : "=r" (__i) \ 91272343Sngie : "m" (*(u_int *)(__kcb_offset(name)))); \ 92272343Sngie __result = *(__kcb_type(name) *)&__i; \ 93272343Sngie \ 94272343Sngie __result; \ 95272343Sngie}) 96272343Sngie 97/* 98 * Sets the value of the per-kse variable name to value val. 99 */ 100#define KCB_SET32(name, val) ({ \ 101 __kcb_type(name) __val = (val); \ 102 \ 103 u_int __i; \ 104 __i = *(u_int *)&__val; \ 105 __asm __volatile("movl %1,%%gs:%0" \ 106 : "=m" (*(u_int *)(__kcb_offset(name))) \ 107 : "r" (__i)); \ 108}) 109 110static __inline u_long 111__kcb_readandclear32(volatile u_long *addr) 112{ 113 u_long result; 114 115 __asm __volatile ( 116 " xorl %0, %0;" 117 " xchgl %%gs:%1, %0;" 118 "# __kcb_readandclear32" 119 : "=&r" (result) 120 : "m" (*addr)); 121 return (result); 122} 123 124#define KCB_READANDCLEAR32(name) ({ \ 125 __kcb_type(name) __result; \ 126 \ 127 __result = (__kcb_type(name)) \ 128 __kcb_readandclear32((u_long *)__kcb_offset(name)); \ 129 __result; \ 130}) 131 132 133#define _kcb_curkcb() KCB_GET32(kcb_self) 134#define _kcb_curtcb() KCB_GET32(kcb_curtcb) 135#define _kcb_curkse() ((struct kse *)KCB_GET32(kcb_kmbx.km_udata)) 136#define _kcb_get_tmbx() KCB_GET32(kcb_kmbx.km_curthread) 137#define _kcb_set_tmbx(value) KCB_SET32(kcb_kmbx.km_curthread, (void *)value) 138#define _kcb_readandclear_tmbx() KCB_READANDCLEAR32(kcb_kmbx.km_curthread) 139 140 141/* 142 * The constructors. 143 */ 144struct tcb *_tcb_ctor(struct pthread *, int); 145void _tcb_dtor(struct tcb *tcb); 146struct kcb *_kcb_ctor(struct kse *); 147void _kcb_dtor(struct kcb *); 148 149/* Called from the KSE to set its private data. */ 150static __inline void 151_kcb_set(struct kcb *kcb) 152{ 153 int val; 154 155 val = (kcb->kcb_ldt << 3) | 7; 156 __asm __volatile("movl %0, %%gs" : : "r" (val)); 157} 158 159/* Get the current kcb. */ 160static __inline struct kcb * 161_kcb_get(void) 162{ 163 return (_kcb_curkcb()); 164} 165 166static __inline struct kse_thr_mailbox * 167_kcb_critical_enter(void) 168{ 169 struct kse_thr_mailbox *crit; 170 171 crit = _kcb_readandclear_tmbx(); 172 return (crit); 173} 174 175static __inline void 176_kcb_critical_leave(struct kse_thr_mailbox *crit) 177{ 178 _kcb_set_tmbx(crit); 179} 180 181static __inline int 182_kcb_in_critical(void) 183{ 184 return (_kcb_get_tmbx() == NULL); 185} 186 187static __inline void 188_tcb_set(struct kcb *kcb, struct tcb *tcb) 189{ 190 kcb->kcb_curtcb = tcb; 191} 192 193static __inline struct tcb * 194_tcb_get(void) 195{ 196 return (_kcb_curtcb()); 197} 198 199static __inline struct pthread * 200_get_curthread(void) 201{ 202 struct tcb *tcb; 203 204 tcb = _kcb_curtcb(); 205 if (tcb != NULL) 206 return (tcb->tcb_thread); 207 else 208 return (NULL); 209} 210 211static __inline struct kse * 212_get_curkse(void) 213{ 214 return ((struct kse *)_kcb_curkse()); 215} 216 217void _i386_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack, 218 size_t stacksz); 219 220static __inline int 221_thread_enter_uts(struct tcb *tcb, struct kcb *kcb) 222{ 223 int ret; 224 225 ret = _thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext); 226 if (ret == 0) { 227 _i386_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, 228 kcb->kcb_kmbx.km_stack.ss_sp, 229 kcb->kcb_kmbx.km_stack.ss_size); 230 /* We should not reach here. */ 231 return (-1); 232 } 233 else if (ret < 0) 234 return (-1); 235 return (0); 236} 237 238static __inline int 239_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) 240{ 241 extern int _libkse_debug; 242 243 if ((kcb == NULL) || (tcb == NULL)) 244 return (-1); 245 kcb->kcb_curtcb = tcb; 246 if (_libkse_debug == 0) { 247 tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp; 248 if (setmbox != 0) 249 _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 250 (intptr_t)&tcb->tcb_tmbx, 251 (intptr_t *)&kcb->kcb_kmbx.km_curthread); 252 else 253 _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 254 0, NULL); 255 } else { 256 if (setmbox) 257 kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX); 258 else 259 kse_switchin(&tcb->tcb_tmbx, 0); 260 } 261 262 /* We should not reach here. */ 263 return (-1); 264} 265 266#endif 267