Przeglądaj źródła

riscv32: use the 32-bit pthread_rwlock_t layout

riscv32 carried the 64-bit variant of the struct: eleven members with
__writer and __shared as ints, two long pads, and __flags last. That is what
aarch64, alpha and riscv64 use, and it matches the __WORDSIZE == 64 branch of
the initializers in pthread.h. On a 32-bit target the 32-bit branch is taken
instead, which places the value in member seven -- __writer here, not __flags.

So PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP wrote its 2 into
__writer, leaving __flags 0: reader preference, plus a bogus writer tid in a
freshly initialized lock. Measured in the object file before the change,
offsetof(__flags) was 44 and the 2 landed at 28.

Switch to the i386 layout, the four char fields in little endian order, which
is what the 32-bit initializers address. __SIZEOF_PTHREAD_RWLOCK_T stays 48,
so the union does not change size and nothing outside moves; only the members
inside it do.

Found on riscv32 with NPTL and shared libraries, gcc 15 against 6.5.10
headers: ten tst-initializers1 variants plus tst-rwlock8 and its -O2 twin,
16 failures in 775 tests. The rwlock8 pair is the runtime half of the same
bug, so this was never a test-only detail. Verified in the object file after
the change: __flags at 24, __writer at 28, and the initializer's 2 sits in
__flags.

Signed-off-by: Ramin Moussavi <lordrasmus@gmail.com>
ramin 1 miesiąc temu
rodzic
commit
7a1b5d182f

+ 6 - 4
libpthread/nptl/sysdeps/unix/sysv/linux/riscv32/bits/pthreadtypes.h

@@ -127,11 +127,13 @@ typedef union
     unsigned int __writer_wakeup;
     unsigned int __nr_readers_queued;
     unsigned int __nr_writers_queued;
+    /* FLAGS must stay at this position in the structure to maintain
+       binary compatibility.  */
+    unsigned char __flags;
+    unsigned char __shared;
+    unsigned char __pad1;
+    unsigned char __pad2;
     int __writer;
-    int __shared;
-    unsigned long int __pad1;
-    unsigned long int __pad2;
-    unsigned int __flags;
   } __data;
   char __size[__SIZEOF_PTHREAD_RWLOCK_T];
   long int __align;