pthread_md.h revision 134326
1113656Sdeischen/*- 2113656Sdeischen * Copyright (c) 2002 Daniel Eischen <deischen@freebsd.org>. 3113656Sdeischen * All rights reserved. 4113656Sdeischen * 5113656Sdeischen * Redistribution and use in source and binary forms, with or without 6113656Sdeischen * modification, are permitted provided that the following conditions 7113656Sdeischen * are met: 8113656Sdeischen * 1. Redistributions of source code must retain the above copyright 9113656Sdeischen * notice, this list of conditions and the following disclaimer. 10113656Sdeischen * 2. Redistributions in binary form must reproduce the above copyright 11113656Sdeischen * notice, this list of conditions and the following disclaimer in the 12113656Sdeischen * documentation and/or other materials provided with the distribution. 13113656Sdeischen * 14113656Sdeischen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15113656Sdeischen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16113656Sdeischen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17113656Sdeischen * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18113656Sdeischen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19113656Sdeischen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20113656Sdeischen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21113656Sdeischen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22113656Sdeischen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23113656Sdeischen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24113656Sdeischen * SUCH DAMAGE. 25113656Sdeischen * 26113656Sdeischen * $FreeBSD: head/lib/libkse/arch/i386/include/pthread_md.h 134326 2004-08-26 02:41:01Z davidxu $ 27113656Sdeischen */ 28113656Sdeischen/* 29113656Sdeischen * Machine-dependent thread prototypes/definitions for the thread kernel. 30113656Sdeischen */ 31113656Sdeischen#ifndef _PTHREAD_MD_H_ 32113656Sdeischen#define _PTHREAD_MD_H_ 33113656Sdeischen 34133801Sdavidxu#include <stddef.h> 35118277Sdeischen#include <sys/kse.h> 36113656Sdeischen#include <ucontext.h> 37113656Sdeischen 38118277Sdeischenextern int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *); 39118277Sdeischenextern int _thr_getcontext(mcontext_t *); 40113656Sdeischen 41120263Smarcel#define KSE_STACKSIZE 16384 42133801Sdavidxu#define DTV_OFFSET offsetof(struct tcb, tcb_dtv) 43120263Smarcel 44118510Sdeischen#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext) 45118510Sdeischen#define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL) 46113656Sdeischen 47118510Sdeischen#define PER_KSE 48118510Sdeischen#undef PER_THREAD 49116771Smarcel 50118510Sdeischenstruct kse; 51118510Sdeischenstruct pthread; 52118510Sdeischen 53116771Smarcel/* 54118510Sdeischen * %gs points to a struct kcb. 55116771Smarcel */ 56118510Sdeischenstruct kcb { 57118510Sdeischen struct tcb *kcb_curtcb; 58118510Sdeischen struct kcb *kcb_self; /* self reference */ 59118510Sdeischen int kcb_ldt; 60118510Sdeischen struct kse *kcb_kse; 61118510Sdeischen struct kse_mailbox kcb_kmbx; 62116771Smarcel}; 63116771Smarcel 64118510Sdeischenstruct tcb { 65133756Sdfr struct tcb *tcb_self; /* required by rtld */ 66133756Sdfr void *tcb_dtv; /* required by rtld */ 67118510Sdeischen struct pthread *tcb_thread; 68118510Sdeischen void *tcb_spare; /* align tcb_tmbx to 16 bytes */ 69118510Sdeischen struct kse_thr_mailbox tcb_tmbx; 70118510Sdeischen}; 71118277Sdeischen 72118510Sdeischen/* 73118510Sdeischen * Evaluates to the byte offset of the per-kse variable name. 74118510Sdeischen */ 75118510Sdeischen#define __kcb_offset(name) __offsetof(struct kcb, name) 76118510Sdeischen 77118510Sdeischen/* 78118510Sdeischen * Evaluates to the type of the per-kse variable name. 79118510Sdeischen */ 80118510Sdeischen#define __kcb_type(name) __typeof(((struct kcb *)0)->name) 81118510Sdeischen 82118510Sdeischen/* 83118510Sdeischen * Evaluates to the value of the per-kse variable name. 84118510Sdeischen */ 85118510Sdeischen#define KCB_GET32(name) ({ \ 86118510Sdeischen __kcb_type(name) __result; \ 87118510Sdeischen \ 88118510Sdeischen u_int __i; \ 89118510Sdeischen __asm __volatile("movl %%gs:%1, %0" \ 90118510Sdeischen : "=r" (__i) \ 91118510Sdeischen : "m" (*(u_int *)(__kcb_offset(name)))); \ 92134326Sdavidxu __result = (__kcb_type(name))__i; \ 93118510Sdeischen \ 94118510Sdeischen __result; \ 95118510Sdeischen}) 96118510Sdeischen 97118510Sdeischen/* 98118510Sdeischen * Sets the value of the per-kse variable name to value val. 99118510Sdeischen */ 100118510Sdeischen#define KCB_SET32(name, val) ({ \ 101118510Sdeischen __kcb_type(name) __val = (val); \ 102118510Sdeischen \ 103118510Sdeischen u_int __i; \ 104134319Sdavidxu __i = (u_int)__val; \ 105118510Sdeischen __asm __volatile("movl %1,%%gs:%0" \ 106118510Sdeischen : "=m" (*(u_int *)(__kcb_offset(name))) \ 107118510Sdeischen : "r" (__i)); \ 108118510Sdeischen}) 109118510Sdeischen 110118510Sdeischenstatic __inline u_long 111118510Sdeischen__kcb_readandclear32(volatile u_long *addr) 112118510Sdeischen{ 113118510Sdeischen u_long result; 114118510Sdeischen 115118510Sdeischen __asm __volatile ( 116118510Sdeischen " xorl %0, %0;" 117118510Sdeischen " xchgl %%gs:%1, %0;" 118118510Sdeischen "# __kcb_readandclear32" 119118510Sdeischen : "=&r" (result) 120118510Sdeischen : "m" (*addr)); 121118510Sdeischen return (result); 122118510Sdeischen} 123118510Sdeischen 124118510Sdeischen#define KCB_READANDCLEAR32(name) ({ \ 125118510Sdeischen __kcb_type(name) __result; \ 126118510Sdeischen \ 127118510Sdeischen __result = (__kcb_type(name)) \ 128118510Sdeischen __kcb_readandclear32((u_long *)__kcb_offset(name)); \ 129118510Sdeischen __result; \ 130118510Sdeischen}) 131118510Sdeischen 132118510Sdeischen 133118510Sdeischen#define _kcb_curkcb() KCB_GET32(kcb_self) 134118510Sdeischen#define _kcb_curtcb() KCB_GET32(kcb_curtcb) 135118510Sdeischen#define _kcb_curkse() ((struct kse *)KCB_GET32(kcb_kmbx.km_udata)) 136118510Sdeischen#define _kcb_get_tmbx() KCB_GET32(kcb_kmbx.km_curthread) 137118510Sdeischen#define _kcb_set_tmbx(value) KCB_SET32(kcb_kmbx.km_curthread, (void *)value) 138118510Sdeischen#define _kcb_readandclear_tmbx() KCB_READANDCLEAR32(kcb_kmbx.km_curthread) 139118510Sdeischen 140118510Sdeischen 141118510Sdeischen/* 142118510Sdeischen * The constructors. 143118510Sdeischen */ 144133756Sdfrstruct tcb *_tcb_ctor(struct pthread *, int); 145118510Sdeischenvoid _tcb_dtor(struct tcb *tcb); 146118510Sdeischenstruct kcb *_kcb_ctor(struct kse *); 147118510Sdeischenvoid _kcb_dtor(struct kcb *); 148118510Sdeischen 149118510Sdeischen/* Called from the KSE to set its private data. */ 150118510Sdeischenstatic __inline void 151118510Sdeischen_kcb_set(struct kcb *kcb) 152118510Sdeischen{ 153118510Sdeischen int val; 154118510Sdeischen 155118510Sdeischen val = (kcb->kcb_ldt << 3) | 7; 156118510Sdeischen __asm __volatile("movl %0, %%gs" : : "r" (val)); 157118510Sdeischen} 158118510Sdeischen 159118510Sdeischen/* Get the current kcb. */ 160118510Sdeischenstatic __inline struct kcb * 161118510Sdeischen_kcb_get(void) 162118510Sdeischen{ 163118510Sdeischen return (_kcb_curkcb()); 164118510Sdeischen} 165118510Sdeischen 166118510Sdeischenstatic __inline struct kse_thr_mailbox * 167118510Sdeischen_kcb_critical_enter(void) 168118510Sdeischen{ 169118510Sdeischen struct kse_thr_mailbox *crit; 170118510Sdeischen 171118510Sdeischen crit = _kcb_readandclear_tmbx(); 172118510Sdeischen return (crit); 173118510Sdeischen} 174118510Sdeischen 175118510Sdeischenstatic __inline void 176118510Sdeischen_kcb_critical_leave(struct kse_thr_mailbox *crit) 177118510Sdeischen{ 178118510Sdeischen _kcb_set_tmbx(crit); 179118510Sdeischen} 180118510Sdeischen 181118277Sdeischenstatic __inline int 182118510Sdeischen_kcb_in_critical(void) 183118277Sdeischen{ 184118510Sdeischen return (_kcb_get_tmbx() == NULL); 185118510Sdeischen} 186118510Sdeischen 187118510Sdeischenstatic __inline void 188118510Sdeischen_tcb_set(struct kcb *kcb, struct tcb *tcb) 189118510Sdeischen{ 190118510Sdeischen kcb->kcb_curtcb = tcb; 191118510Sdeischen} 192118510Sdeischen 193118510Sdeischenstatic __inline struct tcb * 194118510Sdeischen_tcb_get(void) 195118510Sdeischen{ 196118510Sdeischen return (_kcb_curtcb()); 197118510Sdeischen} 198118510Sdeischen 199118510Sdeischenstatic __inline struct pthread * 200118510Sdeischen_get_curthread(void) 201118510Sdeischen{ 202118510Sdeischen struct tcb *tcb; 203118510Sdeischen 204118510Sdeischen tcb = _kcb_curtcb(); 205118510Sdeischen if (tcb != NULL) 206118510Sdeischen return (tcb->tcb_thread); 207118510Sdeischen else 208118510Sdeischen return (NULL); 209118510Sdeischen} 210118510Sdeischen 211118510Sdeischenstatic __inline struct kse * 212118510Sdeischen_get_curkse(void) 213118510Sdeischen{ 214118510Sdeischen return ((struct kse *)_kcb_curkse()); 215118510Sdeischen} 216118510Sdeischen 217118510Sdeischenvoid _i386_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack, 218118510Sdeischen size_t stacksz); 219118510Sdeischen 220118510Sdeischenstatic __inline int 221118510Sdeischen_thread_enter_uts(struct tcb *tcb, struct kcb *kcb) 222118510Sdeischen{ 223118277Sdeischen int ret; 224118277Sdeischen 225118510Sdeischen ret = _thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext); 226118277Sdeischen if (ret == 0) { 227118510Sdeischen _i386_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, 228118510Sdeischen kcb->kcb_kmbx.km_stack.ss_sp, 229118510Sdeischen kcb->kcb_kmbx.km_stack.ss_size); 230118277Sdeischen /* We should not reach here. */ 231118277Sdeischen return (-1); 232118277Sdeischen } 233118277Sdeischen else if (ret < 0) 234118277Sdeischen return (-1); 235118277Sdeischen return (0); 236118277Sdeischen} 237118277Sdeischen 238118277Sdeischenstatic __inline int 239118510Sdeischen_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) 240118277Sdeischen{ 241132125Sdavidxu extern int _libkse_debug; 242132125Sdavidxu 243118510Sdeischen if ((kcb == NULL) || (tcb == NULL)) 244118510Sdeischen return (-1); 245118510Sdeischen kcb->kcb_curtcb = tcb; 246132125Sdavidxu if (_libkse_debug == 0) { 247132125Sdavidxu tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp; 248132125Sdavidxu if (setmbox != 0) 249132125Sdavidxu _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 250132125Sdavidxu (intptr_t)&tcb->tcb_tmbx, 251132125Sdavidxu (intptr_t *)&kcb->kcb_kmbx.km_curthread); 252132125Sdavidxu else 253132125Sdavidxu _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 254132125Sdavidxu 0, NULL); 255132125Sdavidxu } else { 256132125Sdavidxu if (setmbox) 257132125Sdavidxu kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX); 258132125Sdavidxu else 259132125Sdavidxu kse_switchin(&tcb->tcb_tmbx, 0); 260132125Sdavidxu } 261132125Sdavidxu 262118277Sdeischen /* We should not reach here. */ 263118277Sdeischen return (-1); 264118277Sdeischen} 265118277Sdeischen 266113656Sdeischen#endif 267