2 * Copyright (c) 2002 Daniel Eischen <deischen@freebsd.org>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * Machine-dependent thread prototypes/definitions for the thread kernel.
31 #ifndef _PTHREAD_MD_H_
32 #define _PTHREAD_MD_H_
35 #include <sys/types.h>
37 #include <machine/sysarch.h>
40 extern int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *);
41 extern int _thr_getcontext(mcontext_t *);
43 #define KSE_STACKSIZE 16384
44 #define DTV_OFFSET offsetof(struct tcb, tcb_dtv)
46 #define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext)
47 #define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL)
56 * %gs points to a struct kcb.
59 struct tcb *kcb_curtcb;
60 struct kcb *kcb_self; /* self reference */
62 struct kse_mailbox kcb_kmbx;
66 struct tcb *tcb_self; /* required by rtld */
67 void *tcb_dtv; /* required by rtld */
68 struct pthread *tcb_thread;
69 void *tcb_spare; /* align tcb_tmbx to 16 bytes */
70 struct kse_thr_mailbox tcb_tmbx;
74 * Evaluates to the byte offset of the per-kse variable name.
76 #define __kcb_offset(name) __offsetof(struct kcb, name)
79 * Evaluates to the type of the per-kse variable name.
81 #define __kcb_type(name) __typeof(((struct kcb *)0)->name)
84 * Evaluates to the value of the per-kse variable name.
86 #define KCB_GET32(name) ({ \
87 __kcb_type(name) __result; \
90 __asm __volatile("movl %%gs:%1, %0" \
92 : "m" (*(u_int *)(__kcb_offset(name)))); \
93 __result = (__kcb_type(name))__i; \
99 * Sets the value of the per-kse variable name to value val.
101 #define KCB_SET32(name, val) ({ \
102 __kcb_type(name) __val = (val); \
105 __i = (u_int)__val; \
106 __asm __volatile("movl %1,%%gs:%0" \
107 : "=m" (*(u_int *)(__kcb_offset(name))) \
111 static __inline u_long
112 __kcb_readandclear32(volatile u_long *addr)
118 " xchgl %%gs:%1, %0;"
119 "# __kcb_readandclear32"
125 #define KCB_READANDCLEAR32(name) ({ \
126 __kcb_type(name) __result; \
128 __result = (__kcb_type(name)) \
129 __kcb_readandclear32((u_long *)__kcb_offset(name)); \
134 #define _kcb_curkcb() KCB_GET32(kcb_self)
135 #define _kcb_curtcb() KCB_GET32(kcb_curtcb)
136 #define _kcb_curkse() ((struct kse *)KCB_GET32(kcb_kmbx.km_udata))
137 #define _kcb_get_tmbx() KCB_GET32(kcb_kmbx.km_curthread)
138 #define _kcb_set_tmbx(value) KCB_SET32(kcb_kmbx.km_curthread, (void *)value)
139 #define _kcb_readandclear_tmbx() KCB_READANDCLEAR32(kcb_kmbx.km_curthread)
145 struct tcb *_tcb_ctor(struct pthread *, int);
146 void _tcb_dtor(struct tcb *tcb);
147 struct kcb *_kcb_ctor(struct kse *);
148 void _kcb_dtor(struct kcb *);
150 /* Called from the KSE to set its private data. */
152 _kcb_set(struct kcb *kcb)
154 i386_set_gsbase(kcb);
157 /* Get the current kcb. */
158 static __inline struct kcb *
161 return (_kcb_curkcb());
164 static __inline struct kse_thr_mailbox *
165 _kcb_critical_enter(void)
167 struct kse_thr_mailbox *crit;
169 crit = _kcb_readandclear_tmbx();
174 _kcb_critical_leave(struct kse_thr_mailbox *crit)
180 _kcb_in_critical(void)
182 return (_kcb_get_tmbx() == NULL);
186 _tcb_set(struct kcb *kcb, struct tcb *tcb)
188 kcb->kcb_curtcb = tcb;
191 static __inline struct tcb *
194 return (_kcb_curtcb());
197 static __inline struct pthread *
204 return (tcb->tcb_thread);
209 static __inline struct kse *
212 return ((struct kse *)_kcb_curkse());
215 void _i386_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack,
219 _thread_enter_uts(struct tcb *tcb, struct kcb *kcb)
223 ret = _thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext);
225 _i386_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func,
226 kcb->kcb_kmbx.km_stack.ss_sp,
227 kcb->kcb_kmbx.km_stack.ss_size);
228 /* We should not reach here. */
237 _thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox)
239 extern int _libkse_debug;
241 if ((kcb == NULL) || (tcb == NULL))
243 kcb->kcb_curtcb = tcb;
244 if (_libkse_debug == 0) {
245 tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp;
247 _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext,
248 (intptr_t)&tcb->tcb_tmbx,
249 (intptr_t *)(void *)&kcb->kcb_kmbx.km_curthread);
251 _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext,
255 kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX);
257 kse_switchin(&tcb->tcb_tmbx, 0);
260 /* We should not reach here. */