Deleted Added
sdiff udiff text old ( 133756 ) new ( 133801 )
full compact
1/*-
2 * Copyright (c) 2002 Daniel Eischen <deischen@freebsd.org>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/lib/libkse/arch/i386/include/pthread_md.h 133801 2004-08-16 03:27:29Z davidxu $
27 */
28/*
29 * Machine-dependent thread prototypes/definitions for the thread kernel.
30 */
31#ifndef _PTHREAD_MD_H_
32#define _PTHREAD_MD_H_
33
34#include <stddef.h>
35#include <sys/kse.h>
36#include <ucontext.h>
37
38extern int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *);
39extern int _thr_getcontext(mcontext_t *);
40
41#define KSE_STACKSIZE 16384
42#define DTV_OFFSET offsetof(struct tcb, tcb_dtv)
43
44#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext)
45#define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL)
46
47#define PER_KSE
48#undef PER_THREAD
49
50struct kse;
51struct pthread;
52
53/*
54 * %gs points to a struct kcb.
55 */
56struct kcb {
57 struct tcb *kcb_curtcb;
58 struct kcb *kcb_self; /* self reference */
59 int kcb_ldt;
60 struct kse *kcb_kse;
61 struct kse_mailbox kcb_kmbx;
62};
63
64struct tcb {
65 struct tcb *tcb_self; /* required by rtld */
66 void *tcb_dtv; /* required by rtld */
67 struct pthread *tcb_thread;
68 void *tcb_spare; /* align tcb_tmbx to 16 bytes */
69 struct kse_thr_mailbox tcb_tmbx;
70};
71
72/*
73 * Evaluates to the byte offset of the per-kse variable name.
74 */
75#define __kcb_offset(name) __offsetof(struct kcb, name)
76
77/*
78 * Evaluates to the type of the per-kse variable name.
79 */
80#define __kcb_type(name) __typeof(((struct kcb *)0)->name)
81
82/*
83 * Evaluates to the value of the per-kse variable name.
84 */
85#define KCB_GET32(name) ({ \
86 __kcb_type(name) __result; \
87 \
88 u_int __i; \
89 __asm __volatile("movl %%gs:%1, %0" \
90 : "=r" (__i) \
91 : "m" (*(u_int *)(__kcb_offset(name)))); \
92 __result = *(__kcb_type(name) *)&__i; \
93 \
94 __result; \
95})
96
97/*
98 * Sets the value of the per-kse variable name to value val.
99 */
100#define KCB_SET32(name, val) ({ \
101 __kcb_type(name) __val = (val); \
102 \
103 u_int __i; \
104 __i = *(u_int *)&__val; \
105 __asm __volatile("movl %1,%%gs:%0" \
106 : "=m" (*(u_int *)(__kcb_offset(name))) \
107 : "r" (__i)); \
108})
109
110static __inline u_long
111__kcb_readandclear32(volatile u_long *addr)
112{
113 u_long result;
114
115 __asm __volatile (
116 " xorl %0, %0;"
117 " xchgl %%gs:%1, %0;"
118 "# __kcb_readandclear32"
119 : "=&r" (result)
120 : "m" (*addr));
121 return (result);
122}
123
124#define KCB_READANDCLEAR32(name) ({ \
125 __kcb_type(name) __result; \
126 \
127 __result = (__kcb_type(name)) \
128 __kcb_readandclear32((u_long *)__kcb_offset(name)); \
129 __result; \
130})
131
132
133#define _kcb_curkcb() KCB_GET32(kcb_self)
134#define _kcb_curtcb() KCB_GET32(kcb_curtcb)
135#define _kcb_curkse() ((struct kse *)KCB_GET32(kcb_kmbx.km_udata))
136#define _kcb_get_tmbx() KCB_GET32(kcb_kmbx.km_curthread)
137#define _kcb_set_tmbx(value) KCB_SET32(kcb_kmbx.km_curthread, (void *)value)
138#define _kcb_readandclear_tmbx() KCB_READANDCLEAR32(kcb_kmbx.km_curthread)
139
140
141/*
142 * The constructors.
143 */
144struct tcb *_tcb_ctor(struct pthread *, int);
145void _tcb_dtor(struct tcb *tcb);
146struct kcb *_kcb_ctor(struct kse *);
147void _kcb_dtor(struct kcb *);
148
149/* Called from the KSE to set its private data. */
150static __inline void
151_kcb_set(struct kcb *kcb)
152{
153 int val;
154
155 val = (kcb->kcb_ldt << 3) | 7;
156 __asm __volatile("movl %0, %%gs" : : "r" (val));
157}
158
159/* Get the current kcb. */
160static __inline struct kcb *
161_kcb_get(void)
162{
163 return (_kcb_curkcb());
164}
165
166static __inline struct kse_thr_mailbox *
167_kcb_critical_enter(void)
168{
169 struct kse_thr_mailbox *crit;
170
171 crit = _kcb_readandclear_tmbx();
172 return (crit);
173}
174
175static __inline void
176_kcb_critical_leave(struct kse_thr_mailbox *crit)
177{
178 _kcb_set_tmbx(crit);
179}
180
181static __inline int
182_kcb_in_critical(void)
183{
184 return (_kcb_get_tmbx() == NULL);
185}
186
187static __inline void
188_tcb_set(struct kcb *kcb, struct tcb *tcb)
189{
190 kcb->kcb_curtcb = tcb;
191}
192
193static __inline struct tcb *
194_tcb_get(void)
195{
196 return (_kcb_curtcb());
197}
198
199static __inline struct pthread *
200_get_curthread(void)
201{
202 struct tcb *tcb;
203
204 tcb = _kcb_curtcb();
205 if (tcb != NULL)
206 return (tcb->tcb_thread);
207 else
208 return (NULL);
209}
210
211static __inline struct kse *
212_get_curkse(void)
213{
214 return ((struct kse *)_kcb_curkse());
215}
216
217void _i386_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack,
218 size_t stacksz);
219
220static __inline int
221_thread_enter_uts(struct tcb *tcb, struct kcb *kcb)
222{
223 int ret;
224
225 ret = _thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext);
226 if (ret == 0) {
227 _i386_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func,
228 kcb->kcb_kmbx.km_stack.ss_sp,
229 kcb->kcb_kmbx.km_stack.ss_size);
230 /* We should not reach here. */
231 return (-1);
232 }
233 else if (ret < 0)
234 return (-1);
235 return (0);
236}
237
238static __inline int
239_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox)
240{
241 extern int _libkse_debug;
242
243 if ((kcb == NULL) || (tcb == NULL))
244 return (-1);
245 kcb->kcb_curtcb = tcb;
246 if (_libkse_debug == 0) {
247 tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp;
248 if (setmbox != 0)
249 _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext,
250 (intptr_t)&tcb->tcb_tmbx,
251 (intptr_t *)&kcb->kcb_kmbx.km_curthread);
252 else
253 _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext,
254 0, NULL);
255 } else {
256 if (setmbox)
257 kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX);
258 else
259 kse_switchin(&tcb->tcb_tmbx, 0);
260 }
261
262 /* We should not reach here. */
263 return (-1);
264}
265
266#endif