Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch bug-5d170b5ca5 Excluding Merge-Ins
This is equivalent to a diff from 0b3d2ed4aa to b65985a504
|
2015-09-24
| ||
| 11:06 | Fix [5d170b5ca5e12743006d737c79f959f3efabc644|5d170b5ca5]: checkin 9f8b7bea5344f1b0 broke netbsd's t... check-in: 6da7c01325 user: jan.nijtmans tags: trunk | |
| 10:54 | Fix [5d170b5ca5e12743006d737c79f959f3efabc644|5d170b5ca5]: checkin 9f8b7bea5344f1b0 broke netbsd's t... check-in: f30afc36b5 user: jan.nijtmans tags: core-8-5-branch | |
| 10:03 | merge trunk Closed-Leaf check-in: b65985a504 user: jan.nijtmans tags: bug-5d170b5ca5 | |
| 10:01 | merge-mark (almost, just a few cosmetic changes) check-in: 0b3d2ed4aa user: jan.nijtmans tags: trunk | |
| 09:55 | Clean-up tclUnixNotfy.c, restructure it the same as "trunk" version. No functional changes. This wil... check-in: a6517a4eb6 user: jan.nijtmans tags: core-8-5-branch | |
|
2015-09-23
| ||
| 17:29 | Update tests to new ReflectWatch() behavior. check-in: 58d7a51a76 user: dgp tags: trunk | |
| 12:19 | Merge trunk check-in: d58c269d4e user: jan.nijtmans tags: bug-5d170b5ca5 | |
Changes to generic/tclInt.h.
| ︙ | ︙ | |||
3055 3056 3057 3058 3059 3060 3061 | int *lengthPtr, Tcl_Encoding *encodingPtr); MODULE_SCOPE void TclpInitLock(void); MODULE_SCOPE void TclpInitPlatform(void); MODULE_SCOPE void TclpInitUnlock(void); MODULE_SCOPE Tcl_Obj * TclpObjListVolumes(void); MODULE_SCOPE void TclpMasterLock(void); MODULE_SCOPE void TclpMasterUnlock(void); | < < < | 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 | int *lengthPtr, Tcl_Encoding *encodingPtr); MODULE_SCOPE void TclpInitLock(void); MODULE_SCOPE void TclpInitPlatform(void); MODULE_SCOPE void TclpInitUnlock(void); MODULE_SCOPE Tcl_Obj * TclpObjListVolumes(void); MODULE_SCOPE void TclpMasterLock(void); MODULE_SCOPE void TclpMasterUnlock(void); MODULE_SCOPE int TclpMatchFiles(Tcl_Interp *interp, char *separators, Tcl_DString *dirPtr, char *pattern, char *tail); MODULE_SCOPE int TclpObjNormalizePath(Tcl_Interp *interp, Tcl_Obj *pathPtr, int nextCheckpoint); MODULE_SCOPE void TclpNativeJoinPath(Tcl_Obj *prefix, const char *joining); MODULE_SCOPE Tcl_Obj * TclpNativeSplitPath(Tcl_Obj *pathPtr, int *lenPtr); MODULE_SCOPE Tcl_PathType TclpGetNativePathType(Tcl_Obj *pathPtr, |
| ︙ | ︙ |
Changes to generic/tclThread.c.
| ︙ | ︙ | |||
274 275 276 277 278 279 280 |
Tcl_Mutex *mutexPtr)
{
#ifdef TCL_THREADS
TclpFinalizeMutex(mutexPtr);
#endif
TclpMasterLock();
ForgetSyncObject(mutexPtr, &mutexRecord);
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
Tcl_Mutex *mutexPtr)
{
#ifdef TCL_THREADS
TclpFinalizeMutex(mutexPtr);
#endif
TclpMasterLock();
ForgetSyncObject(mutexPtr, &mutexRecord);
TclpMasterUnlock();
}
/*
*----------------------------------------------------------------------
*
* TclRememberCondition
|
| ︙ | ︙ |
Changes to unix/tclUnixNotfy.c.
1 2 3 4 5 6 7 | /* * tclUnixNotify.c -- * * This file contains the implementation of the select()-based * Unix-specific notifier, which is the lowest-level part of the Tcl * event loop. This file works together with generic/tclNotify.c. * | > > | 1 2 3 4 5 6 7 8 9 | #define AT_FORK_INIT_VALUE 0 #define RESET_ATFORK_MUTEX 1 /* * tclUnixNotify.c -- * * This file contains the implementation of the select()-based * Unix-specific notifier, which is the lowest-level part of the Tcl * event loop. This file works together with generic/tclNotify.c. * |
| ︙ | ︙ | |||
93 94 95 96 97 98 99 |
* fields. */
#ifdef __CYGWIN__
void *event; /* Any other thread alerts a notifier
* that an event is ready to be processed
* by sending this event. */
void *hwnd; /* Messaging window. */
#else /* !__CYGWIN__ */
| | > < < < < < < < < < | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
* fields. */
#ifdef __CYGWIN__
void *event; /* Any other thread alerts a notifier
* that an event is ready to be processed
* by sending this event. */
void *hwnd; /* Messaging window. */
#else /* !__CYGWIN__ */
pthread_cond_t waitCV; /* Any other thread alerts a notifier that an
* event is ready to be processed by signaling
* this condition variable. */
#endif /* __CYGWIN__ */
int waitCVinitialized; /* Variable to flag initialization of the structure */
int eventReady; /* True if an event is ready to be processed.
* Used as condition flag together with waitCV
* above. */
#endif /* TCL_THREADS */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
#ifdef TCL_THREADS
/*
* The following static indicates the number of threads that have initialized
* notifiers.
*
* You must hold the notifierMutex lock before accessing this variable.
*/
static int notifierCount = 0;
/*
* The following variable points to the head of a doubly-linked list of
* ThreadSpecificData structures for all threads that are currently waiting on
* an event.
*
* You must hold the notifierMutex lock before accessing this list.
*/
|
| ︙ | ︙ | |||
154 155 156 157 158 159 160 | static int triggerPipe = -1; /* * The notifierMutex locks access to all of the global notifier state. */ | > > > > > > > | > | | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | static int triggerPipe = -1; /* * The notifierMutex locks access to all of the global notifier state. */ pthread_mutex_t notifierInitMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t notifierMutex = PTHREAD_MUTEX_INITIALIZER; /* * The following static indicates if the notifier thread is running. * * You must hold the notifierInitMutex before accessing this variable. */ static int notifierThreadRunning = 0; /* * The notifier thread signals the notifierCV when it has finished * initializing the triggerPipe and right before the notifier thread * terminates. */ static pthread_cond_t notifierCV = PTHREAD_COND_INITIALIZER; /* * The pollState bits * POLL_WANT is set by each thread before it waits on its condition * variable. It is checked by the notifier before it does select. * POLL_DONE is set by the notifier if it goes into select after seeing * POLL_WANT. The idea is to ensure it tries a select with the |
| ︙ | ︙ | |||
190 191 192 193 194 195 196 | /* * Static routines defined in this file. */ #ifdef TCL_THREADS static void NotifierThreadProc(ClientData clientData); | | | | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | /* * Static routines defined in this file. */ #ifdef TCL_THREADS static void NotifierThreadProc(ClientData clientData); #if defined(HAVE_PTHREAD_ATFORK) static int atForkInit = AT_FORK_INIT_VALUE; static void AtForkPrepare(void); static void AtForkParent(void); static void AtForkChild(void); #endif /* HAVE_PTHREAD_ATFORK */ #endif /* TCL_THREADS */ static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); |
| ︙ | ︙ | |||
247 248 249 250 251 252 253 | void *); extern void __stdcall PostQuitMessage(int); extern void *__stdcall RegisterClassW(const WNDCLASS *); extern unsigned char __stdcall ResetEvent(void *); extern unsigned char __stdcall TranslateMessage(const MSG *); /* | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
void *);
extern void __stdcall PostQuitMessage(int);
extern void *__stdcall RegisterClassW(const WNDCLASS *);
extern unsigned char __stdcall ResetEvent(void *);
extern unsigned char __stdcall TranslateMessage(const MSG *);
/*
* Threaded-cygwin specific constants and functions in this file:
*/
static const WCHAR NotfyClassName[] = L"TclNotifier";
static DWORD __stdcall NotifierProc(void *hwnd, unsigned int message,
void *wParam, void *lParam);
#endif /* TCL_THREADS && __CYGWIN__ */
#if TCL_THREADS
/*
*----------------------------------------------------------------------
*
* StartNotifierThread --
*
* Start a notfier thread and wait for the notifier pipe to be created.
*
* Results:
* None.
*
* Side effects:
* Running Thread.
*
*----------------------------------------------------------------------
*/
static void
StartNotifierThread(const char *proc)
{
if (!notifierThreadRunning) {
pthread_mutex_lock(¬ifierInitMutex);
if (!notifierThreadRunning) {
if (TclpThreadCreate(¬ifierThread, NotifierThreadProc, NULL,
TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
Tcl_Panic("%s: unable to start notifier thread", proc);
}
pthread_mutex_lock(¬ifierMutex);
/*
* Wait for the notifier pipe to be created.
*/
while (triggerPipe < 0) {
pthread_cond_wait(¬ifierCV, ¬ifierMutex);
}
pthread_mutex_unlock(¬ifierMutex);
notifierThreadRunning = 1;
}
pthread_mutex_unlock(¬ifierInitMutex);
}
}
#endif /* TCL_THREADS */
/*
*----------------------------------------------------------------------
*
* Tcl_InitNotifier --
*
* Initializes the platform specific notifier state.
*
|
| ︙ | ︙ | |||
282 283 284 285 286 287 288 |
} else {
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#ifdef TCL_THREADS
tsdPtr->eventReady = 0;
/*
| | > > > > > > > > > > > > > > > > > > > > > > > > > > | | | < < < < < < < < < < < | < < < < < < < < < < | < < | < < | 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 |
} else {
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#ifdef TCL_THREADS
tsdPtr->eventReady = 0;
/*
* Initialize thread specific condition variable for this thread.
*/
if (tsdPtr->waitCVinitialized == 0) {
#ifdef __CYGWIN__
WNDCLASS class;
class.style = 0;
class.cbClsExtra = 0;
class.cbWndExtra = 0;
class.hInstance = TclWinGetTclInstance();
class.hbrBackground = NULL;
class.lpszMenuName = NULL;
class.lpszClassName = NotfyClassName;
class.lpfnWndProc = NotifierProc;
class.hIcon = NULL;
class.hCursor = NULL;
RegisterClassW(&class);
tsdPtr->hwnd = CreateWindowExW(NULL, class.lpszClassName,
class.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL,
TclWinGetTclInstance(), NULL);
tsdPtr->event = CreateEventW(NULL, 1 /* manual */,
0 /* !signaled */, NULL);
#else
pthread_cond_init(&tsdPtr->waitCV, NULL);
#endif /* __CYGWIN__ */
tsdPtr->waitCVinitialized = 1;
}
pthread_mutex_lock(¬ifierInitMutex);
#if defined(HAVE_PTHREAD_ATFORK)
/*
* Install pthread_atfork handlers to clean up the notifier in the
* child of a fork.
*/
if (!atForkInit) {
int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild);
if (result) {
Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
}
atForkInit = 1;
}
#endif /* HAVE_PTHREAD_ATFORK */
notifierCount++;
pthread_mutex_unlock(¬ifierInitMutex);
#endif /* TCL_THREADS */
return tsdPtr;
}
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
365 366 367 368 369 370 371 |
if (tclNotifierHooks.finalizeNotifierProc) {
tclNotifierHooks.finalizeNotifierProc(clientData);
return;
} else {
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
| | < | < < < < < < < < < < < < < < < | | | | | | | | > > < | | | > > > > | > | | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 |
if (tclNotifierHooks.finalizeNotifierProc) {
tclNotifierHooks.finalizeNotifierProc(clientData);
return;
} else {
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
pthread_mutex_lock(¬ifierInitMutex);
notifierCount--;
/*
* If this is the last thread to use the notifier, close the notifier
* pipe and wait for the background thread to terminate.
*/
if (notifierCount == 0) {
if (triggerPipe != -1) {
if (write(triggerPipe, "q", 1) != 1) {
Tcl_Panic("Tcl_FinalizeNotifier: %s",
"unable to write q to triggerPipe");
}
close(triggerPipe);
while(triggerPipe != -1) {
pthread_cond_wait(¬ifierCV, ¬ifierMutex);
}
if (notifierThreadRunning) {
int result = pthread_join((pthread_t) notifierThread, NULL);
if (result) {
Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier "
"thread");
}
notifierThreadRunning = 0;
}
}
}
/*
* Clean up any synchronization objects in the thread local storage.
*/
#ifdef __CYGWIN__
DestroyWindow(tsdPtr->hwnd);
CloseHandle(tsdPtr->event);
#else /* __CYGWIN__ */
pthread_cond_destroy(&tsdPtr->waitCV);
#endif /* __CYGWIN__ */
tsdPtr->waitCVinitialized = 0;
pthread_mutex_unlock(¬ifierInitMutex);
#endif /* TCL_THREADS */
}
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
453 454 455 456 457 458 459 |
if (tclNotifierHooks.alertNotifierProc) {
tclNotifierHooks.alertNotifierProc(clientData);
return;
} else {
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = clientData;
| | > | | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 |
if (tclNotifierHooks.alertNotifierProc) {
tclNotifierHooks.alertNotifierProc(clientData);
return;
} else {
#ifdef TCL_THREADS
ThreadSpecificData *tsdPtr = clientData;
pthread_mutex_lock(¬ifierMutex);
tsdPtr->eventReady = 1;
# ifdef __CYGWIN__
PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
# else
pthread_cond_broadcast(&tsdPtr->waitCV);
# endif /* __CYGWIN__ */
pthread_mutex_unlock(¬ifierMutex);
#endif /* TCL_THREADS */
}
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
523 524 525 526 527 528 529 |
Tcl_ServiceModeHook(
int mode) /* Either TCL_SERVICE_ALL, or
* TCL_SERVICE_NONE. */
{
if (tclNotifierHooks.serviceModeHookProc) {
tclNotifierHooks.serviceModeHookProc(mode);
return;
| | | > > | 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 |
Tcl_ServiceModeHook(
int mode) /* Either TCL_SERVICE_ALL, or
* TCL_SERVICE_NONE. */
{
if (tclNotifierHooks.serviceModeHookProc) {
tclNotifierHooks.serviceModeHookProc(mode);
return;
} else if (mode == TCL_SERVICE_ALL) {
#if TCL_THREADS
StartNotifierThread("Tcl_ServiceModeHook");
#endif
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_CreateFileHandler --
|
| ︙ | ︙ | |||
737 738 739 740 741 742 743 744 745 746 747 748 749 750 |
* Search through the file handlers to find the one whose handle matches
* the event. We do this rather than keeping a pointer to the file handler
* directly in the event, so that the handler can be deleted while the
* event is queued without leaving a dangling pointer.
*/
tsdPtr = TCL_TSD_INIT(&dataKey);
for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
filePtr = filePtr->nextPtr) {
if (filePtr->fd != fileEvPtr->fd) {
continue;
}
/*
| > | 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 |
* Search through the file handlers to find the one whose handle matches
* the event. We do this rather than keeping a pointer to the file handler
* directly in the event, so that the handler can be deleted while the
* event is queued without leaving a dangling pointer.
*/
tsdPtr = TCL_TSD_INIT(&dataKey);
for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
filePtr = filePtr->nextPtr) {
if (filePtr->fd != fileEvPtr->fd) {
continue;
}
/*
|
| ︙ | ︙ | |||
874 875 876 877 878 879 880 |
} else {
timeoutPtr = NULL;
#endif /* !TCL_THREADS */
}
#ifdef TCL_THREADS
/*
| | > | | < < < < < < < < < < < < < < < < < < < < < < < | | 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 |
} else {
timeoutPtr = NULL;
#endif /* !TCL_THREADS */
}
#ifdef TCL_THREADS
/*
* Start notifier thread and place this thread on the list of
* interested threads, signal the notifier thread, and wait for a
* response or a timeout.
*/
StartNotifierThread("Tcl_WaitForEvent");
pthread_mutex_lock(¬ifierMutex);
if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0
#if defined(__APPLE__) && defined(__LP64__)
/*
* On 64-bit Darwin, pthread_cond_timedwait() appears to have
* a bug that causes it to wait forever when passed an
* absolute time which has already been exceeded by the system
|
| ︙ | ︙ | |||
967 968 969 970 971 972 973 |
DWORD timeout;
if (timePtr) {
timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
} else {
timeout = 0xFFFFFFFF;
}
| | | > > > > > > > > > > | > | 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 |
DWORD timeout;
if (timePtr) {
timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
} else {
timeout = 0xFFFFFFFF;
}
pthread_mutex_unlock(¬ifierMutex);
MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
pthread_mutex_lock(¬ifierMutex);
}
#else
if (timePtr != NULL) {
Tcl_Time now;
struct timespec ptime;
Tcl_GetTime(&now);
ptime.tv_sec = timePtr->sec + now.sec + (timePtr->usec + now.usec) / 1000000;
ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
pthread_cond_timedwait(&tsdPtr->waitCV, ¬ifierMutex, &ptime);
} else {
pthread_cond_wait(&tsdPtr->waitCV, ¬ifierMutex);
}
#endif /* __CYGWIN__ */
}
tsdPtr->eventReady = 0;
#ifdef __CYGWIN__
while (PeekMessageW(&msg, NULL, 0, 0, 0)) {
/*
|
| ︙ | ︙ | |||
1075 1076 1077 1078 1079 1080 1081 | fileEvPtr->header.proc = FileHandlerEventProc; fileEvPtr->fd = filePtr->fd; Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); } filePtr->readyMask = mask; } #ifdef TCL_THREADS | | | 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 |
fileEvPtr->header.proc = FileHandlerEventProc;
fileEvPtr->fd = filePtr->fd;
Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
}
filePtr->readyMask = mask;
}
#ifdef TCL_THREADS
pthread_mutex_unlock(¬ifierMutex);
#endif /* TCL_THREADS */
return 0;
}
}
#ifdef TCL_THREADS
/*
|
| ︙ | ︙ | |||
1147 1148 1149 1150 1151 1152 1153 |
"could not make trigger pipe close-on-exec");
}
/*
* Install the write end of the pipe into the global variable.
*/
| | | | | | 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 |
"could not make trigger pipe close-on-exec");
}
/*
* Install the write end of the pipe into the global variable.
*/
pthread_mutex_lock(¬ifierMutex);
triggerPipe = fds[1];
/*
* Signal any threads that are waiting.
*/
pthread_cond_broadcast(¬ifierCV);
pthread_mutex_unlock(¬ifierMutex);
/*
* Look for file events and report them to interested threads.
*/
while (1) {
FD_ZERO(&readableMask);
FD_ZERO(&writableMask);
FD_ZERO(&exceptionMask);
/*
* Compute the logical OR of the select masks from all the waiting
* notifiers.
*/
pthread_mutex_lock(¬ifierMutex);
timePtr = NULL;
for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
if (FD_ISSET(i, &tsdPtr->checkMasks.readable)) {
FD_SET(i, &readableMask);
}
if (FD_ISSET(i, &tsdPtr->checkMasks.writable)) {
|
| ︙ | ︙ | |||
1198 1199 1200 1201 1202 1203 1204 | * bits that were present when the thread tried to poll. */ tsdPtr->pollState |= POLL_DONE; timePtr = &poll; } } | | | 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 |
* bits that were present when the thread tried to poll.
*/
tsdPtr->pollState |= POLL_DONE;
timePtr = &poll;
}
}
pthread_mutex_unlock(¬ifierMutex);
/*
* Set up the select mask to include the receive pipe.
*/
if (receivePipe >= numFdBits) {
numFdBits = receivePipe + 1;
|
| ︙ | ︙ | |||
1222 1223 1224 1225 1226 1227 1228 | continue; } /* * Alert any threads that are waiting on a ready file descriptor. */ | | | 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 |
continue;
}
/*
* Alert any threads that are waiting on a ready file descriptor.
*/
pthread_mutex_lock(¬ifierMutex);
for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
found = 0;
for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
&& FD_ISSET(i, &readableMask)) {
FD_SET(i, &tsdPtr->readyMasks.readable);
|
| ︙ | ︙ | |||
1269 1270 1271 1272 1273 1274 1275 | tsdPtr->nextPtr = tsdPtr->prevPtr = NULL; tsdPtr->onList = 0; tsdPtr->pollState = 0; } #ifdef __CYGWIN__ PostMessageW(tsdPtr->hwnd, 1024, 0, 0); #else /* __CYGWIN__ */ | | | | 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 | tsdPtr->nextPtr = tsdPtr->prevPtr = NULL; tsdPtr->onList = 0; tsdPtr->pollState = 0; } #ifdef __CYGWIN__ PostMessageW(tsdPtr->hwnd, 1024, 0, 0); #else /* __CYGWIN__ */ pthread_cond_broadcast(&tsdPtr->waitCV); #endif /* __CYGWIN__ */ } } pthread_mutex_unlock(¬ifierMutex); /* * Consume the next byte from the notifier pipe if the pipe was * readable. Note that there may be multiple bytes pending, but to * avoid a race condition we only read one at a time. */ |
| ︙ | ︙ | |||
1302 1303 1304 1305 1306 1307 1308 |
/*
* Clean up the read end of the pipe and signal any threads waiting on
* termination of the notifier thread.
*/
close(receivePipe);
| | | | | > | < | | 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 |
/*
* Clean up the read end of the pipe and signal any threads waiting on
* termination of the notifier thread.
*/
close(receivePipe);
pthread_mutex_lock(¬ifierMutex);
triggerPipe = -1;
pthread_cond_broadcast(¬ifierCV);
pthread_mutex_unlock(¬ifierMutex);
TclpThreadExit(0);
}
#if defined(HAVE_PTHREAD_ATFORK)
/*
*----------------------------------------------------------------------
*
* AtForkPrepare --
*
* Lock the notifier in preparation for a fork.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
AtForkPrepare(void)
{
#if RESET_ATFORK_MUTEX == 0
pthread_mutex_lock(¬ifierInitMutex);
#endif
}
/*
*----------------------------------------------------------------------
*
* AtForkParent --
*
|
| ︙ | ︙ | |||
1354 1355 1356 1357 1358 1359 1360 |
*
*----------------------------------------------------------------------
*/
static void
AtForkParent(void)
{
| | < | > | 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 |
*
*----------------------------------------------------------------------
*/
static void
AtForkParent(void)
{
#if RESET_ATFORK_MUTEX == 0
pthread_mutex_unlock(¬ifierInitMutex);
#endif
}
/*
*----------------------------------------------------------------------
*
* AtForkChild --
*
|
| ︙ | ︙ | |||
1378 1379 1380 1381 1382 1383 1384 |
*
*----------------------------------------------------------------------
*/
static void
AtForkChild(void)
{
| > > > > > > > > > > | > > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 |
*
*----------------------------------------------------------------------
*/
static void
AtForkChild(void)
{
if (notifierThreadRunning == 1) {
pthread_cond_destroy(¬ifierCV);
}
#if RESET_ATFORK_MUTEX == 0
pthread_mutex_unlock(¬ifierInitMutex);
#else
pthread_mutex_init(¬ifierInitMutex, NULL);
pthread_mutex_init(¬ifierMutex, NULL);
#endif
pthread_cond_init(¬ifierCV, NULL);
/*
* notifierThreadRunning == 1: thread is running, (there might be data in notifier lists)
* atForkInit == 0: InitNotifier was never called
* notifierCount != 0: unbalanced InitNotifier() / FinalizeNotifier calls
* waitingListPtr != 0: there are threads currently waiting for events.
*/
if (atForkInit == 1) {
notifierCount = 0;
if (notifierThreadRunning == 1) {
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
notifierThreadRunning = 0;
close(triggerPipe);
triggerPipe = -1;
/*
* The waitingListPtr might contain event info from multiple
* threads, which are invalid here, so setting it to NULL is not
* unreasonable.
*/
waitingListPtr = NULL;
/*
* The tsdPtr from before the fork is copied as well. But since
* we are paranoic, we don't trust its condvar and reset it.
*/
#ifdef __CYGWIN__
DestroyWindow(tsdPtr->hwnd);
tsdPtr->hwnd = CreateWindowExW(NULL, NotfyClassName,
NotfyClassName, 0, 0, 0, 0, 0, NULL, NULL,
TclWinGetTclInstance(), NULL);
ResetEvent(tsdPtr->event);
#else
pthread_cond_destroy(&tsdPtr->waitCV);
pthread_cond_init(&tsdPtr->waitCV, NULL);
#endif
/*
* In case, we had multiple threads running before the fork,
* make sure, we don't try to reach out to their thread local data.
*/
tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
/*
* The list of registered event handlers at fork time is in
* tsdPtr->firstFileHandlerPtr;
*/
}
}
Tcl_InitNotifier();
}
#endif /* HAVE_PTHREAD_ATFORK */
#endif /* TCL_THREADS */
#endif /* !HAVE_COREFOUNDATION */
|
| ︙ | ︙ |
Changes to unix/tclUnixThrd.c.
| ︙ | ︙ | |||
381 382 383 384 385 386 387 | #endif } /* *---------------------------------------------------------------------- * | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | #endif } /* *---------------------------------------------------------------------- * * Tcl_GetAllocMutex * * This procedure returns a pointer to a statically initialized mutex for * use by the memory allocator. The alloctor must use this lock, because * all other locks are allocated... * * Results: |
| ︙ | ︙ | |||
506 507 508 509 510 511 512 |
pthread_mutex_init(pmutexPtr, NULL);
*mutexPtr = (Tcl_Mutex)pmutexPtr;
TclRememberMutex(mutexPtr);
}
MASTER_UNLOCK;
}
while (1) {
| | | | | | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 |
pthread_mutex_init(pmutexPtr, NULL);
*mutexPtr = (Tcl_Mutex)pmutexPtr;
TclRememberMutex(mutexPtr);
}
MASTER_UNLOCK;
}
while (1) {
pthread_mutex_lock(&mutexLock);
pmutexPtr = *((pthread_mutex_t **)mutexPtr);
if (pmutexPtr == NULL) {
pthread_mutex_unlock(&mutexLock);
goto retry;
}
if (pthread_mutex_trylock(pmutexPtr) == 0) {
pthread_mutex_unlock(&mutexLock);
return;
}
pthread_mutex_unlock(&mutexLock);
/*
* BUGBUG: All core and Thread package tests pass when usleep()
* is used; however, the Thread package tests hang at
* various places when Tcl_Sleep() is used, typically
* while running test "thread-17.8", "thread-17.9", or
* "thread-17.11a". Really, what we want here is just
* to yield to other threads for a while.
|
| ︙ | ︙ |
Changes to win/tclWinThrd.c.
| ︙ | ︙ | |||
478 479 480 481 482 483 484 |
{
LeaveCriticalSection(&masterLock);
}
/*
*----------------------------------------------------------------------
*
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 |
{
LeaveCriticalSection(&masterLock);
}
/*
*----------------------------------------------------------------------
*
* Tcl_GetAllocMutex
*
* This procedure returns a pointer to a statically initialized mutex for
* use by the memory allocator. The alloctor must use this lock, because
* all other locks are allocated...
*
* Results:
|
| ︙ | ︙ | |||
648 649 650 651 652 653 654 |
InitializeCriticalSection(csPtr);
*mutexPtr = (Tcl_Mutex)csPtr;
TclRememberMutex(mutexPtr);
}
MASTER_UNLOCK;
}
while (1) {
| | | | | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 |
InitializeCriticalSection(csPtr);
*mutexPtr = (Tcl_Mutex)csPtr;
TclRememberMutex(mutexPtr);
}
MASTER_UNLOCK;
}
while (1) {
EnterCriticalSection(&mutexLock);
csPtr = *((CRITICAL_SECTION **)mutexPtr);
if (csPtr == NULL) {
LeaveCriticalSection(&mutexLock);
goto retry;
}
if (TryEnterCriticalSection(csPtr)) {
LeaveCriticalSection(&mutexLock);
return;
}
LeaveCriticalSection(&mutexLock);
Tcl_Sleep(TCL_MUTEX_LOCK_SLEEP_TIME);
}
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ |