Tcl Source Code

Check-in [9ce15c7f1a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:NRT relevant only: provides self-calibrating mechanism for TclpUSleep (the actual time of usleep/nanosleep may be longer, due to system latencies and possible limitations in the timer resolution of the hardware); forces context switch or yield the processor if sleep time to small.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | sebres-8-5-event-perf-branch
Files: files | file ages | folders
SHA3-256: 9ce15c7f1acd585fd94ab1fac058c1e5d4502ec434d9e3c973e2d640629ebcbd
User & Date: sebres 2019-03-09 21:04:55.414
Context
2019-05-22
09:18
merge 8.5 check-in: ba97c71d8f user: sebres tags: sebres-8-5-event-perf-branch
2019-03-09
21:22
merge 8-5-event-perf-branch check-in: 697065a8e5 user: sebres tags: sebres-8-6-event-perf-branch
21:04
NRT relevant only: provides self-calibrating mechanism for TclpUSleep (the actual time of usleep/nan... check-in: 9ce15c7f1a user: sebres tags: sebres-8-5-event-perf-branch
20:07
non-native time scale fixed: do scale time only once (not in cycle, since all other times used in ca... check-in: f20b5264a3 user: sebres tags: sebres-8-5-event-perf-branch
Changes
Unified Diff Ignore Whitespace Patch
Changes to unix/tclUnixNotfy.c.
843
844
845
846
847
848
849
850

851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869




870
871
872
873
874

875
876
877
878
879
880
881
 *
 * Note: Adjusting of this values may increase NRT-capability, but also may
 * 	 increase CPU load (resp. busy waits on brief intervals).
 */

#ifndef TCL_TMR_MIN_DELAY
#   define TCL_TMR_MIN_DELAY 100
#   define TCL_TMR_MIN_SLEEP 50

#   define TCL_TMR_OVERHEAD 50
#endif

/*
 *----------------------------------------------------------------------
 *
 * TclpUSleep --
 *
 *	Delay execution for the specified time (in microseconds).
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Time passes.
 *
 *----------------------------------------------------------------------
 */





void
TclpUSleep(
    Tcl_WideInt usec)	/* Time to sleep. */
{
    Tcl_WideInt now, desired;


    if (usec < 0) {
	usec = 0;
    }

    /*
     * TIP #233: Scale from virtual time to real-time for select/usleep.







|
>



















>
>
>
>





>







843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
 *
 * Note: Adjusting of this values may increase NRT-capability, but also may
 * 	 increase CPU load (resp. busy waits on brief intervals).
 */

#ifndef TCL_TMR_MIN_DELAY
#   define TCL_TMR_MIN_DELAY 100
#   define TCL_TMR_MIN_USLEEP 50
#   define TCL_TMR_MIN_NSLEEP 1
#   define TCL_TMR_OVERHEAD 50
#endif

/*
 *----------------------------------------------------------------------
 *
 * TclpUSleep --
 *
 *	Delay execution for the specified time (in microseconds).
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Time passes.
 *
 *----------------------------------------------------------------------
 */

static unsigned int tclMinDelay  = TCL_TMR_MIN_DELAY;
static unsigned int tclMinUSleep = TCL_TMR_MIN_USLEEP;
static unsigned int tclMinNSleep = TCL_TMR_MIN_NSLEEP;

void
TclpUSleep(
    Tcl_WideInt usec)	/* Time to sleep. */
{
    Tcl_WideInt now, desired;
    unsigned int *calibValue;

    if (usec < 0) {
	usec = 0;
    }

    /*
     * TIP #233: Scale from virtual time to real-time for select/usleep.
893
894
895
896
897
898
899
900
901
902
903


904
905
906
907
908
909
910


911
912
913
914
915
916


917
918
919
920




921
922
923
924
925
926







927
928
929
930
931
932
933
    now = TclpGetUTimeMonotonic();
    if ((desired = (now + usec)) < now) { /* overflow */
	desired = 0x7FFFFFFFFFFFFFFFL;
    }

    while (1) {
	
	if (usec >= TCL_TMR_MIN_DELAY) {

	    struct timeval delay;



	    delay.tv_sec  = usec / 1000000;
	    delay.tv_usec = usec % 1000000;

	    (void) select(0, (SELECT_MASK *) 0, (SELECT_MASK *) 0,
		(SELECT_MASK *) 0, &delay);

	} else if (usec >= TCL_TMR_MIN_SLEEP) {


	    usleep((useconds_t)(usec - TCL_TMR_MIN_SLEEP));
	} else {
	    /* nanosleep has the same minimal sleep interval as usleep */
#if 0
	    struct timespec delay;



	    delay.tv_sec  = usec / 1000000;
	    delay.tv_nsec = (usec % 1000000) * 1000; /* usec to nsec */

	    nanosleep(&delay, NULL);




#endif
	}
	
	now = TclpGetUTimeMonotonic();

	if ((usec = (desired - now)) <= 0 /* or tolerance */) {







	    break;
	}
    }
}

/*
 *----------------------------------------------------------------------







|



>
>






|
>
>
|
|
<
<


>
>




>
>
>
>






>
>
>
>
>
>
>







899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922


923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
    now = TclpGetUTimeMonotonic();
    if ((desired = (now + usec)) < now) { /* overflow */
	desired = 0x7FFFFFFFFFFFFFFFL;
    }

    while (1) {
	
	if (usec >= tclMinDelay) {

	    struct timeval delay;

	    calibValue = &tclMinDelay;
	    usec -= (usec % tclMinDelay);
	    delay.tv_sec  = usec / 1000000;
	    delay.tv_usec = usec % 1000000;

	    (void) select(0, (SELECT_MASK *) 0, (SELECT_MASK *) 0,
		(SELECT_MASK *) 0, &delay);

	} else if (usec >= tclMinUSleep) {
	    calibValue = &tclMinUSleep;
	    usec -= (usec % tclMinUSleep);
	    usleep((useconds_t)usec);
	} else if (usec >= tclMinNSleep) {


	    struct timespec delay;

	    calibValue = &tclMinNSleep;
	    usec -= (usec % tclMinNSleep);
	    delay.tv_sec  = usec / 1000000;
	    delay.tv_nsec = (usec % 1000000) * 1000; /* usec to nsec */

	    nanosleep(&delay, NULL);
	} else {
	    calibValue = NULL;
#ifdef _POSIX_PRIORITY_SCHEDULING
	    sched_yield(); /* yield the processor (force context switch). */
#endif
	}
	
	now = TclpGetUTimeMonotonic();

	if ((usec = (desired - now)) <= 0 /* or tolerance */) {
	    /*
	     * Self calibration - sleep was too long, so adjust related value.
	     */
	    if (calibValue && (unsigned int)-usec > *calibValue) {
		*calibValue = (*calibValue + (unsigned int)-usec) / 2;
	    }
	    /* end of sleep */
	    break;
	}
    }
}

/*
 *----------------------------------------------------------------------