Re: nanosleep on mingw

2010-04-04 Thread Bruno Haible
The current implementation of nanosleep is broken on mingw for several reasons:

1) It requires linking with -lws2_32, as evidenced by these error messages:

   gcc-3 -mno-cygwin  -g -O2  -L/usr/local/mingw/lib -o test-nanosleep.exe 
test-nanosleep.o ../gllib/libgnu.a  
   ../gllib/libgnu.a(select.o): In function `rpl_select':
   /home/bruno/testdir2/gllib/select.c:93: undefined reference to 
`_wsaenumnetworkeve...@12'
   /home/bruno/testdir2/gllib/select.c:360: undefined reference to 
`_wsaeventsel...@12'
   /home/bruno/testdir2/gllib/select.c:381: undefined reference to `_sel...@20'
   /home/bruno/testdir2/gllib/select.c:434: undefined reference to 
`_wsaeventsel...@12'
   /home/bruno/testdir2/gllib/select.c:435: undefined reference to 
`___wsafdis...@8'
   /home/bruno/testdir2/gllib/select.c:437: undefined reference to 
`___wsafdis...@8'
   /home/bruno/testdir2/gllib/select.c:439: undefined reference to 
`___wsafdis...@8'
   /home/bruno/testdir2/gllib/select.c:414: undefined reference to `_sel...@20'
   collect2: ld returned 1 exit status
   make[4]: *** [test-nanosleep.exe] Error 1

   But there is no good reason to link with a sockets library just to sleep a
   certain amount of time.

2) Use of this the 'select' function in wsock2 requires a prior invocation
   of WSAStartup() (contained in the 'sockets' module).

   Witness: This program
===
#include winsock2.h
#include sys/time.h
#include stdlib.h
#include stdio.h
#include windows.h

int main (int argc, char *argv[])
{
  int usecs = atoi (argv[1]);
  LARGE_INTEGER pcfreq;
  LARGE_INTEGER before, after;
  struct timeval timeout;
  int ret;

  if (!QueryPerformanceFrequency (pcfreq))
printf (QueryPerformanceFrequency failed\n);

  if (!QueryPerformanceCounter (before))
printf (QueryPerformanceCounter failed\n);

  timeout.tv_sec = usecs / 100;
  timeout.tv_usec = usecs % 100;
  ret = select (0, NULL, NULL, NULL, timeout);
  if (ret  0) printf (select failed, error = %d\n, WSAGetLastError());

  if (!QueryPerformanceCounter (after))
printf (QueryPerformanceCounter failed\n);

  printf (time slept: %g s\n, (double) (after.QuadPart - before.QuadPart) / 
(double) pcfreq.QuadPart);
  return 0;
}
===
   produces the output

   $ ./usleep.exe 6000
   select failed, error = 10093
   time slept: 6.87238e-005 s

   Error 10093 is WSANOTINITIALISED.

3) Use of select without a socket descriptor, just a timeout, fails.

   Witness: This program
===
#include winsock2.h
#include sys/time.h
#include stdlib.h
#include stdio.h
#include windows.h

int main (int argc, char *argv[])
{
  int usecs = atoi (argv[1]);
  LARGE_INTEGER pcfreq;
  WSADATA data;
  LARGE_INTEGER before, after;
  struct timeval timeout;
  int ret;

  if (!QueryPerformanceFrequency (pcfreq))
printf (QueryPerformanceFrequency failed\n);

  WSAStartup (0x201, data);

  if (!QueryPerformanceCounter (before))
printf (QueryPerformanceCounter failed\n);

  timeout.tv_sec = usecs / 100;
  timeout.tv_usec = usecs % 100;
  ret = select (0, NULL, NULL, NULL, timeout);
  if (ret  0) printf (select failed, error = %d\n, WSAGetLastError());

  if (!QueryPerformanceCounter (after))
printf (QueryPerformanceCounter failed\n);

  printf (time slept: %g s\n, (double) (after.QuadPart - before.QuadPart) / 
(double) pcfreq.QuadPart);
  return 0;
}
===
   produces the output

   $ ./usleep.exe 6000
   select failed, error = 10022
   time slept: 0.000258971 s

   Error 10022 is WSAEINVAL.

4) select sleeps for at least 6 ms.

   Witness: This program
===
#include winsock2.h
#include sys/time.h
#include stdlib.h
#include stdio.h
#include windows.h

int main (int argc, char *argv[])
{
  int usecs = atoi (argv[1]);
  LARGE_INTEGER pcfreq;
  WSADATA data;
  SOCKET s;
  fd_set dummy;
  LARGE_INTEGER before, after;
  struct timeval timeout;
  int ret;

  if (!QueryPerformanceFrequency (pcfreq))
printf (QueryPerformanceFrequency failed\n);

  WSAStartup (0x201, data);

  s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  FD_ZERO(dummy);
  FD_SET(s, dummy);

  if (!QueryPerformanceCounter (before))
printf (QueryPerformanceCounter failed\n);

  timeout.tv_sec = usecs / 100;
  timeout.tv_usec = usecs % 100;
  ret = select (0, NULL, NULL, dummy, timeout);
  if (ret  0) printf (select failed, error = %d\n, WSAGetLastError());

  if (!QueryPerformanceCounter (after))
printf (QueryPerformanceCounter failed\n);

  printf (time slept: %g s\n, (double) (after.QuadPart - before.QuadPart) / 
(double) pcfreq.QuadPart);
  return 0;
}

Re: nanosleep on mingw

2010-04-04 Thread Jim Meyering
Bruno Haible wrote:
...
 So here is a proposed patch for implementing a Woe32 nanosleep with a
 resolution of ca. 10 microseconds or higher.

 2010-04-04  Bruno Haible  br...@clisp.org

   Implement nanosleep for native Windows.
   * lib/nanosleep.c (nanosleep): New implementation for native Windows.

 --- lib/nanosleep.c.orig  Sun Apr  4 14:45:40 2010
 +++ lib/nanosleep.c   Sun Apr  4 14:43:28 2010

Nice work.
You're welcome to commit that.




Re: nanosleep on mingw

2010-04-04 Thread Bruno Haible
Jim Meyering wrote:
 You're welcome to commit that.

Committed. The only thing I'm worried about is that it's a compromise
between precision of the time interval and ues of CPU time:
Someone who invokes nanosleep with an argument of 0.3 seconds may complain
that 9.4 ms of busy-looping is not acceptable and that - in his application -
sleeping 0.29 or 0.31 s would be more acceptable than burning CPU time.
But nanosleep does not take a precision argument...

Bruno




Re: nanosleep on mingw

2010-04-03 Thread Jim Meyering
Bruno Haible wrote:
 Similarly, on mingw with warn-on-use.h modified to work like if g++ = 4.3
 were present, I'm seeing this error:

   ../gllib/time.h:359: error: `nanosleep' was not declared in this scope

 It would also be an error on the other platforms lacking nanosleep,
 with g++ 4.3.

 Again, to fix this, one needs to distinguish the case where the function
 is missing and the case where the function is being replaced (overridden).

 Jim, here is a proposed patch. It fixes the error. The big change to
 m4/nanosleep.m4 is mostly an indentation change. OK to commit?


 2010-04-03  Bruno Haible  br...@clisp.org

   nanosleep: Fix C++ test error on mingw.
   * lib/nanosleep.c (nanosleep): Renamed from rpl_nanosleep.
   * lib/time.in.h (nanosleep): Use modern idiom.
   * m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): When the system does not have a
   nanosleep function, set HAVE_NANOSLEEP to 0, instead of setting
   REPLACE_NANOSLEEP to 1.
   * m4/time_h.m4 (gl_HEADER_TIME_H_DEFAULTS): Initialize HAVE_NANOSLEEP.
   * modules/time (Makefile.am): Substitute HAVE_NANOSLEEP.

This looks right, and passed a basic sanity test (coreutils on F12).
Though note that the patches to modules/time and m4/time_h.m4
did not apply and I did them manually.

Please apply.

Thanks for all the fixes.




Re: nanosleep on mingw

2010-04-03 Thread Bruno Haible
Hi Jim,

 Though note that the patches to modules/time and m4/time_h.m4
 did not apply and I did them manually.

Yes, I was constantly changing the same parts of these two files.

 Please apply.

Applied.

Bruno