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$ 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> 35137295Speter#include <sys/types.h> 36118277Sdeischen#include <sys/kse.h> 37137295Speter#include <machine/sysarch.h> 38113656Sdeischen#include <ucontext.h> 39113656Sdeischen 40118277Sdeischenextern int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *); 41118277Sdeischenextern int _thr_getcontext(mcontext_t *); 42113656Sdeischen 43120263Smarcel#define KSE_STACKSIZE 16384 44133801Sdavidxu#define DTV_OFFSET offsetof(struct tcb, tcb_dtv) 45120263Smarcel 46118510Sdeischen#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext) 47118510Sdeischen#define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL) 48113656Sdeischen 49118510Sdeischen#define PER_KSE 50118510Sdeischen#undef PER_THREAD 51116771Smarcel 52118510Sdeischenstruct kse; 53118510Sdeischenstruct pthread; 54118510Sdeischen 55116771Smarcel/* 56118510Sdeischen * %gs points to a struct kcb. 57116771Smarcel */ 58118510Sdeischenstruct kcb { 59118510Sdeischen struct tcb *kcb_curtcb; 60118510Sdeischen struct kcb *kcb_self; /* self reference */ 61118510Sdeischen struct kse *kcb_kse; 62118510Sdeischen struct kse_mailbox kcb_kmbx; 63116771Smarcel}; 64116771Smarcel 65118510Sdeischenstruct tcb { 66133756Sdfr struct tcb *tcb_self; /* required by rtld */ 67133756Sdfr void *tcb_dtv; /* required by rtld */ 68118510Sdeischen struct pthread *tcb_thread; 69118510Sdeischen void *tcb_spare; /* align tcb_tmbx to 16 bytes */ 70118510Sdeischen struct kse_thr_mailbox tcb_tmbx; 71118510Sdeischen}; 72118277Sdeischen 73118510Sdeischen/* 74118510Sdeischen * Evaluates to the byte offset of the per-kse variable name. 75118510Sdeischen */ 76118510Sdeischen#define __kcb_offset(name) __offsetof(struct kcb, name) 77118510Sdeischen 78118510Sdeischen/* 79118510Sdeischen * Evaluates to the type of the per-kse variable name. 80118510Sdeischen */ 81118510Sdeischen#define __kcb_type(name) __typeof(((struct kcb *)0)->name) 82118510Sdeischen 83118510Sdeischen/* 84118510Sdeischen * Evaluates to the value of the per-kse variable name. 85118510Sdeischen */ 86118510Sdeischen#define KCB_GET32(name) ({ \ 87118510Sdeischen __kcb_type(name) __result; \ 88118510Sdeischen \ 89118510Sdeischen u_int __i; \ 90118510Sdeischen __asm __volatile("movl %%gs:%1, %0" \ 91118510Sdeischen : "=r" (__i) \ 92118510Sdeischen : "m" (*(u_int *)(__kcb_offset(name)))); \ 93134326Sdavidxu __result = (__kcb_type(name))__i; \ 94118510Sdeischen \ 95118510Sdeischen __result; \ 96118510Sdeischen}) 97118510Sdeischen 98118510Sdeischen/* 99118510Sdeischen * Sets the value of the per-kse variable name to value val. 100118510Sdeischen */ 101118510Sdeischen#define KCB_SET32(name, val) ({ \ 102118510Sdeischen __kcb_type(name) __val = (val); \ 103118510Sdeischen \ 104118510Sdeischen u_int __i; \ 105134319Sdavidxu __i = (u_int)__val; \ 106118510Sdeischen __asm __volatile("movl %1,%%gs:%0" \ 107118510Sdeischen : "=m" (*(u_int *)(__kcb_offset(name))) \ 108118510Sdeischen : "r" (__i)); \ 109118510Sdeischen}) 110118510Sdeischen 111118510Sdeischenstatic __inline u_long 112118510Sdeischen__kcb_readandclear32(volatile u_long *addr) 113118510Sdeischen{ 114118510Sdeischen u_long result; 115118510Sdeischen 116118510Sdeischen __asm __volatile ( 117118510Sdeischen " xorl %0, %0;" 118118510Sdeischen " xchgl %%gs:%1, %0;" 119118510Sdeischen "# __kcb_readandclear32" 120118510Sdeischen : "=&r" (result) 121118510Sdeischen : "m" (*addr)); 122118510Sdeischen return (result); 123118510Sdeischen} 124118510Sdeischen 125118510Sdeischen#define KCB_READANDCLEAR32(name) ({ \ 126118510Sdeischen __kcb_type(name) __result; \ 127118510Sdeischen \ 128118510Sdeischen __result = (__kcb_type(name)) \ 129118510Sdeischen __kcb_readandclear32((u_long *)__kcb_offset(name)); \ 130118510Sdeischen __result; \ 131118510Sdeischen}) 132118510Sdeischen 133118510Sdeischen 134118510Sdeischen#define _kcb_curkcb() KCB_GET32(kcb_self) 135118510Sdeischen#define _kcb_curtcb() KCB_GET32(kcb_curtcb) 136118510Sdeischen#define _kcb_curkse() ((struct kse *)KCB_GET32(kcb_kmbx.km_udata)) 137118510Sdeischen#define _kcb_get_tmbx() KCB_GET32(kcb_kmbx.km_curthread) 138118510Sdeischen#define _kcb_set_tmbx(value) KCB_SET32(kcb_kmbx.km_curthread, (void *)value) 139118510Sdeischen#define _kcb_readandclear_tmbx() KCB_READANDCLEAR32(kcb_kmbx.km_curthread) 140118510Sdeischen 141118510Sdeischen 142118510Sdeischen/* 143118510Sdeischen * The constructors. 144118510Sdeischen */ 145133756Sdfrstruct tcb *_tcb_ctor(struct pthread *, int); 146118510Sdeischenvoid _tcb_dtor(struct tcb *tcb); 147118510Sdeischenstruct kcb *_kcb_ctor(struct kse *); 148118510Sdeischenvoid _kcb_dtor(struct kcb *); 149118510Sdeischen 150118510Sdeischen/* Called from the KSE to set its private data. */ 151118510Sdeischenstatic __inline void 152118510Sdeischen_kcb_set(struct kcb *kcb) 153118510Sdeischen{ 154147673Speter i386_set_gsbase(kcb); 155118510Sdeischen} 156118510Sdeischen 157118510Sdeischen/* Get the current kcb. */ 158118510Sdeischenstatic __inline struct kcb * 159118510Sdeischen_kcb_get(void) 160118510Sdeischen{ 161118510Sdeischen return (_kcb_curkcb()); 162118510Sdeischen} 163118510Sdeischen 164118510Sdeischenstatic __inline struct kse_thr_mailbox * 165118510Sdeischen_kcb_critical_enter(void) 166118510Sdeischen{ 167118510Sdeischen struct kse_thr_mailbox *crit; 168118510Sdeischen 169118510Sdeischen crit = _kcb_readandclear_tmbx(); 170118510Sdeischen return (crit); 171118510Sdeischen} 172118510Sdeischen 173118510Sdeischenstatic __inline void 174118510Sdeischen_kcb_critical_leave(struct kse_thr_mailbox *crit) 175118510Sdeischen{ 176118510Sdeischen _kcb_set_tmbx(crit); 177118510Sdeischen} 178118510Sdeischen 179118277Sdeischenstatic __inline int 180118510Sdeischen_kcb_in_critical(void) 181118277Sdeischen{ 182118510Sdeischen return (_kcb_get_tmbx() == NULL); 183118510Sdeischen} 184118510Sdeischen 185118510Sdeischenstatic __inline void 186118510Sdeischen_tcb_set(struct kcb *kcb, struct tcb *tcb) 187118510Sdeischen{ 188118510Sdeischen kcb->kcb_curtcb = tcb; 189118510Sdeischen} 190118510Sdeischen 191118510Sdeischenstatic __inline struct tcb * 192118510Sdeischen_tcb_get(void) 193118510Sdeischen{ 194118510Sdeischen return (_kcb_curtcb()); 195118510Sdeischen} 196118510Sdeischen 197118510Sdeischenstatic __inline struct pthread * 198118510Sdeischen_get_curthread(void) 199118510Sdeischen{ 200118510Sdeischen struct tcb *tcb; 201118510Sdeischen 202118510Sdeischen tcb = _kcb_curtcb(); 203118510Sdeischen if (tcb != NULL) 204118510Sdeischen return (tcb->tcb_thread); 205118510Sdeischen else 206118510Sdeischen return (NULL); 207118510Sdeischen} 208118510Sdeischen 209118510Sdeischenstatic __inline struct kse * 210118510Sdeischen_get_curkse(void) 211118510Sdeischen{ 212118510Sdeischen return ((struct kse *)_kcb_curkse()); 213118510Sdeischen} 214118510Sdeischen 215118510Sdeischenvoid _i386_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack, 216118510Sdeischen size_t stacksz); 217118510Sdeischen 218118510Sdeischenstatic __inline int 219118510Sdeischen_thread_enter_uts(struct tcb *tcb, struct kcb *kcb) 220118510Sdeischen{ 221118277Sdeischen int ret; 222118277Sdeischen 223118510Sdeischen ret = _thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext); 224118277Sdeischen if (ret == 0) { 225118510Sdeischen _i386_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, 226118510Sdeischen kcb->kcb_kmbx.km_stack.ss_sp, 227118510Sdeischen kcb->kcb_kmbx.km_stack.ss_size); 228118277Sdeischen /* We should not reach here. */ 229118277Sdeischen return (-1); 230118277Sdeischen } 231118277Sdeischen else if (ret < 0) 232118277Sdeischen return (-1); 233118277Sdeischen return (0); 234118277Sdeischen} 235118277Sdeischen 236118277Sdeischenstatic __inline int 237118510Sdeischen_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) 238118277Sdeischen{ 239132125Sdavidxu extern int _libkse_debug; 240132125Sdavidxu 241118510Sdeischen if ((kcb == NULL) || (tcb == NULL)) 242118510Sdeischen return (-1); 243118510Sdeischen kcb->kcb_curtcb = tcb; 244132125Sdavidxu if (_libkse_debug == 0) { 245132125Sdavidxu tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp; 246132125Sdavidxu if (setmbox != 0) 247132125Sdavidxu _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 248132125Sdavidxu (intptr_t)&tcb->tcb_tmbx, 249174112Sdeischen (intptr_t *)(void *)&kcb->kcb_kmbx.km_curthread); 250132125Sdavidxu else 251132125Sdavidxu _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 252132125Sdavidxu 0, NULL); 253132125Sdavidxu } else { 254132125Sdavidxu if (setmbox) 255132125Sdavidxu kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX); 256132125Sdavidxu else 257132125Sdavidxu kse_switchin(&tcb->tcb_tmbx, 0); 258132125Sdavidxu } 259132125Sdavidxu 260118277Sdeischen /* We should not reach here. */ 261118277Sdeischen return (-1); 262118277Sdeischen} 263118277Sdeischen 264113656Sdeischen#endif 265