pthread_md.h revision 120263
1283514Sarybchik/*- 2283514Sarybchik * Copyright (c) 2002 Daniel Eischen <deischen@freebsd.org>. 3283514Sarybchik * All rights reserved. 4283514Sarybchik * 5283514Sarybchik * Redistribution and use in source and binary forms, with or without 6283514Sarybchik * modification, are permitted provided that the following conditions 7283514Sarybchik * are met: 8283514Sarybchik * 1. Redistributions of source code must retain the above copyright 9283514Sarybchik * notice, this list of conditions and the following disclaimer. 10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright 11283514Sarybchik * notice, this list of conditions and the following disclaimer in the 12283514Sarybchik * documentation and/or other materials provided with the distribution. 13283514Sarybchik * 14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15283514Sarybchik * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16283514Sarybchik * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17283514Sarybchik * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18283514Sarybchik * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19283514Sarybchik * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20283514Sarybchik * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21283514Sarybchik * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22283514Sarybchik * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23283514Sarybchik * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24283514Sarybchik * SUCH DAMAGE. 25283514Sarybchik * 26283514Sarybchik * $FreeBSD: head/lib/libkse/arch/i386/include/pthread_md.h 120263 2003-09-19 23:28:13Z marcel $ 27283514Sarybchik */ 28283514Sarybchik/* 29283514Sarybchik * Machine-dependent thread prototypes/definitions for the thread kernel. 30283514Sarybchik */ 31283514Sarybchik#ifndef _PTHREAD_MD_H_ 32283514Sarybchik#define _PTHREAD_MD_H_ 33283514Sarybchik 34283514Sarybchik#include <sys/kse.h> 35283514Sarybchik#include <ucontext.h> 36283514Sarybchik 37283514Sarybchikextern int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *); 38283514Sarybchikextern int _thr_getcontext(mcontext_t *); 39283514Sarybchik 40283514Sarybchik#define KSE_STACKSIZE 16384 41283514Sarybchik 42283514Sarybchik#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext) 43283514Sarybchik#define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL) 44283514Sarybchik 45283514Sarybchik#define PER_KSE 46283514Sarybchik#undef PER_THREAD 47283514Sarybchik 48283514Sarybchikstruct kse; 49283514Sarybchikstruct pthread; 50283514Sarybchikstruct tdv; 51283514Sarybchik 52283514Sarybchik/* 53283514Sarybchik * %gs points to a struct kcb. 54283514Sarybchik */ 55293974Sarybchikstruct kcb { 56293974Sarybchik struct tcb *kcb_curtcb; 57293974Sarybchik struct kcb *kcb_self; /* self reference */ 58283514Sarybchik int kcb_ldt; 59283514Sarybchik struct kse *kcb_kse; 60283514Sarybchik struct kse_mailbox kcb_kmbx; 61283514Sarybchik}; 62283514Sarybchik 63283514Sarybchikstruct tcb { 64283514Sarybchik struct tdv *tcb_tdv; 65283514Sarybchik struct pthread *tcb_thread; 66283514Sarybchik void *tcb_addr; /* allocated tcb address */ 67283514Sarybchik void *tcb_spare; /* align tcb_tmbx to 16 bytes */ 68283514Sarybchik struct kse_thr_mailbox tcb_tmbx; 69283514Sarybchik}; 70293974Sarybchik 71293974Sarybchik/* 72293974Sarybchik * Evaluates to the byte offset of the per-kse variable name. 73283514Sarybchik */ 74283514Sarybchik#define __kcb_offset(name) __offsetof(struct kcb, name) 75283514Sarybchik 76283514Sarybchik/* 77283514Sarybchik * Evaluates to the type of the per-kse variable name. 78293974Sarybchik */ 79293974Sarybchik#define __kcb_type(name) __typeof(((struct kcb *)0)->name) 80293974Sarybchik 81283514Sarybchik/* 82283514Sarybchik * Evaluates to the value of the per-kse variable name. 83283514Sarybchik */ 84283514Sarybchik#define KCB_GET32(name) ({ \ 85283514Sarybchik __kcb_type(name) __result; \ 86283514Sarybchik \ 87283514Sarybchik u_int __i; \ 88283514Sarybchik __asm __volatile("movl %%gs:%1, %0" \ 89283514Sarybchik : "=r" (__i) \ 90283514Sarybchik : "m" (*(u_int *)(__kcb_offset(name)))); \ 91283514Sarybchik __result = *(__kcb_type(name) *)&__i; \ 92283514Sarybchik \ 93293974Sarybchik __result; \ 94293974Sarybchik}) 95293974Sarybchik 96283514Sarybchik/* 97283514Sarybchik * Sets the value of the per-kse variable name to value val. 98283514Sarybchik */ 99293974Sarybchik#define KCB_SET32(name, val) ({ \ 100283514Sarybchik __kcb_type(name) __val = (val); \ 101293974Sarybchik \ 102283514Sarybchik u_int __i; \ 103283514Sarybchik __i = *(u_int *)&__val; \ 104283514Sarybchik __asm __volatile("movl %1,%%gs:%0" \ 105283514Sarybchik : "=m" (*(u_int *)(__kcb_offset(name))) \ 106283514Sarybchik : "r" (__i)); \ 107293974Sarybchik}) 108293974Sarybchik 109293974Sarybchikstatic __inline u_long 110283514Sarybchik__kcb_readandclear32(volatile u_long *addr) 111283514Sarybchik{ 112283514Sarybchik u_long result; 113283514Sarybchik 114283514Sarybchik __asm __volatile ( 115283514Sarybchik " xorl %0, %0;" 116283514Sarybchik " xchgl %%gs:%1, %0;" 117283514Sarybchik "# __kcb_readandclear32" 118283514Sarybchik : "=&r" (result) 119283514Sarybchik : "m" (*addr)); 120283514Sarybchik return (result); 121283514Sarybchik} 122283514Sarybchik 123283514Sarybchik#define KCB_READANDCLEAR32(name) ({ \ 124283514Sarybchik __kcb_type(name) __result; \ 125283514Sarybchik \ 126283514Sarybchik __result = (__kcb_type(name)) \ 127283514Sarybchik __kcb_readandclear32((u_long *)__kcb_offset(name)); \ 128283514Sarybchik __result; \ 129293974Sarybchik}) 130293974Sarybchik 131293974Sarybchik 132283514Sarybchik#define _kcb_curkcb() KCB_GET32(kcb_self) 133283514Sarybchik#define _kcb_curtcb() KCB_GET32(kcb_curtcb) 134283514Sarybchik#define _kcb_curkse() ((struct kse *)KCB_GET32(kcb_kmbx.km_udata)) 135283514Sarybchik#define _kcb_get_tmbx() KCB_GET32(kcb_kmbx.km_curthread) 136283514Sarybchik#define _kcb_set_tmbx(value) KCB_SET32(kcb_kmbx.km_curthread, (void *)value) 137293974Sarybchik#define _kcb_readandclear_tmbx() KCB_READANDCLEAR32(kcb_kmbx.km_curthread) 138293974Sarybchik 139283514Sarybchik 140283514Sarybchik/* 141283514Sarybchik * The constructors. 142293974Sarybchik */ 143293974Sarybchikstruct tcb *_tcb_ctor(struct pthread *); 144293974Sarybchikvoid _tcb_dtor(struct tcb *tcb); 145293974Sarybchikstruct kcb *_kcb_ctor(struct kse *); 146283514Sarybchikvoid _kcb_dtor(struct kcb *); 147283514Sarybchik 148293939Sarybchik/* Called from the KSE to set its private data. */ 149293939Sarybchikstatic __inline void 150293939Sarybchik_kcb_set(struct kcb *kcb) 151293939Sarybchik{ 152293939Sarybchik int val; 153293939Sarybchik 154293939Sarybchik val = (kcb->kcb_ldt << 3) | 7; 155293958Sarybchik __asm __volatile("movl %0, %%gs" : : "r" (val)); 156293958Sarybchik} 157293958Sarybchik 158293958Sarybchik/* Get the current kcb. */ 159293958Sarybchikstatic __inline struct kcb * 160293958Sarybchik_kcb_get(void) 161293958Sarybchik{ 162283514Sarybchik return (_kcb_curkcb()); 163283514Sarybchik} 164283514Sarybchik 165283514Sarybchikstatic __inline struct kse_thr_mailbox * 166283514Sarybchik_kcb_critical_enter(void) 167283514Sarybchik{ 168283514Sarybchik struct kse_thr_mailbox *crit; 169283514Sarybchik 170283514Sarybchik crit = _kcb_readandclear_tmbx(); 171283514Sarybchik return (crit); 172283514Sarybchik} 173283514Sarybchik 174283514Sarybchikstatic __inline void 175283514Sarybchik_kcb_critical_leave(struct kse_thr_mailbox *crit) 176283514Sarybchik{ 177283514Sarybchik _kcb_set_tmbx(crit); 178283514Sarybchik} 179283514Sarybchik 180283514Sarybchikstatic __inline int 181283514Sarybchik_kcb_in_critical(void) 182283514Sarybchik{ 183293999Sarybchik return (_kcb_get_tmbx() == NULL); 184283514Sarybchik} 185293999Sarybchik 186283514Sarybchikstatic __inline void 187283514Sarybchik_tcb_set(struct kcb *kcb, struct tcb *tcb) 188293999Sarybchik{ 189283514Sarybchik kcb->kcb_curtcb = tcb; 190293999Sarybchik} 191283514Sarybchik 192283514Sarybchikstatic __inline struct tcb * 193283514Sarybchik_tcb_get(void) 194283514Sarybchik{ 195293974Sarybchik return (_kcb_curtcb()); 196293974Sarybchik} 197293974Sarybchik 198283514Sarybchikstatic __inline struct pthread * 199283514Sarybchik_get_curthread(void) 200283514Sarybchik{ 201283514Sarybchik struct tcb *tcb; 202283514Sarybchik 203293974Sarybchik tcb = _kcb_curtcb(); 204293974Sarybchik if (tcb != NULL) 205283514Sarybchik return (tcb->tcb_thread); 206283514Sarybchik else 207283514Sarybchik return (NULL); 208283514Sarybchik} 209283514Sarybchik 210283514Sarybchikstatic __inline struct kse * 211283514Sarybchik_get_curkse(void) 212283514Sarybchik{ 213283514Sarybchik return ((struct kse *)_kcb_curkse()); 214283514Sarybchik} 215283514Sarybchik 216283514Sarybchikvoid _i386_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack, 217283514Sarybchik size_t stacksz); 218283514Sarybchik 219293974Sarybchikstatic __inline int 220293974Sarybchik_thread_enter_uts(struct tcb *tcb, struct kcb *kcb) 221293974Sarybchik{ 222283514Sarybchik int ret; 223283514Sarybchik 224283514Sarybchik ret = _thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext); 225283514Sarybchik if (ret == 0) { 226283514Sarybchik _i386_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, 227283514Sarybchik kcb->kcb_kmbx.km_stack.ss_sp, 228283514Sarybchik kcb->kcb_kmbx.km_stack.ss_size); 229283514Sarybchik /* We should not reach here. */ 230283514Sarybchik return (-1); 231283514Sarybchik } 232283514Sarybchik else if (ret < 0) 233283514Sarybchik return (-1); 234283514Sarybchik return (0); 235283514Sarybchik} 236283514Sarybchik 237283514Sarybchikstatic __inline int 238283514Sarybchik_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) 239283514Sarybchik{ 240283514Sarybchik if ((kcb == NULL) || (tcb == NULL)) 241283514Sarybchik return (-1); 242283514Sarybchik kcb->kcb_curtcb = tcb; 243283514Sarybchik if (setmbox != 0) 244283514Sarybchik _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 245283514Sarybchik (intptr_t)&tcb->tcb_tmbx, 246283514Sarybchik (intptr_t *)&kcb->kcb_kmbx.km_curthread); 247283514Sarybchik else 248283514Sarybchik _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 0, NULL); 249283514Sarybchik /* We should not reach here. */ 250283514Sarybchik return (-1); 251283514Sarybchik} 252283514Sarybchik 253283514Sarybchik#endif 254283514Sarybchik