1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
-
+
|
/*
* 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.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclUnixNotfy.c,v 1.12.2.5 2004/12/09 23:01:35 dgp Exp $
* RCS: @(#) $Id: tclUnixNotfy.c,v 1.12.2.6 2005/01/24 21:45:36 dgp Exp $
*/
#include "tclInt.h"
#include <signal.h>
extern TclStubs tclStubs;
extern Tcl_NotifierProcs tclOriginalNotifier;
|
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
|
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
|
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-
+
|
int
Tcl_WaitForEvent(timePtr)
Tcl_Time *timePtr; /* Maximum block time, or NULL. */
{
FileHandler *filePtr;
FileHandlerEvent *fileEvPtr;
struct timeval timeout, *timeoutPtr;
int mask;
Tcl_Time myTime;
#ifdef TCL_THREADS
int waitForFiles;
Tcl_Time *myTimePtr;
#else
/* Impl. notes: timeout & timeoutPtr are used if, and only if
* threads are not enabled. They are the arguments for the regular
* select() used when the core is not thread-enabled. */
struct timeval timeout, *timeoutPtr;
int numFound;
#endif
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tclStubs.tcl_WaitForEvent != tclOriginalNotifier.waitForEventProc) {
return tclStubs.tcl_WaitForEvent(timePtr);
}
/*
* Set up the timeout structure. Note that if there are no events to
* check for, we return with a negative result rather than blocking
* forever.
*/
if (timePtr) {
/* TIP #233 (Virtualized Time). Is virtual time in effect ?
* And do we actually have something to scale ? If yes to both
* then we call the handler to do this scaling */
myTime.sec = timePtr->sec;
myTime.usec = timePtr->usec;
(*tclScaleTimeProcPtr) (&myTime, tclTimeClientData);
#ifdef TCL_THREADS
myTimePtr = &myTime;
#else
timeout.tv_sec = timePtr->sec;
timeout.tv_usec = timePtr->usec;
timeoutPtr = &timeout;
timeout.tv_sec = myTime.sec;
timeout.tv_usec = myTime.usec;
timeoutPtr = &timeout;
#endif
#ifndef TCL_THREADS
} else if (tsdPtr->numFdBits == 0) {
/*
* If there are no threads, no timeout, and no fds registered,
* then there are no events possible and we must avoid deadlock.
* Note that this is not entirely correct because there might
* be a signal that could interrupt the select call, but we
* don't handle that case if we aren't using threads.
*/
return -1;
#endif
} else {
#ifdef TCL_THREADS
myTimePtr = NULL;
#else
timeoutPtr = NULL;
#endif
}
#ifdef TCL_THREADS
/*
* Place this thread on the list of interested threads, signal the
* notifier thread, and wait for a response or a timeout.
*/
Tcl_MutexLock(¬ifierMutex);
waitForFiles = (tsdPtr->numFdBits > 0);
if (timePtr != NULL && timePtr->sec == 0 && timePtr->usec == 0) {
if (myTimePtr != NULL && myTimePtr->sec == 0 && myTimePtr->usec == 0) {
/*
* Cannot emulate a polling select with a polling condition variable.
* Instead, pretend to wait for files and tell the notifier
* thread what we are doing. The notifier thread makes sure
* it goes through select with its select mask in the same state
* as ours currently is. We block until that happens.
*/
waitForFiles = 1;
tsdPtr->pollState = POLL_WANT;
timePtr = NULL;
myTimePtr = NULL;
} else {
tsdPtr->pollState = 0;
}
if (waitForFiles) {
/*
* Add the ThreadSpecificData structure of this thread to the list
|
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
|
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
|
-
+
|
}
FD_ZERO( &(tsdPtr->readyMasks.readable) );
FD_ZERO( &(tsdPtr->readyMasks.writable) );
FD_ZERO( &(tsdPtr->readyMasks.exceptional) );
if (!tsdPtr->eventReady) {
Tcl_ConditionWait(&tsdPtr->waitCV, ¬ifierMutex, timePtr);
Tcl_ConditionWait(&tsdPtr->waitCV, ¬ifierMutex, myTimePtr);
}
tsdPtr->eventReady = 0;
if (waitForFiles && tsdPtr->onList) {
/*
* Remove the ThreadSpecificData structure of this thread from the
* waiting list. Alert the notifier thread to recompute its select
|