Tcl Source Code

Changes On Branch tip-302
Login

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

Changes In Branch tip-302 Excluding Merge-Ins

This is equivalent to a diff from 255b94edcb to f59a6453b1

2016-04-01
11:56
Two micro-optimizations in Win and UNIX notifier. See: [http://code.activestate.com/lists/tcl-core/1... check-in: b1a8aa4406 user: jan.nijtmans tags: trunk
2016-03-31
07:11
Added patch for win/configure.in into win/configure.ac Leaf check-in: f59a6453b1 user: oehhar tags: tip-302
2016-03-30
20:03
The following patch against a stock tcl 8.6.5 source tree tries to

implement most of TIP #302 for U... check-in: 6fa1088680 user: oehhar tags: tip-302

15:41
merge trunk: check-in: e2b0d6d5e8 user: dgp tags: tip-445
12:57
merge trunk Closed-Leaf check-in: a919e9ea58 user: jan.nijtmans tags: notifier
2016-03-29
12:07
merge trunk check-in: ad2fb188b8 user: dgp tags: novem
10:17
Eliminate AT_FORK_INIT_VALUE/RESET_ATFORK_MUTEX macro's, since other values than the default are not... check-in: 255b94edcb user: jan.nijtmans tags: trunk
2016-03-27
21:28
Better fix for [7d0db7c388f52de81]: In stead of adding dependencies to multiple Makefile lines, comb... check-in: fb6e45132e user: jan.nijtmans tags: trunk

Changes to generic/tclCmdMZ.c.

4120
4121
4122
4123
4124
4125
4126











4127
4128
4129
4130


4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146













4147
4148
4149
4150


4151
4152
4153
4154
4155
4156
4157













4158
4159
4160
4161
4162
4163
4164


4165
4166
4167
4168
4169
4170
4171
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register Tcl_Obj *objPtr;
    Tcl_Obj *objs[4];
    register int i, result;
    int count;
    double totalMicroSec;











#ifndef TCL_WIDE_CLICKS
    Tcl_Time start, stop;
#else
    Tcl_WideInt start, stop;


#endif

    if (objc == 2) {
	count = 1;
    } else if (objc == 3) {
	result = TclGetIntFromObj(interp, objv[2], &count);
	if (result != TCL_OK) {
	    return result;
	}
    } else {
	Tcl_WrongNumArgs(interp, 1, objv, "command ?count?");
	return TCL_ERROR;
    }

    objPtr = objv[1];
    i = count;













#ifndef TCL_WIDE_CLICKS
    Tcl_GetTime(&start);
#else
    start = TclpGetWideClicks();


#endif
    while (i-- > 0) {
	result = Tcl_EvalObjEx(interp, objPtr, 0);
	if (result != TCL_OK) {
	    return result;
	}
    }













#ifndef TCL_WIDE_CLICKS
    Tcl_GetTime(&stop);
    totalMicroSec = ((double) (stop.sec - start.sec)) * 1.0e6
	    + (stop.usec - start.usec);
#else
    stop = TclpGetWideClicks();
    totalMicroSec = ((double) TclpWideClicksToNanoseconds(stop - start))/1.0e3;


#endif

    if (count <= 1) {
	/*
	 * Use int obj since we know time is not fractional. [Bug 1202178]
	 */








>
>
>
>
>
>
>
>
>
>
>




>
>
















>
>
>
>
>
>
>
>
>
>
>
>
>




>
>







>
>
>
>
>
>
>
>
>
>
>
>
>







>
>







4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    register Tcl_Obj *objPtr;
    Tcl_Obj *objs[4];
    register int i, result;
    int count;
    double totalMicroSec;
#ifdef WIN32_USE_TICKCOUNT
#if (_WIN32_WINNT >= 0x0600)
    ULONGLONG start, stop;
#else
    DWORD start, stop;
#endif
#else
#ifdef HAVE_CLOCK_GETTIME
    int monoClock = 1;
    struct timespec start, stop;
#else
#ifndef TCL_WIDE_CLICKS
    Tcl_Time start, stop;
#else
    Tcl_WideInt start, stop;
#endif
#endif
#endif

    if (objc == 2) {
	count = 1;
    } else if (objc == 3) {
	result = TclGetIntFromObj(interp, objv[2], &count);
	if (result != TCL_OK) {
	    return result;
	}
    } else {
	Tcl_WrongNumArgs(interp, 1, objv, "command ?count?");
	return TCL_ERROR;
    }

    objPtr = objv[1];
    i = count;
#ifdef WIN32_USE_TICKCOUNT
#if (_WIN32_WINNT >= 0x0600)
    start = GetTickCount64();
#else
    start = GetTickCount();
#endif
#else
#ifdef HAVE_CLOCK_GETTIME
    if (clock_gettime(CLOCK_MONOTONIC, &start) == -1) {
	clock_gettime(CLOCK_REALTIME, &start);
	monoClock = 0;
    }
#else
#ifndef TCL_WIDE_CLICKS
    Tcl_GetTime(&start);
#else
    start = TclpGetWideClicks();
#endif
#endif
#endif
    while (i-- > 0) {
	result = Tcl_EvalObjEx(interp, objPtr, 0);
	if (result != TCL_OK) {
	    return result;
	}
    }
#ifdef WIN32_USE_TICKCOUNT
#if (_WIN32_WINNT >= 0x0600)
    stop = GetTickCount64();
#else
    stop = GetTickCount();
#endif
    totalMicroSec = (stop - start) * 1000.0;
#else
#ifdef HAVE_CLOCK_GETTIME
    clock_gettime(monoClock ? CLOCK_MONOTONIC : CLOCK_REALTIME, &stop);
    totalMicroSec = ((double) (stop.tv_sec - start.tv_sec)) * 1.0e6
	    + (stop.tv_nsec - start.tv_nsec) / 1000.0;
#else
#ifndef TCL_WIDE_CLICKS
    Tcl_GetTime(&stop);
    totalMicroSec = ((double) (stop.sec - start.sec)) * 1.0e6
	    + (stop.usec - start.usec);
#else
    stop = TclpGetWideClicks();
    totalMicroSec = ((double) TclpWideClicksToNanoseconds(stop - start))/1.0e3;
#endif
#endif
#endif

    if (count <= 1) {
	/*
	 * Use int obj since we know time is not fractional. [Bug 1202178]
	 */

Changes to generic/tclInterp.c.

3412
3413
3414
3415
3416
3417
3418


3419












3420


3421
3422
3423
3424
3425
3426
3427
	Tcl_Release(interp);
    }

    if ((iPtr->limit.active & TCL_LIMIT_TIME) &&
	    ((iPtr->limit.timeGranularity == 1) ||
		(ticker % iPtr->limit.timeGranularity == 0))) {
	Tcl_Time now;















	Tcl_GetTime(&now);


	if (iPtr->limit.time.sec < now.sec ||
		(iPtr->limit.time.sec == now.sec &&
		iPtr->limit.time.usec < now.usec)) {
	    iPtr->limit.exceeded |= TCL_LIMIT_TIME;
	    Tcl_Preserve(interp);
	    RunLimitHandlers(iPtr->limit.timeHandlers, interp);
	    if (iPtr->limit.time.sec > now.sec ||







>
>

>
>
>
>
>
>
>
>
>
>
>
>

>
>







3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
	Tcl_Release(interp);
    }

    if ((iPtr->limit.active & TCL_LIMIT_TIME) &&
	    ((iPtr->limit.timeGranularity == 1) ||
		(ticker % iPtr->limit.timeGranularity == 0))) {
	Tcl_Time now;
#if (_WIN32_WINNT >= 0x0600) && defined(WIN32_USE_TICKCOUNT)
	ULONGLONG ticks = GetTickCount64();

	now.sec = ticks / 1000;
	now.usec = (ticks % 1000) * 1000;
#else
#ifdef HAVE_CLOCK_GETTIME
	struct timespec ts;

	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	    clock_gettime(CLOCK_REALTIME, &ts);
	}
	now.sec = ts.tv_sec;
	now.usec = ts.tv_nsec * 1000;
#else
	Tcl_GetTime(&now);
#endif
#endif
	if (iPtr->limit.time.sec < now.sec ||
		(iPtr->limit.time.sec == now.sec &&
		iPtr->limit.time.usec < now.usec)) {
	    iPtr->limit.exceeded |= TCL_LIMIT_TIME;
	    Tcl_Preserve(interp);
	    RunLimitHandlers(iPtr->limit.timeHandlers, interp);
	    if (iPtr->limit.time.sec > now.sec ||
3854
3855
3856
3857
3858
3859
3860






3861
3862
3863
3864
3865
3866
3867

void
Tcl_LimitTypeSet(
    Tcl_Interp *interp,
    int type)
{
    Interp *iPtr = (Interp *) interp;







    iPtr->limit.active |= type;
}

/*
 *----------------------------------------------------------------------
 *







>
>
>
>
>
>







3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889

void
Tcl_LimitTypeSet(
    Tcl_Interp *interp,
    int type)
{
    Interp *iPtr = (Interp *) interp;
#if (_WIN32_WINNT < 0x0600) && defined(WIN32_USE_TICKCOUNT)
    if (type == TCL_LIMIT_TIME) {
	/* not implemented for _WIN32 */
	return;
    }
#endif

    iPtr->limit.active |= type;
}

/*
 *----------------------------------------------------------------------
 *
4378
4379
4380
4381
4382
4383
4384



4385
4386
4387
4388
4389
4390

4391
4392
4393
4394
4395
4396
4397
    Interp *masterPtr = (Interp *) masterInterp;

    if (masterPtr->limit.active & TCL_LIMIT_COMMANDS) {
	slavePtr->limit.active |= TCL_LIMIT_COMMANDS;
	slavePtr->limit.cmdCount = 0;
	slavePtr->limit.cmdGranularity = masterPtr->limit.cmdGranularity;
    }



    if (masterPtr->limit.active & TCL_LIMIT_TIME) {
	slavePtr->limit.active |= TCL_LIMIT_TIME;
	memcpy(&slavePtr->limit.time, &masterPtr->limit.time,
		sizeof(Tcl_Time));
	slavePtr->limit.timeGranularity = masterPtr->limit.timeGranularity;
    }

}

/*
 *----------------------------------------------------------------------
 *
 * SlaveCommandLimitCmd --
 *







>
>
>






>







4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
    Interp *masterPtr = (Interp *) masterInterp;

    if (masterPtr->limit.active & TCL_LIMIT_COMMANDS) {
	slavePtr->limit.active |= TCL_LIMIT_COMMANDS;
	slavePtr->limit.cmdCount = 0;
	slavePtr->limit.cmdGranularity = masterPtr->limit.cmdGranularity;
    }
#if (_WIN32_WINNT < 0x0600) && defined(WIN32_USE_TICKCOUNT)
    /* not implemented for _WIN32 */
#else
    if (masterPtr->limit.active & TCL_LIMIT_TIME) {
	slavePtr->limit.active |= TCL_LIMIT_TIME;
	memcpy(&slavePtr->limit.time, &masterPtr->limit.time,
		sizeof(Tcl_Time));
	slavePtr->limit.timeGranularity = masterPtr->limit.timeGranularity;
    }
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * SlaveCommandLimitCmd --
 *

Changes to generic/tclTimer.c.

255
256
257
258
259
260
261

























262

263
264
265
266
267
268
269
{
    Tcl_Time time;

    /*
     * Compute when the event should fire.
     */


























    Tcl_GetTime(&time);

    time.sec += milliseconds/1000;
    time.usec += (milliseconds%1000)*1000;
    if (time.usec >= 1000000) {
	time.usec -= 1000000;
	time.sec += 1;
    }
    return TclCreateAbsoluteTimerHandler(&time, proc, clientData);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>







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
{
    Tcl_Time time;

    /*
     * Compute when the event should fire.
     */

#ifdef WIN32_USE_TICKCOUNT
#if (_WIN32_WINNT >= 0x0600)
    ULONGLONG ticks = GetTickCount64();

    time.sec = (long) ((ticks+milliseconds)/1000);
    time.usec = (long) (((ticks+milliseconds)%1000)*1000);
#else
    if (milliseconds > 0x7FFFFFFF) {
	milliseconds = 0x7FFFFFFF;
    } else if (milliseconds < 0) {
	milliseconds = 0;
    }
    time.sec = milliseconds + GetTickCount();
    time.usec = 0;
#endif
#else
#ifdef HAVE_CLOCK_GETTIME
    struct timespec ts;

    if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	clock_gettime(CLOCK_REALTIME, &ts);
    }
    time.sec = ts.tv_sec;
    time.usec = ts.tv_nsec / 1000;
#else
    Tcl_GetTime(&time);
#endif
    time.sec += milliseconds/1000;
    time.usec += (milliseconds%1000)*1000;
    if (time.usec >= 1000000) {
	time.usec -= 1000000;
	time.sec += 1;
    }
    return TclCreateAbsoluteTimerHandler(&time, proc, clientData);
312
313
314
315
316
317
318





319
320
321

322
323
324
325
326
327
328
    /*
     * Add the event to the queue in the correct position
     * (ordered by event firing time).
     */

    for (tPtr2 = tsdPtr->firstTimerHandlerPtr, prevPtr = NULL; tPtr2 != NULL;
	    prevPtr = tPtr2, tPtr2 = tPtr2->nextPtr) {





	if (TCL_TIME_BEFORE(timerHandlerPtr->time, tPtr2->time)) {
	    break;
	}

    }
    timerHandlerPtr->nextPtr = tPtr2;
    if (prevPtr == NULL) {
	tsdPtr->firstTimerHandlerPtr = timerHandlerPtr;
    } else {
	prevPtr->nextPtr = timerHandlerPtr;
    }







>
>
>
>
>



>







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
    /*
     * Add the event to the queue in the correct position
     * (ordered by event firing time).
     */

    for (tPtr2 = tsdPtr->firstTimerHandlerPtr, prevPtr = NULL; tPtr2 != NULL;
	    prevPtr = tPtr2, tPtr2 = tPtr2->nextPtr) {
#if (_WIN32_WINNT < 0x0600) && defined(WIN32_USE_TICKCOUNT)
	if (timerHandlerPtr->time.sec - tPtr2->time.sec < 0) {
	    break;
	}
#else
	if (TCL_TIME_BEFORE(timerHandlerPtr->time, tPtr2->time)) {
	    break;
	}
#endif
    }
    timerHandlerPtr->nextPtr = tPtr2;
    if (prevPtr == NULL) {
	tsdPtr->firstTimerHandlerPtr = timerHandlerPtr;
    } else {
	prevPtr->nextPtr = timerHandlerPtr;
    }
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
	blockTime.sec = 0;
	blockTime.usec = 0;
    } else if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) {
	/*
	 * Compute the timeout for the next timer on the list.
	 */







































	Tcl_GetTime(&blockTime);

	blockTime.sec = tsdPtr->firstTimerHandlerPtr->time.sec - blockTime.sec;
	blockTime.usec = tsdPtr->firstTimerHandlerPtr->time.usec -
		blockTime.usec;
	if (blockTime.usec < 0) {
	    blockTime.sec -= 1;
	    blockTime.usec += 1000000;
	}
	if (blockTime.sec < 0) {
	    blockTime.sec = 0;
	    blockTime.usec = 0;
	}

    } else {
	return;
    }

    Tcl_SetMaxBlockTime(&blockTime);
}








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>











>







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
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
	blockTime.sec = 0;
	blockTime.usec = 0;
    } else if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) {
	/*
	 * Compute the timeout for the next timer on the list.
	 */

#ifdef WIN32_USE_TICKCOUNT
#if (_WIN32_WINNT >= 0x0600)
	ULONGLONG ticks = GetTickCount64();

	blockTime.sec = (long)
	    ((ULONGLONG) tsdPtr->firstTimerHandlerPtr->time.sec -
		(ticks / 1000));
	blockTime.usec = (long)
	    ((ULONGLONG) tsdPtr->firstTimerHandlerPtr->time.usec -
		(ticks % 1000) * 1000);
	if (blockTime.usec < 0) {
	    blockTime.sec -= 1;
	    blockTime.usec += 1000000;
	}
	if (blockTime.sec < 0) {
	    blockTime.sec = 0;
	    blockTime.usec = 0;
	}
#else
	blockTime.sec = tsdPtr->firstTimerHandlerPtr->time.sec - GetTickCount();
	if (blockTime.sec <= 0) {
	    blockTime.sec = 0;
	    blockTime.usec = 0;
	} else {
	    blockTime.usec = (blockTime.sec % 1000) * 1000;
	    blockTime.sec /= 1000;
	}
#endif
#else
#ifdef HAVE_CLOCK_GETTIME
	struct timespec ts;

	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	    clock_gettime(CLOCK_REALTIME, &ts);
	}
	blockTime.sec = ts.tv_sec;
	blockTime.usec = ts.tv_nsec / 1000;
#else
	Tcl_GetTime(&blockTime);
#endif
	blockTime.sec = tsdPtr->firstTimerHandlerPtr->time.sec - blockTime.sec;
	blockTime.usec = tsdPtr->firstTimerHandlerPtr->time.usec -
		blockTime.usec;
	if (blockTime.usec < 0) {
	    blockTime.sec -= 1;
	    blockTime.usec += 1000000;
	}
	if (blockTime.sec < 0) {
	    blockTime.sec = 0;
	    blockTime.usec = 0;
	}
#endif
    } else {
	return;
    }

    Tcl_SetMaxBlockTime(&blockTime);
}

464
465
466
467
468
469
470






































471

472
473
474
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
    ThreadSpecificData *tsdPtr = InitTimer();

    if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) {
	/*
	 * Compute the timeout for the next timer on the list.
	 */







































	Tcl_GetTime(&blockTime);

	blockTime.sec = tsdPtr->firstTimerHandlerPtr->time.sec - blockTime.sec;
	blockTime.usec = tsdPtr->firstTimerHandlerPtr->time.usec -
		blockTime.usec;
	if (blockTime.usec < 0) {
	    blockTime.sec -= 1;
	    blockTime.usec += 1000000;
	}
	if (blockTime.sec < 0) {
	    blockTime.sec = 0;
	    blockTime.usec = 0;
	}


	/*
	 * If the first timer has expired, stick an event on the queue.
	 */

	if (blockTime.sec == 0 && blockTime.usec == 0 &&
		!tsdPtr->timerPending) {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>











>







536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
    ThreadSpecificData *tsdPtr = InitTimer();

    if ((flags & TCL_TIMER_EVENTS) && tsdPtr->firstTimerHandlerPtr) {
	/*
	 * Compute the timeout for the next timer on the list.
	 */

#ifdef WIN32_USE_TICKCOUNT
#if (_WIN32_WINNT >= 0x0600)
	ULONGLONG ticks = GetTickCount64();

	blockTime.sec = (long)
	    ((ULONGLONG) tsdPtr->firstTimerHandlerPtr->time.sec -
		(ticks / 1000));
	blockTime.usec = (long)
	    ((ULONGLONG) tsdPtr->firstTimerHandlerPtr->time.usec -
		(ticks % 1000) * 1000);
	if (blockTime.usec < 0) {
	    blockTime.sec -= 1;
	    blockTime.usec += 1000000;
	}
	if (blockTime.sec < 0) {
	    blockTime.sec = 0;
	    blockTime.usec = 0;
	}
#else
	blockTime.sec = tsdPtr->firstTimerHandlerPtr->time.sec - GetTickCount();
	if (blockTime.sec <= 0) {
	    blockTime.sec = 0;
	    blockTime.usec = 0;
	} else {
	    blockTime.usec = (blockTime.sec % 1000) * 1000;
	    blockTime.sec /= 1000;
	}
#endif
#else
#ifdef HAVE_CLOCK_GETTIME
	struct timespec ts;

	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	    clock_gettime(CLOCK_REALTIME, &ts);
	}
	blockTime.sec = ts.tv_sec;
	blockTime.usec = ts.tv_nsec / 1000;
#else
	Tcl_GetTime(&blockTime);
#endif
	blockTime.sec = tsdPtr->firstTimerHandlerPtr->time.sec - blockTime.sec;
	blockTime.usec = tsdPtr->firstTimerHandlerPtr->time.usec -
		blockTime.usec;
	if (blockTime.usec < 0) {
	    blockTime.sec -= 1;
	    blockTime.usec += 1000000;
	}
	if (blockTime.sec < 0) {
	    blockTime.sec = 0;
	    blockTime.usec = 0;
	}
#endif

	/*
	 * If the first timer has expired, stick an event on the queue.
	 */

	if (blockTime.sec == 0 && blockTime.usec == 0 &&
		!tsdPtr->timerPending) {
522
523
524
525
526
527
528






529
530
531
532
533
534
535
    int flags)			/* Flags that indicate what events to handle,
				 * such as TCL_FILE_EVENTS. */
{
    TimerHandler *timerHandlerPtr, **nextPtrPtr;
    Tcl_Time time;
    int currentTimerId;
    ThreadSpecificData *tsdPtr = InitTimer();







    /*
     * Do nothing if timers aren't enabled. This leaves the event on the
     * queue, so we will get to it as soon as ServiceEvents() is called with
     * timers enabled.
     */








>
>
>
>
>
>







634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
    int flags)			/* Flags that indicate what events to handle,
				 * such as TCL_FILE_EVENTS. */
{
    TimerHandler *timerHandlerPtr, **nextPtrPtr;
    Tcl_Time time;
    int currentTimerId;
    ThreadSpecificData *tsdPtr = InitTimer();
#ifdef HAVE_CLOCK_GETTIME
    struct timespec ts;
#endif
#if (_WIN32_WINNT >= 0x0600) && defined(WIN32_USE_TICKCOUNT)
    ULONGLONG ticks;
#endif

    /*
     * Do nothing if timers aren't enabled. This leaves the event on the
     * queue, so we will get to it as soon as ServiceEvents() is called with
     * timers enabled.
     */

560
561
562
563
564
565
566

















567


568
569
570
571
572
573
574





575
576
577
578

579
580
581
582
583
584
585
     *	  most recently created handler appearing after earlier ones with the
     *	  same expiration time, we don't have to worry about newer generation
     *	  timers appearing before later ones.
     */

    tsdPtr->timerPending = 0;
    currentTimerId = tsdPtr->lastTimerId;

















    Tcl_GetTime(&time);


    while (1) {
	nextPtrPtr = &tsdPtr->firstTimerHandlerPtr;
	timerHandlerPtr = tsdPtr->firstTimerHandlerPtr;
	if (timerHandlerPtr == NULL) {
	    break;
	}






	if (TCL_TIME_BEFORE(time, timerHandlerPtr->time)) {
	    break;
	}


	/*
	 * Bail out if the next timer is of a newer generation.
	 */

	if ((currentTimerId - PTR2INT(timerHandlerPtr->token)) < 0) {
	    break;
	}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>







>
>
>
>
>




>







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
     *	  most recently created handler appearing after earlier ones with the
     *	  same expiration time, we don't have to worry about newer generation
     *	  timers appearing before later ones.
     */

    tsdPtr->timerPending = 0;
    currentTimerId = tsdPtr->lastTimerId;
#ifdef WIN32_USE_TICKCOUNT
#if (_WIN32_WINNT >= 0x0600)
    ticks = GetTickCount64();
    time.sec = ticks / 1000;
    time.usec = (ticks % 1000) * 1000;
#else
    time.sec = GetTickCount();
    time.usec = 0;
#endif
#else
#ifdef HAVE_CLOCK_GETTIME
    if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	clock_gettime(CLOCK_REALTIME, &ts);
    }
    time.sec = ts.tv_sec;
    time.usec = ts.tv_nsec / 1000;
#else
    Tcl_GetTime(&time);
#endif
#endif
    while (1) {
	nextPtrPtr = &tsdPtr->firstTimerHandlerPtr;
	timerHandlerPtr = tsdPtr->firstTimerHandlerPtr;
	if (timerHandlerPtr == NULL) {
	    break;
	}

#if (_WIN32_WINNT < 0x0600) && defined(WIN32_USE_TICKCOUNT)
	if (time.sec - timerHandlerPtr->time.sec < 0) {
	    break;
	}
#else
	if (TCL_TIME_BEFORE(time, timerHandlerPtr->time)) {
	    break;
	}

#endif
	/*
	 * Bail out if the next timer is of a newer generation.
	 */

	if ((currentTimerId - PTR2INT(timerHandlerPtr->token)) < 0) {
	    break;
	}
841
842
843
844
845
846
847







848
849
850
851
852
853
854
    /*
     * At this point, either index = -1 and ms contains the number of ms
     * to wait, or else index is the index of a subcommand.
     */

    switch (index) {
    case -1: {







	if (ms < 0) {
	    ms = 0;
	}
	if (objc == 2) {
	    return AfterDelay(interp, ms);
	}
	afterPtr = ckalloc(sizeof(AfterInfo));







>
>
>
>
>
>
>







984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
    /*
     * At this point, either index = -1 and ms contains the number of ms
     * to wait, or else index is the index of a subcommand.
     */

    switch (index) {
    case -1: {
#ifdef HAVE_CLOCK_GETTIME
	struct timespec ts;
#endif
#if (_WIN32_WINNT >= 0x0600) && defined(WIN32_USE_TICKCOUNT)
	ULONGLONG ticks;
#endif

	if (ms < 0) {
	    ms = 0;
	}
	if (objc == 2) {
	    return AfterDelay(interp, ms);
	}
	afterPtr = ckalloc(sizeof(AfterInfo));
868
869
870
871
872
873
874




























875

876
877
878
879
880
881

882
883
884
885
886
887
888
	 * the future, and wrap-around is unlikely to occur in less than about
	 * 1-10 years. Thus it's unlikely that any old ids will still be
	 * around when wrap-around occurs.
	 */

	afterPtr->id = tsdPtr->afterId;
	tsdPtr->afterId += 1;




























	Tcl_GetTime(&wakeup);

	wakeup.sec += (long)(ms / 1000);
	wakeup.usec += ((long)(ms % 1000)) * 1000;
	if (wakeup.usec > 1000000) {
	    wakeup.sec++;
	    wakeup.usec -= 1000000;
	}

	afterPtr->token = TclCreateAbsoluteTimerHandler(&wakeup,
		AfterProc, afterPtr);
	afterPtr->nextPtr = assocPtr->firstAfterPtr;
	assocPtr->firstAfterPtr = afterPtr;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("after#%d", afterPtr->id));
	return TCL_OK;
    }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>






>







1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
	 * the future, and wrap-around is unlikely to occur in less than about
	 * 1-10 years. Thus it's unlikely that any old ids will still be
	 * around when wrap-around occurs.
	 */

	afterPtr->id = tsdPtr->afterId;
	tsdPtr->afterId += 1;
+#ifdef WIN32_USE_TICKCOUNT
+#if (_WIN32_WINNT >= 0x0600)
+	ticks = GetTickCount64();
+	wakeup.sec = ticks / 1000;
+	wakeup.usec = (ticks % 1000) * 1000;
+	wakeup.sec += (long)(ms / 1000);
+	wakeup.usec += ((long)(ms % 1000)) * 1000;
+	if (wakeup.usec > 1000000) {
+	    wakeup.sec++;
+	    wakeup.usec -= 1000000;
+	}
#else
	if (ms > 0x7FFFFFFF) {
	    ms = 0x7FFFFFFF;
	} else if (ms < 0) {
	    ms = 0;
	}
	wakeup.sec = ms + GetTickCount();
	wakeup.usec = 0;
#endif
#else
#ifdef HAVE_CLOCK_GETTIME
	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	    clock_gettime(CLOCK_REALTIME, &ts);
	}
	wakeup.sec = ts.tv_sec;
	wakeup.usec = ts.tv_nsec / 1000;
#else
	Tcl_GetTime(&wakeup);
#endif
	wakeup.sec += (long)(ms / 1000);
	wakeup.usec += ((long)(ms % 1000)) * 1000;
	if (wakeup.usec > 1000000) {
	    wakeup.sec++;
	    wakeup.usec -= 1000000;
	}
#endif
	afterPtr->token = TclCreateAbsoluteTimerHandler(&wakeup,
		AfterProc, afterPtr);
	afterPtr->nextPtr = assocPtr->firstAfterPtr;
	assocPtr->firstAfterPtr = afterPtr;
	Tcl_SetObjResult(interp, Tcl_ObjPrintf("after#%d", afterPtr->id));
	return TCL_OK;
    }
1008
1009
1010
1011
1012
1013
1014



1015


1016


1017





















1018


1019






1020

1021
1022
1023
1024
1025
1026
1027

1028
1029
1030
1031
1032
1033
1034
1035
1036
1037









1038
1039
1040
1041
1042
1043
1044
 */

static int
AfterDelay(
    Tcl_Interp *interp,
    Tcl_WideInt ms)
{



    Interp *iPtr = (Interp *) interp;





    Tcl_Time endTime, now;





















    Tcl_WideInt diff;









    Tcl_GetTime(&now);

    endTime = now;
    endTime.sec += (long)(ms/1000);
    endTime.usec += ((int)(ms%1000))*1000;
    if (endTime.usec >= 1000000) {
	endTime.sec++;
	endTime.usec -= 1000000;
    }


    do {
	if (Tcl_AsyncReady()) {
	    if (Tcl_AsyncInvoke(interp, TCL_OK) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
	    return TCL_ERROR;
	}









	if (iPtr->limit.timeEvent != NULL
		&& TCL_TIME_BEFORE(iPtr->limit.time, now)) {
	    iPtr->limit.granularityTicker = 0;
	    if (Tcl_LimitCheck(interp) != TCL_OK) {
		return TCL_ERROR;
	    }
	}







>
>
>

>
>

>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>

>
>
>
>
>
>

>







>










>
>
>
>
>
>
>
>
>







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
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
 */

static int
AfterDelay(
    Tcl_Interp *interp,
    Tcl_WideInt ms)
{
    Tcl_Time endTime, now;
#ifdef WIN32_USE_TICKCOUNT
#if (_WIN32_WINNT >= 0x0600)
    Interp *iPtr = (Interp *) interp;
    ULONGLONG ticks = GetTickCount64();
    Tcl_WideInt diff;

    now.sec = ticks/1000;
    now.usec = (ticks%1000)*1000;
    endTime = now;
    endTime.sec += (long)(ms/1000);
    endTime.usec += ((int)(ms%1000))*1000;
    if (endTime.usec >= 1000000) {
	endTime.sec++;
	endTime.usec -= 1000000;
    }
#else
    int diff;

    now.sec = GetTickCount();
    now.usec = 0;
    if (ms > 0x7FFFFFFF) {
	ms = 0x7FFFFFFF;
    } else if (ms < 0) {
	ms = 0;
    }
    endTime.sec = now.sec + ms;
    endTime.usec = 0;
#endif
#else
    Interp *iPtr = (Interp *) interp;
    Tcl_WideInt diff;
#ifdef HAVE_CLOCK_GETTIME
    struct timespec ts;

    if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	clock_gettime(CLOCK_REALTIME, &ts);
    }
    now.sec = ts.tv_sec;
    now.usec = ts.tv_nsec/1000;
#else
    Tcl_GetTime(&now);
#endif
    endTime = now;
    endTime.sec += (long)(ms/1000);
    endTime.usec += ((int)(ms%1000))*1000;
    if (endTime.usec >= 1000000) {
	endTime.sec++;
	endTime.usec -= 1000000;
    }
#endif

    do {
	if (Tcl_AsyncReady()) {
	    if (Tcl_AsyncInvoke(interp, TCL_OK) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
	if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
	    return TCL_ERROR;
	}
#if (_WIN32_WINNT < 0x0600) && defined(WIN32_USE_TICKCOUNT)
	diff = endTime.sec - now.sec;
	if (diff > 0) {
	    Tcl_Sleep((long) diff);
	} else {
	    break;
	}
	now.sec = GetTickCount();
#else
	if (iPtr->limit.timeEvent != NULL
		&& TCL_TIME_BEFORE(iPtr->limit.time, now)) {
	    iPtr->limit.granularityTicker = 0;
	    if (Tcl_LimitCheck(interp) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
1079
1080
1081
1082
1083
1084
1085












1086







1087

1088
1089
1090
1091
1092
1093
1094
	    if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
		return TCL_ERROR;
	    }
	    if (Tcl_LimitCheck(interp) != TCL_OK) {
		return TCL_ERROR;
	    }
	}












        Tcl_GetTime(&now);







    } while (TCL_TIME_BEFORE(now, endTime));

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * GetAfterEvent --







>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|
>







1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
	    if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
		return TCL_ERROR;
	    }
	    if (Tcl_LimitCheck(interp) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
#if (_WIN32_WINNT >= 0x0600) && defined(WIN32_USE_TICKCOUNT)
	ticks = GetTickCount64();
	now.sec = ticks / 1000;
	now.usec = (ticks % 1000) * 1000;
#else
#ifdef HAVE_CLOCK_GETTIME
	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	    clock_gettime(CLOCK_REALTIME, &ts);
	}
	now.sec = ts.tv_sec;
	now.usec = ts.tv_nsec / 1000;
#else
        Tcl_GetTime(&now);
#endif
#endif
#endif
    }
#if (_WIN32_WINNT < 0x0600) && defined(WIN32_USE_TICKCOUNT)
    while (now.sec - endTime.sec < 0);
#else
    while (TCL_TIME_BEFORE(now, endTime));
#endif
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * GetAfterEvent --

Changes to unix/configure.

4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
	fi

	# Does the pthread-implementation provide
	# 'pthread_attr_setstacksize' ?

	ac_saved_libs=$LIBS
	LIBS="$LIBS $THREADS_LIBS"
	for ac_func in pthread_attr_setstacksize pthread_atfork
do :
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
  cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF







|







4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
	fi

	# Does the pthread-implementation provide
	# 'pthread_attr_setstacksize' ?

	ac_saved_libs=$LIBS
	LIBS="$LIBS $THREADS_LIBS"
	for ac_func in pthread_attr_setstacksize pthread_atfork pthread_condattr_setclock
do :
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
  cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
4504
4505
4506
4507
4508
4509
4510





















































4511
4512
4513
4514
4515
4516
4517
$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
  LIBS="$LIBS -lnsl"
fi

fi
























































# Add the threads support libraries
LIBS="$LIBS$THREADS_LIBS"


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
  LIBS="$LIBS -lnsl"
fi

fi


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
if ${ac_cv_lib_rt_clock_gettime+:} false; then :
  $as_echo_n "(cached) " >&6
else
  ac_check_lib_save_LIBS=$LIBS
LIBS="-lrt  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

/* Override any GCC internal prototype to avoid an error.
   Use char because int might match the return type of a GCC
   builtin and then its argument prototype would still apply.  */
#ifdef __cplusplus
extern "C"
#endif
char clock_gettime ();
int
main ()
{
return clock_gettime ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
  ac_cv_lib_rt_clock_gettime=yes
else
  ac_cv_lib_rt_clock_gettime=no
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
  LIBS="$LIBS -lrt"
fi

    for ac_func in clock_gettime clock_nanosleep
do :
  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
  cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

fi
done



# Add the threads support libraries
LIBS="$LIBS$THREADS_LIBS"


    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5

Changes to unix/tcl.m4.

674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
	fi

	# Does the pthread-implementation provide
	# 'pthread_attr_setstacksize' ?

	ac_saved_libs=$LIBS
	LIBS="$LIBS $THREADS_LIBS"
	AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork)
	LIBS=$ac_saved_libs
    else
	TCL_THREADS=0
    fi
    # Do checking message here to not mess up interleaved configure output
    AC_MSG_CHECKING([for building with threads])
    if test "${TCL_THREADS}" = 1; then







|







674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
	fi

	# Does the pthread-implementation provide
	# 'pthread_attr_setstacksize' ?

	ac_saved_libs=$LIBS
	LIBS="$LIBS $THREADS_LIBS"
	AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork pthread_condattr_setclock)
	LIBS=$ac_saved_libs
    else
	TCL_THREADS=0
    fi
    # Do checking message here to not mess up interleaved configure output
    AC_MSG_CHECKING([for building with threads])
    if test "${TCL_THREADS}" = 1; then
2535
2536
2537
2538
2539
2540
2541


2542
2543
2544
2545
2546
2547
2548
    if test "$tcl_checkBoth" = 1; then
	tk_oldLibs=$LIBS
	LIBS="$LIBS -lsocket -lnsl"
	AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
    fi
    AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
	    [LIBS="$LIBS -lnsl"])])


])

#--------------------------------------------------------------------
# SC_TCL_EARLY_FLAGS
#
#	Check for what flags are needed to be passed so the correct OS
#	features are available.







>
>







2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
    if test "$tcl_checkBoth" = 1; then
	tk_oldLibs=$LIBS
	LIBS="$LIBS -lsocket -lnsl"
	AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
    fi
    AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
	    [LIBS="$LIBS -lnsl"])])
    AC_CHECK_LIB(rt, clock_gettime, [LIBS="$LIBS -lrt"])
    AC_CHECK_FUNCS(clock_gettime clock_nanosleep)
])

#--------------------------------------------------------------------
# SC_TCL_EARLY_FLAGS
#
#	Check for what flags are needed to be passed so the correct OS
#	features are available.

Changes to unix/tclConfig.h.in.

14
15
16
17
18
19
20



21
22
23
24
25
26
27
#undef HAVE_BLKCNT_T

/* Defined when compiler supports casting to union type. */
#undef HAVE_CAST_TO_UNION

/* Define to 1 if you have the `chflags' function. */
#undef HAVE_CHFLAGS




/* Define to 1 if you have the `copyfile' function. */
#undef HAVE_COPYFILE

/* Define to 1 if you have the <copyfile.h> header file. */
#undef HAVE_COPYFILE_H








>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#undef HAVE_BLKCNT_T

/* Defined when compiler supports casting to union type. */
#undef HAVE_CAST_TO_UNION

/* Define to 1 if you have the `chflags' function. */
#undef HAVE_CHFLAGS

/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME

/* Define to 1 if you have the `copyfile' function. */
#undef HAVE_COPYFILE

/* Define to 1 if you have the <copyfile.h> header file. */
#undef HAVE_COPYFILE_H

164
165
166
167
168
169
170



171
172
173
174
175
176
177
#undef HAVE_OSSPINLOCKLOCK

/* Define to 1 if you have the `pthread_atfork' function. */
#undef HAVE_PTHREAD_ATFORK

/* Define to 1 if you have the `pthread_attr_setstacksize' function. */
#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE




/* Does putenv() copy strings or incorporate them by reference? */
#undef HAVE_PUTENV_THAT_COPIES

/* Are characters signed? */
#undef HAVE_SIGNED_CHAR








>
>
>







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#undef HAVE_OSSPINLOCKLOCK

/* Define to 1 if you have the `pthread_atfork' function. */
#undef HAVE_PTHREAD_ATFORK

/* Define to 1 if you have the `pthread_attr_setstacksize' function. */
#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE

/* Define to 1 if you have the `pthread_condattr_setclock' function. */
#undef HAVE_PTHREAD_CONDATTR_SETCLOCK

/* Does putenv() copy strings or incorporate them by reference? */
#undef HAVE_PUTENV_THAT_COPIES

/* Are characters signed? */
#undef HAVE_SIGNED_CHAR

Changes to unix/tclUnixChan.c.

1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771




1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789








1790

1791
1792
1793
1794
1795
1796
1797
				 * TCL_EXCEPTION. */
    int timeout)		/* Maximum amount of time to wait for one of
				 * the conditions in mask to occur, in
				 * milliseconds. A value of 0 means don't wait
				 * at all, and a value of -1 means wait
				 * forever. */
{
    Tcl_Time abortTime = {0, 0}, now; /* silence gcc 4 warning */
    struct timeval blockTime, *timeoutPtr;
    int numFound, result = 0;
    fd_set readableMask;
    fd_set writableMask;
    fd_set exceptionMask;





#ifndef _DARWIN_C_SOURCE
    /*
     * Sanity check fd.
     */

    if (fd >= FD_SETSIZE) {
	Tcl_Panic("TclUnixWaitForFile can't handle file id %d", fd);
	/* must never get here, or select masks overrun will occur below */
    }
#endif

    /*
     * If there is a non-zero finite timeout, compute the time when we give
     * up.
     */

    if (timeout > 0) {








	Tcl_GetTime(&now);

	abortTime.sec = now.sec + timeout/1000;
	abortTime.usec = now.usec + (timeout%1000)*1000;
	if (abortTime.usec >= 1000000) {
	    abortTime.usec -= 1000000;
	    abortTime.sec += 1;
	}
	timeoutPtr = &blockTime;







|





>
>
>
>


















>
>
>
>
>
>
>
>

>







1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
				 * TCL_EXCEPTION. */
    int timeout)		/* Maximum amount of time to wait for one of
				 * the conditions in mask to occur, in
				 * milliseconds. A value of 0 means don't wait
				 * at all, and a value of -1 means wait
				 * forever. */
{
    Tcl_Time abortTime = {0, 0}, now = { 0, 0 }; /* silence gcc 4 warning */
    struct timeval blockTime, *timeoutPtr;
    int numFound, result = 0;
    fd_set readableMask;
    fd_set writableMask;
    fd_set exceptionMask;
#ifdef HAVE_CLOCK_GETTIME
    int monoClock = 1;
    struct timespec ts;
#endif

#ifndef _DARWIN_C_SOURCE
    /*
     * Sanity check fd.
     */

    if (fd >= FD_SETSIZE) {
	Tcl_Panic("TclUnixWaitForFile can't handle file id %d", fd);
	/* must never get here, or select masks overrun will occur below */
    }
#endif

    /*
     * If there is a non-zero finite timeout, compute the time when we give
     * up.
     */

    if (timeout > 0) {
#ifdef HAVE_CLOCK_GETTIME
	if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	    clock_gettime(CLOCK_REALTIME, &ts);
	    monoClock = 0;
	}
	now.sec = ts.tv_sec;
	now.usec = ts.tv_nsec / 1000;
#else
	Tcl_GetTime(&now);
#endif
	abortTime.sec = now.sec + timeout/1000;
	abortTime.usec = now.usec + (timeout%1000)*1000;
	if (abortTime.usec >= 1000000) {
	    abortTime.usec -= 1000000;
	    abortTime.sec += 1;
	}
	timeoutPtr = &blockTime;
1872
1873
1874
1875
1876
1877
1878





1879

1880
1881
1882
1883
1884
1885
1886
	    continue;
	}

	/*
	 * The select returned early, so we need to recompute the timeout.
	 */






	Tcl_GetTime(&now);

	if ((abortTime.sec < now.sec)
		|| (abortTime.sec==now.sec && abortTime.usec<=now.usec)) {
	    break;
	}
    }
    return result;
}







>
>
>
>
>

>







1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
	    continue;
	}

	/*
	 * The select returned early, so we need to recompute the timeout.
	 */

#ifdef HAVE_CLOCK_GETTIME
	clock_gettime(monoClock ? CLOCK_MONOTONIC : CLOCK_REALTIME, &ts);
	now.sec = ts.tv_sec;
	now.usec = ts.tv_nsec / 1000;
#else
	Tcl_GetTime(&now);
#endif
	if ((abortTime.sec < now.sec)
		|| (abortTime.sec==now.sec && abortTime.usec<=now.usec)) {
	    break;
	}
    }
    return result;
}

Changes to unix/tclUnixEvent.c.

38
39
40
41
42
43
44











45

46
47
48
49
50
51
52

    /*
     * The only trick here is that select appears to return early under some
     * conditions, so we have to check to make sure that the right amount of
     * time really has elapsed.  If it's too early, go back to sleep again.
     */












    Tcl_GetTime(&before);

    after = before;
    after.sec += ms/1000;
    after.usec += (ms%1000)*1000;
    if (after.usec > 1000000) {
	after.usec -= 1000000;
	after.sec += 1;
    }







>
>
>
>
>
>
>
>
>
>
>

>







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

    /*
     * The only trick here is that select appears to return early under some
     * conditions, so we have to check to make sure that the right amount of
     * time really has elapsed.  If it's too early, go back to sleep again.
     */

#ifdef HAVE_CLOCK_GETTIME
    int monoClock = 1;
    struct timespec ts;

    if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	clock_gettime(CLOCK_REALTIME, &ts);
	monoClock = 0;
    }
    before.sec = ts.tv_sec;
    before.usec = ts.tv_nsec / 1000;
#else
    Tcl_GetTime(&before);
#endif
    after = before;
    after.sec += ms/1000;
    after.usec += (ms%1000)*1000;
    if (after.usec > 1000000) {
	after.usec -= 1000000;
	after.sec += 1;
    }
77
78
79
80
81
82
83





84

85
86
87
88
89
90
91
92
93
94
95

	if ((((int) delay.tv_sec) < 0)
		|| ((delay.tv_usec == 0) && (delay.tv_sec == 0))) {
	    break;
	}
	(void) select(0, (SELECT_MASK *) 0, (SELECT_MASK *) 0,
		(SELECT_MASK *) 0, &delay);





	Tcl_GetTime(&before);

    }
}

#endif /* HAVE_COREFOUNDATION */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>
>

>











89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

	if ((((int) delay.tv_sec) < 0)
		|| ((delay.tv_usec == 0) && (delay.tv_sec == 0))) {
	    break;
	}
	(void) select(0, (SELECT_MASK *) 0, (SELECT_MASK *) 0,
		(SELECT_MASK *) 0, &delay);
#ifdef HAVE_CLOCK_GETTIME
	clock_gettime(monoClock ? CLOCK_MONOTONIC : CLOCK_REALTIME, &ts);
	before.sec = ts.tv_sec;
	before.usec = ts.tv_nsec / 1000;
#else
	Tcl_GetTime(&before);
#endif
    }
}

#endif /* HAVE_COREFOUNDATION */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to unix/tclUnixNotfy.c.

96
97
98
99
100
101
102



103
104
105
106
107
108
109
	 * 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;







>
>
>







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
	 * 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. */
#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
    int monoClock;		/* When true use CLOCK_MONOTONIC */
#endif
#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;
348
349
350
351
352
353
354
355









356








357
358
359
360
361
362
363

	    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(&notifierInitMutex);
#if defined(HAVE_PTHREAD_ATFORK)
	/*








>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>







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

	    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
#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
	    pthread_condattr_t attr;

	    pthread_condattr_init(&attr);
	    tsdPtr->monoClock =
		    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) == 0;
	    if (tsdPtr->monoClock) {
		if (pthread_cond_init(&tsdPtr->waitCV, &attr)) {
		    tsdPtr->monoClock = 0;
		    pthread_cond_init(&tsdPtr->waitCV, NULL);
		}
	    } else {
		pthread_cond_init(&tsdPtr->waitCV, NULL);
	    }
	    pthread_condattr_destroy(&attr);
#else
	    pthread_cond_init(&tsdPtr->waitCV, NULL);
#endif
#endif /* __CYGWIN__ */
	    tsdPtr->waitCVinitialized = 1;
	}

	pthread_mutex_lock(&notifierInitMutex);
#if defined(HAVE_PTHREAD_ATFORK)
	/*
991
992
993
994
995
996
997
998
999
1000













1001
1002

1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
		}
		pthread_mutex_unlock(&notifierMutex);
		MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
		pthread_mutex_lock(&notifierMutex);
	    }
#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, &notifierMutex, &ptime);
	    } else {
	       pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
	    }
#endif /* __CYGWIN__ */
	}
	tsdPtr->eventReady = 0;

#ifdef __CYGWIN__
	while (PeekMessageW(&msg, NULL, 0, 0, 0)) {







<
|

>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
|
|

|







1011
1012
1013
1014
1015
1016
1017

1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
		}
		pthread_mutex_unlock(&notifierMutex);
		MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
		pthread_mutex_lock(&notifierMutex);
	    }
#else
	    if (timePtr != NULL) {

		struct timespec ptime;

#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
		if (tsdPtr->monoClock) {
		    clock_gettime(CLOCK_MONOTONIC, &ptime);
		} else {
		    clock_gettime(CLOCK_REALTIME, &ptime);
		}
		ptime.tv_sec += timePtr->sec +
		    (timePtr->usec * 1000 + ptime.tv_nsec) / 1000000000;
		ptime.tv_nsec = (timePtr->usec * 1000 + ptime.tv_nsec) %
		    1000000000;
#else
		Tcl_Time now;

		Tcl_GetTime(&now);
		ptime.tv_sec = timePtr->sec + now.sec +
		    (timePtr->usec + now.usec) / 1000000;
		ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
#endif
		pthread_cond_timedwait(&tsdPtr->waitCV, &notifierMutex, &ptime);
	    } else {
		pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
	    }
#endif /* __CYGWIN__ */
	}
	tsdPtr->eventReady = 0;

#ifdef __CYGWIN__
	while (PeekMessageW(&msg, NULL, 0, 0, 0)) {

Changes to unix/tclUnixPort.h.

634
635
636
637
638
639
640



















641
642
643
644
645
646
647
#   if defined (__llvm__) && \
	    (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 2 || \
	    (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ > 0))))
#	undef USE_VFORK
#   endif /* __llvm__ */
#endif /* __APPLE__ */




















/*
 *---------------------------------------------------------------------------
 * The following macros and declarations represent the interface between
 * generic and unix-specific parts of Tcl. Some of the macros may override
 * functions declared in tclInt.h.
 *---------------------------------------------------------------------------
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
#   if defined (__llvm__) && \
	    (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 2 || \
	    (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ > 0))))
#	undef USE_VFORK
#   endif /* __llvm__ */
#endif /* __APPLE__ */

/*
 *---------------------------------------------------------------------------
 * Use clock_gettime() only if _POSIX_MONOTONIC_CLOCK present.
 *---------------------------------------------------------------------------
 */

#if defined(HAVE_CLOCK_GETTIME) && !defined(_POSIX_MONOTONIC_CLOCK)
#   undef HAVE_CLOCK_GETTIME
#endif

#ifdef TCL_THREADS
#   ifndef HAVE_CLOCK_GETTIME
#	undef HAVE_PTHREAD_CONDATTR_SETCLOCK
#   endif
#   ifndef HAVE_PTHREAD_CONDATTR_SETCLOCK
#	undef HAVE_CLOCK_GETTIME
#   endif
#endif

/*
 *---------------------------------------------------------------------------
 * The following macros and declarations represent the interface between
 * generic and unix-specific parts of Tcl. Some of the macros may override
 * functions declared in tclInt.h.
 *---------------------------------------------------------------------------
 */

Changes to unix/tclUnixThrd.c.

516
517
518
519
520
521
522



523
524
525
526
527
528
529
530
531
532

















533
534

535
536
537
538
539
540
541
542
543
544











545
546
547
548
549
550
551
552
553
554
555

556
557
558
559
560
561
562
    Tcl_Condition *condPtr,	/* Really (pthread_cond_t **) */
    Tcl_Mutex *mutexPtr,	/* Really (pthread_mutex_t **) */
    const Tcl_Time *timePtr) /* Timeout on waiting period */
{
    pthread_cond_t *pcondPtr;
    pthread_mutex_t *pmutexPtr;
    struct timespec ptime;




    if (*condPtr == NULL) {
	pthread_mutex_lock(&masterLock);

	/*
	 * Double check inside mutex to avoid race, then initialize condition
	 * variable if necessary.
	 */

	if (*condPtr == NULL) {

















	    pcondPtr = ckalloc(sizeof(pthread_cond_t));
	    pthread_cond_init(pcondPtr, NULL);

	    *condPtr = (Tcl_Condition) pcondPtr;
	    TclRememberCondition(condPtr);
	}
	pthread_mutex_unlock(&masterLock);
    }
    pmutexPtr = *((pthread_mutex_t **)mutexPtr);
    pcondPtr = *((pthread_cond_t **)condPtr);
    if (timePtr == NULL) {
	pthread_cond_wait(pcondPtr, pmutexPtr);
    } else {











	Tcl_Time now;

	/*
	 * Make sure to take into account the microsecond component of the
	 * current time, including possible overflow situations. [Bug #411603]
	 */

	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(pcondPtr, pmutexPtr, &ptime);
    }
}

/*
 *----------------------------------------------------------------------
 *







>
>
>










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>










>
>
>
>
>
>
>
>
>
>
>











>







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
    Tcl_Condition *condPtr,	/* Really (pthread_cond_t **) */
    Tcl_Mutex *mutexPtr,	/* Really (pthread_mutex_t **) */
    const Tcl_Time *timePtr) /* Timeout on waiting period */
{
    pthread_cond_t *pcondPtr;
    pthread_mutex_t *pmutexPtr;
    struct timespec ptime;
#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
    int *flagPtr;
#endif

    if (*condPtr == NULL) {
	pthread_mutex_lock(&masterLock);

	/*
	 * Double check inside mutex to avoid race, then initialize condition
	 * variable if necessary.
	 */

	if (*condPtr == NULL) {
#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
	    pthread_condattr_t attr;

	    pcondPtr = ckalloc(sizeof(pthread_cond_t) + sizeof(int));
	    flagPtr = (int *) (pcondPtr + 1);
	    pthread_condattr_init(&attr);
	    *flagPtr = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) == 0;
	    if (*flagPtr) {
		if (pthread_cond_init(pcondPtr, &attr)) {
		    *flagPtr = 0;
		    pthread_cond_init(pcondPtr, NULL);
		}
	    } else {
		pthread_cond_init(pcondPtr, NULL);
	    }
	    pthread_condattr_destroy(&attr);
#else
	    pcondPtr = ckalloc(sizeof(pthread_cond_t));
	    pthread_cond_init(pcondPtr, NULL);
#endif
	    *condPtr = (Tcl_Condition) pcondPtr;
	    TclRememberCondition(condPtr);
	}
	pthread_mutex_unlock(&masterLock);
    }
    pmutexPtr = *((pthread_mutex_t **)mutexPtr);
    pcondPtr = *((pthread_cond_t **)condPtr);
    if (timePtr == NULL) {
	pthread_cond_wait(pcondPtr, pmutexPtr);
    } else {
#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK)
	flagPtr = (int *) (pcondPtr + 1);
	if (*flagPtr) {
	    clock_gettime(CLOCK_MONOTONIC, &ptime);
	} else {
	    clock_gettime(CLOCK_REALTIME, &ptime);
	}
	ptime.tv_sec += timePtr->sec +
	    (timePtr->usec * 1000 + ptime.tv_nsec) / 1000000000;
	ptime.tv_nsec = (timePtr->usec * 1000 + ptime.tv_nsec) % 1000000000;
#else
	Tcl_Time now;

	/*
	 * Make sure to take into account the microsecond component of the
	 * current time, including possible overflow situations. [Bug #411603]
	 */

	Tcl_GetTime(&now);
	ptime.tv_sec = timePtr->sec + now.sec +
	    (timePtr->usec + now.usec) / 1000000;
	ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
#endif
	pthread_cond_timedwait(pcondPtr, pmutexPtr, &ptime);
    }
}

/*
 *----------------------------------------------------------------------
 *

Changes to unix/tclUnixTime.c.

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
132
133
 */

unsigned long
TclpGetClicks(void)
{
    unsigned long now;









#ifdef NO_GETTOD
    if (tclGetTimeProcPtr != NativeGetTime) {
	Tcl_Time time;

	tclGetTimeProcPtr(&time, tclTimeClientData);
	now = time.sec*1000000 + time.usec;
    } else {
	/*
	 * A semi-NativeGetTime, specialized to clicks.
	 */
	struct tms dummy;

	now = (unsigned long) times(&dummy);
    }
#else
    Tcl_Time time;

    tclGetTimeProcPtr(&time, tclTimeClientData);
    now = time.sec*1000000 + time.usec;

#endif

    return now;
}
#ifdef TCL_WIDE_CLICKS

/*







>
>
>
>
>
>
>
>



















>







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
132
133
134
135
136
137
138
139
140
141
142
 */

unsigned long
TclpGetClicks(void)
{
    unsigned long now;

#ifdef HAVE_CLOCK_GETTIME
    struct timespec ts;

    if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
	clock_gettime(CLOCK_REALTIME, &ts);
    }
    now = ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
#else
#ifdef NO_GETTOD
    if (tclGetTimeProcPtr != NativeGetTime) {
	Tcl_Time time;

	tclGetTimeProcPtr(&time, tclTimeClientData);
	now = time.sec*1000000 + time.usec;
    } else {
	/*
	 * A semi-NativeGetTime, specialized to clicks.
	 */
	struct tms dummy;

	now = (unsigned long) times(&dummy);
    }
#else
    Tcl_Time time;

    tclGetTimeProcPtr(&time, tclTimeClientData);
    now = time.sec*1000000 + time.usec;
#endif
#endif

    return now;
}
#ifdef TCL_WIDE_CLICKS

/*
372
373
374
375
376
377
378

379
380
381

382
383
384
385
386
387
388

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    ClientData clientData)
{

    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_QueryTimeProc --
 *







>



>







381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    ClientData clientData)
{
#ifndef HAVE_CLOCK_GETTIME
    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_QueryTimeProc --
 *

Changes to win/configure.

1397
1398
1399
1400
1401
1402
1403


1404
1405
1406
1407
1408
1409
1410
                          embed manifest if possible (default: yes)

Optional Packages:
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --with-encoding         encoding for configuration values
  --with-celib=DIR        use Windows/CE support library from DIR



Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
              nonstandard directory <lib dir>
  LIBS        libraries to pass to the linker, e.g. -l<library>







>
>







1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
                          embed manifest if possible (default: yes)

Optional Packages:
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --with-encoding         encoding for configuration values
  --with-celib=DIR        use Windows/CE support library from DIR
  --with-tickcount        use GetTickCount for timers, turns off interp time
                          limits

Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
              nonstandard directory <lib dir>
  LIBS        libraries to pass to the linker, e.g. -l<library>
4668
4669
4670
4671
4672
4673
4674


























4675
4676
4677
4678
4679
4680
4681
*mingw32*)
    TCL_EXE="tclsh"
    ;;
*)
    TCL_EXE="TCL_LIBRARY=\"\${LIBRARY_DIR}\"; export TCL_LIBRARY; ./\${TCLSH}"
    ;;
esac



























#------------------------------------------------------------------------
#	Add stuff for zlib; note that this is mostly done in the makefile now
#	as we just assume that the platform hasn't got a usable z.lib
#------------------------------------------------------------------------

if test "${enable_shared+set}" = "set"; then :







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
*mingw32*)
    TCL_EXE="tclsh"
    ;;
*)
    TCL_EXE="TCL_LIBRARY=\"\${LIBRARY_DIR}\"; export TCL_LIBRARY; ./\${TCLSH}"
    ;;
esac

# *** HaO 2016-03-30 this may be at the wrong place.
# *** should be in Line 4410 betwen
#	_ACEOF
# and
#	echo "$as_me:$LINENO: checking for intptr_t" >&5
#	echo $ECHO_N "checking for intptr_t... $ECHO_C" >&6
#	if test "${ac_cv_type_intptr_t+set}" = set; then

# Check whether --with-tickcount or --without-tickcount was given.
if test "${with_tickcount+set}" = set; then
  withval="$with_tickcount"
  tcl_ok=$withval
else
  tcl_ok=no
fi;
echo "$as_me:$LINENO: result: $tcl_ok" >&5
echo "${ECHO_T}$tcl_ok" >&6
if test $tcl_ok = yes; then

cat >>confdefs.h <<\_ACEOF
#define WIN32_USE_TICKCOUNT 1
_ACEOF

fi


#------------------------------------------------------------------------
#	Add stuff for zlib; note that this is mostly done in the makefile now
#	as we just assume that the platform hasn't got a usable z.lib
#------------------------------------------------------------------------

if test "${enable_shared+set}" = "set"; then :

Changes to win/configure.ac.

137
138
139
140
141
142
143









144
145
146
147
148
149
150
  ], [
    AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win32/zdll.lib])
  ])
], [
  AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}])
])
AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?])










AC_CHECK_TYPE([intptr_t], [
    AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],







>
>
>
>
>
>
>
>
>







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  ], [
    AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win32/zdll.lib])
  ])
], [
  AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}])
])
AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?])

AC_ARG_WITH(tickcount,
    AC_HELP_STRING([--with-tickcount],
	[use GetTickCount for timers, turns off interp time limits]),
    [tcl_ok=$withval], [tcl_ok=no])
AC_MSG_RESULT([$tcl_ok])
if test $tcl_ok = yes; then
    AC_DEFINE(WIN32_USE_TICKCOUNT, 1, [Use GetTickCount for timers?])
fi

AC_CHECK_TYPE([intptr_t], [
    AC_DEFINE([HAVE_INTPTR_T], 1, [Do we have the intptr_t type?])], [
    AC_CACHE_CHECK([for pointer-size signed integer type], tcl_cv_intptr_t, [
    for tcl_cv_intptr_t in "int" "long" "long long" none; do
	if test "$tcl_cv_intptr_t" != none; then
	    AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT],

Changes to win/tclWinNotify.c.

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
	int status;

	/*
	 * Compute the timeout in milliseconds.
	 */

	if (timePtr) {






	    /*
	     * TIP #233 (Virtualized Time). Convert virtual domain delay to
	     * real-time.
	     */

	    Tcl_Time myTime;

	    myTime.sec  = timePtr->sec;
	    myTime.usec = timePtr->usec;

	    if (myTime.sec != 0 || myTime.usec != 0) {
		tclScaleTimeProcPtr(&myTime, tclTimeClientData);
	    }

	    timeout = myTime.sec * 1000 + myTime.usec / 1000;

	} else {
	    timeout = INFINITE;
	}

	/*
	 * Check to see if there are any messages in the queue before waiting
	 * because MsgWaitForMultipleObjects will not wake up if there are







>
>
>
>
>
>















>







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
471
472
473
474
475
476
	int status;

	/*
	 * Compute the timeout in milliseconds.
	 */

	if (timePtr) {
#if (_WIN32_WINNT < 0x0600) && defined(WIN32_USE_TICKCOUNT)
	    timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
	    if (timeout == INFINITE) {
		timeout--;
	    }
#else
	    /*
	     * TIP #233 (Virtualized Time). Convert virtual domain delay to
	     * real-time.
	     */

	    Tcl_Time myTime;

	    myTime.sec  = timePtr->sec;
	    myTime.usec = timePtr->usec;

	    if (myTime.sec != 0 || myTime.usec != 0) {
		tclScaleTimeProcPtr(&myTime, tclTimeClientData);
	    }

	    timeout = myTime.sec * 1000 + myTime.usec / 1000;
#endif
	} else {
	    timeout = INFINITE;
	}

	/*
	 * Check to see if there are any messages in the queue before waiting
	 * because MsgWaitForMultipleObjects will not wake up if there are
544
545
546
547
548
549
550








































551
552
553
554
555
556
557
 *----------------------------------------------------------------------
 */

void
Tcl_Sleep(
    int ms)			/* Number of milliseconds to sleep. */
{








































    /*
     * Simply calling 'Sleep' for the requisite number of milliseconds can
     * make the process appear to wake up early because it isn't synchronized
     * with the CPU performance counter that is used in tclWinTime.c. This
     * behavior is probably benign, but messes up some of the corner cases in
     * the test suite. We get around this problem by repeating the 'Sleep'
     * call as many times as necessary to make the clock advance by the







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
 *----------------------------------------------------------------------
 */

void
Tcl_Sleep(
    int ms)			/* Number of milliseconds to sleep. */
{
#ifdef WIN32_USE_TICKCOUNT
#if (_WIN32_WINNT >= 0x0600)
    ULONGLONG now;		/* Current wall clock time. */
    ULONGLONG desired;		/* Desired wakeup time. */
    ULONGLONG sleepTime;

    now = GetTickCount64();
#else
    DWORD now;			/* Current wall clock time. */
    DWORD desired;		/* Desired wakeup time. */
    DWORD sleepTime;

    now = GetTickCount();
#endif

    if (ms < 0) {
	ms = 0;
#if (_WIN32_WINNT < 0x0600)
    } else if (ms > 0x7FFFFFFF) {
	ms = 0x7FFFFFFF;
#endif
    }
    desired = now + ms;
    sleepTime = ms;
    for (;;) {
	SleepEx(sleepTime, TRUE);
#if (_WIN32_WINNT >= 0x0600)
	now = GetTickCount64();
	if (now - desired >= 0) {
	    break;
	}
#else
	now = GetTickCount();
	if ((long) now - (long) desired >= 0) {
	    break;
	}
#endif
	sleepTime = desired - now;
    }
#else
    /*
     * Simply calling 'Sleep' for the requisite number of milliseconds can
     * make the process appear to wake up early because it isn't synchronized
     * with the CPU performance counter that is used in tclWinTime.c. This
     * behavior is probably benign, but messes up some of the corner cases in
     * the test suite. We get around this problem by repeating the 'Sleep'
     * call as many times as necessary to make the clock advance by the
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608

	vdelay.sec  = desired.sec  - now.sec;
	vdelay.usec = desired.usec - now.usec;

	tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
	sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000;
    }

}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>









640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656

	vdelay.sec  = desired.sec  - now.sec;
	vdelay.usec = desired.usec - now.usec;

	tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
	sleepTime = vdelay.sec * 1000 + vdelay.usec / 1000;
    }
#endif
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to win/tclWinTime.c.

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
    0
};

/*
 * Declarations for functions defined later in this file.
 */

static struct tm *	ComputeGMT(const time_t *tp);
static void		StopCalibration(ClientData clientData);
static DWORD WINAPI	CalibrationThread(LPVOID arg);
static void 		UpdateTimeEachSecond(void);
static void		ResetCounterSamples(Tcl_WideUInt fileTime,
			    Tcl_WideInt perfCounter, Tcl_WideInt perfFreq);
static Tcl_WideInt	AccumulateSample(Tcl_WideInt perfCounter,
			    Tcl_WideUInt fileTime);

static void		NativeScaleTime(Tcl_Time* timebuf,
			    ClientData clientData);
static void		NativeGetTime(Tcl_Time* timebuf,
			    ClientData clientData);

/*
 * TIP #233 (Virtualized Time): Data for the time hooks, if any.







|







>







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
    0
};

/*
 * Declarations for functions defined later in this file.
 */

#ifndef WIN32_USE_TICKCOUNT
static void		StopCalibration(ClientData clientData);
static DWORD WINAPI	CalibrationThread(LPVOID arg);
static void 		UpdateTimeEachSecond(void);
static void		ResetCounterSamples(Tcl_WideUInt fileTime,
			    Tcl_WideInt perfCounter, Tcl_WideInt perfFreq);
static Tcl_WideInt	AccumulateSample(Tcl_WideInt perfCounter,
			    Tcl_WideUInt fileTime);
#endif
static void		NativeScaleTime(Tcl_Time* timebuf,
			    ClientData clientData);
static void		NativeGetTime(Tcl_Time* timebuf,
			    ClientData clientData);

/*
 * TIP #233 (Virtualized Time): Data for the time hooks, if any.
290
291
292
293
294
295
296



297
298
299
300
301
302
303
     * Note: Outer check for 'initialized' is a performance win since it
     * avoids an extra mutex lock in the common case.
     */

    if (!timeInfo.initialized) {
	TclpInitLock();
	if (!timeInfo.initialized) {



	    timeInfo.perfCounterAvailable =
		    QueryPerformanceFrequency(&timeInfo.nominalFreq);

	    /*
	     * Some hardware abstraction layers use the CPU clock in place of
	     * the real-time clock as a performance counter reference. This
	     * results in:







>
>
>







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
     * Note: Outer check for 'initialized' is a performance win since it
     * avoids an extra mutex lock in the common case.
     */

    if (!timeInfo.initialized) {
	TclpInitLock();
	if (!timeInfo.initialized) {
#ifdef WIN32_USE_TICKCOUNT
	    timeInfo.perfCounterAvailable = 0;
#else
	    timeInfo.perfCounterAvailable =
		    QueryPerformanceFrequency(&timeInfo.nominalFreq);

	    /*
	     * Some hardware abstraction layers use the CPU clock in place of
	     * the real-time clock as a performance counter reference. This
	     * results in:
383
384
385
386
387
388
389

390
391
392
393
394
395
396
		 * outlive unloading tclXX.dll
		 */

		WaitForSingleObject(timeInfo.readyEvent, INFINITE);
		CloseHandle(timeInfo.readyEvent);
		Tcl_CreateExitHandler(StopCalibration, NULL);
	    }

	    timeInfo.initialized = TRUE;
	}
	TclpInitUnlock();
    }

    if (timeInfo.perfCounterAvailable && timeInfo.curCounterFreq.QuadPart!=0) {
	/*







>







387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
		 * outlive unloading tclXX.dll
		 */

		WaitForSingleObject(timeInfo.readyEvent, INFINITE);
		CloseHandle(timeInfo.readyEvent);
		Tcl_CreateExitHandler(StopCalibration, NULL);
	    }
#endif /* !WIN32_USE_TICKCOUNT */
	    timeInfo.initialized = TRUE;
	}
	TclpInitUnlock();
    }

    if (timeInfo.perfCounterAvailable && timeInfo.curCounterFreq.QuadPart!=0) {
	/*
448
449
450
451
452
453
454

455
456
457
458
459
460
461

	_ftime(&t);
	timePtr->sec = (long)t.time;
	timePtr->usec = t.millitm * 1000;
    }
}


/*
 *----------------------------------------------------------------------
 *
 * StopCalibration --
 *
 *	Turns off the calibration thread in preparation for exiting the
 *	process.







>







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467

	_ftime(&t);
	timePtr->sec = (long)t.time;
	timePtr->usec = t.millitm * 1000;
    }
}

#ifndef WIN32_USE_TICKCOUNT
/*
 *----------------------------------------------------------------------
 *
 * StopCalibration --
 *
 *	Turns off the calibration thread in preparation for exiting the
 *	process.
481
482
483
484
485
486
487

488
489
490
491
492
493
494
     * paused state so we need to timeout and continue.
     */

    WaitForSingleObject(timeInfo.calibrationThread, 100);
    CloseHandle(timeInfo.exitEvent);
    CloseHandle(timeInfo.calibrationThread);
}


/*
 *----------------------------------------------------------------------
 *
 * TclpGetDate --
 *
 *	This function converts between seconds and struct tm. If useGMT is







>







487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
     * paused state so we need to timeout and continue.
     */

    WaitForSingleObject(timeInfo.calibrationThread, 100);
    CloseHandle(timeInfo.exitEvent);
    CloseHandle(timeInfo.calibrationThread);
}
#endif /* !WIN32_USE_TICKCOUNT */

/*
 *----------------------------------------------------------------------
 *
 * TclpGetDate --
 *
 *	This function converts between seconds and struct tm. If useGMT is
703
704
705
706
707
708
709

710
711
712
713
714
715
716
    if (tmPtr->tm_wday < 0) {
	tmPtr->tm_wday += 7;
    }

    return tmPtr;
}


/*
 *----------------------------------------------------------------------
 *
 * CalibrationThread --
 *
 *	Thread that manages calibration of the hi-resolution time derived from
 *	the performance counter, to keep it synchronized with the system







>







710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
    if (tmPtr->tm_wday < 0) {
	tmPtr->tm_wday += 7;
    }

    return tmPtr;
}

#ifndef WIN32_USE_TICKCOUNT
/*
 *----------------------------------------------------------------------
 *
 * CalibrationThread --
 *
 *	Thread that manages calibration of the hi-resolution time derived from
 *	the performance counter, to keep it synchronized with the system
1029
1030
1031
1032
1033
1034
1035

1036
1037
1038
1039
1040
1041
1042
	if (++timeInfo.sampleNo >= SAMPLES) {
	    timeInfo.sampleNo = 0;
	}

	return estFreq;
    }
}


/*
 *----------------------------------------------------------------------
 *
 * TclpGmtime --
 *
 *	Wrapper around the 'gmtime' library function to make it thread safe.







>







1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
	if (++timeInfo.sampleNo >= SAMPLES) {
	    timeInfo.sampleNo = 0;
	}

	return estFreq;
    }
}
#endif /* !WIN32_USE_TICKCOUNT */

/*
 *----------------------------------------------------------------------
 *
 * TclpGmtime --
 *
 *	Wrapper around the 'gmtime' library function to make it thread safe.
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123

1124
1125
1126
1127
1128
1129
1130

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    ClientData clientData)
{

    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_QueryTimeProc --
 *







>



>







1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    ClientData clientData)
{
#if !defined(WIN32_USE_TICKCOUNT) || (_WIN32_WINNT >= 0x0600)
    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_QueryTimeProc --
 *