[toolchain] uClibc: fix errno access in pthreads (#8166, #8177)
[openwrt.git] / toolchain / uClibc / patches-0.9.31 / 901-MIPS-restore-INLINE_SYSCALL-macro.patch
1 From 911bf867eb82e28799e81578c50d82ee166cebb5 Mon Sep 17 00:00:00 2001
2 From: Gabor Juhos <juhosg@openwrt.org>
3 Date: Tue, 6 Apr 2010 17:25:56 +0200
4 Subject: [PATCH] MIPS: restore INLINE_SYSCALL macro
5
6 The MIPS specific INLINE_SYSCALL macro has been renamed to
7 INLINE_SYSCALL_NCS with:
8
9   763bbf9e9a27426c9be8322dca5ddf2cb4dbc464
10
11   syscall: unify part 2: NCS variety
12
13   Declare common NCS (non-constant syscall) variants and convert the
14   existing ports over to this.
15
16 This change breaks system calls. The code generated with using of the
17 new macro does not obey the restartable syscall convention used by the
18 linux kernel. When it tries to restart the syscall the errno value is
19 not being replaced by the syscall number.
20
21 This causes weird behaviour of the 'ping' command in busybox for
22 example:
23
24 root@OpenWrt:/# ping 192.168.1.254
25 PING 192.168.1.254 (192.168.1.254): 56 data bytes
26 64 bytes from 192.168.1.254: seq=0 ttl=128 time=6.292 ms
27 ping: recvfrom: Function not implemented
28 64 bytes from 192.168.1.254: seq=1 ttl=128 time=0.719 ms
29 ping: recvfrom: Function not implemented
30 64 bytes from 192.168.1.254: seq=2 ttl=128 time=0.489 ms
31 ping: recvfrom: Function not implemented
32 64 bytes from 192.168.1.254: seq=3 ttl=128 time=0.486 ms
33 ping: recvfrom: Function not implemented
34 64 bytes from 192.168.1.254: seq=4 ttl=128 time=0.487 ms
35 ping: recvfrom: Function not implemented
36 64 bytes from 192.168.1.254: seq=5 ttl=128 time=0.939 ms
37 ping: recvfrom: Function not implemented
38 64 bytes from 192.168.1.254: seq=6 ttl=128 time=0.971 ms
39 ping: recvfrom: Function not implemented
40 64 bytes from 192.168.1.254: seq=7 ttl=128 time=0.488 ms
41 ping: recvfrom: Funct^C
42 --- 192.168.1.254 ping statistics ---
43 9 packets transmitted, 9 packets received, 0% packet loss
44 round-trip min/avg/max = 0.486/1.307/6.292 ms
45 root@OpenWrt:/#
46
47 Here is the relevant assembler code parts of the 'recvfrom' function:
48
49 with the current INLINE_SYSCALL_NCS:
50 00000000 <__GI_recvfrom>:
51   ...
52   2c:   24021050        li      v0,4176
53   30:   8fd1003c        lw      s1,60(s8)
54   34:   8fd00038        lw      s0,56(s8)
55   38:   27bdffe0        addiu   sp,sp,-32
56   3c:   afb00010        sw      s0,16(sp)
57   40:   afb10014        sw      s1,20(sp)  <-- wrong
58   44:   0000000c        syscall
59   48:   27bd0020        addiu   sp,sp,32
60   ...
61
62 with the old INLINE_SYSCALL:
63 00000000 <__libc_recvfrom>:
64   ...
65   28:   8fd0003c        lw      s0,60(s8)
66   2c:   8fc20038        lw      v0,56(s8)
67   30:   27bdffe0        addiu   sp,sp,-32
68   34:   afa20010        sw      v0,16(sp)
69   38:   afb00014        sw      s0,20(sp)
70   3c:   24021050        li      v0,4176   <-- good
71   40:   0000000c        syscall
72   44:   27bd0020        addiu   sp,sp,32
73   ...
74
75 Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
76 Cc: Mike Frysinger <vapier@gentoo.org>
77 ---
78 Notes:
79
80 The ideal solution would to fix the 'internal_syscall' macros to generate
81 correct code for the NCS case as well. However the INLINE_SYSCALL macro
82 generates smaller code if the syscall number is constant, so it is
83 useful in such cases.
84
85 Additionally, the current INLINE_SYSCALL_NCS in the 'mips/bits/syscall.h'
86 is a duplicate of the one in the 'common/bits/syscalls-common.h' so it
87 should be removed anyway.
88 ---
89  libc/sysdeps/linux/mips/bits/syscalls.h |    4 ++--
90  1 files changed, 2 insertions(+), 2 deletions(-)
91
92 diff --git a/libc/sysdeps/linux/mips/bits/syscalls.h b/libc/sysdeps/linux/mips/bits/syscalls.h
93 index 28b0f91..944d038 100644
94 --- a/libc/sysdeps/linux/mips/bits/syscalls.h
95 +++ b/libc/sysdeps/linux/mips/bits/syscalls.h
96 @@ -19,9 +19,9 @@
97  
98  /* Define a macro which expands into the inline wrapper code for a system
99     call.  */
100 -#define INLINE_SYSCALL_NCS(name, nr, args...)                               \
101 +#define INLINE_SYSCALL(name, nr, args...)                               \
102    ({ INTERNAL_SYSCALL_DECL(err);                                       \
103 -     long result_var = INTERNAL_SYSCALL_NCS (name, err, nr, args);             \
104 +     long result_var = INTERNAL_SYSCALL(name, err, nr, args);          \
105       if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) )                 \
106         {                                                               \
107          __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err));        \
108 -- 
109 1.5.3.2
110