Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perl does not build on Darwin platforms with clock_gettime #15396

Open
p5pRT opened this issue Jun 17, 2016 · 28 comments
Open

perl does not build on Darwin platforms with clock_gettime #15396

p5pRT opened this issue Jun 17, 2016 · 28 comments

Comments

@p5pRT
Copy link

p5pRT commented Jun 17, 2016

Migrated from rt.perl.org#128427 (status was 'open')

Searchable as RT128427$

@p5pRT
Copy link
Author

p5pRT commented Jun 17, 2016

From @mistydemeo

Created by @mistydemeo

Time​::HiRes contains code to emulate clock_gettime on Darwin, which
historically has not included that function. Most of this is guarded
by #ifdefs which check for both Darwin and the absense of clock_gettime.
However, the latter isn't applied consistently, resulting in build
errors on Darwin versions which include a native clock_gettime.

The attached patch fixes this by adjusting one #ifdef.

Perl Info

Flags:
    category=library
    severity=high
    Type=Patch
    PatchStatus=HasPatch
    module=Time::HiRes

Site configuration information for perl 5.24.0:

Configured by brew at Sat Jun  4 10:59:48 BST 2016.

Summary of my perl5 (revision 5 version 24 subversion 0) configuration:

  Platform:
    osname=darwin, osvers=15.5.0, archname=darwin-thread-multi-2level
    uname='darwin elcapitanvm.local 15.5.0 darwin kernel version 15.5.0:
tue apr 19 18:36:36 pdt 2016; root:xnu-3248.50.21~8release_x86_64 x86_64 '
    config_args='-des -Dprefix=/usr/local/Cellar/perl/5.24.0_1
-Dprivlib=/usr/local/Cellar/perl/5.24.0_1/lib/perl5/5.24.0
-Dsitelib=/usr/local/Cellar/perl/5.24.0_1/lib/perl5/site_perl/5.24.0
-Dotherlibdirs=/usr/local/lib/perl5/site_perl/5.24.0
-Dperlpath=/usr/local/opt/perl/bin/perl
-Dstartperl=#!/usr/local/opt/perl/bin/perl
-Dman1dir=/usr/local/Cellar/perl/5.24.0_1/share/man/man1
-Dman3dir=/usr/local/Cellar/perl/5.24.0_1/share/man/man3 -Duseshrplib
-Duselargefiles -Dusethreads'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.11
-fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include
-DPERL_USE_SAFE_PUTENV',
    optimize='-O3',
    cppflags='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.11
-fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion='', gccversion='4.2.1 Compatible Apple LLVM 7.3.0
(clang-703.0.31)', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678,
doublekind=3
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16,
longdblkind=3
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -mmacosx-version-min=10.11 -fstack-protector-strong
-L/usr/local/lib'
    libpth=/usr/local/lib /usr/include/libxml2
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.3.0/lib
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/lib
/usr/lib
    libs=-lpthread -ldbm -ldl -lm -lutil -lc
    perllibs=-lpthread -ldl -lm -lutil -lc
    libc=, so=dylib, useshrplib=true, libperl=libperl.dylib
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags=' -mmacosx-version-min=10.11 -bundle
-undefined dynamic_lookup -L/usr/local/lib -fstack-protector-strong'



@INC for perl 5.24.0:

/usr/local/Cellar/perl/5.24.0_1/lib/perl5/site_perl/5.24.0/darwin-thread-multi-2level
    /usr/local/Cellar/perl/5.24.0_1/lib/perl5/site_perl/5.24.0

/usr/local/Cellar/perl/5.24.0_1/lib/perl5/5.24.0/darwin-thread-multi-2level
    /usr/local/Cellar/perl/5.24.0_1/lib/perl5/5.24.0
    /usr/local/lib/perl5/site_perl/5.24.0
    .


Environment for perl 5.24.0:
    DYLD_LIBRARY_PATH (unset)
    HOME=/Users/mistydemeo
    LANG=en_CA.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)

PATH=/Users/mistydemeo/.rbenv/shims:/Users/mistydemeo/.nodenv/shims:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
    PERL_BADLANG (unset)
    SHELL=/usr/local/bin/fish

@p5pRT
Copy link
Author

p5pRT commented Jun 17, 2016

From @mistydemeo

0001-Fix-GetTime.c-on-Darwin-with-clock_gettime.patch
From fbf8563dea38a8e209d3289ddcab4b18760842a8 Mon Sep 17 00:00:00 2001
From: Misty De Meo <mistydemeo@github.com>
Date: Wed, 15 Jun 2016 15:02:13 -0700
Subject: [PATCH] Fix GetTime.c on Darwin with clock_gettime

On Darwin versions with clock_gettime, #ifdefs will prevent the
mach-specific time functions from being used in most places, and
the mach time headers won't be included; however, this section
was guarded incorrectly and would still try to use them.
---
 rts/posix/GetTime.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/rts/posix/GetTime.c b/rts/posix/GetTime.c
index 130d3f1..4d25795 100644
--- a/rts/posix/GetTime.c
+++ b/rts/posix/GetTime.c
@@ -29,14 +29,14 @@
 // we'll implement getProcessCPUTime() and getProcessElapsedTime()
 // separately, using getrusage() and gettimeofday() respectively
 
-#ifdef darwin_HOST_OS
+#if !defined(HAVE_CLOCK_GETTIME) && defined(darwin_HOST_OS)
 static uint64_t timer_scaling_factor_numer = 0;
 static uint64_t timer_scaling_factor_denom = 0;
 #endif
 
 void initializeTimer()
 {
-#ifdef darwin_HOST_OS
+#if !defined(HAVE_CLOCK_GETTIME) && defined(darwin_HOST_OS)
     mach_timebase_info_data_t info;
     (void) mach_timebase_info(&info);
     timer_scaling_factor_numer = (uint64_t)info.numer;
-- 
2.9.0

@p5pRT
Copy link
Author

p5pRT commented Jun 18, 2016

From @jkeenan

On Fri Jun 17 13​:22​:07 2016, mistydemeo@​gmail.com wrote​:

This is a bug report for perl from mistydemeo@​gmail.com,
generated with the help of perlbug 1.40 running under perl 5.24.0.

-----------------------------------------------------------------
[Please describe your issue here]

Time​::HiRes contains code to emulate clock_gettime on Darwin, which
historically has not included that function. Most of this is guarded
by #ifdefs which check for both Darwin and the absense of
clock_gettime.
However, the latter isn't applied consistently, resulting in build
errors on Darwin versions which include a native clock_gettime.

The attached patch fixes this by adjusting one #ifdef.

It's not clear to me what source code you have drawn your patch against.

When I ack or grep the Perl 5 core distribution, I find no directory named 'rts'. Nor do I find the string 'darwin_HOST_OS' in any source code.

#####
$ ack '\brts\b' MANIFEST
[no output]

$ find . -type d -name '*rts*'
./cpan/Devel-PPPort/parts

$ ack darwin_HOST_OS .
[no output]
#####

Can you clarify?

Thank you very much.

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Jun 18, 2016

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jun 18, 2016

From @mauke

Am 18.06.2016 um 14​:06 schrieb James E Keenan via RT​:

On Fri Jun 17 13​:22​:07 2016, mistydemeo@​gmail.com wrote​:

This is a bug report for perl from mistydemeo@​gmail.com,
generated with the help of perlbug 1.40 running under perl 5.24.0.

-----------------------------------------------------------------
[Please describe your issue here]

Time​::HiRes contains code to emulate clock_gettime on Darwin, which
historically has not included that function. Most of this is guarded
by #ifdefs which check for both Darwin and the absense of
clock_gettime.
However, the latter isn't applied consistently, resulting in build
errors on Darwin versions which include a native clock_gettime.

The attached patch fixes this by adjusting one #ifdef.

It's not clear to me what source code you have drawn your patch against.

When I ack or grep the Perl 5 core distribution, I find no directory named 'rts'. Nor do I find the string 'darwin_HOST_OS' in any source code.

#####
$ ack '\brts\b' MANIFEST
[no output]

$ find . -type d -name '*rts*'
./cpan/Devel-PPPort/parts

$ ack darwin_HOST_OS .
[no output]
#####

Can you clarify?

Wow, this is pretty amazing. I have no idea how this happened, but the
patch seems to be against
https://github.com/ghc/ghc/blob/master/rts/posix/GetTime.c, which is the
runtime system of ghc (the Glasgow Haskell Compiler).

--
Lukas Mai <plokinom@​gmail.com>

@p5pRT
Copy link
Author

p5pRT commented Jun 18, 2016

From @mauke

On Sat Jun 18 09​:58​:28 2016, plokinom@​gmail.com wrote​:

Wow, this is pretty amazing. I have no idea how this happened, but the
patch seems to be against
https://github.com/ghc/ghc/blob/master/rts/posix/GetTime.c, which is
the
runtime system of ghc (the Glasgow Haskell Compiler).

Forwarding a message from the original reporter​:

| GHC has an almost identical bug, and when reporting the bug to perl, I
| inadvertently attached the GHC patch instead of the perl patch. I've
| attached the correct patch to this email.

@p5pRT
Copy link
Author

p5pRT commented Jun 18, 2016

From @mauke

0001-Time-HiRes-fix-Darwins-with-clock_gettime.patch
From 76264435f3fcc23c80831f940059bfb80122dcc9 Mon Sep 17 00:00:00 2001
From: Misty De Meo <mistydemeo@github.com>
Date: Fri, 17 Jun 2016 12:49:44 -0700
Subject: [PATCH] Time::HiRes: fix Darwins with clock_gettime

Not all of the Darwin time code was guarded by the same set of #ifdefs,
leading to bugs on Darwin platforms with clock_gettime where a struct
would not be defined but would still be used elsewhere.
---
 dist/Time-HiRes/HiRes.xs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dist/Time-HiRes/HiRes.xs b/dist/Time-HiRes/HiRes.xs
index 38ca0dc..ed60336 100644
--- a/dist/Time-HiRes/HiRes.xs
+++ b/dist/Time-HiRes/HiRes.xs
@@ -940,7 +940,7 @@ BOOT:
   }
 #   endif
 #endif
-#if defined(PERL_DARWIN)
+#if defined(PERL_DARWIN) && !defined(CLOCK_REALTIME)
 #  ifdef USE_ITHREADS
   MUTEX_INIT(&darwin_time_mutex);
 #  endif
-- 
2.9.0

@p5pRT
Copy link
Author

p5pRT commented Jun 19, 2016

From @mistydemeo

Apologies, it appears I attached the incorrect patch. The correct patch is
attached.

@p5pRT
Copy link
Author

p5pRT commented Jun 19, 2016

From @mistydemeo

0001-Time-HiRes-fix-Darwins-with-clock_gettime.patch
From 76264435f3fcc23c80831f940059bfb80122dcc9 Mon Sep 17 00:00:00 2001
From: Misty De Meo <mistydemeo@github.com>
Date: Fri, 17 Jun 2016 12:49:44 -0700
Subject: [PATCH] Time::HiRes: fix Darwins with clock_gettime

Not all of the Darwin time code was guarded by the same set of #ifdefs,
leading to bugs on Darwin platforms with clock_gettime where a struct
would not be defined but would still be used elsewhere.
---
 dist/Time-HiRes/HiRes.xs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dist/Time-HiRes/HiRes.xs b/dist/Time-HiRes/HiRes.xs
index 38ca0dc..ed60336 100644
--- a/dist/Time-HiRes/HiRes.xs
+++ b/dist/Time-HiRes/HiRes.xs
@@ -940,7 +940,7 @@ BOOT:
   }
 #   endif
 #endif
-#if defined(PERL_DARWIN)
+#if defined(PERL_DARWIN) && !defined(CLOCK_REALTIME)
 #  ifdef USE_ITHREADS
   MUTEX_INIT(&darwin_time_mutex);
 #  endif
-- 
2.9.0

@p5pRT
Copy link
Author

p5pRT commented Jun 19, 2016

From @mistydemeo

Hi, Lukas,

Apologies for the incorrect patch. GHC had nearly the same bug, and I
inadvertantly attached the incorrect patch. I attempted to reply
earlier with the correct patch, but the tracker has been dropping my
messages.

On Sat, Jun 18, 2016 at 9​:58 AM, Lukas Mai via RT
<perlbug-followup@​perl.org> wrote​:

Am 18.06.2016 um 14​:06 schrieb James E Keenan via RT​:

On Fri Jun 17 13​:22​:07 2016, mistydemeo@​gmail.com wrote​:

This is a bug report for perl from mistydemeo@​gmail.com,
generated with the help of perlbug 1.40 running under perl 5.24.0.

-----------------------------------------------------------------
[Please describe your issue here]

Time​::HiRes contains code to emulate clock_gettime on Darwin, which
historically has not included that function. Most of this is guarded
by #ifdefs which check for both Darwin and the absense of
clock_gettime.
However, the latter isn't applied consistently, resulting in build
errors on Darwin versions which include a native clock_gettime.

The attached patch fixes this by adjusting one #ifdef.

It's not clear to me what source code you have drawn your patch against.

When I ack or grep the Perl 5 core distribution, I find no directory named 'rts'. Nor do I find the string 'darwin_HOST_OS' in any source code.

#####
$ ack '\brts\b' MANIFEST
[no output]

$ find . -type d -name '*rts*'
./cpan/Devel-PPPort/parts

$ ack darwin_HOST_OS .
[no output]
#####

Can you clarify?

Wow, this is pretty amazing. I have no idea how this happened, but the
patch seems to be against
https://github.com/ghc/ghc/blob/master/rts/posix/GetTime.c, which is the
runtime system of ghc (the Glasgow Haskell Compiler).

--
Lukas Mai <plokinom@​gmail.com>

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2016

From @iabyn

On Fri, Jun 17, 2016 at 01​:24​:43PM -0700, Misty De Meo wrote​:

Apologies, it appears I attached the incorrect patch. The correct patch is
attached.

Thanks, applied as

  2d41a26

and I've added you to AUTHORS with

  ba3530a

--
"Foul and greedy Dwarf - you have eaten the last candle."
  -- "Hordes of the Things", BBC Radio.

@p5pRT
Copy link
Author

p5pRT commented Jun 22, 2016

From @jhi

On Mon Jun 20 00​:36​:34 2016, davem wrote​:

On Fri, Jun 17, 2016 at 01​:24​:43PM -0700, Misty De Meo wrote​:

Apologies, it appears I attached the incorrect patch. The correct patch is
attached.

Thanks, applied as

2d41a263c0e09e6dfabecd28212d7e80b42dc3e6

This change unfortunately didn't quite work.

In OS X 10.11.5 (at least, but got also failure reports from other versions), the change meant that the mutex
init was skipped, which meant that the further mutex use panicked (correctly) if the Perl was built with threads. So what exactly was the intent of the change?

You said "resulting in build errors on Darwin versions which include a native clock_gettime"? What are these platforms? Non-Apple Darwin builds? That is fine, but the change needs to be something different.

and I've added you to AUTHORS with

ba3530a211029e1fe07e19b385b9f7c17af92ac5

@p5pRT
Copy link
Author

p5pRT commented Jun 22, 2016

From @jhi

On Wed Jun 22 04​:37​:18 2016, jhi wrote​:

On Mon Jun 20 00​:36​:34 2016, davem wrote​:

On Fri, Jun 17, 2016 at 01​:24​:43PM -0700, Misty De Meo wrote​:

Apologies, it appears I attached the incorrect patch. The correct
patch is
attached.

Thanks, applied as

2d41a26

This change unfortunately didn't quite work.

In OS X 10.11.5 (at least, but got also failure reports from other
versions), the change meant that the mutex
init was skipped, which meant that the further mutex use panicked
(correctly) if the Perl was built with threads. So what exactly was
the intent of the change?

You said "resulting in build errors on Darwin versions which include a
native clock_gettime"? What are these platforms? Non-Apple Darwin
builds? That is fine, but the change needs to be something different.

Ah, I see it now. The test !defined(CLOCK_REALTIME) is not valid anymore later in the file because the Darwin emulation defines it. I'll fix this.

@p5pRT
Copy link
Author

p5pRT commented Sep 6, 2016

From @dcollinsn

The code in question has been modified in more recent versions of Time-HiRes, for example, to use PERL_DARWIN_MUTEX. Are these changes sufficient? http​://perl5.git.perl.org/perl.git/commitdiff/c4a535af41823cc84534bf8dbecfdcc3eb7daa86

If not, the patch from Misty may have been overwritten when the new version of Time-HiRes was brought into blead (is it cpan-upstream?). Jarkko, have you had a chance to look into the issues you identified?

--
Dan Collins

@p5pRT
Copy link
Author

p5pRT commented Sep 6, 2016

From [Unknown Contact. See original ticket]

The code in question has been modified in more recent versions of Time-HiRes, for example, to use PERL_DARWIN_MUTEX. Are these changes sufficient? http​://perl5.git.perl.org/perl.git/commitdiff/c4a535af41823cc84534bf8dbecfdcc3eb7daa86

If not, the patch from Misty may have been overwritten when the new version of Time-HiRes was brought into blead (is it cpan-upstream?). Jarkko, have you had a chance to look into the issues you identified?

--
Dan Collins

@p5pRT
Copy link
Author

p5pRT commented Sep 8, 2016

From @jhi

On Tue Sep 06 10​:48​:17 2016, dcollinsn@​gmail.com wrote​:

The code in question has been modified in more recent versions of
Time-HiRes, for example, to use PERL_DARWIN_MUTEX. Are these changes
sufficient?
http​://perl5.git.perl.org/perl.git/commitdiff/c4a535af41823cc84534bf8dbecfdcc3eb7daa86

If not, the patch from Misty may have been overwritten when the new
version of Time-HiRes was brought into blead (is it cpan-upstream?).
Jarkko, have you had a chance to look into the issues you identified?

The latest versions of T-H should be all good in all known versions of OS X. Sierra, whatever.
If they are not, new bug reports should be filed. As far as I know, this one can be closed.

--
Dan Collins

@p5pRT
Copy link
Author

p5pRT commented Sep 8, 2016

From @tonycoz

On Wed Sep 07 18​:31​:46 2016, jhi wrote​:

On Tue Sep 06 10​:48​:17 2016, dcollinsn@​gmail.com wrote​:

The code in question has been modified in more recent versions of
Time-HiRes, for example, to use PERL_DARWIN_MUTEX. Are these changes
sufficient?
http​://perl5.git.perl.org/perl.git/commitdiff/c4a535af41823cc84534bf8dbecfdcc3eb7daa86

If not, the patch from Misty may have been overwritten when the new
version of Time-HiRes was brought into blead (is it cpan-upstream?).
Jarkko, have you had a chance to look into the issues you identified?

The latest versions of T-H should be all good in all known versions of
OS X. Sierra, whatever.
If they are not, new bug reports should be filed. As far as I know,
this one can be closed.

The issue is more building 5.24 on Sierra, is there a minimal fix for the build
issue which can be backported to 5.24?

Tony

@p5pRT
Copy link
Author

p5pRT commented Nov 15, 2016

From @jkeenan

On Thu, 08 Sep 2016 01​:58​:19 GMT, tonyc wrote​:

On Wed Sep 07 18​:31​:46 2016, jhi wrote​:

On Tue Sep 06 10​:48​:17 2016, dcollinsn@​gmail.com wrote​:

The code in question has been modified in more recent versions of
Time-HiRes, for example, to use PERL_DARWIN_MUTEX. Are these
changes
sufficient?
http​://perl5.git.perl.org/perl.git/commitdiff/c4a535af41823cc84534bf8dbecfdcc3eb7daa86

If not, the patch from Misty may have been overwritten when the new
version of Time-HiRes was brought into blead (is it cpan-
upstream?).
Jarkko, have you had a chance to look into the issues you
identified?

The latest versions of T-H should be all good in all known versions
of
OS X. Sierra, whatever.
If they are not, new bug reports should be filed. As far as I know,
this one can be closed.

The issue is more building 5.24 on Sierra, is there a minimal fix for
the build
issue which can be backported to 5.24?

Tony

MoarVM also faced this problem​: MoarVM/MoarVM@20c8591

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Nov 16, 2016

From @FROGGS

The issue is more building 5.24 on Sierra, is there a minimal fix for
the build
issue which can be backported to 5.24?

Tony

Hi, this is what we did for Perl 6​: MoarVM/MoarVM@20c8591

I hope that helps a little.

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2016

From @jkeenan

On Thu, 08 Sep 2016 01​:58​:19 GMT, tonyc wrote​:

On Wed Sep 07 18​:31​:46 2016, jhi wrote​:

On Tue Sep 06 10​:48​:17 2016, dcollinsn@​gmail.com wrote​:

The code in question has been modified in more recent versions of
Time-HiRes, for example, to use PERL_DARWIN_MUTEX. Are these
changes
sufficient?
http​://perl5.git.perl.org/perl.git/commitdiff/c4a535af41823cc84534bf8dbecfdcc3eb7daa86

If not, the patch from Misty may have been overwritten when the new
version of Time-HiRes was brought into blead (is it cpan-
upstream?).
Jarkko, have you had a chance to look into the issues you
identified?

The latest versions of T-H should be all good in all known versions
of
OS X. Sierra, whatever.
If they are not, new bug reports should be filed. As far as I know,
this one can be closed.

The issue is more building 5.24 on Sierra, is there a minimal fix for
the build
issue which can be backported to 5.24?

Tony

Tony, Jarkko, Dan​: Can you advise where we stand on this ticket?

Thank you very much.

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2016

From @craigberry

On Thu, Dec 29, 2016 at 8​:00 AM, James E Keenan via RT
<perlbug-followup@​perl.org> wrote​:

On Thu, 08 Sep 2016 01​:58​:19 GMT, tonyc wrote​:

On Wed Sep 07 18​:31​:46 2016, jhi wrote​:

On Tue Sep 06 10​:48​:17 2016, dcollinsn@​gmail.com wrote​:

The code in question has been modified in more recent versions of
Time-HiRes, for example, to use PERL_DARWIN_MUTEX. Are these
changes
sufficient?
http​://perl5.git.perl.org/perl.git/commitdiff/c4a535af41823cc84534bf8dbecfdcc3eb7daa86

If not, the patch from Misty may have been overwritten when the new
version of Time-HiRes was brought into blead (is it cpan-
upstream?).
Jarkko, have you had a chance to look into the issues you
identified?

The latest versions of T-H should be all good in all known versions
of
OS X. Sierra, whatever.
If they are not, new bug reports should be filed. As far as I know,
this one can be closed.

The issue is more building 5.24 on Sierra, is there a minimal fix for
the build
issue which can be backported to 5.24?

Tony

Tony, Jarkko, Dan​: Can you advise where we stand on this ticket?

Thank you very much.

--
James E Keenan (jkeenan@​cpan.org)

As of v5.24.1-RC4-13-gb7d278c, there is one remaining test failure​:

$ ../../perl -I../../lib t/clock.t
1..5
# I am the main process 19721, starting the watchdog process...
# The watchdog process 19722 launched, continuing testing...
# I am the watchdog process 19722, sleeping for 360 seconds...
ok 1 - require Time​::HiRes;
# have_clock_gettime = 1
# have_clock_getres = 1
# have_clock_nanosleep = 1
# have_clock = 1
# CLOCK_REALTIME​: try = 1
# t1 = 1483046030.35294, t0 = 1483046028.84275
# dt = 1.51018714904785, rt = 0.00679143269856763
ok 2
ok 3
Time​::HiRes​::clock_nanosleep()​: unimplemented in this platform at
t/clock.t line 74.
# I am the main process 19721, terminating the watchdog process 19722
before it terminates me in 358 seconds (testing took 2 seconds).
# kill KILL 19722 = 1
# All done.
# Looks like you planned 5 tests but ran 3.
# Looks like your test exited with 60 just after 3.

I've attached a patch that updates maint-5.24 to the current CPAN
release of Tiime​::HiRes and can confirm that this gets all tests
passing on macOS Sierra.

As far as I can see the only new feature is the addition of a
high-resolution utime(). All other changes are bug fixes, most of
them darwin-related. Disentangling which bug fixes are strictly
necessary might be riskier (and certainly more work) than just taking
the whole thing. All of the relevant changes have been in blead for a
couple of months, meaning we'd probably know about it by now if they
were problematic.

At least this is an alternative to leaving the test failure as-is. I
think the only other alternative would be for someone to trawl through
all the changes and produce a more minimal patch.

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 2016

From @craigberry

0001-Upgrade-Time-HiRes-to-1.9741.patch
From 1e9051b4cc316ba63b74357def12032c778a1b36 Mon Sep 17 00:00:00 2001
From: "Craig A. Berry" <craigberry@mac.com>
Date: Thu, 29 Dec 2016 16:04:32 -0600
Subject: [PATCH] Upgrade Time::HiRes to 1.9741.

This is exceptional for a maint release but is necessary to fix
macOS Sierra builds.
---
 MANIFEST                             |   1 +
 Porting/Maintainers.pl               |   2 +-
 dist/Time-HiRes/Changes              |  69 +++++++++++++
 dist/Time-HiRes/HiRes.pm             |  44 ++++++--
 dist/Time-HiRes/HiRes.xs             | 195 ++++++++++++++++++++++++++++++-----
 dist/Time-HiRes/Makefile.PL          | 137 ++++++++++++++++++++++--
 dist/Time-HiRes/fallback/const-c.inc |  79 ++++++++------
 dist/Time-HiRes/t/Watchdog.pm        |  18 ++--
 dist/Time-HiRes/t/alarm.t            |  30 +++---
 dist/Time-HiRes/t/clock.t            |  28 ++---
 dist/Time-HiRes/t/gettimeofday.t     |  14 +--
 dist/Time-HiRes/t/itimer.t           |  18 ++--
 dist/Time-HiRes/t/nanosleep.t        |   6 +-
 dist/Time-HiRes/t/sleep.t            |   6 +-
 dist/Time-HiRes/t/stat.t             |   8 +-
 dist/Time-HiRes/t/time.t             |   6 +-
 dist/Time-HiRes/t/tv_interval.t      |   4 +-
 dist/Time-HiRes/t/ualarm.t           |  36 +++----
 dist/Time-HiRes/t/usleep.t           |  12 +--
 dist/Time-HiRes/t/utime.t            | 138 +++++++++++++++++++++++++
 dist/Time-HiRes/typemap              |   2 +
 21 files changed, 685 insertions(+), 168 deletions(-)
 create mode 100644 dist/Time-HiRes/t/utime.t

diff --git a/MANIFEST b/MANIFEST
index 893abbf..d53dc0e 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -3558,6 +3558,7 @@ dist/Time-HiRes/t/time.t		Test for Time::HiRes
 dist/Time-HiRes/t/tv_interval.t		Test for Time::HiRes
 dist/Time-HiRes/t/ualarm.t		Test for Time::HiRes
 dist/Time-HiRes/t/usleep.t		Test for Time::HiRes
+dist/Time-HiRes/t/utime.t		Test for Time::HiRes
 dist/Time-HiRes/t/Watchdog.pm		Test for Time::HiRes
 dist/Time-HiRes/typemap			Time::HiRes extension
 dist/XSLoader/Makefile.PL	Dynamic Loader makefile writer
diff --git a/Porting/Maintainers.pl b/Porting/Maintainers.pl
index bf47b40..f886c57 100755
--- a/Porting/Maintainers.pl
+++ b/Porting/Maintainers.pl
@@ -1378,7 +1378,7 @@ use File::Glob qw(:case);
     },
 
     'Time::HiRes' => {
-        'DISTRIBUTION' => 'RJBS/Time-HiRes-1.9728.tar.gz',
+        'DISTRIBUTION' => 'RJBS/Time-HiRes-1.9741.tar.gz',
         'FILES'        => q[dist/Time-HiRes],
     },
 
diff --git a/dist/Time-HiRes/Changes b/dist/Time-HiRes/Changes
index 9d097c5..c2ad5a5 100644
--- a/dist/Time-HiRes/Changes
+++ b/dist/Time-HiRes/Changes
@@ -1,5 +1,74 @@
 Revision history for the Perl extension Time::HiRes.
 
+1.9741 [2016-11-20]
+  - C++11 compatibility: blead a914236c
+  - El Capitan compatibility: blead 45bbc013
+  - use CLOCK_REALTIME for clock_nanosleep scan: blead 56ed632c
+  - include file consistency in scans: blead 605b4dbe
+  - use clockid_t consistently: blead 2979fdf3
+  - use hv_fetchs(): blead 07e4dd7a
+  - scan for clockid_t (needed for macos Sierra): blead 69d1f2c2
+  - darwin lacks clockid_t: blead d1e7b5aa
+    [rt.cpan.org #129789]
+  - provide template for tempfile: blead 91dca83e
+  - explicit cast for clockid_t in C++11: blead 1c566547
+  - upgrade to a newer ppport (3.35)
+
+1.9740 [2016-09-25]
+  - the ext3/ext2 filesystems do not have subsecond resolution,
+    therefore skip the t/utime.t test
+    [rt.cpan.org #116127]
+
+1.9739 [2016-06-28]
+  - the upcoming macOS 10.12 (Sierra, the operating system formerly
+    known as OS X, or Darwin) has implemented the clock_gettime()
+    and clock_getres() interfaces but not the clock_nanosleep()
+
+1.9738 [2016-06-26]
+  - fix the dates in the Changes, it's not July yet
+    [rt.cpan.org #115553]
+  - in cygwin, drop the utime.t expected timestamp resolution
+  - documented for utime that the actual timestamp resolution depends
+    on the operating system and the filesystem, just like for stat
+  - looks like in gnukfreebsd 10.1 neither futimens or utimensat work
+    even though they exist, skipping utime tests there for now
+  - demodernize the Test::More use in utime.t (no subtest) to
+    better support older Perl installations
+  - for all the tests, drop the Test::More 0.82 requirement,
+    the only "modern" thing used is the note routine which
+    can be replaced with print("# ...\n") (or printf),
+    with this works back at least with Test::More 0.54 (perl 5.8.7) 
+
+1.9737 [2016-06-22]
+  - utime in HiRes.xs had dXSARGS which was unnecessary, leading
+    to two markstack pops, panic, and two-minute wait for the watchdog
+    (thanks to Dave Mitchell for the eagle-eye)
+  - even though 5.10.x should have the Perl_ck_warner, many CPAN
+    smokes proved otherwise, so requiring now at least 5.12 for
+    Perl_ck_warner use in IS_SAFE_PATHNAME() 
+
+1.9736 [2016-06-22]
+  - the IS_SAFE_PATHNAME() emulation was too modern for Perl 5.10
+  - make it so that only one value is set for -DTIME_HIRES_STAT
+    even on systems that support many options
+  - the 1.9734 (only released in blead, and as part of the development
+    release 5.25.2) fix for Darwin's clock_gettime was wrong under
+    threaded builds, leading into mutex panics in clock.t 
+  - the d_hires_utime determination was made more precise
+  - the utime.t was failing in platforms where only one of
+    futimens/utimensat was present (neither or both was okay)
+
+1.9735 [2016-06-20]
+  - Time::HiRes should override `utime` to allow setting hires
+    (futimens and utimensat support)
+    [rt.perl.org #114809]
+  - the utime patch used IS_SAFE_PATHNAME() which isn't available in
+    too old Perls, so emulate (in case the Devel::PPPort is too old)
+
+1.9734 [2016-06-17]
+  - fix Darwins with clock_gettime: blead 2d41a263
+    [rt.perl.org #128427]
+
 1.9733 [2016-04-23]
   - C90 declaration-after-statement error with darwin threads: blead de1003b4
     [rt.cpan.org #113856]
diff --git a/dist/Time-HiRes/HiRes.pm b/dist/Time-HiRes/HiRes.pm
index ad9a65c..a3ddd59 100644
--- a/dist/Time-HiRes/HiRes.pm
+++ b/dist/Time-HiRes/HiRes.pm
@@ -23,12 +23,12 @@ our @EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval
 		 ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF
 		 TIMER_ABSTIME
 		 d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
-		 d_nanosleep d_clock_gettime d_clock_getres
+		 d_nanosleep d_clock_gettime d_clock_getres d_hires_utime
 		 d_clock d_clock_nanosleep
-		 stat lstat
+		 stat lstat utime
 		);
 
-our $VERSION = '1.9733';
+our $VERSION = '1.9741';
 our $XS_VERSION = $VERSION;
 $VERSION = eval $VERSION;
 
@@ -60,6 +60,7 @@ sub import {
 	    ($i eq 'clock'           && !&d_clock)           ||
 	    ($i eq 'nanosleep'       && !&d_nanosleep)       ||
 	    ($i eq 'usleep'          && !&d_usleep)          ||
+	    ($i eq 'utime'           && !&d_hires_utime)     ||
 	    ($i eq 'ualarm'          && !&d_ualarm)) {
 	    require Carp;
 	    Carp::croak("Time::HiRes::$i(): unimplemented in this platform");
@@ -92,7 +93,7 @@ Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
 
   use Time::HiRes qw( usleep ualarm gettimeofday tv_interval nanosleep
 		      clock_gettime clock_getres clock_nanosleep clock
-                      stat lstat );
+                      stat lstat utime);
 
   usleep ($microseconds);
   nanosleep ($nanoseconds);
@@ -137,6 +138,9 @@ Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
   my @stat = stat(FH);
   my @stat = lstat("file");
 
+  use Time::HiRes qw( utime );
+  utime $floating_seconds, $floating_seconds, file...;
+
 =head1 DESCRIPTION
 
 The C<Time::HiRes> module implements a Perl interface to the
@@ -446,6 +450,26 @@ if the operations are
 the access time stamp from t2 need not be greater-than the modify
 time stamp from t1: it may be equal or I<less>.
 
+=item utime LIST
+
+As L<perlfunc/utime>
+but with the ability to set the access/modify file timestamps
+in subsecond resolution, if the operating system and the filesystem
+both support such timestamps.  To override the standard utime():
+
+    use Time::HiRes qw(utime);
+
+Test for the value of &Time::HiRes::d_hires_utime to find out whether
+the operating system supports setting subsecond file timestamps.
+
+As with CORE::utime(), passing undef as both the atime and mtime will
+call the syscall with a NULL argument.
+
+The actual achievable subsecond resolution depends on the combination
+of the operating system and the filesystem.
+
+Returns the number of files successfully changed.
+
 =back
 
 =head1 EXAMPLES
@@ -535,7 +559,7 @@ VMS have emulations for it.)
 Here is an example of using C<NVtime> from C:
 
   NV (*myNVtime)(); /* Returns -1 on failure. */
-  SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
+  SV **svp = hv_fetchs(PL_modglobal, "Time::NVtime", 0);
   if (!svp)         croak("Time::HiRes is required");
   if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
   myNVtime = INT2PTR(NV(*)(), SvIV(*svp));
@@ -586,9 +610,13 @@ might help in this (in case your system supports CLOCK_MONOTONIC).
 Some systems have APIs but not implementations: for example QNX and Haiku
 have the interval timer APIs but not the functionality.
 
-In OS X clock_getres(), clock_gettime() and clock_nanosleep() are
-emulated using the Mach timers; as a side effect of being emulated
-the CLOCK_REALTIME and CLOCK_MONOTONIC are the same timer.
+In pre-Sierra macOS (pre-10.12, OS X) clock_getres(), clock_gettime()
+and clock_nanosleep() are emulated using the Mach timers; as a side
+effect of being emulated the CLOCK_REALTIME and CLOCK_MONOTONIC are
+the same timer.
+
+gnukfreebsd seems to have non-functional futimens() and utimensat()
+(at least as of 10.1): therefore the hires utime() does not work.
 
 =head1 SEE ALSO
 
diff --git a/dist/Time-HiRes/HiRes.xs b/dist/Time-HiRes/HiRes.xs
index 38ca0dc..6b0dba8 100644
--- a/dist/Time-HiRes/HiRes.xs
+++ b/dist/Time-HiRes/HiRes.xs
@@ -87,6 +87,10 @@ extern "C" {
 #   undef ITIMER_REALPROF
 #endif
 
+#ifndef TIME_HIRES_CLOCKID_T
+typedef int clockid_t;
+#endif
+
 #if defined(TIME_HIRES_CLOCK_GETTIME) && defined(_STRUCT_ITIMERSPEC)
 
 /* HP-UX has CLOCK_XXX values but as enums, not as defines.
@@ -747,21 +751,33 @@ hrstatns(UV *atime_nsec, UV *mtime_nsec, UV *ctime_nsec)
 #endif /* !TIME_HIRES_STAT */
 }
 
-/* Until Apple implements clock_gettime() (ditto clock_getres())
- * we will emulate it using Mach interfaces. */
-#if defined(PERL_DARWIN) && !defined(CLOCK_REALTIME)
-
-#  include <mach/mach_time.h>
+/* Until Apple implements clock_gettime()
+ * (ditto clock_getres() and clock_nanosleep())
+ * we will emulate them using the Mach kernel interfaces. */
+#if defined(PERL_DARWIN) && \
+  (defined(TIME_HIRES_CLOCK_GETTIME_EMULATION)   || \
+   defined(TIME_HIRES_CLOCK_GETRES_EMULATION)    || \
+   defined(TIME_HIRES_CLOCK_NANOSLEEP_EMULATION))
 
+#ifndef CLOCK_REALTIME
 #  define CLOCK_REALTIME  0x01
 #  define CLOCK_MONOTONIC 0x02
+#endif
 
+#ifndef TIMER_ABSTIME
 #  define TIMER_ABSTIME   0x01
+#endif
 
 #ifdef USE_ITHREADS
+#  define PERL_DARWIN_MUTEX
+#endif
+
+#ifdef PERL_DARWIN_MUTEX
 STATIC perl_mutex darwin_time_mutex;
 #endif
 
+#include <mach/mach_time.h>
+
 static uint64_t absolute_time_init;
 static mach_timebase_info_data_t timebase_info;
 static struct timespec timespec_init;
@@ -769,7 +785,7 @@ static struct timespec timespec_init;
 static int darwin_time_init() {
   struct timeval tv;
   int success = 1;
-#ifdef USE_ITHREADS
+#ifdef PERL_DARWIN_MUTEX
   MUTEX_LOCK(&darwin_time_mutex);
 #endif
   if (absolute_time_init == 0) {
@@ -784,13 +800,14 @@ static int darwin_time_init() {
       }
     }
   }
-#ifdef USE_ITHREADS
+#ifdef PERL_DARWIN_MUTEX
   MUTEX_UNLOCK(&darwin_time_mutex);
 #endif
   return success;
 }
 
-static int clock_gettime(int clock_id, struct timespec *ts) {
+#ifdef TIME_HIRES_CLOCK_GETTIME_EMULATION
+static int th_clock_gettime(clockid_t clock_id, struct timespec *ts) {
   if (darwin_time_init() && timebase_info.denom) {
     switch (clock_id) {
       case CLOCK_REALTIME:
@@ -822,7 +839,12 @@ static int clock_gettime(int clock_id, struct timespec *ts) {
   return -1;
 }
 
-static int clock_getres(int clock_id, struct timespec *ts) {
+#define clock_gettime(clock_id, ts) th_clock_gettime((clock_id), (ts))
+
+#endif /* TIME_HIRES_CLOCK_GETTIME_EMULATION */
+
+#ifdef TIME_HIRES_CLOCK_GETRES_EMULATION
+static int th_clock_getres(clockid_t clock_id, struct timespec *ts) {
   if (darwin_time_init() && timebase_info.denom) {
     switch (clock_id) {
       case CLOCK_REALTIME:
@@ -842,7 +864,11 @@ static int clock_getres(int clock_id, struct timespec *ts) {
   return -1;
 }
 
-static int clock_nanosleep(int clock_id, int flags,
+#define clock_getres(clock_id, ts) th_clock_getres((clock_id), (ts))
+#endif /* TIME_HIRES_CLOCK_GETRES_EMULATION */
+
+#ifdef TIME_HIRES_CLOCK_NANOSLEEP_EMULATION
+static int th_clock_nanosleep(clockid_t clock_id, int flags,
 			   const struct timespec *rqtp,
 			   struct timespec *rmtp) {
   if (darwin_time_init()) {
@@ -880,6 +906,11 @@ static int clock_nanosleep(int clock_id, int flags,
   return -1;
 }
 
+#define clock_nanosleep(clock_id, flags, rqtp, rmtp) \
+  th_clock_nanosleep((clock_id), (flags), (rqtp), (rmtp))
+
+#endif /* TIME_HIRES_CLOCK_NANOSLEEP_EMULATION */
+
 #endif /* PERL_DARWIN */
 
 #include "const-c.inc"
@@ -921,6 +952,22 @@ nsec_without_unslept(struct timespec *sleepfor,
 
 #endif
 
+/* In case Perl and/or Devel::PPPort are too old, minimally emulate
+ * IS_SAFE_PATHNAME() (which looks for zero bytes in the pathname). */
+#ifndef IS_SAFE_PATHNAME
+#if PERL_VERSION >= 12 /* Perl_ck_warner is 5.10.0 -> */
+#ifdef WARN_SYSCALLS
+#define WARNEMUCAT WARN_SYSCALLS /* 5.22.0 -> */
+#else
+#define WARNEMUCAT WARN_MISC
+#endif
+#define WARNEMU(opname) Perl_ck_warner(aTHX_ packWARN(WARNEMUCAT), "Invalid \\0 character in pathname for %s",opname)
+#else
+#define WARNEMU(opname) Perl_warn(aTHX_ "Invalid \\0 character in pathname for %s",opname)
+#endif
+#define IS_SAFE_PATHNAME(pv, len, opname) (((len)>1)&&memchr((pv), 0, (len)-1)?(SETERRNO(ENOENT, LIB_INVARG),WARNEMU(opname),FALSE):(TRUE))
+#endif
+
 MODULE = Time::HiRes            PACKAGE = Time::HiRes
 
 PROTOTYPES: ENABLE
@@ -941,7 +988,7 @@ BOOT:
 #   endif
 #endif
 #if defined(PERL_DARWIN)
-#  ifdef USE_ITHREADS
+#  if defined(USE_ITHREADS) && defined(PERL_DARWIN_MUTEX)
   MUTEX_INIT(&darwin_time_mutex);
 #  endif
 #endif
@@ -978,7 +1025,8 @@ usleep(useconds)
 		    useconds -= NV_1E6 * seconds;
 		}
 	    } else if (useconds < 0.0)
-	        croak("Time::HiRes::usleep(%"NVgf"): negative time not invented yet", useconds);
+	        croak("Time::HiRes::usleep(%" NVgf
+                      "): negative time not invented yet", useconds);
 	    usleep((U32)useconds);
 	} else
 	    PerlProc_pause();
@@ -1000,7 +1048,8 @@ nanosleep(nsec)
 	struct timespec sleepfor, unslept;
 	CODE:
 	if (nsec < 0.0)
-	    croak("Time::HiRes::nanosleep(%"NVgf"): negative time not invented yet", nsec);
+	    croak("Time::HiRes::nanosleep(%" NVgf
+                  "): negative time not invented yet", nsec);
         nanosleep_init(nsec, &sleepfor, &unslept);
 	if (nanosleep(&sleepfor, &unslept) == 0) {
 	    RETVAL = nsec;
@@ -1045,11 +1094,15 @@ sleep(...)
 		   useconds = -(IV)useconds;
 #endif /* #if defined(__sparc64__) && defined(__GNUC__) */
 		   if ((IV)useconds < 0)
-		     croak("Time::HiRes::sleep(%"NVgf"): internal error: useconds < 0 (unsigned %"UVuf" signed %"IVdf")", seconds, useconds, (IV)useconds);
+		     croak("Time::HiRes::sleep(%" NVgf
+                           "): internal error: useconds < 0 (unsigned %" UVuf
+                           " signed %" IVdf ")",
+                           seconds, useconds, (IV)useconds);
 		 }
 		 usleep(useconds);
 	    } else
-	        croak("Time::HiRes::sleep(%"NVgf"): negative time not invented yet", seconds);
+	        croak("Time::HiRes::sleep(%" NVgf
+                      "): negative time not invented yet", seconds);
 	} else
 	    PerlProc_pause();
 	gettimeofday(&Tb, NULL);
@@ -1097,7 +1150,9 @@ ualarm(useconds,uinterval=0)
 	  }
 #else
 	if (useconds >= IV_1E6 || uinterval >= IV_1E6) 
-		croak("Time::HiRes::ualarm(%d, %d): useconds or uinterval equal to or more than %"IVdf, useconds, uinterval, IV_1E6);
+		croak("Time::HiRes::ualarm(%d, %d): useconds or uinterval"
+                      " equal to or more than %" IVdf,
+                      useconds, uinterval, IV_1E6);
 	RETVAL = ualarm(useconds, uinterval);
 #endif
 
@@ -1110,7 +1165,8 @@ alarm(seconds,interval=0)
 	NV interval
 	CODE:
 	if (seconds < 0.0 || interval < 0.0)
-	    croak("Time::HiRes::alarm(%"NVgf", %"NVgf"): negative time not invented yet", seconds, interval);
+	    croak("Time::HiRes::alarm(%" NVgf ", %" NVgf
+                  "): negative time not invented yet", seconds, interval);
 	{
 	  IV iseconds = (IV)seconds;
 	  IV iinterval = (IV)interval;
@@ -1118,7 +1174,9 @@ alarm(seconds,interval=0)
 	  NV finterval = interval - iinterval;
 	  IV useconds, uinterval;
 	  if (fseconds >= 1.0 || finterval >= 1.0)
-		croak("Time::HiRes::alarm(%"NVgf", %"NVgf"): seconds or interval too large to split correctly", seconds, interval);
+		croak("Time::HiRes::alarm(%" NVgf ", %" NVgf
+                      "): seconds or interval too large to split correctly",
+                      seconds, interval);
 	  useconds = IV_1E6 * fseconds;
 	  uinterval = IV_1E6 * finterval;
 #if defined(HAS_SETITIMER) && defined(ITIMER_REAL)
@@ -1138,7 +1196,9 @@ alarm(seconds,interval=0)
 	  }
 #else
 	  if (iseconds || iinterval)
-		croak("Time::HiRes::alarm(%"NVgf", %"NVgf"): seconds or interval equal to or more than 1.0 ", seconds, interval);
+		croak("Time::HiRes::alarm(%" NVgf ", %" NVgf
+                      "): seconds or interval equal to or more than 1.0 ",
+                      seconds, interval);
 	    RETVAL = (NV)ualarm( useconds, uinterval ) / NV_1E6;
 #endif
 	}
@@ -1266,7 +1326,9 @@ setitimer(which, seconds, interval = 0)
 	struct itimerval oldit;
     PPCODE:
 	if (seconds < 0.0 || interval < 0.0)
-	    croak("Time::HiRes::setitimer(%"IVdf", %"NVgf", %"NVgf"): negative time not invented yet", (IV)which, seconds, interval);
+	    croak("Time::HiRes::setitimer(%" IVdf ", %" NVgf ", %" NVgf
+                  "): negative time not invented yet",
+                  (IV)which, seconds, interval);
 	newit.it_value.tv_sec  = (IV)seconds;
 	newit.it_value.tv_usec =
 	  (IV)((seconds  - (NV)newit.it_value.tv_sec)    * NV_1E6);
@@ -1317,11 +1379,89 @@ getitimer(which)
 
 #endif /* #if defined(HAS_GETITIMER) && defined(HAS_SETITIMER) */
 
+#if defined(TIME_HIRES_UTIME)
+
+I32
+utime(accessed, modified, ...)
+PROTOTYPE: $$@
+    PREINIT:
+	SV* accessed;
+	SV* modified;
+	SV* file;
+
+	struct timespec utbuf[2];
+	struct timespec *utbufp = utbuf;
+	int tot;
+
+    CODE:
+	accessed = ST(0);
+	modified = ST(1);
+	items -= 2;
+	tot = 0;
+
+	if ( accessed == &PL_sv_undef && modified == &PL_sv_undef )
+		utbufp = NULL;
+	else {
+		if (SvNV(accessed) < 0.0 || SvNV(modified) < 0.0)
+                    croak("Time::HiRes::utime(%" NVgf ", %" NVgf
+                          "): negative time not invented yet",
+                              SvNV(accessed), SvNV(modified));
+		Zero(&utbuf, sizeof utbuf, char);
+		utbuf[0].tv_sec = (Time_t)SvNV(accessed);  /* time accessed */
+		utbuf[0].tv_nsec = (long)( ( SvNV(accessed) - utbuf[0].tv_sec ) * 1e9 );
+		utbuf[1].tv_sec = (Time_t)SvNV(modified);  /* time modified */
+		utbuf[1].tv_nsec = (long)( ( SvNV(modified) - utbuf[1].tv_sec ) * 1e9 );
+	}
+
+	while (items > 0) {
+		file = POPs; items--;
+
+		if (SvROK(file) && GvIO(SvRV(file)) && IoIFP(sv_2io(SvRV(file)))) {
+			int fd =  PerlIO_fileno(IoIFP(sv_2io(file)));
+			if (fd < 0)
+				SETERRNO(EBADF,RMS_IFI);
+			else 
+#ifdef HAS_FUTIMENS
+			if (futimens(fd, utbufp) == 0)
+				tot++;
+#else  /* HAS_FUTIMES */
+				croak("futimens unimplemented in this platform");
+#endif /* HAS_FUTIMES */
+		}
+		else {
+#ifdef HAS_UTIMENSAT
+			STRLEN len;
+			char * name = SvPV(file, len);
+			if (IS_SAFE_PATHNAME(name, len, "utime") &&
+			    utimensat(AT_FDCWD, name, utbufp, 0) == 0)
+				tot++;
+#else  /* HAS_UTIMENSAT */
+			croak("utimensat unimplemented in this platform");
+#endif /* HAS_UTIMENSAT */
+		}
+	} /* while items */
+	RETVAL = tot;
+
+    OUTPUT:
+	RETVAL
+
+#else  /* #if defined(TIME_HIRES_UTIME) */
+
+I32
+utime(accessed, modified, ...)
+    CODE:
+        croak("Time::HiRes::utime(): unimplemented in this platform");
+        RETVAL = 0;
+    OUTPUT:
+	RETVAL
+
+#endif /* #if defined(TIME_HIRES_UTIME) */
+
 #if defined(TIME_HIRES_CLOCK_GETTIME)
 
 NV
 clock_gettime(clock_id = CLOCK_REALTIME)
-	int clock_id
+	clockid_t clock_id
     PREINIT:
 	struct timespec ts;
 	int status = -1;
@@ -1340,7 +1480,7 @@ clock_gettime(clock_id = CLOCK_REALTIME)
 
 NV
 clock_gettime(clock_id = 0)
-	int clock_id
+	clockid_t clock_id
     CODE:
 	PERL_UNUSED_ARG(clock_id);
         croak("Time::HiRes::clock_gettime(): unimplemented in this platform");
@@ -1354,7 +1494,7 @@ clock_gettime(clock_id = 0)
 
 NV
 clock_getres(clock_id = CLOCK_REALTIME)
-	int clock_id
+	clockid_t clock_id
     PREINIT:
 	int status = -1;
 	struct timespec ts;
@@ -1373,7 +1513,7 @@ clock_getres(clock_id = CLOCK_REALTIME)
 
 NV
 clock_getres(clock_id = 0)
-	int clock_id
+	clockid_t clock_id
     CODE:
 	PERL_UNUSED_ARG(clock_id);
         croak("Time::HiRes::clock_getres(): unimplemented in this platform");
@@ -1387,14 +1527,15 @@ clock_getres(clock_id = 0)
 
 NV
 clock_nanosleep(clock_id, nsec, flags = 0)
-	int clock_id
+	clockid_t clock_id
 	NV  nsec
 	int flags
     PREINIT:
 	struct timespec sleepfor, unslept;
     CODE:
 	if (nsec < 0.0)
-	    croak("Time::HiRes::clock_nanosleep(..., %"NVgf"): negative time not invented yet", nsec);
+	    croak("Time::HiRes::clock_nanosleep(..., %" NVgf
+                  "): negative time not invented yet", nsec);
         nanosleep_init(nsec, &sleepfor, &unslept);
 	if (clock_nanosleep(clock_id, flags, &sleepfor, &unslept) == 0) {
 	    RETVAL = nsec;
@@ -1408,7 +1549,7 @@ clock_nanosleep(clock_id, nsec, flags = 0)
 
 NV
 clock_nanosleep(clock_id, nsec, flags = 0)
-	int clock_id
+	clockid_t clock_id
 	NV  nsec
 	int flags
     CODE:
diff --git a/dist/Time-HiRes/Makefile.PL b/dist/Time-HiRes/Makefile.PL
index 087ab79..9060fa2 100644
--- a/dist/Time-HiRes/Makefile.PL
+++ b/dist/Time-HiRes/Makefile.PL
@@ -290,6 +290,7 @@ sub has_clock_xxx_syscall {
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
+#include <time.h>
 #include <$SYSCALL_H>
 int main(int argc, char** argv)
 {
@@ -309,6 +310,7 @@ sub has_clock_xxx {
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
+#include <time.h>
 int main(int argc, char** argv)
 {
     struct timespec ts;
@@ -325,6 +327,7 @@ sub has_clock {
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
+#include <time.h>
 int main(int argc, char** argv)
 {
     clock_t tictoc;
@@ -348,12 +351,63 @@ int main(int argc, char** argv)
     struct timespec ts2;
     ts1.tv_sec  = 0;
     ts1.tv_nsec = 750000000;;
-    ret = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts1, &ts2);
+    /* All implementations are supposed to support CLOCK_REALTIME. */
+    ret = clock_nanosleep(CLOCK_REALTIME, 0, &ts1, &ts2);
+    ret == 0 ? exit(0) : exit(errno ? errno : -1);
+}
+EOM
+}
+
+sub has_futimens {
+    return 1 if
+    try_compile_and_link(<<EOM);
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include <sys/stat.h>
+int main(int argc, char** argv)
+{
+    int ret;
+    struct timespec ts[2];
+    ret = futimens(0, ts);
     ret == 0 ? exit(0) : exit(errno ? errno : -1);
 }
 EOM
 }
 
+sub has_utimensat{
+    return 1 if
+    try_compile_and_link(<<EOM);
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+int main(int argc, char** argv)
+{
+    int ret;
+    struct timespec ts[2];
+    ret = utimensat(AT_FDCWD, 0, ts, 0);
+    ret == 0 ? exit(0) : exit(errno ? errno : -1);
+}
+EOM
+}
+
+sub has_clockid_t{
+    return 1 if
+    try_compile_and_link(<<EOM);
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include <time.h>
+int main(int argc, char** argv)
+{
+    clockid_t id = CLOCK_REALTIME;
+    exit(id == CLOCK_REALTIME ? 1 : 0);
+}
+EOM
+}
+
 sub DEFINE {
     my ($def, $val) = @_;
     my $define = defined $val ? "$def=$val" : $def ;
@@ -534,6 +588,16 @@ EOD
         print "(It would not be portable anyway.)\n";
     }
 
+    print "Looking for clockid_t... ";
+    my $has_clockid_t;
+    if (has_clockid_t()) {
+	print "found.\n";
+        $has_clockid_t++;
+	$DEFINE .= ' -DTIME_HIRES_CLOCKID_T';
+    } else {
+	print "NOT found, will use int.\n";
+    }
+
     print "Looking for clock_gettime()... ";
     my $has_clock_gettime;
     my $has_clock_gettime_emulation;
@@ -548,7 +612,7 @@ EOD
     } elsif ($^O eq 'darwin') {
        $has_clock_gettime_emulation++;
        $has_clock_gettime++;
-       $DEFINE .= ' -DTIME_HIRES_CLOCK_GETTIME';
+       $DEFINE .= ' -DTIME_HIRES_CLOCK_GETTIME -DTIME_HIRES_CLOCK_GETTIME_EMULATION';
     }
 
     if ($has_clock_gettime) {
@@ -577,7 +641,7 @@ EOD
     } elsif ($^O eq 'darwin') {
        $has_clock_getres_emulation++;
        $has_clock_getres++;
-       $DEFINE .= ' -DTIME_HIRES_CLOCK_GETRES';
+       $DEFINE .= ' -DTIME_HIRES_CLOCK_GETRES -DTIME_HIRES_CLOCK_GETRES_EMULATION';
     }
 
     if ($has_clock_getres) {
@@ -603,7 +667,7 @@ EOD
     } elsif ($^O eq 'darwin') {
         $has_clock_nanosleep++;
         $has_clock_nanosleep_emulation++;
-	$DEFINE .= ' -DTIME_HIRES_CLOCK_NANOSLEEP';
+	$DEFINE .= ' -DTIME_HIRES_CLOCK_NANOSLEEP -DTIME_HIRES_CLOCK_NANOSLEEP_EMULATION';
     }
 
     if ($has_clock_nanosleep) {
@@ -631,6 +695,36 @@ EOD
 	print "NOT found.\n";
     }
 
+    print "Looking for futimens()... ";
+    my $has_futimens;
+    if (has_futimens()) {
+        $has_futimens++;
+	$DEFINE .= ' -DHAS_FUTIMENS';
+    }
+
+    if ($has_futimens) {
+        print "found.\n";
+    } else {
+	print "NOT found.\n";
+    }
+
+    print "Looking for utimensat()... ";
+    my $has_utimensat;
+    if (has_utimensat()) {
+        $has_utimensat++;
+	$DEFINE .= ' -DHAS_UTIMENSAT';
+    }
+
+    if ($has_utimensat) {
+        print "found.\n";
+    } else {
+	print "NOT found.\n";
+    }
+
+    if ($has_futimens or $has_utimensat) {
+	$DEFINE .= ' -DTIME_HIRES_UTIME';
+    }
+
     print "Looking for stat() subsecond timestamps...\n";
 
     print "Trying struct stat st_atimespec.tv_nsec...";
@@ -644,7 +738,7 @@ int main(int argc, char** argv) {
 }
 EOM
       $has_stat_st_xtimespec++;
-      DEFINE('TIME_HIRES_STAT', 1);
+      DEFINE('TIME_HIRES_STAT_ST_XTIMESPEC');  # 1
     }
 
     if ($has_stat_st_xtimespec) {
@@ -664,7 +758,7 @@ int main(int argc, char** argv) {
 }
 EOM
       $has_stat_st_xtimensec++;
-      DEFINE('TIME_HIRES_STAT', 2);
+      DEFINE('TIME_HIRES_STAT_ST_XTIMENSEC');  # 2
     }
 
     if ($has_stat_st_xtimensec) {
@@ -684,7 +778,7 @@ int main(int argc, char** argv) {
 }
 EOM
       $has_stat_st_xtime_n++;
-      DEFINE('TIME_HIRES_STAT', 3);
+      DEFINE('TIME_HIRES_STAT_ST_XTIME_N');  # 3
     }
 
     if ($has_stat_st_xtime_n) {
@@ -704,7 +798,7 @@ int main(int argc, char** argv) {
 }
 EOM
       $has_stat_st_xtim++;
-      DEFINE('TIME_HIRES_STAT', 4);
+      DEFINE('TIME_HIRES_STAT_XTIM');  # 4
     }
 
     if ($has_stat_st_xtim) {
@@ -724,7 +818,7 @@ int main(int argc, char** argv) {
 }
 EOM
       $has_stat_st_uxtime++;
-      DEFINE('TIME_HIRES_STAT', 5);
+      DEFINE('TIME_HIRES_STAT_ST_UXTIME');  # 5
     }
 
     if ($has_stat_st_uxtime) {
@@ -733,6 +827,19 @@ EOM
 	print "NOT found.\n";
     }
 
+    # See HiRes.xs hrstatns()
+    if ($has_stat_st_xtimespec) {
+        DEFINE('TIME_HIRES_STAT', 1);
+    } elsif ($has_stat_st_xtimensec) {
+        DEFINE('TIME_HIRES_STAT', 2);
+    } elsif ($has_stat_st_xtime_n) {
+        DEFINE('TIME_HIRES_STAT', 3);
+    } elsif ($has_stat_st_xtim) {
+        DEFINE('TIME_HIRES_STAT', 4);
+    } elsif ($has_stat_st_uxtime) {
+        DEFINE('TIME_HIRES_STAT', 5);
+    }    
+
    if ($DEFINE =~ /-DTIME_HIRES_STAT=\d+/) {
     print "You seem to have stat() subsecond timestamps.\n";
     print "(Your struct stat has them, but the filesystems must help.)\n";
@@ -791,7 +898,7 @@ sub doMakefile {
 	    'DynaLoader' => 0,
 	    'Exporter' => 0,
 	    'ExtUtils::MakeMaker' => 0,
-	    'Test::More' => "0.82",
+	    'Test::More' => 0,
 	    'strict' => 0,
 	},
 	'dist'      => {
@@ -869,7 +976,8 @@ sub doConstants {
                       );
 	foreach (qw (d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
 		     d_nanosleep d_clock_gettime d_clock_getres
-		     d_clock d_clock_nanosleep d_hires_stat)) {
+		     d_clock d_clock_nanosleep d_hires_stat
+                     d_futimens d_utimensat d_hires_utime)) {
 	    my $macro = $_;
 	    if ($macro =~ /^(d_nanosleep|d_clock)$/) {
 		$macro =~ s/^d_(.+)/TIME_HIRES_\U$1/;
@@ -879,6 +987,13 @@ sub doConstants {
 		push @names, {name => $_, macro => "TIME_HIRES_STAT", value => $d_hires_stat,
 			      default => ["IV", "0"]};
 		next;
+	    } elsif ($macro =~ /^(d_hires_utime)$/) {
+		my $d_hires_utime =
+                    ($DEFINE =~ /-DHAS_FUTIMENS/ ||
+                     $DEFINE =~ /-DHAS_UTIMENSAT/) ? 1 : 0;
+		push @names, {name => $_, macro => "TIME_HIRES_UTIME", value => $d_hires_utime,
+			      default => ["IV", "0"]};
+		next;
 	    } elsif ($macro =~ /^(d_clock_gettime|d_clock_getres|d_clock_nanosleep)$/) {
 		$macro =~ s/^d_(.+)/TIME_HIRES_\U$1/;
 		my $val = ($DEFINE =~ /-D$macro\b/) ? 1 : 0;
diff --git a/dist/Time-HiRes/fallback/const-c.inc b/dist/Time-HiRes/fallback/const-c.inc
index a862617..524db16 100644
--- a/dist/Time-HiRes/fallback/const-c.inc
+++ b/dist/Time-HiRes/fallback/const-c.inc
@@ -19,6 +19,7 @@ typedef double NV; /* 5.6 and later define NVTYPE, and typedef NV to it.  */
 #ifndef pTHX_
 #define pTHX_ /* 5.6 or later define this for threading support.  */
 #endif
+
 static int
 constant_11 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
@@ -87,6 +88,51 @@ constant_11 (pTHX_ const char *name, IV *iv_return) {
 }
 
 static int
+constant_13 (pTHX_ const char *name, IV *iv_return) {
+  /* When generated this function returned values for the list of names given
+     here.  However, subsequent manual editing may have added or removed some.
+     CLOCK_HIGHRES TIMER_ABSTIME d_hires_utime */
+  /* Offset 1 gives the best switch position.  */
+  switch (name[1]) {
+  case 'I':
+    if (memEQ(name, "TIMER_ABSTIME", 13)) {
+    /*                ^                  */
+#ifdef TIMER_ABSTIME
+      *iv_return = TIMER_ABSTIME;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case 'L':
+    if (memEQ(name, "CLOCK_HIGHRES", 13)) {
+    /*                ^                  */
+#ifdef CLOCK_HIGHRES
+      *iv_return = CLOCK_HIGHRES;
+      return PERL_constant_ISIV;
+#else
+      return PERL_constant_NOTDEF;
+#endif
+    }
+    break;
+  case '_':
+    if (memEQ(name, "d_hires_utime", 13)) {
+    /*                ^                  */
+#ifdef TIME_HIRES_UTIME
+      *iv_return = 1;
+      return PERL_constant_ISIV;
+#else
+      *iv_return = 0;
+      return PERL_constant_ISIV;
+#endif
+    }
+    break;
+  }
+  return PERL_constant_NOTFOUND;
+}
+
+static int
 constant_14 (pTHX_ const char *name, IV *iv_return) {
   /* When generated this function returned values for the list of names given
      here.  However, subsequent manual editing may have added or removed some.
@@ -250,16 +296,17 @@ my @names = (qw(CLOCKS_PER_SEC CLOCK_HIGHRES CLOCK_MONOTONIC
             {name=>"d_getitimer", type=>"IV", macro=>"HAS_GETITIMER", value=>"1", default=>["IV", "0"]},
             {name=>"d_gettimeofday", type=>"IV", macro=>"HAS_GETTIMEOFDAY", value=>"1", default=>["IV", "0"]},
             {name=>"d_hires_stat", type=>"IV", macro=>"TIME_HIRES_STAT", value=>"1", default=>["IV", "0"]},
+            {name=>"d_hires_utime", type=>"IV", macro=>"TIME_HIRES_UTIME", value=>"1", default=>["IV", "0"]},
             {name=>"d_nanosleep", type=>"IV", macro=>"TIME_HIRES_NANOSLEEP", value=>"1", default=>["IV", "0"]},
             {name=>"d_setitimer", type=>"IV", macro=>"HAS_SETITIMER", value=>"1", default=>["IV", "0"]},
             {name=>"d_ualarm", type=>"IV", macro=>"HAS_UALARM", value=>"1", default=>["IV", "0"]},
             {name=>"d_usleep", type=>"IV", macro=>"HAS_USLEEP", value=>"1", default=>["IV", "0"]});
 
-print constant_types(); # macro defs
+print constant_types(), "\n"; # macro defs
 foreach (C_constant ("Time::HiRes", 'constant', 'IV', $types, undef, 3, @names) ) {
     print $_, "\n"; # C constant subs
 }
-print "#### XS Section:\n";
+print "\n#### XS Section:\n";
 print XS_constant ("Time::HiRes", $types);
 __END__
    */
@@ -322,33 +369,7 @@ __END__
     }
     break;
   case 13:
-    /* Names all of length 13.  */
-    /* CLOCK_HIGHRES TIMER_ABSTIME */
-    /* Offset 2 gives the best switch position.  */
-    switch (name[2]) {
-    case 'M':
-      if (memEQ(name, "TIMER_ABSTIME", 13)) {
-      /*                 ^                 */
-#ifdef TIMER_ABSTIME
-        *iv_return = TIMER_ABSTIME;
-        return PERL_constant_ISIV;
-#else
-        return PERL_constant_NOTDEF;
-#endif
-      }
-      break;
-    case 'O':
-      if (memEQ(name, "CLOCK_HIGHRES", 13)) {
-      /*                 ^                 */
-#ifdef CLOCK_HIGHRES
-        *iv_return = CLOCK_HIGHRES;
-        return PERL_constant_ISIV;
-#else
-        return PERL_constant_NOTDEF;
-#endif
-      }
-      break;
-    }
+    return constant_13 (aTHX_ name, iv_return);
     break;
   case 14:
     return constant_14 (aTHX_ name, iv_return);
diff --git a/dist/Time-HiRes/t/Watchdog.pm b/dist/Time-HiRes/t/Watchdog.pm
index 83e8543..44ec808 100644
--- a/dist/Time-HiRes/t/Watchdog.pm
+++ b/dist/Time-HiRes/t/Watchdog.pm
@@ -10,44 +10,44 @@ my $watchdog_pid;
 my $TheEnd;
 
 if ($Config{d_fork}) {
-    note "I am the main process $$, starting the watchdog process...";
+    print("# I am the main process $$, starting the watchdog process...\n");
     $watchdog_pid = fork();
     if (defined $watchdog_pid) {
 	if ($watchdog_pid == 0) { # We are the kid, set up the watchdog.
 	    my $ppid = getppid();
-	    note "I am the watchdog process $$, sleeping for $waitfor seconds...";
+	    print("# I am the watchdog process $$, sleeping for $waitfor seconds...\n");
 	    sleep($waitfor - 2);    # Workaround for perlbug #49073
 	    sleep(2);               # Wait for parent to exit
 	    if (kill(0, $ppid)) {   # Check if parent still exists
 		warn "\n$0: overall time allowed for tests (${waitfor}s) exceeded!\n";
-		note "Terminating main process $ppid...";
+		print("Terminating main process $ppid...\n");
 		kill('KILL', $ppid);
-		note "This is the watchdog process $$, over and out.";
+		print("# This is the watchdog process $$, over and out.\n");
 	    }
 	    exit(0);
 	} else {
-	    note "The watchdog process $watchdog_pid launched, continuing testing...";
+	    print("# The watchdog process $watchdog_pid launched, continuing testing...\n");
 	    $TheEnd = time() + $waitfor;
 	}
     } else {
 	warn "$0: fork failed: $!\n";
     }
 } else {
-    note "No watchdog process (need fork)";
+    print("# No watchdog process (need fork)\n");
 }
 
 END {
     if ($watchdog_pid) { # Only in the main process.
 	my $left = $TheEnd - time();
-	note sprintf "I am the main process $$, terminating the watchdog process $watchdog_pid before it terminates me in %d seconds (testing took %d seconds).", $left, $waitfor - $left;
+	printf("# I am the main process $$, terminating the watchdog process $watchdog_pid before it terminates me in %d seconds (testing took %d seconds).\n", $left, $waitfor - $left);
 	if (kill(0, $watchdog_pid)) {
 	    local $? = 0;
 	    my $kill = kill('KILL', $watchdog_pid); # We are done, the watchdog can go.
 	    wait();
-	    note sprintf "kill KILL $watchdog_pid = %d", $kill;
+	    printf("# kill KILL $watchdog_pid = %d\n", $kill);
 	}
 	unlink("ktrace.out"); # Used in BSD system call tracing.
-	note "All done.";
+	print("# All done.\n");
     }
 }
 
diff --git a/dist/Time-HiRes/t/alarm.t b/dist/Time-HiRes/t/alarm.t
index 841694f..f600f99 100644
--- a/dist/Time-HiRes/t/alarm.t
+++ b/dist/Time-HiRes/t/alarm.t
@@ -1,6 +1,6 @@
 use strict;
 
-use Test::More 0.82 tests => 10;
+use Test::More tests => 10;
 use t::Watchdog;
 
 BEGIN { require_ok "Time::HiRes"; }
@@ -29,12 +29,14 @@ SKIP: {
 
     my ($r, $i, $not, $ok);
 
+    $not = "";
+
     $r = [Time::HiRes::gettimeofday()];
     $i = 5;
     my $oldaction;
     if ($use_sigaction) {
 	$oldaction = new POSIX::SigAction;
-	note sprintf "sigaction tick, ALRM = %d", &POSIX::SIGALRM;
+	printf("# sigaction tick, ALRM = %d\n", &POSIX::SIGALRM);
 
 	# Perl's deferred signals may be too wimpy to break through
 	# a restartable select(), so use POSIX::sigaction if available.
@@ -44,7 +46,7 @@ SKIP: {
 			 $oldaction)
 	    or die "Error setting SIGALRM handler with sigaction: $!\n";
     } else {
-	note "SIG tick";
+	print("# SIG tick\n");
 	$SIG{ALRM} = "tick";
     }
 
@@ -56,8 +58,8 @@ SKIP: {
 	    Time::HiRes::alarm(0.3);
 	    select (undef, undef, undef, 3);
 	    my $ival = Time::HiRes::tv_interval ($r);
-	    note "Select returned! $i $ival";
-	    note abs($ival/3 - 1);
+	    print("# Select returned! $i $ival\n");
+	    printf("# %s\n", abs($ival/3 - 1));
 	    # Whether select() gets restarted after signals is
 	    # implementation dependent.  If it is restarted, we
 	    # will get about 3.3 seconds: 3 from the select, 0.3
@@ -86,7 +88,7 @@ SKIP: {
     sub tick {
 	$i--;
 	my $ival = Time::HiRes::tv_interval ($r);
-	note "Tick! $i $ival";
+	print("# Tick! $i $ival\n");
 	my $exp = 0.3 * (5 - $i);
 	if ($exp == 0) {
 	    $not = "tick: divisor became zero";
@@ -106,8 +108,8 @@ SKIP: {
 	Time::HiRes::alarm(0); # can't cancel usig %SIG
     }
 
+    print("# $not\n");
     ok !$not;
-    note $not || $ok;
 }
 
 SKIP: {
@@ -126,7 +128,7 @@ SKIP: {
     # http://groups.google.com/group/perl.perl5.porters/browse_thread/thread/adaffaaf939b042e/20dafc298df737f0%2320dafc298df737f0?sa=X&oi=groupsr&start=0&num=3
     # Perl changes [18765] and [18770], perl bug [perl #20920]
 
-    note "Finding delay loop...";
+    print("# Finding delay loop...\n");
 
     my $T = 0.01;
     my $DelayN = 1024;
@@ -137,7 +139,7 @@ SKIP: {
 	 for ($i = 0; $i < $DelayN; $i++) { }
 	 my $t1 = Time::HiRes::time();
 	 my $dt = $t1 - $t0;
-	 note "N = $DelayN, t1 = $t1, t0 = $t0, dt = $dt";
+	 print("# N = $DelayN, t1 = $t1, t0 = $t0, dt = $dt\n");
 	 last N if $dt > $T;
 	 $DelayN *= 2;
      } while (1);
@@ -169,7 +171,7 @@ SKIP: {
 
     $SIG{ALRM} = sub {
 	$a++;
-	note "Alarm $a - ", Time::HiRes::time();
+	printf("# Alarm $a - %s\n", Time::HiRes::time());
 	Time::HiRes::alarm(0) if $a >= $A; # Disarm the alarm.
 	$Delay->(2); # Try burning CPU at least for 2T seconds.
     }; 
@@ -204,18 +206,18 @@ SKIP: {
 	my $alrm = 0;
 	$SIG{ALRM} = sub { $alrm++ };
 	my $got = Time::HiRes::alarm(2.7);
-	ok $got == 0 or note $got;
+	ok $got == 0 or print("# $got\n");
 
 	my $t0 = Time::HiRes::time();
 	1 while Time::HiRes::time() - $t0 <= 1;
 
 	$got = Time::HiRes::alarm(0);
-	ok $got > 0 && $got < 1.8 or note $got;
+	ok $got > 0 && $got < 1.8 or print("# $got\n");
 
-	ok $alrm == 0 or note $alrm;
+	ok $alrm == 0 or print("# $alrm\n");
 
 	$got = Time::HiRes::alarm(0);
-	ok $got == 0 or note $got;
+	ok $got == 0 or print("# $got\n");
     }
 }
 
diff --git a/dist/Time-HiRes/t/clock.t b/dist/Time-HiRes/t/clock.t
index 6d11dd2..346ca57 100644
--- a/dist/Time-HiRes/t/clock.t
+++ b/dist/Time-HiRes/t/clock.t
@@ -1,6 +1,6 @@
 use strict;
 
-use Test::More 0.82 tests => 5;
+use Test::More tests => 5;
 use t::Watchdog;
 
 BEGIN { require_ok "Time::HiRes"; }
@@ -13,10 +13,10 @@ sub has_symbol {
     return $@ eq '';
 }
 
-note sprintf "have_clock_gettime   = %d", &Time::HiRes::d_clock_gettime;
-note sprintf "have_clock_getres    = %d", &Time::HiRes::d_clock_getres;
-note sprintf "have_clock_nanosleep = %d", &Time::HiRes::d_clock_nanosleep;
-note sprintf "have_clock           = %d", &Time::HiRes::d_clock;
+printf("# have_clock_gettime   = %d\n", &Time::HiRes::d_clock_gettime);
+printf("# have_clock_getres    = %d\n", &Time::HiRes::d_clock_getres);
+printf("# have_clock_nanosleep = %d\n", &Time::HiRes::d_clock_nanosleep);
+printf("# have_clock           = %d\n", &Time::HiRes::d_clock);
 
 # Ideally, we'd like to test that the timers are rather precise.
 # However, if the system is busy, there are no guarantees on how
@@ -36,25 +36,25 @@ SKIP: {
     my $ok = 0;
  TRY: {
 	for my $try (1..3) {
-	    note "CLOCK_REALTIME: try = $try";
+	    print("# CLOCK_REALTIME: try = $try\n");
 	    my $t0 = Time::HiRes::clock_gettime(&CLOCK_REALTIME);
 	    my $T = 1.5;
 	    Time::HiRes::sleep($T);
 	    my $t1 = Time::HiRes::clock_gettime(&CLOCK_REALTIME);
 	    if ($t0 > 0 && $t1 > $t0) {
-		note "t1 = $t1, t0 = $t0";
+		print("# t1 = $t1, t0 = $t0\n");
 		my $dt = $t1 - $t0;
 		my $rt = abs(1 - $dt / $T);
-		note "dt = $dt, rt = $rt";
+		print("# dt = $dt, rt = $rt\n");
 		if ($rt <= 2 * $limit) {
 		    $ok = 1;
 		    last TRY;
 		}
 	    } else {
-		note "Error: t0 = $t0, t1 = $t1";
+		print("# Error: t0 = $t0, t1 = $t1\n");
 	    }
 	    my $r = rand() + rand();
-	    note sprintf "Sleeping for %.6f seconds...\n", $r;
+	    printf("# Sleeping for %.6f seconds...\n", $r);
 	    Time::HiRes::sleep($r);
 	}
     }
@@ -64,7 +64,7 @@ SKIP: {
 SKIP: {
     skip "no clock_getres", 1 unless &Time::HiRes::d_clock_getres;
     my $tr = Time::HiRes::clock_getres();
-    ok $tr > 0 or note "tr = $tr";
+    ok $tr > 0 or print("# tr = $tr\n");
 }
 
 SKIP: {
@@ -73,17 +73,17 @@ SKIP: {
     my $s = 1.5e9;
     my $t = Time::HiRes::clock_nanosleep(&CLOCK_REALTIME, $s);
     my $r = abs(1 - $t / $s);
-    ok $r < 2 * $limit or note "t = $t, r = $r";
+    ok $r < 2 * $limit or print("# t = $t, r = $r\n");
 }
 
 SKIP: {
     skip "no clock", 1 unless &Time::HiRes::d_clock;
     my @clock = Time::HiRes::clock();
-    note "clock = @clock";
+    print("# clock = @clock\n");
     for my $i (1..3) {
 	for (my $j = 0; $j < 1e6; $j++) { }
 	push @clock, Time::HiRes::clock();
-	note "clock = @clock";
+	print("# clock = @clock\n");
     }
     ok $clock[0] >= 0 &&
 	$clock[1] > $clock[0] &&
diff --git a/dist/Time-HiRes/t/gettimeofday.t b/dist/Time-HiRes/t/gettimeofday.t
index 8f7c5f3..69defe8 100644
--- a/dist/Time-HiRes/t/gettimeofday.t
+++ b/dist/Time-HiRes/t/gettimeofday.t
@@ -8,26 +8,26 @@ BEGIN {
     }
 }
 
-use Test::More 0.82 tests => 6;
+use Test::More tests => 6;
 use t::Watchdog;
 
 my @one = Time::HiRes::gettimeofday();
-note 'gettimeofday returned ', 0+@one, ' args';
+printf("# gettimeofday returned %d args\n", 0+@one);
 ok @one == 2;
-ok $one[0] > 850_000_000 or note "@one too small";
+ok $one[0] > 850_000_000 or print("# @one too small\n");
 
 sleep 1;
 
 my @two = Time::HiRes::gettimeofday();
 ok $two[0] > $one[0] || ($two[0] == $one[0] && $two[1] > $one[1])
-	or note "@two is not greater than @one";
+	or print("# @two is not greater than @one\n");
 
 my $f = Time::HiRes::time();
-ok $f > 850_000_000 or note "$f too small";
-ok $f - $two[0] < 2 or note "$f - $two[0] >= 2";
+ok $f > 850_000_000 or print("# $f too small\n");
+ok $f - $two[0] < 2 or print("# $f - $two[0] >= 2\n");
 
 my $r = [Time::HiRes::gettimeofday()];
 my $g = Time::HiRes::tv_interval $r;
-ok $g < 2 or note $g;
+ok $g < 2 or print("# $g\n");
 
 1;
diff --git a/dist/Time-HiRes/t/itimer.t b/dist/Time-HiRes/t/itimer.t
index 9eb2b93..31cdd67 100644
--- a/dist/Time-HiRes/t/itimer.t
+++ b/dist/Time-HiRes/t/itimer.t
@@ -25,7 +25,7 @@ BEGIN {
     }
 }
 
-use Test::More 0.82 tests => 2;
+use Test::More tests => 2;
 use t::Watchdog;
 
 my $limit = 0.25; # 25% is acceptable slosh for testing timers
@@ -35,11 +35,11 @@ my $r = [Time::HiRes::gettimeofday()];
 
 $SIG{VTALRM} = sub {
     $i ? $i-- : Time::HiRes::setitimer(&Time::HiRes::ITIMER_VIRTUAL, 0);
-    note "Tick! $i ", Time::HiRes::tv_interval($r);
+    printf("# Tick! $i %s\n", Time::HiRes::tv_interval($r));
 };	
 
-note "setitimer: ", join(" ",
-    Time::HiRes::setitimer(&Time::HiRes::ITIMER_VIRTUAL, 0.5, 0.4));
+printf("# setitimer: %s\n", join(" ",
+       Time::HiRes::setitimer(&Time::HiRes::ITIMER_VIRTUAL, 0.5, 0.4)));
 
 # Assume interval timer granularity of $limit * 0.5 seconds.  Too bold?
 my $virt = Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL);
@@ -47,19 +47,19 @@ ok(defined $virt && abs($virt / 0.5) - 1 < $limit,
    "ITIMER_VIRTUAL defined with sufficient granularity")
    or diag "virt=" . (defined $virt ? $virt : 'undef');
 
-note "getitimer: ", join(" ",
-    Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL));
+printf("# getitimer: %s\n", join(" ",
+       Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL)));
 
 while (Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL)) {
     my $j;
     for (1..1000) { $j++ } # Can't be unbreakable, must test getitimer().
 }
 
-note "getitimer: ", join(" ",
-    Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL));
+printf("# getitimer: %s\n", join(" ",
+       Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL)));
 
 $virt = Time::HiRes::getitimer(&Time::HiRes::ITIMER_VIRTUAL);
-note "at end, i=$i";
+print("# at end, i=$i\n");
 is($virt, 0, "time left should be zero");
 
 $SIG{VTALRM} = 'DEFAULT';
diff --git a/dist/Time-HiRes/t/nanosleep.t b/dist/Time-HiRes/t/nanosleep.t
index aef9db6..c17a7e4 100644
--- a/dist/Time-HiRes/t/nanosleep.t
+++ b/dist/Time-HiRes/t/nanosleep.t
@@ -8,7 +8,7 @@ BEGIN {
     }
 }
 
-use Test::More 0.82 tests => 3;
+use Test::More tests => 3;
 use t::Watchdog;
 
 eval { Time::HiRes::nanosleep(-5) };
@@ -21,7 +21,7 @@ my $two = CORE::time;
 Time::HiRes::nanosleep(10_000_000);
 my $three = CORE::time;
 ok $one == $two || $two == $three
-    or note "slept too long, $one $two $three";
+    or print("# slept too long, $one $two $three\n");
 
 SKIP: {
     skip "no gettimeofday", 1 unless &Time::HiRes::d_gettimeofday;
@@ -29,7 +29,7 @@ SKIP: {
     Time::HiRes::nanosleep(500_000_000);
     my $f2 = Time::HiRes::time();
     my $d = $f2 - $f;
-    ok $d > 0.4 && $d < 0.9 or note "slept $d secs $f to $f2";
+    ok $d > 0.4 && $d < 0.9 or print("# slept $d secs $f to $f2\n");
 }
 
 1;
diff --git a/dist/Time-HiRes/t/sleep.t b/dist/Time-HiRes/t/sleep.t
index e7cc627..c4d802b 100644
--- a/dist/Time-HiRes/t/sleep.t
+++ b/dist/Time-HiRes/t/sleep.t
@@ -1,6 +1,6 @@
 use strict;
 
-use Test::More 0.82 tests => 4;
+use Test::More tests => 4;
 use t::Watchdog;
 
 BEGIN { require_ok "Time::HiRes"; }
@@ -26,12 +26,12 @@ like $@, qr/::sleep\(-1\): negative time not invented yet/,
 SKIP: {
     skip "no subsecond alarm", 2 unless $can_subsecond_alarm;
     my $f = Time::HiRes::time; 
-    note "time...$f";
+    print("# time...$f\n");
     ok 1;
 
     my $r = [Time::HiRes::gettimeofday()];
     Time::HiRes::sleep (0.5);
-    note "sleep...", Time::HiRes::tv_interval($r);
+    printf("# sleep...%s\n", Time::HiRes::tv_interval($r));
     ok 1;
 }
 
diff --git a/dist/Time-HiRes/t/stat.t b/dist/Time-HiRes/t/stat.t
index 68a6fb6..e7552b5 100644
--- a/dist/Time-HiRes/t/stat.t
+++ b/dist/Time-HiRes/t/stat.t
@@ -13,7 +13,7 @@ BEGIN {
     }
 }
 
-use Test::More 0.82 tests => 43;
+use Test::More tests => 43;
 use t::Watchdog;
 
 my @atime;
@@ -42,8 +42,8 @@ for (1..5) {
     is_deeply $lstat, $stat;
 }
 1 while unlink $$;
-note "mtime = @mtime";
-note "atime = @atime";
+print("# mtime = @mtime\n");
+print("# atime = @atime\n");
 my $ai = 0;
 my $mi = 0;
 my $ss = 0;
@@ -63,7 +63,7 @@ for (my $i = 1; $i < @mtime; $i++) {
 	$ss++;
     }
 }
-note "ai = $ai, mi = $mi, ss = $ss";
+print("# ai = $ai, mi = $mi, ss = $ss\n");
 # Need at least 75% of monotonical increase and
 # 20% of subsecond results. Yes, this is guessing.
 SKIP: {
diff --git a/dist/Time-HiRes/t/time.t b/dist/Time-HiRes/t/time.t
index feec479..6f219f9 100644
--- a/dist/Time-HiRes/t/time.t
+++ b/dist/Time-HiRes/t/time.t
@@ -1,6 +1,6 @@
 use strict;
 
-use Test::More 0.82 tests => 2;
+use Test::More tests => 2;
 use t::Watchdog;
 
 BEGIN { require_ok "Time::HiRes"; }
@@ -16,8 +16,8 @@ SKIP: {
     # (CORE::time() may be rounding down, up, or closest),
     # but allow 10% of slop.
     ok abs($s) / $n <= 1.10
-	or note "Time::HiRes::time() not close to CORE::time()";
-    note "s = $s, n = $n, s/n = ", abs($s)/$n;
+	or print("# Time::HiRes::time() not close to CORE::time()\n");
+    printf("# s = $s, n = $n, s/n = %s\n", abs($s)/$n);
 }
 
 1;
diff --git a/dist/Time-HiRes/t/tv_interval.t b/dist/Time-HiRes/t/tv_interval.t
index bffcf39..8ac876d 100644
--- a/dist/Time-HiRes/t/tv_interval.t
+++ b/dist/Time-HiRes/t/tv_interval.t
@@ -1,10 +1,10 @@
 use strict;
 
-use Test::More 0.82 tests => 2;
+use Test::More tests => 2;
 
 BEGIN { require_ok "Time::HiRes"; }
 
 my $f = Time::HiRes::tv_interval [5, 100_000], [10, 500_000];
-ok abs($f - 5.4) < 0.001 or note $f;
+ok abs($f - 5.4) < 0.001 or print("# $f\n");
 
 1;
diff --git a/dist/Time-HiRes/t/ualarm.t b/dist/Time-HiRes/t/ualarm.t
index 12ef4b5..b50a175 100644
--- a/dist/Time-HiRes/t/ualarm.t
+++ b/dist/Time-HiRes/t/ualarm.t
@@ -8,7 +8,7 @@ BEGIN {
     }
 }
 
-use Test::More 0.82 tests => 12;
+use Test::More tests => 12;
 use t::Watchdog;
 
 use Config;
@@ -24,13 +24,13 @@ SKIP: {
     $tick = 0; Time::HiRes::ualarm(10_000); while ($tick == 0) { }
     my $three = CORE::time;
     ok $one == $two || $two == $three
-	or note "slept too long, $one $two $three";
-    note "tick = $tick, one = $one, two = $two, three = $three";
+	or print("# slept too long, $one $two $three\n");
+    print("# tick = $tick, one = $one, two = $two, three = $three\n");
 
     $tick = 0; Time::HiRes::ualarm(10_000, 10_000); while ($tick < 3) { }
     ok 1;
     Time::HiRes::ualarm(0);
-    note "tick = $tick, one = $one, two = $two, three = $three";
+    print("# tick = $tick, one = $one, two = $two, three = $three\n");
 }
 
 eval { Time::HiRes::ualarm(-4) };
@@ -59,24 +59,24 @@ for my $n (100_000, 1_100_000, 2_200_000, 4_300_000) {
 	my $alarmed = 0;
 	local $SIG{ ALRM } = sub { $alarmed++ };
 	my $t0 = Time::HiRes::time();
-	note "t0 = $t0";
-	note "ualarm($n)";
+	print("# t0 = $t0\n");
+	print("# ualarm($n)\n");
 	Time::HiRes::ualarm($n); 1 while $alarmed == 0;
 	my $t1 = Time::HiRes::time();
-	note "t1 = $t1";
+	print("# t1 = $t1\n");
 	my $dt = $t1 - $t0;
-	note "dt = $dt";
+	print("# dt = $dt\n");
 	my $r = $dt / ($n/1e6);
-	note "r = $r";
+	print("# r = $r\n");
 	$ok =
 	    ($n < 1_000_000 || # Too much noise.
 	     ($r >= 0.8 && $r <= 1.6));
 	last if $ok;
 	my $nap = bellish(3, 15);
-	note sprintf "Retrying in %.1f seconds...\n", $nap;
+	printf("# Retrying in %.1f seconds...\n", $nap);
 	Time::HiRes::sleep($nap);
     }
-    ok $ok or note "ualarm($n) close enough";
+    ok $ok or print("# ualarm($n) close enough\n");
 }
 
 {
@@ -93,12 +93,12 @@ for my $n (100_000, 1_100_000, 2_200_000, 4_300_000) {
     } while $t1 - $t0 <= 0.3;
     my $got1 = Time::HiRes::ualarm(0);
 
-    note "t0 = $t0";
-    note "got0 = $got0";
-    note "t1 = $t1";
-    note "t1 - t0 = ", ($t1 - $t0);
-    note "got1 = $got1";
-    ok $got0 == 0 or note $got0;
+    print("# t0 = $t0\n");
+    print("# got0 = $got0\n");
+    print("# t1 = $t1\n");
+    printf("# t1 - t0 = %s\n", ($t1 - $t0));
+    print("# got1 = $got1\n");
+    ok $got0 == 0 or print("# $got0\n");
     SKIP: {
 	skip "alarm interval exceeded", 2 if $t1 - $t0 >= 0.5;
 	ok $got1 > 0;
@@ -106,7 +106,7 @@ for my $n (100_000, 1_100_000, 2_200_000, 4_300_000) {
     }
     ok $got1 < 300_000;
     my $got2 = Time::HiRes::ualarm(0);
-    ok $got2 == 0 or note $got2;
+    ok $got2 == 0 or print("# $got2\n");
 }
 
 1;
diff --git a/dist/Time-HiRes/t/usleep.t b/dist/Time-HiRes/t/usleep.t
index 0d6bacf..bdf372b 100644
--- a/dist/Time-HiRes/t/usleep.t
+++ b/dist/Time-HiRes/t/usleep.t
@@ -8,7 +8,7 @@ BEGIN {
     }
 }
 
-use Test::More 0.82 tests => 6;
+use Test::More tests => 6;
 use t::Watchdog;
 
 eval { Time::HiRes::usleep(-2) };
@@ -23,7 +23,7 @@ my $two = CORE::time;
 Time::HiRes::usleep(10_000);
 my $three = CORE::time;
 ok $one == $two || $two == $three
-or note "slept too long, $one $two $three";
+or print("# slept too long, $one $two $three\n");
 
 SKIP: {
     skip "no gettimeofday", 1 unless &Time::HiRes::d_gettimeofday;
@@ -31,7 +31,7 @@ SKIP: {
     Time::HiRes::usleep(500_000);
     my $f2 = Time::HiRes::time();
     my $d = $f2 - $f;
-    ok $d > 0.4 && $d < 0.9 or note "slept $d secs $f to $f2";
+    ok $d > 0.4 && $d < 0.9 or print("# slept $d secs $f to $f2\n");
 }
 
 SKIP: {
@@ -39,7 +39,7 @@ SKIP: {
     my $r = [ Time::HiRes::gettimeofday() ];
     Time::HiRes::sleep( 0.5 );
     my $f = Time::HiRes::tv_interval $r;
-    ok $f > 0.4 && $f < 0.9 or note "slept $f instead of 0.5 secs.";
+    ok $f > 0.4 && $f < 0.9 or print("# slept $f instead of 0.5 secs.\n");
 }
 
 SKIP: {
@@ -59,7 +59,7 @@ SKIP: {
 
     SKIP: {
 	skip $msg, 1 unless $td < $sleep * (1 + $limit);
-	ok $a < $limit or note $msg;
+	ok $a < $limit or print("# $msg\n");
     }
 
     $t0 = Time::HiRes::gettimeofday();
@@ -71,7 +71,7 @@ SKIP: {
 
     SKIP: {
 	skip $msg, 1 unless $td < $sleep * (1 + $limit);
-	ok $a < $limit or note $msg;
+	ok $a < $limit or print("# $msg\n");
     }
 }
 
diff --git a/dist/Time-HiRes/t/utime.t b/dist/Time-HiRes/t/utime.t
new file mode 100644
index 0000000..e64f99b
--- /dev/null
+++ b/dist/Time-HiRes/t/utime.t
@@ -0,0 +1,138 @@
+use strict;
+
+BEGIN {
+    require Time::HiRes;
+    require Test::More;
+    require File::Temp;
+    unless(&Time::HiRes::d_hires_utime) {
+	Test::More::plan(skip_all => "no hires_utime");
+    }
+    unless (&Time::HiRes::d_futimens) {
+	Test::More::plan(skip_all => "no futimens()");
+    }
+    unless (&Time::HiRes::d_utimensat) {
+	Test::More::plan(skip_all => "no utimensat()");
+    }
+    if ($^O eq 'gnukfreebsd') {
+	Test::More::plan(skip_all => "futimens() and utimensat() not working in $^O");
+    }
+    if ($^O eq 'linux' && -e '/proc/mounts') {
+        # The linux might be wrong when ext3
+        # is available in other operating systems,
+        # but then we need other methods for detecting
+        # the filesystem type of the tempfiles.
+        my ($fh, $fn) = File::Temp::tempfile( "Time-HiRes-utime-XXXXXXXXX", UNLINK => 1);
+        sub getfstype {
+            my ($fn) = @_;
+            my $cmd = "df $fn";
+            open(my $df, "$cmd |") or die "$cmd: $!";
+             my @df = <$df>;  # Assume $df[0] is header line.
+             my $dev = +(split(" ", $df[1]))[0];
+             open(my $mounts, "/proc/mounts") or die "/proc/mounts: $!";
+             while (<$mounts>) {
+                 my @m = split(" ");
+                 if ($m[0] eq $dev) { return $m[2] }
+             }
+             return;
+          }
+          my $fstype = getfstype($fn);
+          unless (defined $fstype) {
+              warn "Unknown fstype for $fn\n";
+          } else {
+              print "# fstype = $fstype\n";
+              if ($fstype eq 'ext3' || $fstype eq 'ext2') {
+                  Test::More::plan(skip_all => "fstype $fstype has no subsecond timestamps in $^O");
+            }
+        }
+    }
+}
+
+use Test::More tests => 18;
+use t::Watchdog;
+use File::Temp qw( tempfile );
+
+use Config;
+
+# Hope initially for nanosecond accuracy.
+my $atime = 1.111111111;
+my $mtime = 2.222222222;
+
+if ($^O eq 'cygwin') {
+   # Cygwin timestamps have less precision.
+   $atime = 1.1111111;
+   $mtime = 2.2222222;
+}
+print "# \$^O = $^O, atime = $atime, mtime = $mtime\n";
+
+print "# utime \$fh\n";
+{
+	my ($fh, $filename) = tempfile( "Time-HiRes-utime-XXXXXXXXX", UNLINK => 1 );
+	is Time::HiRes::utime($atime, $mtime, $fh), 1, "One file changed";
+	my ($got_atime, $got_mtime) = ( Time::HiRes::stat($filename) )[8, 9];
+	is $got_atime, $atime, "atime set correctly";
+	is $got_mtime, $mtime, "mtime set correctly";
+};
+
+print "#utime \$filename\n";
+{
+	my ($fh, $filename) = tempfile( "Time-HiRes-utime-XXXXXXXXX", UNLINK => 1 );
+	is Time::HiRes::utime($atime, $mtime, $filename), 1, "One file changed";
+	my ($got_atime, $got_mtime) = ( Time::HiRes::stat($fh) )[8, 9];
+	is $got_atime, $atime, "atime set correctly";
+	is $got_mtime, $mtime, "mtime set correctly";
+};
+
+print "utime \$filename and \$fh\n";
+{
+	my ($fh1, $filename1) = tempfile( "Time-HiRes-utime-XXXXXXXXX", UNLINK => 1 );
+	my ($fh2, $filename2) = tempfile( "Time-HiRes-utime-XXXXXXXXX", UNLINK => 1 );
+	is Time::HiRes::utime($atime, $mtime, $filename1, $fh2), 2, "Two files changed";
+	{
+		my ($got_atime, $got_mtime) = ( Time::HiRes::stat($fh1) )[8, 9];
+		is $got_atime, $atime, "File 1 atime set correctly";
+		is $got_mtime, $mtime, "File 1 mtime set correctly";
+	}
+	{
+		my ($got_atime, $got_mtime) = ( Time::HiRes::stat($filename2) )[8, 9];
+		is $got_atime, $atime, "File 2 atime set correctly";
+		is $got_mtime, $mtime, "File 2 mtime set correctly";
+	}
+};
+
+print "# utime undef sets time to now\n";
+{
+	my ($fh1, $filename1) = tempfile( "Time-HiRes-utime-XXXXXXXXX", UNLINK => 1 );
+	my ($fh2, $filename2) = tempfile( "Time-HiRes-utime-XXXXXXXXX", UNLINK => 1 );
+
+	my $now = Time::HiRes::time;
+	is Time::HiRes::utime(undef, undef, $filename1, $fh2), 2, "Two files changed";
+
+	{
+		my ($got_atime, $got_mtime) = ( Time::HiRes::stat($fh1) )[8, 9];
+		cmp_ok abs( $got_atime - $now), '<', 0.1, "File 1 atime set correctly";
+		cmp_ok abs( $got_mtime - $now), '<', 0.1, "File 1 mtime set correctly";
+	}
+	{
+		my ($got_atime, $got_mtime) = ( Time::HiRes::stat($filename2) )[8, 9];
+		cmp_ok abs( $got_atime - $now), '<', 0.1, "File 2 atime set correctly";
+		cmp_ok abs( $got_mtime - $now), '<', 0.1, "File 2 mtime set correctly";
+	}
+};
+
+print "# negative atime dies\n";
+{
+	eval { Time::HiRes::utime(-4, $mtime) };
+	like $@, qr/::utime\(-4, 2\.22222\): negative time not invented yet/,
+		"negative time error";
+};
+
+print "# negative mtime dies;\n";
+{
+	eval { Time::HiRes::utime($atime, -4) };
+	like $@, qr/::utime\(1.11111, -4\): negative time not invented yet/,
+		"negative time error";
+};
+
+done_testing;
+
+1;
diff --git a/dist/Time-HiRes/typemap b/dist/Time-HiRes/typemap
index 1124eb6..3fa91f3 100644
--- a/dist/Time-HiRes/typemap
+++ b/dist/Time-HiRes/typemap
@@ -28,6 +28,8 @@ AV *			T_AVREF
 HV *			T_HVREF
 CV *			T_CVREF
 
+clockid_t               T_IV
+
 IV			T_IV
 UV			T_UV
 NV                      T_NV
-- 
2.10.1 (Apple Git-78)

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2017

From @wolfsage

On Thu, Dec 29, 2016 at 6​:07 PM, Craig A. Berry <craig.a.berry@​gmail.com> wrote​:

I've attached a patch that updates maint-5.24 to the current CPAN
release of Tiime​::HiRes and can confirm that this gets all tests
passing on macOS Sierra.

ether said in #p5p that she was unable to build 5.24.2 because of this issue.

I checked and it does not appear that this (or any upgrade to
Time​::HiRes) made it into 5.24.2, so people will have trouble
installing it on this OS.

Do we need another point release for 5.24.* to fix this..?

-- Matthew Horsfall (alh)

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2017

From @craigberry

On Fri, Jul 21, 2017 at 2​:12 PM, Matthew Horsfall (alh)
<wolfsage@​gmail.com> wrote​:

On Thu, Dec 29, 2016 at 6​:07 PM, Craig A. Berry <craig.a.berry@​gmail.com> wrote​:

I've attached a patch that updates maint-5.24 to the current CPAN
release of Tiime​::HiRes and can confirm that this gets all tests
passing on macOS Sierra.

ether said in #p5p that she was unable to build 5.24.2 because of this issue.

I checked and it does not appear that this (or any upgrade to
Time​::HiRes) made it into 5.24.2, so people will have trouble
installing it on this OS.

Do we need another point release for 5.24.* to fix this..?

5.24.2 was limited to the base.pm fixes. So yes, this will not be
fixed unless it gets into the next maint-5.24 release. I have voted
for my own patch​:

<https://perl5.git.perl.org/perl.git/commitdiff/63784e26bef8426a67e8780734da0d0e7a9d052b>

It needs one more vote. Perhaps the only wrinkle now is whether it
should get 1.9742 rather than 1.9741.

@p5pRT
Copy link
Author

p5pRT commented Jul 21, 2017

From @wolfsage

On Jul 21, 2017, at 7​:47 PM, Craig A. Berry <craig.a.berry@​gmail.com> wrote​:

On Fri, Jul 21, 2017 at 2​:12 PM, Matthew Horsfall (alh)
<wolfsage@​gmail.com> wrote​:

On Thu, Dec 29, 2016 at 6​:07 PM, Craig A. Berry <craig.a.berry@​gmail.com> wrote​:

I've attached a patch that updates maint-5.24 to the current CPAN
release of Tiime​::HiRes and can confirm that this gets all tests
passing on macOS Sierra.

ether said in #p5p that she was unable to build 5.24.2 because of this issue.

I checked and it does not appear that this (or any upgrade to
Time​::HiRes) made it into 5.24.2, so people will have trouble
installing it on this OS.

Do we need another point release for 5.24.* to fix this..?

5.24.2 was limited to the base.pm fixes. So yes, this will not be
fixed unless it gets into the next maint-5.24 release. I have voted
for my own patch​:

<https://perl5.git.perl.org/perl.git/commitdiff/63784e26bef8426a67e8780734da0d0e7a9d052b>

It needs one more vote. Perhaps the only wrinkle now is whether it
should get 1.9742 rather than 1.9741.

+1 from me, thanks.

-- Matthew Horsfall (alh)

@p5pRT
Copy link
Author

p5pRT commented Jul 23, 2017

From @xsawyerx

On 07/22/2017 01​:57 AM, wolfsage@​gmail.com wrote​:

On Jul 21, 2017, at 7​:47 PM, Craig A. Berry <craig.a.berry@​gmail.com> wrote​:

On Fri, Jul 21, 2017 at 2​:12 PM, Matthew Horsfall (alh)
<wolfsage@​gmail.com> wrote​:

On Thu, Dec 29, 2016 at 6​:07 PM, Craig A. Berry <craig.a.berry@​gmail.com> wrote​:

I've attached a patch that updates maint-5.24 to the current CPAN
release of Tiime​::HiRes and can confirm that this gets all tests
passing on macOS Sierra.

ether said in #p5p that she was unable to build 5.24.2 because of this issue.

I checked and it does not appear that this (or any upgrade to
Time​::HiRes) made it into 5.24.2, so people will have trouble
installing it on this OS.

Do we need another point release for 5.24.* to fix this..?
5.24.2 was limited to the base.pm fixes. So yes, this will not be
fixed unless it gets into the next maint-5.24 release. I have voted
for my own patch​:

<https://perl5.git.perl.org/perl.git/commitdiff/63784e26bef8426a67e8780734da0d0e7a9d052b>

It needs one more vote. Perhaps the only wrinkle now is whether it
should get 1.9742 rather than 1.9741.
+1 from me, thanks.

From me as well. Reflected here​:
https://perl5.git.perl.org/perl.git/commitdiff/31e0d510bd365f1c040cd8bdcb00065ff67f02d5.

@p5pRT
Copy link
Author

p5pRT commented Jul 24, 2017

From @steve-m-hay

On 23 July 2017 at 19​:42, Sawyer X <xsawyerx@​gmail.com> wrote​:

On 07/22/2017 01​:57 AM, wolfsage@​gmail.com wrote​:

On Jul 21, 2017, at 7​:47 PM, Craig A. Berry <craig.a.berry@​gmail.com> wrote​:

On Fri, Jul 21, 2017 at 2​:12 PM, Matthew Horsfall (alh)
<wolfsage@​gmail.com> wrote​:

On Thu, Dec 29, 2016 at 6​:07 PM, Craig A. Berry <craig.a.berry@​gmail.com> wrote​:

I've attached a patch that updates maint-5.24 to the current CPAN
release of Tiime​::HiRes and can confirm that this gets all tests
passing on macOS Sierra.

ether said in #p5p that she was unable to build 5.24.2 because of this issue.

I checked and it does not appear that this (or any upgrade to
Time​::HiRes) made it into 5.24.2, so people will have trouble
installing it on this OS.

Do we need another point release for 5.24.* to fix this..?
5.24.2 was limited to the base.pm fixes. So yes, this will not be
fixed unless it gets into the next maint-5.24 release. I have voted
for my own patch​:

<https://perl5.git.perl.org/perl.git/commitdiff/63784e26bef8426a67e8780734da0d0e7a9d052b>

It needs one more vote. Perhaps the only wrinkle now is whether it
should get 1.9742 rather than 1.9741.
+1 from me, thanks.

From me as well. Reflected here​:
https://perl5.git.perl.org/perl.git/commitdiff/31e0d510bd365f1c040cd8bdcb00065ff67f02d5.

I'm happy to take Craig's patch to update to 1.9741 for 5.24.3. Are
the extra changes in 1.9742 safe & worthwhile? It looks like 'yes' on
both fronts to me, but should I be concerned about the entirely red
column ('gnu') here?​:
http​://matrix.cpantesters.org/?dist=Time-HiRes+1.9742

@p5pRT
Copy link
Author

p5pRT commented Aug 8, 2017

From @steve-m-hay

On Mon, 24 Jul 2017 13​:17​:04 -0700, shay wrote​:

On 23 July 2017 at 19​:42, Sawyer X <xsawyerx@​gmail.com> wrote​:

On 07/22/2017 01​:57 AM, wolfsage@​gmail.com wrote​:

On Jul 21, 2017, at 7​:47 PM, Craig A. Berry
<craig.a.berry@​gmail.com> wrote​:

On Fri, Jul 21, 2017 at 2​:12 PM, Matthew Horsfall (alh)
<wolfsage@​gmail.com> wrote​:

On Thu, Dec 29, 2016 at 6​:07 PM, Craig A. Berry
<craig.a.berry@​gmail.com> wrote​:

I've attached a patch that updates maint-5.24 to the current CPAN
release of Tiime​::HiRes and can confirm that this gets all tests
passing on macOS Sierra.

ether said in #p5p that she was unable to build 5.24.2 because of
this issue.

I checked and it does not appear that this (or any upgrade to
Time​::HiRes) made it into 5.24.2, so people will have trouble
installing it on this OS.

Do we need another point release for 5.24.* to fix this..?
5.24.2 was limited to the base.pm fixes. So yes, this will not be
fixed unless it gets into the next maint-5.24 release. I have
voted
for my own patch​:

<https://perl5.git.perl.org/perl.git/commitdiff/63784e26bef8426a67e8780734da0d0e7a9d052b>

It needs one more vote. Perhaps the only wrinkle now is whether it
should get 1.9742 rather than 1.9741.
+1 from me, thanks.

From me as well. Reflected here​:
https://perl5.git.perl.org/perl.git/commitdiff/31e0d510bd365f1c040cd8bdcb00065ff67f02d5.

I'm happy to take Craig's patch to update to 1.9741 for 5.24.3. Are
the extra changes in 1.9742 safe & worthwhile? It looks like 'yes' on
both fronts to me, but should I be concerned about the entirely red
column ('gnu') here?​:
http​://matrix.cpantesters.org/?dist=Time-HiRes+1.9742

I've now pulled 1.9741 into maint-5.24, ready for perl-5.24.3. I didn't take 1.9742 (or 1.9744, which has since arrived as well!) because maint-5.26 currently has 1.9741 and I didn't like the idea of an upgrade from perl-5.24 to perl-5.26 rolling back to an older Time-HiRes (and there is no pressing need to upgrade Time-HiRes in perl-5.26 as far as I know).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants