Deleted Added
full compact
pthread_md.h (133857) pthread_md.h (161802)
1/*
1/*
2 * Copyright (c) 2003 Marcel Moolenaar
2 * Copyright (c) 2003-2006 Marcel Moolenaar
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 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
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 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: head/lib/libkse/arch/ia64/include/pthread_md.h 133857 2004-08-16 14:07:38Z davidxu $
26 * $FreeBSD: head/lib/libkse/arch/ia64/include/pthread_md.h 161802 2006-09-01 06:17:16Z marcel $
27 */
28
29#ifndef _PTHREAD_MD_H_
30#define _PTHREAD_MD_H_
31
32#include <sys/kse.h>
33#include <stddef.h>
34#include <ucontext.h>
35
36#define KSE_STACKSIZE 16384
27 */
28
29#ifndef _PTHREAD_MD_H_
30#define _PTHREAD_MD_H_
31
32#include <sys/kse.h>
33#include <stddef.h>
34#include <ucontext.h>
35
36#define KSE_STACKSIZE 16384
37#define DTV_OFFSET offsetof(struct tcb, tcb_tp.tp_tdv)
37#define DTV_OFFSET offsetof(struct tcb, tcb_tp.tp_dtv)
38
39#define THR_GETCONTEXT(ucp) _ia64_save_context(&(ucp)->uc_mcontext)
40#define THR_SETCONTEXT(ucp) PANIC("THR_SETCONTEXT() now in use!\n")
41
42#define PER_THREAD
43
44struct kcb;
45struct kse;
46struct pthread;
47struct tcb;
38
39#define THR_GETCONTEXT(ucp) _ia64_save_context(&(ucp)->uc_mcontext)
40#define THR_SETCONTEXT(ucp) PANIC("THR_SETCONTEXT() now in use!\n")
41
42#define PER_THREAD
43
44struct kcb;
45struct kse;
46struct pthread;
47struct tcb;
48struct tdv; /* We don't know what this is yet? */
49
50/*
51 * tp points to one of these. We define the static TLS as an array
52 * of long double to enforce 16-byte alignment of the TLS memory,
53 * struct ia64_tp, struct tcb and also struct kcb. Both static and
54 * dynamic allocation of any of these structures will result in a
55 * valid, well-aligned thread pointer.
56 */
57struct ia64_tp {
48
49/*
50 * tp points to one of these. We define the static TLS as an array
51 * of long double to enforce 16-byte alignment of the TLS memory,
52 * struct ia64_tp, struct tcb and also struct kcb. Both static and
53 * dynamic allocation of any of these structures will result in a
54 * valid, well-aligned thread pointer.
55 */
56struct ia64_tp {
58 struct tdv *tp_tdv; /* dynamic TLS */
57 void *tp_dtv; /* dynamic thread vector. */
59 uint64_t _reserved_;
60 long double tp_tls[0]; /* static TLS */
61};
62
63struct tcb {
64 struct kse_thr_mailbox tcb_tmbx;
65 struct pthread *tcb_thread;
66 struct kcb *tcb_curkcb;
67 long tcb_isfake;
68 struct ia64_tp tcb_tp;
69};
70
71struct kcb {
72 struct kse_mailbox kcb_kmbx;
58 uint64_t _reserved_;
59 long double tp_tls[0]; /* static TLS */
60};
61
62struct tcb {
63 struct kse_thr_mailbox tcb_tmbx;
64 struct pthread *tcb_thread;
65 struct kcb *tcb_curkcb;
66 long tcb_isfake;
67 struct ia64_tp tcb_tp;
68};
69
70struct kcb {
71 struct kse_mailbox kcb_kmbx;
73 struct tcb kcb_faketcb;
74 struct tcb *kcb_curtcb;
75 struct kse *kcb_kse;
72 struct kse *kcb_kse;
73 struct tcb *kcb_curtcb;
74 struct tcb kcb_faketcb;
76};
77
75};
76
78register struct ia64_tp *_tp __asm("%r13");
77register struct ia64_tp *_tp __asm("r13");
78#define IA64_SET_TP(x) __asm __volatile("mov r13 = %0;;" :: "r"(x))
79
80#define _tcb ((struct tcb*)((char*)(_tp) - offsetof(struct tcb, tcb_tp)))
81
82/*
83 * The kcb and tcb constructors.
84 */
85struct tcb *_tcb_ctor(struct pthread *, int);
86void _tcb_dtor(struct tcb *);
87struct kcb *_kcb_ctor(struct kse *kse);
88void _kcb_dtor(struct kcb *);
89
90/* Called from the KSE to set its private data. */
91static __inline void
92_kcb_set(struct kcb *kcb)
93{
94 /* There is no thread yet; use the fake tcb. */
79
80#define _tcb ((struct tcb*)((char*)(_tp) - offsetof(struct tcb, tcb_tp)))
81
82/*
83 * The kcb and tcb constructors.
84 */
85struct tcb *_tcb_ctor(struct pthread *, int);
86void _tcb_dtor(struct tcb *);
87struct kcb *_kcb_ctor(struct kse *kse);
88void _kcb_dtor(struct kcb *);
89
90/* Called from the KSE to set its private data. */
91static __inline void
92_kcb_set(struct kcb *kcb)
93{
94 /* There is no thread yet; use the fake tcb. */
95 _tp = &kcb->kcb_faketcb.tcb_tp;
95 IA64_SET_TP(&kcb->kcb_faketcb.tcb_tp);
96}
97
98/*
99 * Get the current kcb.
100 *
101 * This can only be called while in a critical region; don't
102 * worry about having the kcb changed out from under us.
103 */
104static __inline struct kcb *
105_kcb_get(void)
106{
107 return (_tcb->tcb_curkcb);
108}
109
110/*
111 * Enter a critical region.
112 *
113 * Read and clear km_curthread in the kse mailbox.
114 */
115static __inline struct kse_thr_mailbox *
116_kcb_critical_enter(void)
117{
118 struct kse_thr_mailbox *crit;
119 uint32_t flags;
120
121 if (_tcb->tcb_isfake != 0) {
122 /*
123 * We already are in a critical region since
124 * there is no current thread.
125 */
126 crit = NULL;
127 } else {
128 flags = _tcb->tcb_tmbx.tm_flags;
129 _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL;
130 crit = _tcb->tcb_curkcb->kcb_kmbx.km_curthread;
131 _tcb->tcb_curkcb->kcb_kmbx.km_curthread = NULL;
132 _tcb->tcb_tmbx.tm_flags = flags;
133 }
134 return (crit);
135}
136
137static __inline void
138_kcb_critical_leave(struct kse_thr_mailbox *crit)
139{
140 /* No need to do anything if this is a fake tcb. */
141 if (_tcb->tcb_isfake == 0)
142 _tcb->tcb_curkcb->kcb_kmbx.km_curthread = crit;
143}
144
145static __inline int
146_kcb_in_critical(void)
147{
148 uint32_t flags;
149 int ret;
150
151 if (_tcb->tcb_isfake != 0) {
152 /*
153 * We are in a critical region since there is no
154 * current thread.
155 */
156 ret = 1;
157 } else {
158 flags = _tcb->tcb_tmbx.tm_flags;
159 _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL;
160 ret = (_tcb->tcb_curkcb->kcb_kmbx.km_curthread == NULL);
161 _tcb->tcb_tmbx.tm_flags = flags;
162 }
163 return (ret);
164}
165
166static __inline void
167_tcb_set(struct kcb *kcb, struct tcb *tcb)
168{
169 if (tcb == NULL)
170 tcb = &kcb->kcb_faketcb;
171 kcb->kcb_curtcb = tcb;
172 tcb->tcb_curkcb = kcb;
96}
97
98/*
99 * Get the current kcb.
100 *
101 * This can only be called while in a critical region; don't
102 * worry about having the kcb changed out from under us.
103 */
104static __inline struct kcb *
105_kcb_get(void)
106{
107 return (_tcb->tcb_curkcb);
108}
109
110/*
111 * Enter a critical region.
112 *
113 * Read and clear km_curthread in the kse mailbox.
114 */
115static __inline struct kse_thr_mailbox *
116_kcb_critical_enter(void)
117{
118 struct kse_thr_mailbox *crit;
119 uint32_t flags;
120
121 if (_tcb->tcb_isfake != 0) {
122 /*
123 * We already are in a critical region since
124 * there is no current thread.
125 */
126 crit = NULL;
127 } else {
128 flags = _tcb->tcb_tmbx.tm_flags;
129 _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL;
130 crit = _tcb->tcb_curkcb->kcb_kmbx.km_curthread;
131 _tcb->tcb_curkcb->kcb_kmbx.km_curthread = NULL;
132 _tcb->tcb_tmbx.tm_flags = flags;
133 }
134 return (crit);
135}
136
137static __inline void
138_kcb_critical_leave(struct kse_thr_mailbox *crit)
139{
140 /* No need to do anything if this is a fake tcb. */
141 if (_tcb->tcb_isfake == 0)
142 _tcb->tcb_curkcb->kcb_kmbx.km_curthread = crit;
143}
144
145static __inline int
146_kcb_in_critical(void)
147{
148 uint32_t flags;
149 int ret;
150
151 if (_tcb->tcb_isfake != 0) {
152 /*
153 * We are in a critical region since there is no
154 * current thread.
155 */
156 ret = 1;
157 } else {
158 flags = _tcb->tcb_tmbx.tm_flags;
159 _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL;
160 ret = (_tcb->tcb_curkcb->kcb_kmbx.km_curthread == NULL);
161 _tcb->tcb_tmbx.tm_flags = flags;
162 }
163 return (ret);
164}
165
166static __inline void
167_tcb_set(struct kcb *kcb, struct tcb *tcb)
168{
169 if (tcb == NULL)
170 tcb = &kcb->kcb_faketcb;
171 kcb->kcb_curtcb = tcb;
172 tcb->tcb_curkcb = kcb;
173 _tp = &tcb->tcb_tp;
173 IA64_SET_TP(&tcb->tcb_tp);
174}
175
176static __inline struct tcb *
177_tcb_get(void)
178{
179 return (_tcb);
180}
181
182static __inline struct pthread *
183_get_curthread(void)
184{
185 return (_tcb->tcb_thread);
186}
187
188/*
189 * Get the current kse.
190 *
191 * Like _kcb_get(), this can only be called while in a critical region.
192 */
193static __inline struct kse *
194_get_curkse(void)
195{
196 return (_tcb->tcb_curkcb->kcb_kse);
197}
198
199void _ia64_break_setcontext(mcontext_t *mc);
200void _ia64_enter_uts(kse_func_t uts, struct kse_mailbox *km, void *stack,
201 size_t stacksz);
202int _ia64_restore_context(mcontext_t *mc, intptr_t val, intptr_t *loc);
203int _ia64_save_context(mcontext_t *mc);
204
205static __inline int
206_thread_enter_uts(struct tcb *tcb, struct kcb *kcb)
207{
208 if (_ia64_save_context(&tcb->tcb_tmbx.tm_context.uc_mcontext) == 0) {
209 /* Make the fake tcb the current thread. */
210 kcb->kcb_curtcb = &kcb->kcb_faketcb;
174}
175
176static __inline struct tcb *
177_tcb_get(void)
178{
179 return (_tcb);
180}
181
182static __inline struct pthread *
183_get_curthread(void)
184{
185 return (_tcb->tcb_thread);
186}
187
188/*
189 * Get the current kse.
190 *
191 * Like _kcb_get(), this can only be called while in a critical region.
192 */
193static __inline struct kse *
194_get_curkse(void)
195{
196 return (_tcb->tcb_curkcb->kcb_kse);
197}
198
199void _ia64_break_setcontext(mcontext_t *mc);
200void _ia64_enter_uts(kse_func_t uts, struct kse_mailbox *km, void *stack,
201 size_t stacksz);
202int _ia64_restore_context(mcontext_t *mc, intptr_t val, intptr_t *loc);
203int _ia64_save_context(mcontext_t *mc);
204
205static __inline int
206_thread_enter_uts(struct tcb *tcb, struct kcb *kcb)
207{
208 if (_ia64_save_context(&tcb->tcb_tmbx.tm_context.uc_mcontext) == 0) {
209 /* Make the fake tcb the current thread. */
210 kcb->kcb_curtcb = &kcb->kcb_faketcb;
211 _tp = &kcb->kcb_faketcb.tcb_tp;
211 IA64_SET_TP(&kcb->kcb_faketcb.tcb_tp);
212 _ia64_enter_uts(kcb->kcb_kmbx.km_func, &kcb->kcb_kmbx,
213 kcb->kcb_kmbx.km_stack.ss_sp,
214 kcb->kcb_kmbx.km_stack.ss_size);
215 /* We should not reach here. */
216 return (-1);
217 }
218 return (0);
219}
220
221static __inline int
222_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox)
223{
224 mcontext_t *mc;
225
226 _tcb_set(kcb, tcb);
227 mc = &tcb->tcb_tmbx.tm_context.uc_mcontext;
228 if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) {
229 if (setmbox) {
230 mc->mc_flags |= _MC_FLAGS_KSE_SET_MBOX;
231 mc->mc_special.ifa =
232 (intptr_t)&kcb->kcb_kmbx.km_curthread;
233 mc->mc_special.isr = (intptr_t)&tcb->tcb_tmbx;
234 }
235 _ia64_break_setcontext(mc);
236 } else if (mc->mc_flags & _MC_FLAGS_SYSCALL_CONTEXT) {
237 if (setmbox)
238 kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX);
239 else
240 kse_switchin(&tcb->tcb_tmbx, 0);
241 } else {
242 if (setmbox)
243 _ia64_restore_context(mc, (intptr_t)&tcb->tcb_tmbx,
244 (intptr_t *)&kcb->kcb_kmbx.km_curthread);
245 else
246 _ia64_restore_context(mc, 0, NULL);
247 }
248 /* We should not reach here. */
249 return (-1);
250}
251
252#endif /* _PTHREAD_MD_H_ */
212 _ia64_enter_uts(kcb->kcb_kmbx.km_func, &kcb->kcb_kmbx,
213 kcb->kcb_kmbx.km_stack.ss_sp,
214 kcb->kcb_kmbx.km_stack.ss_size);
215 /* We should not reach here. */
216 return (-1);
217 }
218 return (0);
219}
220
221static __inline int
222_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox)
223{
224 mcontext_t *mc;
225
226 _tcb_set(kcb, tcb);
227 mc = &tcb->tcb_tmbx.tm_context.uc_mcontext;
228 if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) {
229 if (setmbox) {
230 mc->mc_flags |= _MC_FLAGS_KSE_SET_MBOX;
231 mc->mc_special.ifa =
232 (intptr_t)&kcb->kcb_kmbx.km_curthread;
233 mc->mc_special.isr = (intptr_t)&tcb->tcb_tmbx;
234 }
235 _ia64_break_setcontext(mc);
236 } else if (mc->mc_flags & _MC_FLAGS_SYSCALL_CONTEXT) {
237 if (setmbox)
238 kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX);
239 else
240 kse_switchin(&tcb->tcb_tmbx, 0);
241 } else {
242 if (setmbox)
243 _ia64_restore_context(mc, (intptr_t)&tcb->tcb_tmbx,
244 (intptr_t *)&kcb->kcb_kmbx.km_curthread);
245 else
246 _ia64_restore_context(mc, 0, NULL);
247 }
248 /* We should not reach here. */
249 return (-1);
250}
251
252#endif /* _PTHREAD_MD_H_ */