Discussion:
No thread safety in clock_gettime (hires_ns::prime)
(too old to reply)
James E. King III
2018-11-23 16:27:37 UTC
Permalink
Using 32-bit cygwin that I set up yesterday. I found that a call to
clock_gettime(CLOCK_MONOTONIC, ..) has a one-time initialization that
is not thread-safe. If two threads call this at the same time, they
will race. The results I am seeing are typically that one of the two
callers get a timespec structure with zero values, and no error return
code from the call.

I prepared a small test that exposes this issue. Given it is a race
condition, you have to run the test in a loop for it to happen. I
have attached the Makefile and source code. If you run "make test" it
will expose the issue:

$ make test
cc -c -o cyg_hires_clock_race.o cyg_hires_clock_race.c
cc cyg_hires_clock_race.o -o cyg_hires_clock_race
ERROR: one of the timespec structures was zero:
main thread: tv_sec = 356242 tv_nsec = 376075900
2nd thread: tv_sec = 0 tv_nsec = 0
ERROR: one of the timespec structures was zero:
main thread: tv_sec = 356242 tv_nsec = 519016800
2nd thread: tv_sec = 0 tv_nsec = 0
ERROR: one of the timespec structures was zero:
main thread: tv_sec = 356242 tv_nsec = 734794100
2nd thread: tv_sec = 0 tv_nsec = 0
ERROR: one of the timespec structures was zero:
main thread: tv_sec = 356243 tv_nsec = 463632400
2nd thread: tv_sec = 0 tv_nsec = 0
make: *** [Makefile:6: test] Error 1

Relevant cygwin version information:

Cygwin DLL version info:
DLL version: 2.11.2
DLL epoch: 19
DLL old termios: 5
DLL malloc env: 28
Cygwin conv: 181
API major: 0
API minor: 329
Shared data: 5
DLL identifier: cygwin1
Mount registry: 3
Cygwin registry name: Cygwin
Installations name: Installations
Cygdrive default prefix:
Build date:
Shared id: cygwin1S5
Corinna Vinschen
2018-11-26 17:01:40 UTC
Permalink
Post by James E. King III
Using 32-bit cygwin that I set up yesterday.
Don't do that. Use 64 bit Cygwin whenever possible. 32 bit is a lost
cause.
Post by James E. King III
I found that a call to
clock_gettime(CLOCK_MONOTONIC, ..) has a one-time initialization that
is not thread-safe. If two threads call this at the same time, they
will race. The results I am seeing are typically that one of the two
callers get a timespec structure with zero values, and no error return
code from the call.
Thanks for the testcase, but I can't reproduce the problem, neither on
32 bit nor on 64 bit. I tweaked your makefile to have a 100K loop I
started multiple times with differently optimzed code, but to no avail.

To account for that, I inspected the code doing the initialization and
found that it uses REALTIME priority when trying to make sure multiple
threads don't collide. This is a bit on the dangerous side, apparently.

I tweaked the code to use a spinlock instead.

I'm just about to upload new developer snapshots to
https://cygwin.com/snapshots/

Should be up in 10 mins or so. Can you please try if this fixes the
problem for you?


Thanks,
Corinna
--
Corinna Vinschen
Cygwin Maintainer
cyg Simple
2018-11-26 17:34:33 UTC
Permalink
Post by Corinna Vinschen
Post by James E. King III
Using 32-bit cygwin that I set up yesterday.
Don't do that. Use 64 bit Cygwin whenever possible. 32 bit is a lost
cause.
When exactly will it be a lost cause for Cygwin? I.E. Are you planning
to discontinue maintenance for 32bit anytime soon? Anyone needing it
could continue to use the existing distribution. I ask only because I
agree with your statement that it is a lost cause.
--
cyg Simple

--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Houder
2018-11-26 17:38:25 UTC
Permalink
[snip]
Post by Corinna Vinschen
Post by James E. King III
I found that a call to
clock_gettime(CLOCK_MONOTONIC, ..) has a one-time initialization that
is not thread-safe. If two threads call this at the same time, they
will race. The results I am seeing are typically that one of the two
callers get a timespec structure with zero values, and no error return
code from the call.
Thanks for the testcase, but I can't reproduce the problem, neither on
32 bit nor on 64 bit. I tweaked your makefile to have a 100K loop I
started multiple times with differently optimzed code, but to no avail.
I can, easily. (Windows 7, 64-bits. Unmodified Makefile.)

Henri


--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Andrey Repin
2018-11-26 17:50:52 UTC
Permalink
Greetings, Corinna Vinschen!
Post by Corinna Vinschen
Post by James E. King III
Using 32-bit cygwin that I set up yesterday.
Don't do that. Use 64 bit Cygwin whenever possible. 32 bit is a lost
cause.
Not until manufacturers stop selling 32-bit systems.
--
With best regards,
Andrey Repin
Monday, November 26, 2018 20:50:31

Sorry for my terrible english...


--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Houder
2018-11-26 18:07:44 UTC
Permalink
[snip]
Post by Corinna Vinschen
Post by James E. King III
I found that a call to
clock_gettime(CLOCK_MONOTONIC, ..) has a one-time initialization that
is not thread-safe. If two threads call this at the same time, they
will race. The results I am seeing are typically that one of the two
callers get a timespec structure with zero values, and no error return
code from the call.
Thanks for the testcase, but I can't reproduce the problem, neither on
32 bit nor on 64 bit. I tweaked your makefile to have a 100K loop I
started multiple times with differently optimzed code, but to no avail.
To account for that, I inspected the code doing the initialization and
found that it uses REALTIME priority when trying to make sure multiple
threads don't collide. This is a bit on the dangerous side, apparently.
I tweaked the code to use a spinlock instead.
I'm just about to upload new developer snapshots to
https://cygwin.com/snapshots/
Should be up in 10 mins or so. Can you please try if this fixes the
problem for you?
- only replaced the cygwin1.dll ...

Henri

64-@@ uname -a
CYGWIN_NT-6.1 Seven 2.11.3(0.329/5/3) x86_64 Cygwin
64-@@ ls -l /bin/cygwin1*
-rwxr-xr-x 1 Henri None 3339661 Nov 8 14:36 /bin/cygwin1-2.11.2.X
-rwxr-xr-x 1 Henri None 3337995 Nov 26 18:43 /bin/cygwin1-64-20181126.X
-rwxr-xr-x 1 Henri None 3337995 Nov 26 18:43 /bin/cygwin1.dll
64-@@ cd threads
64-@@ make test
64-@@ make test
64-@@ make test
64-@@ make test
64-@@ make test
64-@@ make test
64-@@ make test
64-@@ make test
64-@@ vi Makefile
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ #... wait a while ...
64-@@ for loop in {1..100}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..1000}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..1000}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..1000}; do ./cyg_hires_clock_race.exe; done
64-@@ for loop in {1..10000}; do ./cyg_hires_clock_race.exe; done
64-@@# That is enough!

=====


--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Corinna Vinschen
2018-11-27 09:37:38 UTC
Permalink
Post by Houder
[snip]
Post by Corinna Vinschen
Post by James E. King III
I found that a call to
clock_gettime(CLOCK_MONOTONIC, ..) has a one-time initialization that
is not thread-safe. If two threads call this at the same time, they
will race. The results I am seeing are typically that one of the two
callers get a timespec structure with zero values, and no error return
code from the call.
Thanks for the testcase, but I can't reproduce the problem, neither on
32 bit nor on 64 bit. I tweaked your makefile to have a 100K loop I
started multiple times with differently optimzed code, but to no avail.
To account for that, I inspected the code doing the initialization and
found that it uses REALTIME priority when trying to make sure multiple
threads don't collide. This is a bit on the dangerous side, apparently.
I tweaked the code to use a spinlock instead.
I'm just about to upload new developer snapshots to
https://cygwin.com/snapshots/
Should be up in 10 mins or so. Can you please try if this fixes the
problem for you?
- only replaced the cygwin1.dll ...
Henri
CYGWIN_NT-6.1 Seven 2.11.3(0.329/5/3) x86_64 Cygwin
-rwxr-xr-x 1 Henri None 3339661 Nov 8 14:36 /bin/cygwin1-2.11.2.X
-rwxr-xr-x 1 Henri None 3337995 Nov 26 18:43 /bin/cygwin1-64-20181126.X
-rwxr-xr-x 1 Henri None 3337995 Nov 26 18:43 /bin/cygwin1.dll
Thanks a lot for testing! (Particulary since I couldn't even
reproduce this on W7)


Corinna
--
Corinna Vinschen
Cygwin Maintainer
Houder
2018-11-27 10:19:46 UTC
Permalink
[snip]
Post by Corinna Vinschen
Post by Houder
CYGWIN_NT-6.1 Seven 2.11.3(0.329/5/3) x86_64 Cygwin
-rwxr-xr-x 1 Henri None 3339661 Nov 8 14:36 /bin/cygwin1-2.11.2.X
-rwxr-xr-x 1 Henri None 3337995 Nov 26 18:43 /bin/cygwin1-64-20181126.X
-rwxr-xr-x 1 Henri None 3337995 Nov 26 18:43 /bin/cygwin1.dll
[snip]
Post by Corinna Vinschen
Thanks a lot for testing! (Particulary since I couldn't even
reproduce this on W7)
Perhaps my machine is a bit "peculiar" ... :-)
(the real litmus test is, of course, James E. King III's application, not the STC)

Henri

/home/corinna/src/cygwin/cygwin-2.11.2/cygwin-2.11.2-1.i686/src/newlib-cygwin/winsup/cygwin/cygheap.cc
64-@@ uname -a
CYGWIN_NT-6.1 Seven 2.11.2(0.329/5/3) 2018-08-31 13:05 x86_64 Cygwin

64-@@ cd threads
64-@@ for loop in {1..1000}; do ./cyg_hires_clock_race.exe; done
ERROR: one of the timespec structures was zero:
main thread: tv_sec = 3455 tv_nsec = 350898985
2nd thread: tv_sec = 0 tv_nsec = 0
64-@@ for loop in {1..1000}; do ./cyg_hires_clock_race.exe; done
ERROR: one of the timespec structures was zero:
main thread: tv_sec = 3461 tv_nsec = 157276019
2nd thread: tv_sec = 0 tv_nsec = 0
ERROR: one of the timespec structures was zero:
main thread: tv_sec = 3467 tv_nsec = 493831379
2nd thread: tv_sec = 0 tv_nsec = 0
ERROR: one of the timespec structures was zero:
main thread: tv_sec = 3467 tv_nsec = 855769393
2nd thread: tv_sec = 0 tv_nsec = 0

Perhaps the following is significant?

64-@@ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 60
model name : Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
stepping : 3
cpu MHz : 3398.000
cache size : 8192 KB
...

processor : 7
vendor_id : GenuineIntel
cpu family : 6
model : 60
model name : Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
stepping : 3
cpu MHz : 3398.000
cache size : 8192 KB
physical id : 0
siblings : 8
core id : 3
cpu cores : 4
apicid : 7
initial apicid : 7
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca \
cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe pni dtes64 \
monitor ds_cpl vmx smx est tm2 ssse3 fma cx16 xtpr pdcm sse4_1 sse4_2 \
x2apic movbe popcnt aes xsave osxsave avx f16c rdrand lahf_lm ida arat \
epb xsaveopt pln pts dtherm fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid
clflush size : 64
cache_alignment : 64
address sizes : 39 bits physical, 48 bits virtual
power management:

=====


--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Houder
2018-11-27 10:29:09 UTC
Permalink
On Tue, 27 Nov 2018 11:19:46, Houder wrote:
[snip]
Post by Houder
Perhaps my machine is a bit "peculiar" ... :-)
(the real litmus test is, of course, James E. King III's application, not the STC)
Henri
/home/corinna/src/cygwin/cygwin-2.11.2/cygwin-2.11.2-1.i686/src/newlib-cygwin/winsup/cygwin/cygheap.cc
Sorry!
/home/corinna/src/cygwin/cygwin-2.11.2/cygwin-2.11.2-1.x86_64/src/newlib-cygwin/winsup/cygwin/cygheap.cc
^^^^^^
(copied from the wrong window while composing my reply)

Henri
Post by Houder
CYGWIN_NT-6.1 Seven 2.11.2(0.329/5/3) 2018-08-31 13:05 x86_64 Cygwin
=====


--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Corinna Vinschen
2018-11-27 13:07:39 UTC
Permalink
Post by Houder
[snip]
Post by Corinna Vinschen
Post by Houder
CYGWIN_NT-6.1 Seven 2.11.3(0.329/5/3) x86_64 Cygwin
-rwxr-xr-x 1 Henri None 3339661 Nov 8 14:36 /bin/cygwin1-2.11.2.X
-rwxr-xr-x 1 Henri None 3337995 Nov 26 18:43 /bin/cygwin1-64-20181126.X
-rwxr-xr-x 1 Henri None 3337995 Nov 26 18:43 /bin/cygwin1.dll
[snip]
Post by Corinna Vinschen
Thanks a lot for testing! (Particulary since I couldn't even
reproduce this on W7)
Perhaps my machine is a bit "peculiar" ... :-)
I guess mine are the peculiar ones, being VMs :}


Corinna
--
Corinna Vinschen
Cygwin Maintainer
Loading...