1 |
dashley |
71 |
/* $Header$ */ |
2 |
|
|
/* |
3 |
|
|
* tclThread.c -- |
4 |
|
|
* |
5 |
|
|
* This file implements Platform independent thread operations. |
6 |
|
|
* Most of the real work is done in the platform dependent files. |
7 |
|
|
* |
8 |
|
|
* Copyright (c) 1998 by Sun Microsystems, Inc. |
9 |
|
|
* |
10 |
|
|
* See the file "license.terms" for information on usage and redistribution |
11 |
|
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
12 |
|
|
* |
13 |
|
|
* RCS: @(#) $Id: tclthread.c,v 1.1.1.1 2001/06/13 04:46:27 dtashley Exp $ |
14 |
|
|
*/ |
15 |
|
|
|
16 |
|
|
#include "tclInt.h" |
17 |
|
|
|
18 |
|
|
/* |
19 |
|
|
* There are three classes of synchronization objects: |
20 |
|
|
* mutexes, thread data keys, and condition variables. |
21 |
|
|
* The following are used to record the memory used for these |
22 |
|
|
* objects so they can be finalized. |
23 |
|
|
* |
24 |
|
|
* These statics are guarded by the mutex in the caller of |
25 |
|
|
* TclRememberThreadData, e.g., TclpThreadDataKeyInit |
26 |
|
|
*/ |
27 |
|
|
|
28 |
|
|
typedef struct { |
29 |
|
|
int num; /* Number of objects remembered */ |
30 |
|
|
int max; /* Max size of the array */ |
31 |
|
|
char **list; /* List of pointers */ |
32 |
|
|
} SyncObjRecord; |
33 |
|
|
|
34 |
|
|
static SyncObjRecord keyRecord; |
35 |
|
|
static SyncObjRecord mutexRecord; |
36 |
|
|
static SyncObjRecord condRecord; |
37 |
|
|
|
38 |
|
|
/* |
39 |
|
|
* Prototypes of functions used only in this file |
40 |
|
|
*/ |
41 |
|
|
|
42 |
|
|
static void RememberSyncObject _ANSI_ARGS_((char *objPtr, |
43 |
|
|
SyncObjRecord *recPtr)); |
44 |
|
|
static void ForgetSyncObject _ANSI_ARGS_((char *objPtr, |
45 |
|
|
SyncObjRecord *recPtr)); |
46 |
|
|
|
47 |
|
|
/* |
48 |
|
|
* Several functions are #defined to nothing in tcl.h if TCL_THREADS is not |
49 |
|
|
* specified. Here we undo that so the procedures are defined in the |
50 |
|
|
* stubs table. |
51 |
|
|
*/ |
52 |
|
|
#ifndef TCL_THREADS |
53 |
|
|
#undef Tcl_MutexLock |
54 |
|
|
#undef Tcl_MutexUnlock |
55 |
|
|
#undef Tcl_MutexFinalize |
56 |
|
|
#undef Tcl_ConditionNotify |
57 |
|
|
#undef Tcl_ConditionWait |
58 |
|
|
#undef Tcl_ConditionFinalize |
59 |
|
|
#endif |
60 |
|
|
|
61 |
|
|
|
62 |
|
|
/* |
63 |
|
|
*---------------------------------------------------------------------- |
64 |
|
|
* |
65 |
|
|
* Tcl_GetThreadData -- |
66 |
|
|
* |
67 |
|
|
* This procedure allocates and initializes a chunk of thread |
68 |
|
|
* local storage. |
69 |
|
|
* |
70 |
|
|
* Results: |
71 |
|
|
* A thread-specific pointer to the data structure. |
72 |
|
|
* |
73 |
|
|
* Side effects: |
74 |
|
|
* Will allocate memory the first time this thread calls for |
75 |
|
|
* this chunk of storage. |
76 |
|
|
* |
77 |
|
|
*---------------------------------------------------------------------- |
78 |
|
|
*/ |
79 |
|
|
|
80 |
|
|
VOID * |
81 |
|
|
Tcl_GetThreadData(keyPtr, size) |
82 |
|
|
Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */ |
83 |
|
|
int size; /* Size of storage block */ |
84 |
|
|
{ |
85 |
|
|
VOID *result; |
86 |
|
|
#ifdef TCL_THREADS |
87 |
|
|
|
88 |
|
|
/* |
89 |
|
|
* See if this is the first thread to init this key. |
90 |
|
|
*/ |
91 |
|
|
|
92 |
|
|
if (*keyPtr == NULL) { |
93 |
|
|
TclpThreadDataKeyInit(keyPtr); |
94 |
|
|
} |
95 |
|
|
|
96 |
|
|
/* |
97 |
|
|
* Initialize the key for this thread. |
98 |
|
|
*/ |
99 |
|
|
|
100 |
|
|
result = TclpThreadDataKeyGet(keyPtr); |
101 |
|
|
if (result == NULL) { |
102 |
|
|
result = (VOID *)ckalloc((size_t)size); |
103 |
|
|
memset(result, 0, (size_t)size); |
104 |
|
|
TclpThreadDataKeySet(keyPtr, result); |
105 |
|
|
} |
106 |
|
|
#else |
107 |
|
|
if (*keyPtr == NULL) { |
108 |
|
|
result = (VOID *)ckalloc((size_t)size); |
109 |
|
|
memset((char *)result, 0, (size_t)size); |
110 |
|
|
*keyPtr = (Tcl_ThreadDataKey)result; |
111 |
|
|
TclRememberDataKey(keyPtr); |
112 |
|
|
} |
113 |
|
|
result = *(VOID **)keyPtr; |
114 |
|
|
#endif |
115 |
|
|
return result; |
116 |
|
|
} |
117 |
|
|
|
118 |
|
|
/* |
119 |
|
|
*---------------------------------------------------------------------- |
120 |
|
|
* |
121 |
|
|
* TclThreadDataKeyGet -- |
122 |
|
|
* |
123 |
|
|
* This procedure returns a pointer to a block of thread local storage. |
124 |
|
|
* |
125 |
|
|
* Results: |
126 |
|
|
* A thread-specific pointer to the data structure, or NULL |
127 |
|
|
* if the memory has not been assigned to this key for this thread. |
128 |
|
|
* |
129 |
|
|
* Side effects: |
130 |
|
|
* None. |
131 |
|
|
* |
132 |
|
|
*---------------------------------------------------------------------- |
133 |
|
|
*/ |
134 |
|
|
|
135 |
|
|
VOID * |
136 |
|
|
TclThreadDataKeyGet(keyPtr) |
137 |
|
|
Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, |
138 |
|
|
* really (pthread_key_t **) */ |
139 |
|
|
{ |
140 |
|
|
#ifdef TCL_THREADS |
141 |
|
|
return (VOID *)TclpThreadDataKeyGet(keyPtr); |
142 |
|
|
#else |
143 |
|
|
char *result = *(char **)keyPtr; |
144 |
|
|
return (VOID *)result; |
145 |
|
|
#endif /* TCL_THREADS */ |
146 |
|
|
} |
147 |
|
|
|
148 |
|
|
|
149 |
|
|
/* |
150 |
|
|
*---------------------------------------------------------------------- |
151 |
|
|
* |
152 |
|
|
* TclThreadDataKeySet -- |
153 |
|
|
* |
154 |
|
|
* This procedure sets a thread local storage pointer. |
155 |
|
|
* |
156 |
|
|
* Results: |
157 |
|
|
* None. |
158 |
|
|
* |
159 |
|
|
* Side effects: |
160 |
|
|
* The assigned value will be returned by TclpThreadDataKeyGet. |
161 |
|
|
* |
162 |
|
|
*---------------------------------------------------------------------- |
163 |
|
|
*/ |
164 |
|
|
|
165 |
|
|
void |
166 |
|
|
TclThreadDataKeySet(keyPtr, data) |
167 |
|
|
Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, |
168 |
|
|
* really (pthread_key_t **) */ |
169 |
|
|
VOID *data; /* Thread local storage */ |
170 |
|
|
{ |
171 |
|
|
#ifdef TCL_THREADS |
172 |
|
|
if (*keyPtr == NULL) { |
173 |
|
|
TclpThreadDataKeyInit(keyPtr); |
174 |
|
|
} |
175 |
|
|
TclpThreadDataKeySet(keyPtr, data); |
176 |
|
|
#else |
177 |
|
|
*keyPtr = (Tcl_ThreadDataKey)data; |
178 |
|
|
#endif /* TCL_THREADS */ |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
|
182 |
|
|
|
183 |
|
|
/* |
184 |
|
|
*---------------------------------------------------------------------- |
185 |
|
|
* |
186 |
|
|
* RememberSyncObject |
187 |
|
|
* |
188 |
|
|
* Keep a list of (mutexes/condition variable/data key) |
189 |
|
|
* used during finalization. |
190 |
|
|
* |
191 |
|
|
* Results: |
192 |
|
|
* None. |
193 |
|
|
* |
194 |
|
|
* Side effects: |
195 |
|
|
* Add to the appropriate list. |
196 |
|
|
* |
197 |
|
|
*---------------------------------------------------------------------- |
198 |
|
|
*/ |
199 |
|
|
|
200 |
|
|
static void |
201 |
|
|
RememberSyncObject(objPtr, recPtr) |
202 |
|
|
char *objPtr; /* Pointer to sync object */ |
203 |
|
|
SyncObjRecord *recPtr; /* Record of sync objects */ |
204 |
|
|
{ |
205 |
|
|
char **newList; |
206 |
|
|
int i, j; |
207 |
|
|
|
208 |
|
|
/* |
209 |
|
|
* Save the pointer to the allocated object so it can be finalized. |
210 |
|
|
* Grow the list of pointers if necessary, copying only non-NULL |
211 |
|
|
* pointers to the new list. |
212 |
|
|
*/ |
213 |
|
|
|
214 |
|
|
if (recPtr->num >= recPtr->max) { |
215 |
|
|
recPtr->max += 8; |
216 |
|
|
newList = (char **)ckalloc(recPtr->max * sizeof(char *)); |
217 |
|
|
for (i=0,j=0 ; i<recPtr->num ; i++) { |
218 |
|
|
if (recPtr->list[i] != NULL) { |
219 |
|
|
newList[j++] = recPtr->list[i]; |
220 |
|
|
} |
221 |
|
|
} |
222 |
|
|
if (recPtr->list != NULL) { |
223 |
|
|
ckfree((char *)recPtr->list); |
224 |
|
|
} |
225 |
|
|
recPtr->list = newList; |
226 |
|
|
recPtr->num = j; |
227 |
|
|
} |
228 |
|
|
recPtr->list[recPtr->num] = objPtr; |
229 |
|
|
recPtr->num++; |
230 |
|
|
} |
231 |
|
|
|
232 |
|
|
/* |
233 |
|
|
*---------------------------------------------------------------------- |
234 |
|
|
* |
235 |
|
|
* ForgetSyncObject |
236 |
|
|
* |
237 |
|
|
* Remove a single object from the list. |
238 |
|
|
* |
239 |
|
|
* Results: |
240 |
|
|
* None. |
241 |
|
|
* |
242 |
|
|
* Side effects: |
243 |
|
|
* Remove from the appropriate list. |
244 |
|
|
* |
245 |
|
|
*---------------------------------------------------------------------- |
246 |
|
|
*/ |
247 |
|
|
|
248 |
|
|
static void |
249 |
|
|
ForgetSyncObject(objPtr, recPtr) |
250 |
|
|
char *objPtr; /* Pointer to sync object */ |
251 |
|
|
SyncObjRecord *recPtr; /* Record of sync objects */ |
252 |
|
|
{ |
253 |
|
|
int i; |
254 |
|
|
|
255 |
|
|
for (i=0 ; i<recPtr->num ; i++) { |
256 |
|
|
if (objPtr == recPtr->list[i]) { |
257 |
|
|
recPtr->list[i] = NULL; |
258 |
|
|
return; |
259 |
|
|
} |
260 |
|
|
} |
261 |
|
|
} |
262 |
|
|
|
263 |
|
|
/* |
264 |
|
|
*---------------------------------------------------------------------- |
265 |
|
|
* |
266 |
|
|
* TclRememberMutex |
267 |
|
|
* |
268 |
|
|
* Keep a list of mutexes used during finalization. |
269 |
|
|
* |
270 |
|
|
* Results: |
271 |
|
|
* None. |
272 |
|
|
* |
273 |
|
|
* Side effects: |
274 |
|
|
* Add to the mutex list. |
275 |
|
|
* |
276 |
|
|
*---------------------------------------------------------------------- |
277 |
|
|
*/ |
278 |
|
|
|
279 |
|
|
void |
280 |
|
|
TclRememberMutex(mutexPtr) |
281 |
|
|
Tcl_Mutex *mutexPtr; |
282 |
|
|
{ |
283 |
|
|
RememberSyncObject((char *)mutexPtr, &mutexRecord); |
284 |
|
|
} |
285 |
|
|
|
286 |
|
|
/* |
287 |
|
|
*---------------------------------------------------------------------- |
288 |
|
|
* |
289 |
|
|
* Tcl_MutexFinalize |
290 |
|
|
* |
291 |
|
|
* Finalize a single mutex and remove it from the |
292 |
|
|
* list of remembered objects. |
293 |
|
|
* |
294 |
|
|
* Results: |
295 |
|
|
* None. |
296 |
|
|
* |
297 |
|
|
* Side effects: |
298 |
|
|
* Remove the mutex from the list. |
299 |
|
|
* |
300 |
|
|
*---------------------------------------------------------------------- |
301 |
|
|
*/ |
302 |
|
|
|
303 |
|
|
void |
304 |
|
|
Tcl_MutexFinalize(mutexPtr) |
305 |
|
|
Tcl_Mutex *mutexPtr; |
306 |
|
|
{ |
307 |
|
|
#ifdef TCL_THREADS |
308 |
|
|
TclpFinalizeMutex(mutexPtr); |
309 |
|
|
#endif |
310 |
|
|
ForgetSyncObject((char *)mutexPtr, &mutexRecord); |
311 |
|
|
} |
312 |
|
|
|
313 |
|
|
/* |
314 |
|
|
*---------------------------------------------------------------------- |
315 |
|
|
* |
316 |
|
|
* TclRememberDataKey |
317 |
|
|
* |
318 |
|
|
* Keep a list of thread data keys used during finalization. |
319 |
|
|
* |
320 |
|
|
* Results: |
321 |
|
|
* None. |
322 |
|
|
* |
323 |
|
|
* Side effects: |
324 |
|
|
* Add to the key list. |
325 |
|
|
* |
326 |
|
|
*---------------------------------------------------------------------- |
327 |
|
|
*/ |
328 |
|
|
|
329 |
|
|
void |
330 |
|
|
TclRememberDataKey(keyPtr) |
331 |
|
|
Tcl_ThreadDataKey *keyPtr; |
332 |
|
|
{ |
333 |
|
|
RememberSyncObject((char *)keyPtr, &keyRecord); |
334 |
|
|
} |
335 |
|
|
|
336 |
|
|
/* |
337 |
|
|
*---------------------------------------------------------------------- |
338 |
|
|
* |
339 |
|
|
* TclRememberCondition |
340 |
|
|
* |
341 |
|
|
* Keep a list of condition variables used during finalization. |
342 |
|
|
* |
343 |
|
|
* Results: |
344 |
|
|
* None. |
345 |
|
|
* |
346 |
|
|
* Side effects: |
347 |
|
|
* Add to the condition variable list. |
348 |
|
|
* |
349 |
|
|
*---------------------------------------------------------------------- |
350 |
|
|
*/ |
351 |
|
|
|
352 |
|
|
void |
353 |
|
|
TclRememberCondition(condPtr) |
354 |
|
|
Tcl_Condition *condPtr; |
355 |
|
|
{ |
356 |
|
|
RememberSyncObject((char *)condPtr, &condRecord); |
357 |
|
|
} |
358 |
|
|
|
359 |
|
|
/* |
360 |
|
|
*---------------------------------------------------------------------- |
361 |
|
|
* |
362 |
|
|
* Tcl_ConditionFinalize |
363 |
|
|
* |
364 |
|
|
* Finalize a single condition variable and remove it from the |
365 |
|
|
* list of remembered objects. |
366 |
|
|
* |
367 |
|
|
* Results: |
368 |
|
|
* None. |
369 |
|
|
* |
370 |
|
|
* Side effects: |
371 |
|
|
* Remove the condition variable from the list. |
372 |
|
|
* |
373 |
|
|
*---------------------------------------------------------------------- |
374 |
|
|
*/ |
375 |
|
|
|
376 |
|
|
void |
377 |
|
|
Tcl_ConditionFinalize(condPtr) |
378 |
|
|
Tcl_Condition *condPtr; |
379 |
|
|
{ |
380 |
|
|
#ifdef TCL_THREADS |
381 |
|
|
TclpFinalizeCondition(condPtr); |
382 |
|
|
#endif |
383 |
|
|
ForgetSyncObject((char *)condPtr, &condRecord); |
384 |
|
|
} |
385 |
|
|
|
386 |
|
|
/* |
387 |
|
|
*---------------------------------------------------------------------- |
388 |
|
|
* |
389 |
|
|
* TclFinalizeThreadData -- |
390 |
|
|
* |
391 |
|
|
* This procedure cleans up the thread-local storage. This is |
392 |
|
|
* called once for each thread. |
393 |
|
|
* |
394 |
|
|
* Results: |
395 |
|
|
* None. |
396 |
|
|
* |
397 |
|
|
* Side effects: |
398 |
|
|
* Frees up all thread local storage. |
399 |
|
|
* |
400 |
|
|
*---------------------------------------------------------------------- |
401 |
|
|
*/ |
402 |
|
|
|
403 |
|
|
void |
404 |
|
|
TclFinalizeThreadData() |
405 |
|
|
{ |
406 |
|
|
int i; |
407 |
|
|
Tcl_ThreadDataKey *keyPtr; |
408 |
|
|
|
409 |
|
|
TclpMasterLock(); |
410 |
|
|
for (i=0 ; i<keyRecord.num ; i++) { |
411 |
|
|
keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i]; |
412 |
|
|
#ifdef TCL_THREADS |
413 |
|
|
TclpFinalizeThreadData(keyPtr); |
414 |
|
|
#else |
415 |
|
|
if (*keyPtr != NULL) { |
416 |
|
|
ckfree((char *)*keyPtr); |
417 |
|
|
*keyPtr = NULL; |
418 |
|
|
} |
419 |
|
|
#endif |
420 |
|
|
} |
421 |
|
|
#ifdef TCL_THREADS |
422 |
|
|
TclpMasterUnlock(); |
423 |
|
|
#endif |
424 |
|
|
} |
425 |
|
|
|
426 |
|
|
/* |
427 |
|
|
*---------------------------------------------------------------------- |
428 |
|
|
* |
429 |
|
|
* TclFinalizeSynchronization -- |
430 |
|
|
* |
431 |
|
|
* This procedure cleans up all synchronization objects: |
432 |
|
|
* mutexes, condition variables, and thread-local storage. |
433 |
|
|
* |
434 |
|
|
* Results: |
435 |
|
|
* None. |
436 |
|
|
* |
437 |
|
|
* Side effects: |
438 |
|
|
* Frees up the memory. |
439 |
|
|
* |
440 |
|
|
*---------------------------------------------------------------------- |
441 |
|
|
*/ |
442 |
|
|
|
443 |
|
|
void |
444 |
|
|
TclFinalizeSynchronization() |
445 |
|
|
{ |
446 |
|
|
#ifdef TCL_THREADS |
447 |
|
|
Tcl_ThreadDataKey *keyPtr; |
448 |
|
|
Tcl_Mutex *mutexPtr; |
449 |
|
|
Tcl_Condition *condPtr; |
450 |
|
|
int i; |
451 |
|
|
|
452 |
|
|
TclpMasterLock(); |
453 |
|
|
for (i=0 ; i<keyRecord.num ; i++) { |
454 |
|
|
keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i]; |
455 |
|
|
TclpFinalizeThreadDataKey(keyPtr); |
456 |
|
|
} |
457 |
|
|
if (keyRecord.list != NULL) { |
458 |
|
|
ckfree((char *)keyRecord.list); |
459 |
|
|
keyRecord.list = NULL; |
460 |
|
|
} |
461 |
|
|
keyRecord.max = 0; |
462 |
|
|
keyRecord.num = 0; |
463 |
|
|
|
464 |
|
|
for (i=0 ; i<mutexRecord.num ; i++) { |
465 |
|
|
mutexPtr = (Tcl_Mutex *)mutexRecord.list[i]; |
466 |
|
|
if (mutexPtr != NULL) { |
467 |
|
|
TclpFinalizeMutex(mutexPtr); |
468 |
|
|
} |
469 |
|
|
} |
470 |
|
|
if (mutexRecord.list != NULL) { |
471 |
|
|
ckfree((char *)mutexRecord.list); |
472 |
|
|
mutexRecord.list = NULL; |
473 |
|
|
} |
474 |
|
|
mutexRecord.max = 0; |
475 |
|
|
mutexRecord.num = 0; |
476 |
|
|
|
477 |
|
|
for (i=0 ; i<condRecord.num ; i++) { |
478 |
|
|
condPtr = (Tcl_Condition *)condRecord.list[i]; |
479 |
|
|
if (condPtr != NULL) { |
480 |
|
|
TclpFinalizeCondition(condPtr); |
481 |
|
|
} |
482 |
|
|
} |
483 |
|
|
if (condRecord.list != NULL) { |
484 |
|
|
ckfree((char *)condRecord.list); |
485 |
|
|
condRecord.list = NULL; |
486 |
|
|
} |
487 |
|
|
condRecord.max = 0; |
488 |
|
|
condRecord.num = 0; |
489 |
|
|
|
490 |
|
|
TclpMasterUnlock(); |
491 |
|
|
#else |
492 |
|
|
if (keyRecord.list != NULL) { |
493 |
|
|
ckfree((char *)keyRecord.list); |
494 |
|
|
keyRecord.list = NULL; |
495 |
|
|
} |
496 |
|
|
keyRecord.max = 0; |
497 |
|
|
keyRecord.num = 0; |
498 |
|
|
#endif |
499 |
|
|
} |
500 |
|
|
|
501 |
|
|
|
502 |
|
|
/* |
503 |
|
|
*---------------------------------------------------------------------- |
504 |
|
|
* |
505 |
|
|
* Tcl_ExitThread -- |
506 |
|
|
* |
507 |
|
|
* This procedure is called to terminate the current thread. |
508 |
|
|
* This should be used by extensions that create threads with |
509 |
|
|
* additional interpreters in them. |
510 |
|
|
* |
511 |
|
|
* Results: |
512 |
|
|
* None. |
513 |
|
|
* |
514 |
|
|
* Side effects: |
515 |
|
|
* All thread exit handlers are invoked, then the thread dies. |
516 |
|
|
* |
517 |
|
|
*---------------------------------------------------------------------- |
518 |
|
|
*/ |
519 |
|
|
|
520 |
|
|
void |
521 |
|
|
Tcl_ExitThread(status) |
522 |
|
|
int status; |
523 |
|
|
{ |
524 |
|
|
Tcl_FinalizeThread(); |
525 |
|
|
#ifdef TCL_THREADS |
526 |
|
|
TclpThreadExit(status); |
527 |
|
|
#endif |
528 |
|
|
} |
529 |
|
|
|
530 |
|
|
#ifndef TCL_THREADS |
531 |
|
|
|
532 |
|
|
/* |
533 |
|
|
*---------------------------------------------------------------------- |
534 |
|
|
* |
535 |
|
|
* Tcl_ConditionWait, et al. -- |
536 |
|
|
* |
537 |
|
|
* These noop procedures are provided so the stub table does |
538 |
|
|
* not have to be conditionalized for threads. The real |
539 |
|
|
* implementations of these functions live in the platform |
540 |
|
|
* specific files. |
541 |
|
|
* |
542 |
|
|
* Results: |
543 |
|
|
* None. |
544 |
|
|
* |
545 |
|
|
* Side effects: |
546 |
|
|
* None. |
547 |
|
|
* |
548 |
|
|
*---------------------------------------------------------------------- |
549 |
|
|
*/ |
550 |
|
|
|
551 |
|
|
#undef Tcl_ConditionWait |
552 |
|
|
void |
553 |
|
|
Tcl_ConditionWait(condPtr, mutexPtr, timePtr) |
554 |
|
|
Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */ |
555 |
|
|
Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ |
556 |
|
|
Tcl_Time *timePtr; /* Timeout on waiting period */ |
557 |
|
|
{ |
558 |
|
|
} |
559 |
|
|
|
560 |
|
|
#undef Tcl_ConditionNotify |
561 |
|
|
void |
562 |
|
|
Tcl_ConditionNotify(condPtr) |
563 |
|
|
Tcl_Condition *condPtr; |
564 |
|
|
{ |
565 |
|
|
} |
566 |
|
|
|
567 |
|
|
#undef Tcl_MutexLock |
568 |
|
|
void |
569 |
|
|
Tcl_MutexLock(mutexPtr) |
570 |
|
|
Tcl_Mutex *mutexPtr; |
571 |
|
|
{ |
572 |
|
|
} |
573 |
|
|
|
574 |
|
|
#undef Tcl_MutexUnlock |
575 |
|
|
void |
576 |
|
|
Tcl_MutexUnlock(mutexPtr) |
577 |
|
|
Tcl_Mutex *mutexPtr; |
578 |
|
|
{ |
579 |
|
|
} |
580 |
|
|
#endif |
581 |
|
|
|
582 |
|
|
/* End of tclthread.c */ |