1 |
/* |
/* |
2 |
* Mach Operating System |
* Mach Operating System |
3 |
* Copyright (c) 1991 Carnegie-Mellon University |
* Copyright (c) 1992,1991 Carnegie-Mellon University |
4 |
* All rights reserved. The CMU software License Agreement specifies |
* All rights reserved. The CMU software License Agreement specifies |
5 |
* the terms and conditions for use and redistribution. |
* the terms and conditions for use and redistribution. |
6 |
*/ |
*/ |
7 |
/* |
/* |
8 |
* HISTORY |
* HISTORY |
9 |
* $Log$ |
* $Log$ |
10 |
* Revision 1.2 2001/03/31 23:10:55 roland |
* Revision 1.3 2002/05/27 02:50:10 roland |
11 |
* 2001-03-31 Roland McGrath <roland@frob.com> |
* 2002-05-26 Roland McGrath <roland@frob.com> |
12 |
* |
* |
13 |
* * cthreads.h: Fix obsolescent #endif syntax. |
* Changes merged from CMU MK83a version: |
14 |
* * cthread_internals.h: Likewise. |
* * cthreads.h, options.h: Various cleanups. |
15 |
* * cancel-cond.c: Likewise. |
* * call.c, cthread_data.c, sync.c, mig_support.c: Likewise. |
16 |
* * stack.c: Likewise. |
* * i386/cthreads.h, i386/thread.c, i386/lock.s: Likewise. |
17 |
|
* * cthread_internals.h: Add decls for internal functions. |
18 |
|
* (struct cproc): Use vm_offset_t for stack_base and stack_size members. |
19 |
|
* Use natural_t for context member. |
20 |
|
* * cprocs.c: Use prototypes for all defns. |
21 |
* * cthreads.c: Likewise. |
* * cthreads.c: Likewise. |
22 |
* * cprocs.c: Likewise. |
* (cthread_exit): Cast any_t to integer_t before int. |
|
* * call.c: Likewise. |
|
|
* * i386/thread.c: Likewise. |
|
|
* * cthread_data.c: Likewise. |
|
|
* |
|
|
* Revision 1.1 1992/10/06 18:31:04 mib |
|
|
* entered into RCS |
|
23 |
* |
* |
24 |
|
* Revision 2.4 93/05/10 17:51:20 rvb |
25 |
|
* Make cthread_set_data and cthread_data macros. |
26 |
|
* [93/05/06 rvb] |
27 |
|
* |
28 |
|
* Revision 2.3 93/01/14 18:04:52 danner |
29 |
|
* Converted file to ANSI C. |
30 |
|
* Removed usage of obsolete type any_t. |
31 |
|
* [92/12/18 pds] |
32 |
|
* |
33 |
* Revision 2.2 92/05/23 11:35:17 jfriedl |
* Revision 2.2 92/05/23 11:35:17 jfriedl |
34 |
* Snarfed from multi-server sources at CMU. |
* Snarfed from multi-server sources at CMU. |
35 |
* No stdio (for use with single-server). |
* No stdio (for use with single-server). |
36 |
* |
* |
37 |
* |
* |
38 |
* Revision 2.2 91/03/25 14:14:45 jjc |
* Revision 2.2 91/03/25 14:14:45 jjc |
39 |
* For compatibility with cthread_data: |
* For compatibility with cthread_data: |
40 |
* 1) Added routines, cthread_data and cthread_set_data, |
* 1) Added routines, cthread_data and cthread_set_data, |
47 |
* Made simple implementation from POSIX threads specification for |
* Made simple implementation from POSIX threads specification for |
48 |
* thread specific data. |
* thread specific data. |
49 |
* [91/03/07 jjc] |
* [91/03/07 jjc] |
50 |
* |
* |
51 |
*/ |
*/ |
|
#include <cthreads.h> |
|
52 |
|
|
53 |
|
#include <stdio.h> |
54 |
|
#include <cthreads.h> |
55 |
|
|
|
#ifdef CTHREAD_DATA |
|
|
#define CTHREAD_KEY_FIRST (cthread_key_t)1 /* first free key */ |
|
|
#else /* CTHREAD_DATA */ |
|
|
#define CTHREAD_KEY_FIRST CTHREAD_KEY_NULL /* first free key */ |
|
|
#endif /* CTHREAD_DATA */ |
|
56 |
#define CTHREAD_KEY_MAX (cthread_key_t)8 /* max. no. of keys */ |
#define CTHREAD_KEY_MAX (cthread_key_t)8 /* max. no. of keys */ |
57 |
#define CTHREAD_KEY_NULL (cthread_key_t)0 |
#define CTHREAD_KEY_NULL (cthread_key_t)0 |
58 |
|
|
59 |
#ifdef CTHREAD_DATA |
#if defined(CTHREAD_DATA) |
60 |
/* |
/* |
61 |
* Key reserved for cthread_data |
* Key reserved for cthread_data |
62 |
*/ |
*/ |
63 |
#define CTHREAD_KEY_RESERVED CTHREAD_KEY_NULL |
#define CTHREAD_KEY_RESERVED CTHREAD_KEY_NULL |
64 |
#endif /* CTHREAD_DATA */ |
|
65 |
|
#define CTHREAD_KEY_FIRST (cthread_key_t)1 /* first free key */ |
66 |
|
#else /* not defined(CTHREAD_DATA) */ |
67 |
|
#define CTHREAD_KEY_FIRST CTHREAD_KEY_NULL /* first free key */ |
68 |
|
#endif /* defined(CTHREAD_DATA) */ |
69 |
|
|
70 |
|
|
71 |
/* lock protecting key creation */ |
/* lock protecting key creation */ |
81 |
* maintained on a thread specific basis. |
* maintained on a thread specific basis. |
82 |
* Returns 0 if successful and returns -1 otherwise. |
* Returns 0 if successful and returns -1 otherwise. |
83 |
*/ |
*/ |
84 |
cthread_keycreate(key) |
int |
85 |
cthread_key_t *key; |
cthread_keycreate(cthread_key_t *key) |
86 |
{ |
{ |
87 |
if (cthread_key >= CTHREAD_KEY_FIRST && cthread_key < CTHREAD_KEY_MAX) { |
if (cthread_key >= CTHREAD_KEY_FIRST && cthread_key < CTHREAD_KEY_MAX) { |
88 |
mutex_lock((mutex_t)&cthread_data_lock); |
mutex_lock((mutex_t)&cthread_data_lock); |
103 |
* If the calling thread doesn't have a value for the given key, |
* If the calling thread doesn't have a value for the given key, |
104 |
* the value returned is CTHREAD_DATA_VALUE_NULL. |
* the value returned is CTHREAD_DATA_VALUE_NULL. |
105 |
*/ |
*/ |
106 |
cthread_getspecific(key, value) |
int |
107 |
cthread_key_t key; |
cthread_getspecific(cthread_key_t key, void **value) |
|
any_t *value; |
|
108 |
{ |
{ |
109 |
register cthread_t self; |
register cthread_t self; |
110 |
register any_t *thread_data; |
register void **thread_data; |
111 |
|
|
112 |
*value = CTHREAD_DATA_VALUE_NULL; |
*value = CTHREAD_DATA_VALUE_NULL; |
113 |
if (key < CTHREAD_KEY_NULL || key >= cthread_key) |
if (key < CTHREAD_KEY_NULL || key >= cthread_key) |
114 |
return(-1); |
return(-1); |
115 |
|
|
116 |
self = cthread_self(); |
self = cthread_self(); |
117 |
thread_data = (any_t *)(self->private_data); |
thread_data = (void **)(self->private_data); |
118 |
if (thread_data != (any_t *)0) |
if (thread_data != NULL) |
119 |
*value = thread_data[key]; |
*value = thread_data[key]; |
120 |
|
|
121 |
return(0); |
return(0); |
126 |
* Set private data associated with given key |
* Set private data associated with given key |
127 |
* Returns 0 if successful and returns -1 otherwise. |
* Returns 0 if successful and returns -1 otherwise. |
128 |
*/ |
*/ |
129 |
cthread_setspecific(key, value) |
int |
130 |
cthread_key_t key; |
cthread_setspecific(cthread_key_t key, void *value) |
|
any_t value; |
|
131 |
{ |
{ |
132 |
register int i; |
register int i; |
133 |
register cthread_t self; |
register cthread_t self; |
134 |
register any_t *thread_data; |
register void **thread_data; |
135 |
|
|
136 |
if (key < CTHREAD_KEY_NULL || key >= cthread_key) |
if (key < CTHREAD_KEY_NULL || key >= cthread_key) |
137 |
return(-1); |
return(-1); |
138 |
|
|
139 |
self = cthread_self(); |
self = cthread_self(); |
140 |
thread_data = (any_t *)(self->private_data); |
thread_data = (void **)(self->private_data); |
141 |
if (thread_data != (any_t *)0) |
if (thread_data != NULL) |
142 |
thread_data[key] = value; |
thread_data[key] = value; |
143 |
else { |
else { |
144 |
/* |
/* |
146 |
* point cthread_data at it, and then set the |
* point cthread_data at it, and then set the |
147 |
* data for the given key with the given value. |
* data for the given key with the given value. |
148 |
*/ |
*/ |
149 |
thread_data = (any_t *)malloc(CTHREAD_KEY_MAX * sizeof(any_t)); |
thread_data = malloc(CTHREAD_KEY_MAX * sizeof(void *)); |
150 |
if (thread_data == (any_t *)0) { |
if (thread_data == NULL) { |
151 |
printf("cthread_setspecific: malloc failed\n"); |
printf("cthread_setspecific: malloc failed\n"); |
152 |
return(-1); |
return(-1); |
153 |
} |
} |
154 |
self->private_data = (any_t)thread_data; |
self->private_data = thread_data; |
155 |
|
|
156 |
for (i = 0; i < CTHREAD_KEY_MAX; i++) |
for (i = 0; i < CTHREAD_KEY_MAX; i++) |
157 |
thread_data[i] = CTHREAD_DATA_VALUE_NULL; |
thread_data[i] = CTHREAD_DATA_VALUE_NULL; |
162 |
} |
} |
163 |
|
|
164 |
|
|
165 |
#ifdef CTHREAD_DATA |
#if defined(CTHREAD_DATA_XX) |
166 |
/* |
/* |
167 |
* Set thread specific "global" variable, |
* Set thread specific "global" variable, |
168 |
* using new POSIX routines. |
* using new POSIX routines. |
169 |
* Crash and burn if the thread given isn't the calling thread. |
* Crash and burn if the thread given isn't the calling thread. |
170 |
* XXX For compatibility with old cthread_set_data() XXX |
* XXX For compatibility with old cthread_set_data() XXX |
171 |
*/ |
*/ |
172 |
cthread_set_data(t, x) |
int |
173 |
cthread_t t; |
cthread_set_data(cthread_t t, void *x) |
|
any_t x; |
|
174 |
{ |
{ |
175 |
register cthread_t self; |
register cthread_t self; |
176 |
|
|
179 |
return(cthread_setspecific(CTHREAD_KEY_RESERVED, x)); |
return(cthread_setspecific(CTHREAD_KEY_RESERVED, x)); |
180 |
else { |
else { |
181 |
ASSERT(t == self); |
ASSERT(t == self); |
182 |
|
return(-1); |
183 |
} |
} |
184 |
} |
} |
185 |
|
|
190 |
* Crash and burn if the thread given isn't the calling thread. |
* Crash and burn if the thread given isn't the calling thread. |
191 |
* XXX For compatibility with old cthread_data() XXX |
* XXX For compatibility with old cthread_data() XXX |
192 |
*/ |
*/ |
193 |
any_t |
void * |
194 |
cthread_data(t) |
cthread_data(cthread_t t) |
|
cthread_t t; |
|
195 |
{ |
{ |
196 |
register cthread_t self; |
register cthread_t self; |
197 |
any_t value; |
void *value; |
198 |
|
|
199 |
self = cthread_self(); |
self = cthread_self(); |
200 |
if (t == self) { |
if (t == self) { |
203 |
} |
} |
204 |
else { |
else { |
205 |
ASSERT(t == self); |
ASSERT(t == self); |
206 |
|
return(NULL); |
207 |
} |
} |
208 |
} |
} |
209 |
#endif /* CTHREAD_DATA */ |
#endif /* defined(CTHREAD_DATA_XX) */ |