This symbol was causing a build failure with the new toolchain. It
looks like it has always been wrong.
The main issue was checking for PIC rather than __PIC__.
Remove all PSEUDO_* macros and ther SYSCALL_ERROR_NAME macro as they are
not needed by uclibc-ng, they are used in glibc for building up syscalls
there, but not here.
Fixes error:
/opt/shorne/software/or1k-linux/bin/../lib/gcc/or1k-linux/9.0.1/../../../../or1k-linux/bin/ld: libc/libc_so.a(or1k_clone.os): pc-relative relocation against dynamic symbol __syscall_error
/opt/shorne/software/or1k-linux/bin/../lib/gcc/or1k-linux/9.0.1/../../../../or1k-linux/bin/ld: final link failed: bad value
Signed-off-by: Stafford Horne <shorne(a)gmail.com>
---
libc/sysdeps/linux/or1k/or1k_clone.S | 8 +++++--
libc/sysdeps/linux/or1k/sysdep.h | 32 ----------------------------
2 files changed, 6 insertions(+), 34 deletions(-)
diff --git a/libc/sysdeps/linux/or1k/or1k_clone.S b/libc/sysdeps/linux/or1k/or1k_clone.S
index a2c16ac9e..2de873a02 100644
--- a/libc/sysdeps/linux/or1k/or1k_clone.S
+++ b/libc/sysdeps/linux/or1k/or1k_clone.S
@@ -71,7 +71,11 @@ L(oldpid):
l.ori r3, r11, 0
L(error):
- l.j SYSCALL_ERROR_NAME
+#ifdef __PIC__
+ l.j plt(__syscall_error)
+#else
+ l.j __syscall_error
+#endif
l.ori r3,r11,0
-PSEUDO_END (__or1k_clone)
+END (__or1k_clone)
diff --git a/libc/sysdeps/linux/or1k/sysdep.h b/libc/sysdeps/linux/or1k/sysdep.h
index 4dba3f2a0..782981c55 100644
--- a/libc/sysdeps/linux/or1k/sysdep.h
+++ b/libc/sysdeps/linux/or1k/sysdep.h
@@ -43,38 +43,6 @@ License along with the GNU C Library; if not, see
l.sys 1; \
l.nop
-#define PSEUDO(name, syscall_name, args) \
- ENTRY (name); \
- DO_CALL(syscall_name); \
- /* if -4096 < ret < 0 holds, it's an error */ \
- l.sfgeui r11, 0xf001; \
- l.bf L(pseudo_end); \
- l.nop
-
-#define PSEUDO_NOERRNO(name, syscall_name, args) \
- ENTRY (name); \
- DO_CALL(syscall_name)
-
-#define PSEUDO_END(name) \
-L(pseudo_end): \
- l.j SYSCALL_ERROR_NAME; \
- l.ori r3,r11,0; \
- END (name)
-
-#define PSEUDO_END_NOERRNO(name) \
- END (name)
-
-#ifndef PIC
-/* For static code, on error jump to __syscall_error directly. */
-# define SYSCALL_ERROR_NAME __syscall_error
-#elif NOT_IN_libc
-/* Use the internal name for libc/libpthread shared objects. */
-# define SYSCALL_ERROR_NAME __GI___syscall_error
-#else
-/* Otherwise, on error do a full PLT jump. */
-# define SYSCALL_ERROR_NAME plt(__syscall_error)
-#endif
-
/* Make use of .size directive. */
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
--
2.21.0
Hello,
I would like to know if there is consensus on the fact that this program
hanging on a deadlock is a uClibc-ng bug: https://pastebin.com/11qLsTW5
I've asked people to try this on several arch/libc combination, it works
well (no hang) on:
* x86_64/glibc
* x86_64/musl
* armv7l/musl
Also, I've run the puts.c test (linked above) on 3 archs with uClibc-ng,
it fails (hangs) on:
* or1k/uClibc-ng
* mips32r6/uClibc-ng
* k1c/uClibc-ng (port not completely published yet)
See failure logs + strace -f of what happens when hanging:
https://mypads.framapad.org/mypads/?/mypads/group/uclibc-ng-10be37ap/pad/vi…
My understanding of the issue is that:
puts, and possibly other libc functions, are taking a lock (
https://elixir.bootlin.com/uclibc-ng/latest/source/libc/stdio/puts.c#L17
) and end up calling write() which is a cancellation point. (
https://elixir.bootlin.com/uclibc-ng/latest/source/libc/stdio/_stdio.h#L150
)
So, if a thread is canceled, is asynchronous mode (which is the default
one), and the cancelation is triggered by the write() inside the puts(),
then the thread will unwind and exit without unlocking the puts lock.
Then, any other thread calling puts() will hang indefinetely (and hang
other threads if it hangs with locks held...).
My understanding of what can be done to fix this issue:
1/ Either make puts a non cancelation point (see man 7 pthreads, puts is
not listed in mandatory cancelation point, only in "may"). For instance
it is not a cancelation point in glibc.
2/ Or keep puts as a cancelation point and fix the puts code so that it
releases the lock upon cancelation (using pthread_cleanup_push/pop for
instance)
In case people think this is indeed a bug, here are examples of code
fixes that I have in mind, please don't hesitate to comment or/and
propose something else:
1/ https://pastebin.com/ePsWJzdi
2/ https://pastebin.com/5EA4RedS
One problem of those fixes is that we need to identify all libc
functions that take a lock and call a cancellable function and apply
such kind of fixes... This is not easy and a bit painful.
Thanks!
Regards,
--
Yann Sionneau
The internal heap structures were not protected properly in
memalign(). If multiple threads were concurrently allocating memory and
one of them were requesting aligned memory via valloc,memalign or
posix_memalign the internal heap data structures could be corrupted.
Signed-off-by: Kjetil Oftedal <oftedal(a)gmail.com>
---
libc/stdlib/malloc/memalign.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/libc/stdlib/malloc/memalign.c b/libc/stdlib/malloc/memalign.c
index 74d5dbd..0d3de67 100644
--- a/libc/stdlib/malloc/memalign.c
+++ b/libc/stdlib/malloc/memalign.c
@@ -77,7 +77,9 @@ memalign (size_t alignment, size_t size)
init_size = addr - tot_addr;
}
+ __heap_lock (&__malloc_heap_lock);
__heap_free (heap, base, init_size);
+ __heap_unlock (&__malloc_heap_lock);
/* Remember that we've freed the initial part of MEM. */
base += init_size;
@@ -85,9 +87,11 @@ memalign (size_t alignment, size_t size)
/* Return the end part of MEM to the heap, unless it's too small. */
end_addr = addr + size;
- if (end_addr + MALLOC_REALLOC_MIN_FREE_SIZE < tot_end_addr)
+ if (end_addr + MALLOC_REALLOC_MIN_FREE_SIZE < tot_end_addr) {
+ __heap_lock (&__malloc_heap_lock);
__heap_free (heap, (void *)end_addr, tot_end_addr - end_addr);
- else
+ __heap_unlock (&__malloc_heap_lock);
+ } else
/* We didn't free the end, so include it in the size. */
end_addr = tot_end_addr;
--
1.7.9.5