pthread_md.h revision 120263
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 120263 2003-09-19 23:28:13Z marcel $ 27113656Sdeischen */ 28113656Sdeischen/* 29113656Sdeischen * Machine-dependent thread prototypes/definitions for the thread kernel. 30113656Sdeischen */ 31113656Sdeischen#ifndef _PTHREAD_MD_H_ 32113656Sdeischen#define _PTHREAD_MD_H_ 33113656Sdeischen 34118277Sdeischen#include <sys/kse.h> 35113656Sdeischen#include <ucontext.h> 36113656Sdeischen 37118277Sdeischenextern int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *); 38118277Sdeischenextern int _thr_getcontext(mcontext_t *); 39113656Sdeischen 40120263Smarcel#define KSE_STACKSIZE 16384 41120263Smarcel 42118510Sdeischen#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext) 43118510Sdeischen#define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL) 44113656Sdeischen 45118510Sdeischen#define PER_KSE 46118510Sdeischen#undef PER_THREAD 47116771Smarcel 48118510Sdeischenstruct kse; 49118510Sdeischenstruct pthread; 50118510Sdeischenstruct tdv; 51118510Sdeischen 52116771Smarcel/* 53118510Sdeischen * %gs points to a struct kcb. 54116771Smarcel */ 55118510Sdeischenstruct kcb { 56118510Sdeischen struct tcb *kcb_curtcb; 57118510Sdeischen struct kcb *kcb_self; /* self reference */ 58118510Sdeischen int kcb_ldt; 59118510Sdeischen struct kse *kcb_kse; 60118510Sdeischen struct kse_mailbox kcb_kmbx; 61116771Smarcel}; 62116771Smarcel 63118510Sdeischenstruct tcb { 64118510Sdeischen struct tdv *tcb_tdv; 65118510Sdeischen struct pthread *tcb_thread; 66118510Sdeischen void *tcb_addr; /* allocated tcb address */ 67118510Sdeischen void *tcb_spare; /* align tcb_tmbx to 16 bytes */ 68118510Sdeischen struct kse_thr_mailbox tcb_tmbx; 69118510Sdeischen}; 70118277Sdeischen 71118510Sdeischen/* 72118510Sdeischen * Evaluates to the byte offset of the per-kse variable name. 73118510Sdeischen */ 74118510Sdeischen#define __kcb_offset(name) __offsetof(struct kcb, name) 75118510Sdeischen 76118510Sdeischen/* 77118510Sdeischen * Evaluates to the type of the per-kse variable name. 78118510Sdeischen */ 79118510Sdeischen#define __kcb_type(name) __typeof(((struct kcb *)0)->name) 80118510Sdeischen 81118510Sdeischen/* 82118510Sdeischen * Evaluates to the value of the per-kse variable name. 83118510Sdeischen */ 84118510Sdeischen#define KCB_GET32(name) ({ \ 85118510Sdeischen __kcb_type(name) __result; \ 86118510Sdeischen \ 87118510Sdeischen u_int __i; \ 88118510Sdeischen __asm __volatile("movl %%gs:%1, %0" \ 89118510Sdeischen : "=r" (__i) \ 90118510Sdeischen : "m" (*(u_int *)(__kcb_offset(name)))); \ 91118510Sdeischen __result = *(__kcb_type(name) *)&__i; \ 92118510Sdeischen \ 93118510Sdeischen __result; \ 94118510Sdeischen}) 95118510Sdeischen 96118510Sdeischen/* 97118510Sdeischen * Sets the value of the per-kse variable name to value val. 98118510Sdeischen */ 99118510Sdeischen#define KCB_SET32(name, val) ({ \ 100118510Sdeischen __kcb_type(name) __val = (val); \ 101118510Sdeischen \ 102118510Sdeischen u_int __i; \ 103118510Sdeischen __i = *(u_int *)&__val; \ 104118510Sdeischen __asm __volatile("movl %1,%%gs:%0" \ 105118510Sdeischen : "=m" (*(u_int *)(__kcb_offset(name))) \ 106118510Sdeischen : "r" (__i)); \ 107118510Sdeischen}) 108118510Sdeischen 109118510Sdeischenstatic __inline u_long 110118510Sdeischen__kcb_readandclear32(volatile u_long *addr) 111118510Sdeischen{ 112118510Sdeischen u_long result; 113118510Sdeischen 114118510Sdeischen __asm __volatile ( 115118510Sdeischen " xorl %0, %0;" 116118510Sdeischen " xchgl %%gs:%1, %0;" 117118510Sdeischen "# __kcb_readandclear32" 118118510Sdeischen : "=&r" (result) 119118510Sdeischen : "m" (*addr)); 120118510Sdeischen return (result); 121118510Sdeischen} 122118510Sdeischen 123118510Sdeischen#define KCB_READANDCLEAR32(name) ({ \ 124118510Sdeischen __kcb_type(name) __result; \ 125118510Sdeischen \ 126118510Sdeischen __result = (__kcb_type(name)) \ 127118510Sdeischen __kcb_readandclear32((u_long *)__kcb_offset(name)); \ 128118510Sdeischen __result; \ 129118510Sdeischen}) 130118510Sdeischen 131118510Sdeischen 132118510Sdeischen#define _kcb_curkcb() KCB_GET32(kcb_self) 133118510Sdeischen#define _kcb_curtcb() KCB_GET32(kcb_curtcb) 134118510Sdeischen#define _kcb_curkse() ((struct kse *)KCB_GET32(kcb_kmbx.km_udata)) 135118510Sdeischen#define _kcb_get_tmbx() KCB_GET32(kcb_kmbx.km_curthread) 136118510Sdeischen#define _kcb_set_tmbx(value) KCB_SET32(kcb_kmbx.km_curthread, (void *)value) 137118510Sdeischen#define _kcb_readandclear_tmbx() KCB_READANDCLEAR32(kcb_kmbx.km_curthread) 138118510Sdeischen 139118510Sdeischen 140118510Sdeischen/* 141118510Sdeischen * The constructors. 142118510Sdeischen */ 143118510Sdeischenstruct tcb *_tcb_ctor(struct pthread *); 144118510Sdeischenvoid _tcb_dtor(struct tcb *tcb); 145118510Sdeischenstruct kcb *_kcb_ctor(struct kse *); 146118510Sdeischenvoid _kcb_dtor(struct kcb *); 147118510Sdeischen 148118510Sdeischen/* Called from the KSE to set its private data. */ 149118510Sdeischenstatic __inline void 150118510Sdeischen_kcb_set(struct kcb *kcb) 151118510Sdeischen{ 152118510Sdeischen int val; 153118510Sdeischen 154118510Sdeischen val = (kcb->kcb_ldt << 3) | 7; 155118510Sdeischen __asm __volatile("movl %0, %%gs" : : "r" (val)); 156118510Sdeischen} 157118510Sdeischen 158118510Sdeischen/* Get the current kcb. */ 159118510Sdeischenstatic __inline struct kcb * 160118510Sdeischen_kcb_get(void) 161118510Sdeischen{ 162118510Sdeischen return (_kcb_curkcb()); 163118510Sdeischen} 164118510Sdeischen 165118510Sdeischenstatic __inline struct kse_thr_mailbox * 166118510Sdeischen_kcb_critical_enter(void) 167118510Sdeischen{ 168118510Sdeischen struct kse_thr_mailbox *crit; 169118510Sdeischen 170118510Sdeischen crit = _kcb_readandclear_tmbx(); 171118510Sdeischen return (crit); 172118510Sdeischen} 173118510Sdeischen 174118510Sdeischenstatic __inline void 175118510Sdeischen_kcb_critical_leave(struct kse_thr_mailbox *crit) 176118510Sdeischen{ 177118510Sdeischen _kcb_set_tmbx(crit); 178118510Sdeischen} 179118510Sdeischen 180118277Sdeischenstatic __inline int 181118510Sdeischen_kcb_in_critical(void) 182118277Sdeischen{ 183118510Sdeischen return (_kcb_get_tmbx() == NULL); 184118510Sdeischen} 185118510Sdeischen 186118510Sdeischenstatic __inline void 187118510Sdeischen_tcb_set(struct kcb *kcb, struct tcb *tcb) 188118510Sdeischen{ 189118510Sdeischen kcb->kcb_curtcb = tcb; 190118510Sdeischen} 191118510Sdeischen 192118510Sdeischenstatic __inline struct tcb * 193118510Sdeischen_tcb_get(void) 194118510Sdeischen{ 195118510Sdeischen return (_kcb_curtcb()); 196118510Sdeischen} 197118510Sdeischen 198118510Sdeischenstatic __inline struct pthread * 199118510Sdeischen_get_curthread(void) 200118510Sdeischen{ 201118510Sdeischen struct tcb *tcb; 202118510Sdeischen 203118510Sdeischen tcb = _kcb_curtcb(); 204118510Sdeischen if (tcb != NULL) 205118510Sdeischen return (tcb->tcb_thread); 206118510Sdeischen else 207118510Sdeischen return (NULL); 208118510Sdeischen} 209118510Sdeischen 210118510Sdeischenstatic __inline struct kse * 211118510Sdeischen_get_curkse(void) 212118510Sdeischen{ 213118510Sdeischen return ((struct kse *)_kcb_curkse()); 214118510Sdeischen} 215118510Sdeischen 216118510Sdeischenvoid _i386_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack, 217118510Sdeischen size_t stacksz); 218118510Sdeischen 219118510Sdeischenstatic __inline int 220118510Sdeischen_thread_enter_uts(struct tcb *tcb, struct kcb *kcb) 221118510Sdeischen{ 222118277Sdeischen int ret; 223118277Sdeischen 224118510Sdeischen ret = _thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext); 225118277Sdeischen if (ret == 0) { 226118510Sdeischen _i386_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, 227118510Sdeischen kcb->kcb_kmbx.km_stack.ss_sp, 228118510Sdeischen kcb->kcb_kmbx.km_stack.ss_size); 229118277Sdeischen /* We should not reach here. */ 230118277Sdeischen return (-1); 231118277Sdeischen } 232118277Sdeischen else if (ret < 0) 233118277Sdeischen return (-1); 234118277Sdeischen return (0); 235118277Sdeischen} 236118277Sdeischen 237118277Sdeischenstatic __inline int 238118510Sdeischen_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) 239118277Sdeischen{ 240118510Sdeischen if ((kcb == NULL) || (tcb == NULL)) 241118510Sdeischen return (-1); 242118510Sdeischen kcb->kcb_curtcb = tcb; 243118510Sdeischen if (setmbox != 0) 244118510Sdeischen _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 245118510Sdeischen (intptr_t)&tcb->tcb_tmbx, 246118510Sdeischen (intptr_t *)&kcb->kcb_kmbx.km_curthread); 247118510Sdeischen else 248118510Sdeischen _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 0, NULL); 249118277Sdeischen /* We should not reach here. */ 250118277Sdeischen return (-1); 251118277Sdeischen} 252118277Sdeischen 253113656Sdeischen#endif 254