[PATCH v8] Cygwin: pipe: Switch pipe mode to blocking mode by default

Corinna Vinschen corinna-cygwin@cygwin.com
Thu Oct 31 10:15:59 GMT 2024


Hi Takashi,

On Oct 31 17:36, Takashi Yano wrote:
> Hi Corinna,
> 
> On Mon, 28 Oct 2024 12:57:05 +0100
> Corinna Vinschen wrote:
> > On Oct 28 20:25, Takashi Yano wrote:
> > > Is the test case I used different from yours? Without the 2nd arg,
> > > $ ./a.exe 40000
> > > pipe capacity: 65536
> > > write: writable 1, 40000 25536
> > > write: writable 1, SIGALRM 24576 960
> > > write: writable 0, SIGALRM -1 / Interrupted system call
> > 
> > This is the same testcase I pasted last week:
> > 
> >   $ ./x 40000
> >   pipe capacity: 65536
> >   write: writable 1, 40000 25536
> >   write: writable 1, SIGALRM 24576 960
> >   write: writable 0, SIGALRM 512 448
> >   write: writable 0, SIGALRM 256 192
> >   write: writable 0, SIGALRM 128 64
> >   write: writable 0, SIGALRM 64 0
> >   write: writable 0, SIGALRM -1 / Interrupted system call
> > 
> > So why does it not get into the last else case after calling
> > pipe_data_available()?  Do you get a different return value
> > from pipe_data_available()? If so, what and why?
> 
> I checked the behaviour in my environment.
> __builtin_clzl(960) returns 54 in my environment.
> So, result of
> 	len1 = 1 << (31 - __builtin_clzl (avail));
> is undefined. If I modify this to:
> 	len1 = 1 << (63 - __builtin_clzl (avail));
> I can get:
> 
> $ ./a.exe 40000 1
> pipe capacity: 65536
> write: writable 1, 40000 25536
> write: writable 1, 24576 960
> write: writable 0, 512 448
> write: writable 0, 256 192
> write: writable 0, 128 64
> write: writable 0, 64 0
> write: writable 0, -1 / Resource temporarily unavailable
> 
> with the commit 686e46ce7148 as well as with my v9 patch.
> 
> Could you please fix?

Yes, I will, but this is still puzzeling. While negative shift values
are undefined in C, there's this:

  The Intel Pentium SAL instruction (generated by both gcc and Microsoft
  C++ to evaluate left-shifts) only uses the bottom five bits of the
  shift amount

The last 5 bits of 63 - 54 =   9 are 01001,
the last 5 bits of 31 - 54 = -23 are 01001 as well.

I wrote a STC:

------------------------------------
#include <stdio.h>
#include <stdlib.h>

int
main (int argc, char **argv)
{
  ssize_t avail = atol (argv[1]);

  int x1 = 31 - __builtin_clzl (avail);
  int x2 = 63 - __builtin_clzl (avail);

  printf ("%ld %d %u %u\n",
	  avail,
	  __builtin_clzl (avail),
	  1 << x1,
	  1 << x2);
  return 0;
}
------------------------------------

The workaround with x1 and x2 is necessary, otherwise gcc will
fold the two expressions into a single sall instruction, even
when building without optimization.

I can build the STC on Cygwin and with the Cygwin cross-compiler on
Linux.  Both compilers generate identical assembler code.

In my environment the result is in both cases the same:

  $ ./clz-cyg 960
  960 54 512 512
  $ ./clz-lin 960
  960 54 512 512

I get the same result, with and without -O2 (but then again, with -O2
the sall instructions are folded into a single instruction again).

Do you get a different result?  Do you run this on an AMD CPU perhaps,
and the AMDs implement the SAL instruction differently?


Corinna


More information about the Cygwin-patches mailing list