@@ -246,6 +246,10 @@ typedef int clockid_t;
246
246
# define HAS_GETTIMEOFDAY
247
247
# endif
248
248
249
+ # ifndef HAS_NV_GETTIMEOFDAY
250
+ # define HAS_NV_GETTIMEOFDAY
251
+ # endif
252
+
249
253
/* shows up in winsock.h?
250
254
struct timeval {
251
255
long tv_sec;
@@ -270,6 +274,7 @@ typedef struct {
270
274
typedef BOOL (WINAPI * pfnQueryPerformanceCounter_T )(LARGE_INTEGER * );
271
275
272
276
static unsigned __int64 tick_frequency = 0 ;
277
+ static NV tick_frequency_nv = 0 ;
273
278
static unsigned __int64 qpc_res_ns = 0 ;
274
279
static unsigned __int64 qpc_res_ns_realtime = 0 ;
275
280
static pfnQueryPerformanceCounter_T pfnQueryPerformanceCounter = NULL ;
@@ -331,6 +336,10 @@ START_MY_CXT
331
336
# undef clock_gettime
332
337
# define clock_gettime (clock_id , tp ) _clock_gettime(aTHX_ clock_id, tp)
333
338
339
+ # define TIME_HIRES_NV_CLOCK_GETTIME
340
+ # undef nv_clock_gettime
341
+ # define nv_clock_gettime (clock_id , _bp ) _nv_clock_gettime(aTHX_ clock_id, _bp)
342
+
334
343
# undef clock_getres
335
344
# define clock_getres (clock_id , tp ) _clock_getres(clock_id, tp)
336
345
@@ -447,6 +456,18 @@ _gettimeofday_x(pTHX)
447
456
return tp ;
448
457
}
449
458
459
+ PERL_STATIC_FORCE_INLINE NV
460
+ nv_gettimeofday_x (pTHX )
461
+ {
462
+ FT_t ft ;
463
+
464
+ GetSystemTimePreciseAsFileTime (& ft .ft_val );
465
+
466
+ /* FP seconds since epoch */
467
+ return ((NV )((U64 )((U64 )ft .ft_i64 ) - ((U64 )EPOCH_BIAS ))) / ((NV )NV_1E7 );
468
+ }
469
+ #define nv_gettimeofday () nv_gettimeofday_x(aTHX)
470
+
450
471
/* force inline it, because XS_Time__HiRes_clock_gettime() is the only caller */
451
472
452
473
PERL_STATIC_FORCE_INLINE int
@@ -477,6 +498,30 @@ _clock_gettime(pTHX_ clockid_t clock_id, struct timespec *tp)
477
498
return 0 ;
478
499
}
479
500
501
+ PERL_STATIC_FORCE_INLINE NV
502
+ _nv_clock_gettime (pTHX_ clockid_t clock_id , bool * statusp )
503
+ {
504
+ FT_t ft ;
505
+ unsigned __int64 ticks ;
506
+ unsigned __int64 time_sys ;
507
+
508
+ * statusp = 0 ;
509
+ switch (clock_id ) {
510
+ case CLOCK_REALTIME :
511
+ GetSystemTimePreciseAsFileTime (& ft .ft_val );
512
+ time_sys = ft .ft_i64 ;
513
+ return ((NV )((U64 )((U64 )time_sys ) - ((U64 )EPOCH_BIAS ))) / ((NV )NV_1E7 );
514
+ case CLOCK_MONOTONIC :
515
+ QueryPerformanceCounter ((LARGE_INTEGER * )& ft .ft_i64 );
516
+ ticks = ft .ft_i64 ;
517
+ return ((NV )ticks ) / tick_frequency_nv ;
518
+ default :
519
+ * statusp = 1 ;
520
+ errno = EINVAL ;
521
+ return -1.0 ;
522
+ }
523
+ }
524
+
480
525
static int
481
526
_clock_getres (clockid_t clock_id , struct timespec * tp )
482
527
{
@@ -807,21 +852,29 @@ myNVtime()
807
852
return myNVtime_cxt (aTHX );
808
853
# endif
809
854
# endif
855
+ #ifdef HAS_NV_GETTIMEOFDAY
856
+ return nv_gettimeofday ();
857
+ #else
810
858
struct timeval Tp ;
811
859
int status ;
812
860
status = gettimeofday (& Tp , NULL );
813
861
return status == 0 ? Tp .tv_sec + (Tp .tv_usec / NV_1E6 ) : -1.0 ;
862
+ #endif
814
863
}
815
864
816
865
#ifdef PERL_IMPLICIT_CONTEXT
817
866
818
867
static NV
819
868
myNVtime_cxt (pTHX )
820
869
{
870
+ #ifdef HAS_NV_GETTIMEOFDAY
871
+ return nv_gettimeofday ();
872
+ #else
821
873
struct timeval Tp ;
822
874
int status ;
823
875
status = gettimeofday (& Tp , NULL );
824
876
return status == 0 ? Tp .tv_sec + (Tp .tv_usec / NV_1E6 ) : -1.0 ;
877
+ #endif
825
878
}
826
879
827
880
#endif
@@ -1116,10 +1169,10 @@ nsec_without_unslept(struct timespec *sleepfor,
1116
1169
#endif
1117
1170
1118
1171
STATIC void
1119
- S_croak_xs_unimplemented (const CV * const cv );
1172
+ S_croak_xs_unimplemented (CV * const cv );
1120
1173
1121
1174
STATIC void
1122
- S_croak_xs_unimplemented (const CV * const cv )
1175
+ S_croak_xs_unimplemented (CV * const cv )
1123
1176
{
1124
1177
dTHX ;
1125
1178
SV * sv = cv_name (cv , NULL , 0 );
@@ -1175,6 +1228,7 @@ BOOT:
1175
1228
"QueryPerformanceFrequency" );
1176
1229
l_tick_frequency = l_tick_frequency_mem ;
1177
1230
/* 32-bit CPU anti-sharding paranoia */
1231
+ tick_frequency_nv = (NV )l_tick_frequency ;
1178
1232
S_InterlockedExchange64 (& tick_frequency , l_tick_frequency );
1179
1233
}
1180
1234
l_qpc_res_ns = qpc_res_ns ;
@@ -1509,30 +1563,47 @@ alarm(seconds,interval=0)
1509
1563
1510
1564
#ifdef HAS_GETTIMEOFDAY
1511
1565
1566
+ #ifdef HAS_NV_GETTIMEOFDAY
1567
+ # define HAS_NV_GETTIMEOFDAY_BOOL 1
1568
+ #else
1569
+ # define HAS_NV_GETTIMEOFDAY_BOOL 0
1570
+ #endif
1571
+
1512
1572
void
1513
1573
gettimeofday ()
1514
1574
PREINIT :
1515
1575
struct timeval Tp ;
1516
1576
int status ;
1517
1577
OP * const op = PL_op ;
1518
1578
U8 is_G_LIST = GIMME_V == G_LIST ;
1579
+ NV nv ;
1580
+ const U8 do_taint = 1 ;
1519
1581
PPCODE :
1520
1582
if (is_G_LIST )
1521
1583
EXTEND (sp , 2 );
1584
+ else if (HAS_NV_GETTIMEOFDAY_BOOL ) {
1585
+ #ifdef HAS_NV_GETTIMEOFDAY
1586
+ nv = nv_gettimeofday ();
1587
+ #endif
1588
+ goto ret_1_nv ;
1589
+ }
1522
1590
status = gettimeofday (& Tp , NULL );
1523
1591
if (status == 0 ) {
1524
- if (is_G_LIST ) { /* copy to registers to prove sv_2mortal/newSViv */
1592
+ if (HAS_NV_GETTIMEOFDAY_BOOL || is_G_LIST ) {
1593
+ /* copy to registers to prove sv_2mortal/newSViv */
1525
1594
IV sec = Tp .tv_sec ; /* can't modify the values */
1526
1595
IV usec = Tp .tv_usec ;
1527
1596
PUSHs (sv_2mortal (newSViv (sec )));
1528
1597
PUSHs (sv_2mortal (newSViv (usec )));
1529
1598
} else {
1530
1599
/* no Perl_leave_adjust_stacks() hazard here,
1531
1600
only a PP vs call_sv() hazard */
1532
- NV nv = Tp .tv_sec + (Tp .tv_usec / NV_1E6 );
1533
- const U8 do_taint = 1 ;
1534
- NV TARGn_nv = nv ;
1601
+ NV TARGn_nv ;
1535
1602
SV * rsv ;
1603
+ nv = Tp .tv_sec + (Tp .tv_usec / NV_1E6 );
1604
+
1605
+ ret_1_nv :
1606
+ TARGn_nv = nv ;
1536
1607
if (op -> op_private & OPpENTERSUB_HASTARG ) {
1537
1608
rsv = PAD_SV (op -> op_targ );
1538
1609
if (LIKELY (
@@ -1559,17 +1630,23 @@ gettimeofday()
1559
1630
void
1560
1631
time ()
1561
1632
PREINIT :
1562
- struct timeval Tp ;
1563
1633
SV * rsv ;
1564
1634
NV RETVAL ;
1565
- CODE :
1635
+ #ifndef HAS_NV_GETTIMEOFDAY
1636
+ struct timeval Tp ;
1566
1637
int status ;
1638
+ #endif
1639
+ CODE :
1640
+ #ifndef HAS_NV_GETTIMEOFDAY
1567
1641
status = gettimeofday (& Tp , NULL );
1568
1642
if (status == 0 ) {
1569
1643
RETVAL = Tp .tv_sec + (Tp .tv_usec / NV_1E6 );
1570
1644
} else {
1571
1645
RETVAL = -1.0 ;
1572
1646
}
1647
+ #else
1648
+ RETVAL = nv_gettimeofday ();
1649
+ #endif
1573
1650
TMR_TARGn (rsv , RETVAL , 1 );
1574
1651
PUSHs (rsv ); /* 0 in, 1 out, entersub guarenteed 1 slot */
1575
1652
PUTBACK ;
@@ -1739,17 +1816,27 @@ void
1739
1816
clock_gettime (clock_id = CLOCK_REALTIME )
1740
1817
clockid_t clock_id
1741
1818
PREINIT :
1819
+ #ifndef TIME_HIRES_NV_CLOCK_GETTIME
1742
1820
struct timespec ts ;
1743
1821
int status ;
1822
+ #endif
1744
1823
SV * rsv ;
1745
1824
NV RETVAL ;
1746
1825
PPCODE :
1747
1826
# ifdef TIME_HIRES_CLOCK_GETTIME_SYSCALL
1748
1827
status = syscall (SYS_clock_gettime , clock_id , & ts );
1749
1828
# else
1829
+ # ifndef TIME_HIRES_NV_CLOCK_GETTIME
1750
1830
status = clock_gettime (clock_id , & ts );
1751
- # endif
1752
1831
RETVAL = status == 0 ? ts .tv_sec + (NV ) ts .tv_nsec / NV_1E9 : -1 ;
1832
+ # else
1833
+ {
1834
+ bool status ;
1835
+ NV nv = nv_clock_gettime (clock_id , & status );
1836
+ RETVAL = status == 0 ? nv : -1 ;
1837
+ }
1838
+ # endif
1839
+ # endif
1753
1840
TMR_TARGn (rsv , RETVAL , 1 );
1754
1841
PUSHs (rsv ); /* 0 or 1 in, 1 out, PPCODE: did rewind */
1755
1842
PUTBACK ;
0 commit comments