Hi Collin,

Let me add some context. A few months ago mingw-w64 added support for POSIX 
macros _FILE_BITS and _TIME_BITS.

Some winpthreads' functions are using `struct timespec` but they were not 
handling _TIME_BITS macro. This could result in situations when winpthreads' 
functions would be compiled with 32-bit time_t but used with 64-bit time_t 
(with _TIME_BITS=64). This would produce incorrect results.

I wrote _TIME_BITS handling for winpthreads. We added explicit 32-bit and 
64-bit versions for functions which use `struct timespec` (e.g. nonosleep32 and 
nanosleep64), previously there was only external nanosleep. In order to avoid 
breaking existing binaries, we still provide external nanosleep.

Keep in mind that while winpthreads is part of mingw runtime, it can be built 
and used with MSVC. With gcc/clang we could simply use inline assembly to 
rename the symbols, but this would not work with MSVC. The remaining options 
were to define macros like

```
#if _TIME_BITS == 64
#define nanosleep nanosleep64
#else
#define nanosleep nanosleep32
#endif
```

or using inline wrappers which call explicitly sized version. I choose the 
latter.

You may notice WINPTHREAD_NANOSLEEP_DECL macro in declaration of nanosleep and 
other functions. When building the library, it defines nanosleep as external 
function. When header files used by the client code, it defines it as (static, 
in C) inline wrapper.

Since winpthreads' header files define nanosleep as inline function, it 
prevents gnulib from overriding it.

I would like to fix this in winpthreads, I'm just not sure how this can be 
achieved taking MSVC into account.

- Kirill Makurin
________________________________
From: [email protected] 
<[email protected]> on behalf of Jeffrey 
Walton <[email protected]>
Sent: Sunday, November 16, 2025 12:42 PM
To: Collin Funk <[email protected]>
Cc: [email protected] <[email protected]>; [email protected] 
<[email protected]>; Bruno Haible <[email protected]>
Subject: Re: nanosleep: Avoid a redefinition on MinGW.

On Sat, Nov 15, 2025 at 10:22 PM Collin Funk <[email protected]> wrote:
>
> Using the reproduction steps Tim shared [1], this patch fixes the
> redeclaration on MinGW:
>
>     depbase=`echo nanosleep.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
>     x86_64-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I..  
> -DGNULIB_STRICT_CHECKING=1   -g -O2 -MT nanosleep.o -MD -MP -MF $depbase.Tpo 
> -c -o nanosleep.o nanosleep.c &&\
>     mv -f $depbase.Tpo $depbase.Po
>     nanosleep.c:97:1: error: redefinition of 'nanosleep'
>        97 | nanosleep (const struct timespec *requested_delay,
>           | ^~~~~~~~~
>     In file included from /usr/share/mingw-w64/include/time.h:323,
>                      from ./time.h:54,
>                      from nanosleep.c:23:
>     /usr/share/mingw-w64/include/pthread_time.h:79:39: note: previous 
> definition of 'nanosleep' with type 'int(const struct timespec *, struct 
> timespec *)'
>        79 | WINPTHREAD_NANOSLEEP_DECL int __cdecl nanosleep(const struct 
> timespec *request, struct timespec *remain)
>           |                                       ^~~~~~~~~
>     make[4]: *** [Makefile:2248: nanosleep.o] Error 1
>
> I left the cross guess as "no" so the function gets replaced. This is
> because MinGW does not use QueryPerformanceCounter, so I assume that
> does not work as well for small durations [2].

QueryPerformanceCounter is not monotonically increasing in practice.
Time can appear to run backwards if subsequent QueryPerformanceCounter
is run on a different core.  See
<https://stackoverflow.com/questions/27419223/time-running-backwards-with-queryperformancecounter>.

> I'm not sure if that is correct and/or if it should be documented. So I
> will hold off pushing for review.
>
> [1] https://savannah.gnu.org/bugs/?67704
> [2] 
> https://github.com/mingw-w64/mingw-w64/blob/master/mingw-w64-libraries/winpthreads/src/nanosleep.c

Jeff

Reply via email to