1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
/* Internal per-thread variables for the Hurd.
Copyright (C) 1994, 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _HURD_THREADVAR_H
#define _HURD_THREADVAR_H
/* The per-thread variables are found by ANDing this mask
with the value of the stack pointer and then adding this offset.
In the multi-threaded case, cthreads initialization sets
__hurd_threadvar_stack_mask to ~(cthread_stack_size - 1), a mask which
finds the base of the fixed-size cthreads stack; and
__hurd_threadvar_stack_offset to a small offset that skips the data
cthreads itself maintains at the base of each thread's stack.
In the single-threaded case, __hurd_threadvar_stack_mask is zero, so the
stack pointer is ignored; and __hurd_threadvar_stack_offset gives the
address of a small allocated region which contains the variables for the
single thread. */
extern unsigned long int __hurd_threadvar_stack_mask;
extern unsigned long int __hurd_threadvar_stack_offset;
/* A special case must always be made for the signal thread. Even when there
is only one user thread and an allocated region can be used for the user
thread's variables, the signal thread needs to have its own location for
per-thread variables. The variables __hurd_sigthread_stack_base and
__hurd_sigthread_stack_end define the bounds of the stack used by the
signal thread, so that thread can always be specifically identified. */
extern unsigned long int __hurd_sigthread_stack_base;
extern unsigned long int __hurd_sigthread_stack_end;
extern unsigned long int *__hurd_sigthread_variables;
/* At the location described by the two variables above,
there are __hurd_threadvar_max `unsigned long int's of per-thread data. */
extern unsigned int __hurd_threadvar_max;
/* These values are the indices for the standard per-thread variables. */
enum __hurd_threadvar_index
{
_HURD_THREADVAR_MIG_REPLY, /* Reply port for MiG user stub functions. */
_HURD_THREADVAR_ERRNO, /* `errno' value for this thread. */
_HURD_THREADVAR_SIGSTATE, /* This thread's `struct hurd_sigstate'. */
_HURD_THREADVAR_DYNAMIC_USER, /* Dynamically-assigned user variables. */
_HURD_THREADVAR_MAX /* Default value for __hurd_threadvar_max. */
};
#ifndef _EXTERN_INLINE
#define _EXTERN_INLINE extern __inline
#endif
/* Return the location of the value for the per-thread variable with index
INDEX used by the thread whose stack pointer is SP. */
_EXTERN_INLINE unsigned long int *
__hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index,
void *__sp)
{
unsigned long int __stack = (unsigned long int) __sp;
return &((__stack >= __hurd_sigthread_stack_base &&
__stack < __hurd_sigthread_stack_end)
? __hurd_sigthread_variables
: (unsigned long int *) ((__stack & __hurd_threadvar_stack_mask) +
__hurd_threadvar_stack_offset))[__index];
}
#include <machine-sp.h> /* Define __thread_stack_pointer. */
/* Return the location of the current thread's value for the
per-thread variable with index INDEX. */
extern unsigned long int *
__hurd_threadvar_location (enum __hurd_threadvar_index __index)
/* This declaration tells the compiler that the value is constant
given the same argument. We assume this won't be called twice from
the same stack frame by different threads. */
__attribute__ ((__const__));
_EXTERN_INLINE unsigned long int *
__hurd_threadvar_location (enum __hurd_threadvar_index __index)
{
return __hurd_threadvar_location_from_sp (__index,
__thread_stack_pointer ());
}
/* Return the current thread's location for `errno'.
The syntax of this function allows redeclarations like `int errno'. */
_EXTERN_INLINE int *
__hurd_errno_location (void)
{
return (int *) __hurd_threadvar_location (_HURD_THREADVAR_ERRNO);
}
#endif /* hurd/threadvar.h */
|