authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-06 14:13:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-06 14:13:57-07:00
loge5fab3ba6898cce3eba63192b0944f4e2208a3b8
treeb03fc02418a2d18fcf239c0012969a3774cbf844
parentdba94f453a55d02cc87667fc5636aed3237483f6

update musl sources to 1.2.1


158 files changed, 2753 insertions(+), 1762 deletions(-)

lib/libc/musl/arch/arm/syscall_arch.h-6
......@@ -98,12 +98,6 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
9898 __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
9999}
100100
101#define VDSO_USEFUL
102#define VDSO_CGT32_SYM "__vdso_clock_gettime"
103#define VDSO_CGT32_VER "LINUX_2.6"
104#define VDSO_CGT_SYM "__vdso_clock_gettime64"
105#define VDSO_CGT_VER "LINUX_2.6"
106
107101#define SYSCALL_FADVISE_6_ARG
108102
109103#define SYSCALL_IPC_BROKEN_MODE
lib/libc/musl/arch/mips/bits/signal.h+1-1
......@@ -93,7 +93,7 @@ typedef struct __ucontext {
9393#define SIGTRAP 5
9494#define SIGABRT 6
9595#define SIGIOT SIGABRT
96#define SIGSTKFLT 7
96#define SIGEMT 7
9797#define SIGFPE 8
9898#define SIGKILL 9
9999#define SIGBUS 10
lib/libc/musl/arch/mips/syscall_arch.h+40-40
......@@ -18,26 +18,26 @@
1818static inline long __syscall0(long n)
1919{
2020 register long r7 __asm__("$7");
21 register long r2 __asm__("$2") = n;
21 register long r2 __asm__("$2");
2222 __asm__ __volatile__ (
23 "syscall"
24 : "+r"(r2), "=r"(r7)
25 :
23 "addu $2,$0,%2 ; syscall"
24 : "=&r"(r2), "=r"(r7)
25 : "ir"(n), "0"(r2)
2626 : SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
27 return r7 ? -r2 : r2;
27 return r7 && r2>0 ? -r2 : r2;
2828}
2929
3030static inline long __syscall1(long n, long a)
3131{
3232 register long r4 __asm__("$4") = a;
3333 register long r7 __asm__("$7");
34 register long r2 __asm__("$2") = n;
34 register long r2 __asm__("$2");
3535 __asm__ __volatile__ (
36 "syscall"
37 : "+r"(r2), "=r"(r7)
38 : "r"(r4)
36 "addu $2,$0,%2 ; syscall"
37 : "=&r"(r2), "=r"(r7)
38 : "ir"(n), "0"(r2), "r"(r4)
3939 : SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
40 return r7 ? -r2 : r2;
40 return r7 && r2>0 ? -r2 : r2;
4141}
4242
4343static inline long __syscall2(long n, long a, long b)
......@@ -45,13 +45,13 @@ static inline long __syscall2(long n, long a, long b)
4545 register long r4 __asm__("$4") = a;
4646 register long r5 __asm__("$5") = b;
4747 register long r7 __asm__("$7");
48 register long r2 __asm__("$2") = n;
48 register long r2 __asm__("$2");
4949 __asm__ __volatile__ (
50 "syscall"
51 : "+r"(r2), "=r"(r7)
52 : "r"(r4), "r"(r5)
50 "addu $2,$0,%2 ; syscall"
51 : "=&r"(r2), "=r"(r7)
52 : "ir"(n), "0"(r2), "r"(r4), "r"(r5)
5353 : SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
54 return r7 ? -r2 : r2;
54 return r7 && r2>0 ? -r2 : r2;
5555}
5656
5757static inline long __syscall3(long n, long a, long b, long c)
......@@ -60,13 +60,13 @@ static inline long __syscall3(long n, long a, long b, long c)
6060 register long r5 __asm__("$5") = b;
6161 register long r6 __asm__("$6") = c;
6262 register long r7 __asm__("$7");
63 register long r2 __asm__("$2") = n;
63 register long r2 __asm__("$2");
6464 __asm__ __volatile__ (
65 "syscall"
66 : "+r"(r2), "=r"(r7)
67 : "r"(r4), "r"(r5), "r"(r6)
65 "addu $2,$0,%2 ; syscall"
66 : "=&r"(r2), "=r"(r7)
67 : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
6868 : SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
69 return r7 ? -r2 : r2;
69 return r7 && r2>0 ? -r2 : r2;
7070}
7171
7272static inline long __syscall4(long n, long a, long b, long c, long d)
......@@ -75,13 +75,13 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
7575 register long r5 __asm__("$5") = b;
7676 register long r6 __asm__("$6") = c;
7777 register long r7 __asm__("$7") = d;
78 register long r2 __asm__("$2") = n;
78 register long r2 __asm__("$2");
7979 __asm__ __volatile__ (
80 "syscall"
81 : "+r"(r2), "+r"(r7)
82 : "r"(r4), "r"(r5), "r"(r6)
80 "addu $2,$0,%2 ; syscall"
81 : "=&r"(r2), "+r"(r7)
82 : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
8383 : SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
84 return r7 ? -r2 : r2;
84 return r7 && r2>0 ? -r2 : r2;
8585}
8686
8787static inline long __syscall5(long n, long a, long b, long c, long d, long e)
......@@ -91,15 +91,15 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
9191 register long r6 __asm__("$6") = c;
9292 register long r7 __asm__("$7") = d;
9393 register long r8 __asm__("$8") = e;
94 register long r2 __asm__("$2") = n;
94 register long r2 __asm__("$2");
9595 __asm__ __volatile__ (
9696 "subu $sp,$sp,32 ; sw $8,16($sp) ; "
97 "syscall ;"
97 "addu $2,$0,%3 ; syscall ;"
9898 "addu $sp,$sp,32"
99 : "+r"(r2), "+r"(r7), "+r"(r8)
100 : "r"(r4), "r"(r5), "r"(r6)
99 : "=&r"(r2), "+r"(r7), "+r"(r8)
100 : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
101101 : SYSCALL_CLOBBERLIST, "$9", "$10");
102 return r7 ? -r2 : r2;
102 return r7 && r2>0 ? -r2 : r2;
103103}
104104
105105static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
......@@ -110,15 +110,15 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
110110 register long r7 __asm__("$7") = d;
111111 register long r8 __asm__("$8") = e;
112112 register long r9 __asm__("$9") = f;
113 register long r2 __asm__("$2") = n;
113 register long r2 __asm__("$2");
114114 __asm__ __volatile__ (
115115 "subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; "
116 "syscall ;"
116 "addu $2,$0,%4 ; syscall ;"
117117 "addu $sp,$sp,32"
118 : "+r"(r2), "+r"(r7), "+r"(r8), "+r"(r9)
119 : "r"(r4), "r"(r5), "r"(r6)
118 : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9)
119 : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
120120 : SYSCALL_CLOBBERLIST, "$10");
121 return r7 ? -r2 : r2;
121 return r7 && r2>0 ? -r2 : r2;
122122}
123123
124124static inline long __syscall7(long n, long a, long b, long c, long d, long e, long f, long g)
......@@ -130,15 +130,15 @@ static inline long __syscall7(long n, long a, long b, long c, long d, long e, lo
130130 register long r8 __asm__("$8") = e;
131131 register long r9 __asm__("$9") = f;
132132 register long r10 __asm__("$10") = g;
133 register long r2 __asm__("$2") = n;
133 register long r2 __asm__("$2");
134134 __asm__ __volatile__ (
135135 "subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; sw $10,24($sp) ; "
136 "syscall ;"
136 "addu $2,$0,%5 ; syscall ;"
137137 "addu $sp,$sp,32"
138 : "+r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10)
139 : "r"(r4), "r"(r5), "r"(r6)
138 : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10)
139 : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
140140 : SYSCALL_CLOBBERLIST);
141 return r7 ? -r2 : r2;
141 return r7 && r2>0 ? -r2 : r2;
142142}
143143
144144#define VDSO_USEFUL
lib/libc/musl/arch/mips64/bits/signal.h+1-1
......@@ -112,7 +112,7 @@ typedef struct __ucontext {
112112#define SIGTRAP 5
113113#define SIGABRT 6
114114#define SIGIOT SIGABRT
115#define SIGSTKFLT 7
115#define SIGEMT 7
116116#define SIGFPE 8
117117#define SIGKILL 9
118118#define SIGBUS 10
lib/libc/musl/arch/mips64/syscall_arch.h+35-35
......@@ -16,26 +16,26 @@
1616static inline long __syscall0(long n)
1717{
1818 register long r7 __asm__("$7");
19 register long r2 __asm__("$2") = n;
19 register long r2 __asm__("$2");
2020 __asm__ __volatile__ (
21 "syscall"
22 : "+&r"(r2), "=r"(r7)
23 :
21 "daddu $2,$0,%2 ; syscall"
22 : "=&r"(r2), "=r"(r7)
23 : "ir"(n), "0"(r2)
2424 : SYSCALL_CLOBBERLIST);
25 return r7 ? -r2 : r2;
25 return r7 && r2>0 ? -r2 : r2;
2626}
2727
2828static inline long __syscall1(long n, long a)
2929{
3030 register long r4 __asm__("$4") = a;
3131 register long r7 __asm__("$7");
32 register long r2 __asm__("$2") = n;
32 register long r2 __asm__("$2");
3333 __asm__ __volatile__ (
34 "syscall"
35 : "+&r"(r2), "=r"(r7)
36 : "r"(r4)
34 "daddu $2,$0,%2 ; syscall"
35 : "=&r"(r2), "=r"(r7)
36 : "ir"(n), "0"(r2), "r"(r4)
3737 : SYSCALL_CLOBBERLIST);
38 return r7 ? -r2 : r2;
38 return r7 && r2>0 ? -r2 : r2;
3939}
4040
4141static inline long __syscall2(long n, long a, long b)
......@@ -43,14 +43,14 @@ static inline long __syscall2(long n, long a, long b)
4343 register long r4 __asm__("$4") = a;
4444 register long r5 __asm__("$5") = b;
4545 register long r7 __asm__("$7");
46 register long r2 __asm__("$2") = n;
46 register long r2 __asm__("$2");
4747
4848 __asm__ __volatile__ (
49 "syscall"
50 : "+&r"(r2), "=r"(r7)
51 : "r"(r4), "r"(r5)
49 "daddu $2,$0,%2 ; syscall"
50 : "=&r"(r2), "=r"(r7)
51 : "ir"(n), "0"(r2), "r"(r4), "r"(r5)
5252 : SYSCALL_CLOBBERLIST);
53 return r7 ? -r2 : r2;
53 return r7 && r2>0 ? -r2 : r2;
5454}
5555
5656static inline long __syscall3(long n, long a, long b, long c)
......@@ -59,14 +59,14 @@ static inline long __syscall3(long n, long a, long b, long c)
5959 register long r5 __asm__("$5") = b;
6060 register long r6 __asm__("$6") = c;
6161 register long r7 __asm__("$7");
62 register long r2 __asm__("$2") = n;
62 register long r2 __asm__("$2");
6363
6464 __asm__ __volatile__ (
65 "syscall"
66 : "+&r"(r2), "=r"(r7)
67 : "r"(r4), "r"(r5), "r"(r6)
65 "daddu $2,$0,%2 ; syscall"
66 : "=&r"(r2), "=r"(r7)
67 : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
6868 : SYSCALL_CLOBBERLIST);
69 return r7 ? -r2 : r2;
69 return r7 && r2>0 ? -r2 : r2;
7070}
7171
7272static inline long __syscall4(long n, long a, long b, long c, long d)
......@@ -75,14 +75,14 @@ static inline long __syscall4(long n, long a, long b, long c, long d)
7575 register long r5 __asm__("$5") = b;
7676 register long r6 __asm__("$6") = c;
7777 register long r7 __asm__("$7") = d;
78 register long r2 __asm__("$2") = n;
78 register long r2 __asm__("$2");
7979
8080 __asm__ __volatile__ (
81 "syscall"
82 : "+&r"(r2), "+r"(r7)
83 : "r"(r4), "r"(r5), "r"(r6)
81 "daddu $2,$0,%2 ; syscall"
82 : "=&r"(r2), "+r"(r7)
83 : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6)
8484 : SYSCALL_CLOBBERLIST);
85 return r7 ? -r2 : r2;
85 return r7 && r2>0 ? -r2 : r2;
8686}
8787
8888static inline long __syscall5(long n, long a, long b, long c, long d, long e)
......@@ -92,14 +92,14 @@ static inline long __syscall5(long n, long a, long b, long c, long d, long e)
9292 register long r6 __asm__("$6") = c;
9393 register long r7 __asm__("$7") = d;
9494 register long r8 __asm__("$8") = e;
95 register long r2 __asm__("$2") = n;
95 register long r2 __asm__("$2");
9696
9797 __asm__ __volatile__ (
98 "syscall"
99 : "+&r"(r2), "+r"(r7)
100 : "r"(r4), "r"(r5), "r"(r6), "r"(r8)
98 "daddu $2,$0,%2 ; syscall"
99 : "=&r"(r2), "+r"(r7)
100 : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8)
101101 : SYSCALL_CLOBBERLIST);
102 return r7 ? -r2 : r2;
102 return r7 && r2>0 ? -r2 : r2;
103103}
104104
105105static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
......@@ -110,14 +110,14 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
110110 register long r7 __asm__("$7") = d;
111111 register long r8 __asm__("$8") = e;
112112 register long r9 __asm__("$9") = f;
113 register long r2 __asm__("$2") = n;
113 register long r2 __asm__("$2");
114114
115115 __asm__ __volatile__ (
116 "syscall"
117 : "+&r"(r2), "+r"(r7)
118 : "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
116 "daddu $2,$0,%2 ; syscall"
117 : "=&r"(r2), "+r"(r7)
118 : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9)
119119 : SYSCALL_CLOBBERLIST);
120 return r7 ? -r2 : r2;
120 return r7 && r2>0 ? -r2 : r2;
121121}
122122
123123#define VDSO_USEFUL
lib/libc/musl/arch/powerpc/bits/mman.h-1
......@@ -4,7 +4,6 @@
44#define MAP_NORESERVE 0x40
55#undef MAP_LOCKED
66#define MAP_LOCKED 0x80
7#undef MAP_SYNC
87
98#undef MCL_CURRENT
109#define MCL_CURRENT 0x2000
lib/libc/musl/arch/powerpc64/bits/mman.h-1
......@@ -4,7 +4,6 @@
44#define MAP_NORESERVE 0x40
55#undef MAP_LOCKED
66#define MAP_LOCKED 0x80
7#undef MAP_SYNC
87
98#undef MCL_CURRENT
109#define MCL_CURRENT 0x2000
lib/libc/musl/include/arpa/inet.h-5
......@@ -24,11 +24,6 @@ struct in_addr inet_makeaddr(in_addr_t, in_addr_t);
2424in_addr_t inet_lnaof(struct in_addr);
2525in_addr_t inet_netof(struct in_addr);
2626
27#undef INET_ADDRSTRLEN
28#undef INET6_ADDRSTRLEN
29#define INET_ADDRSTRLEN 16
30#define INET6_ADDRSTRLEN 46
31
3227#ifdef __cplusplus
3328}
3429#endif
lib/libc/musl/include/netinet/in.h-2
......@@ -60,8 +60,6 @@ struct ipv6_mreq {
6060
6161extern const struct in6_addr in6addr_any, in6addr_loopback;
6262
63#undef INET_ADDRSTRLEN
64#undef INET6_ADDRSTRLEN
6563#define INET_ADDRSTRLEN 16
6664#define INET6_ADDRSTRLEN 46
6765
lib/libc/musl/include/pthread.h+3
......@@ -74,6 +74,9 @@ extern "C" {
7474#define PTHREAD_BARRIER_SERIAL_THREAD (-1)
7575
7676
77#define PTHREAD_NULL ((pthread_t)0)
78
79
7780int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict);
7881int pthread_detach(pthread_t);
7982_Noreturn void pthread_exit(void *);
lib/libc/musl/src/errno/__strerror.h+6-7
......@@ -1,8 +1,9 @@
1/* This file is sorted such that 'errors' which represent exceptional
2 * conditions under which a correct program may fail come first, followed
3 * by messages that indicate an incorrect program or system failure. The
4 * macro E() along with double-inclusion is used to ensure that ordering
5 * of the strings remains synchronized. */
1/* The first entry is a catch-all for codes not enumerated here.
2 * This file is included multiple times to declare and define a structure
3 * with these messages, and then to define a lookup table translating
4 * error codes to offsets of corresponding fields in the structure. */
5
6E(0, "No error information")
67
78E(EILSEQ, "Illegal byte sequence")
89E(EDOM, "Domain error")
......@@ -101,5 +102,3 @@ E(EDQUOT, "Quota exceeded")
101102E(ENOMEDIUM, "No medium found")
102103E(EMEDIUMTYPE, "Wrong medium type")
103104E(EMULTIHOP, "Multihop attempted")
104
105E(0, "No error information")
lib/libc/musl/src/errno/strerror.c+26-15
......@@ -1,30 +1,41 @@
11#include <errno.h>
2#include <stddef.h>
23#include <string.h>
34#include "locale_impl.h"
45
5#define E(a,b) ((unsigned char)a),
6static const unsigned char errid[] = {
6/* mips has one error code outside of the 8-bit range due to a
7 * historical typo, so we just remap it. */
8#if EDQUOT==1133
9#define EDQUOT_ORIG 1133
10#undef EDQUOT
11#define EDQUOT 109
12#endif
13
14static const struct errmsgstr_t {
15#define E(n, s) char str##n[sizeof(s)];
16#include "__strerror.h"
17#undef E
18} errmsgstr = {
19#define E(n, s) s,
720#include "__strerror.h"
21#undef E
822};
923
10#undef E
11#define E(a,b) b "\0"
12static const char errmsg[] =
24static const unsigned short errmsgidx[] = {
25#define E(n, s) [n] = offsetof(struct errmsgstr_t, str##n),
1326#include "__strerror.h"
14;
27#undef E
28};
1529
1630char *__strerror_l(int e, locale_t loc)
1731{
1832 const char *s;
19 int i;
20 /* mips has one error code outside of the 8-bit range due to a
21 * historical typo, so we just remap it. */
22 if (EDQUOT==1133) {
23 if (e==109) e=-1;
24 else if (e==EDQUOT) e=109;
25 }
26 for (i=0; errid[i] && errid[i] != e; i++);
27 for (s=errmsg; i; s++, i--) for (; *s; s++);
33#ifdef EDQUOT_ORIG
34 if (e==EDQUOT) e=0;
35 else if (e==EDQUOT_ORIG) e=EDQUOT;
36#endif
37 if (e >= sizeof errmsgidx / sizeof *errmsgidx) e = 0;
38 s = (char *)&errmsgstr + errmsgidx[e];
2839 return (char *)LCTRANS(s, LC_MESSAGES, loc);
2940}
3041
lib/libc/musl/src/fenv/sh/fenv.S+2
......@@ -12,6 +12,8 @@ fegetround:
1212.type __fesetround, @function
1313__fesetround:
1414 sts fpscr, r0
15 mov #-4, r1
16 and r1, r0
1517 or r4, r0
1618 lds r0, fpscr
1719 rts
lib/libc/musl/src/internal/atomic.h+15
......@@ -315,4 +315,19 @@ static inline int a_clz_64(uint64_t x)
315315}
316316#endif
317317
318#ifndef a_clz_32
319#define a_clz_32 a_clz_32
320static inline int a_clz_32(uint32_t x)
321{
322 x >>= 1;
323 x |= x >> 1;
324 x |= x >> 2;
325 x |= x >> 4;
326 x |= x >> 8;
327 x |= x >> 16;
328 x++;
329 return 31-a_ctz_32(x);
330}
331#endif
332
318333#endif
lib/libc/musl/src/internal/dynlink.h+5
......@@ -105,4 +105,9 @@ hidden void __dl_vseterr(const char *, va_list);
105105
106106hidden ptrdiff_t __tlsdesc_static(), __tlsdesc_dynamic();
107107
108hidden extern int __malloc_replaced;
109hidden extern int __aligned_alloc_replaced;
110hidden void __malloc_donate(char *, char *);
111hidden int __malloc_allzerop(void *);
112
108113#endif
lib/libc/musl/src/internal/libc.h+5-4
......@@ -18,10 +18,11 @@ struct tls_module {
1818};
1919
2020struct __libc {
21 int can_do_threads;
22 int threaded;
23 int secure;
24 volatile int threads_minus_1;
21 char can_do_threads;
22 char threaded;
23 char secure;
24 volatile signed char need_locks;
25 int threads_minus_1;
2526 size_t *auxv;
2627 struct tls_module *tls_head;
2728 size_t tls_size, tls_align, tls_cnt;
lib/libc/musl/src/internal/libm.h+2-2
......@@ -236,13 +236,13 @@ hidden int __rem_pio2(double,double*);
236236hidden double __sin(double,double,int);
237237hidden double __cos(double,double);
238238hidden double __tan(double,double,int);
239hidden double __expo2(double);
239hidden double __expo2(double,double);
240240
241241hidden int __rem_pio2f(float,double*);
242242hidden float __sindf(double);
243243hidden float __cosdf(double);
244244hidden float __tandf(double,int);
245hidden float __expo2f(float);
245hidden float __expo2f(float,float);
246246
247247hidden int __rem_pio2l(long double, long double *);
248248hidden long double __sinl(long double, long double, int);
lib/libc/musl/src/internal/malloc_impl.h deleted-46
......@@ -1,46 +0,0 @@
1#ifndef MALLOC_IMPL_H
2#define MALLOC_IMPL_H
3
4#include <sys/mman.h>
5
6hidden void *__expand_heap(size_t *);
7
8hidden void __malloc_donate(char *, char *);
9
10hidden void *__memalign(size_t, size_t);
11
12struct chunk {
13 size_t psize, csize;
14 struct chunk *next, *prev;
15};
16
17struct bin {
18 volatile int lock[2];
19 struct chunk *head;
20 struct chunk *tail;
21};
22
23#define SIZE_ALIGN (4*sizeof(size_t))
24#define SIZE_MASK (-SIZE_ALIGN)
25#define OVERHEAD (2*sizeof(size_t))
26#define MMAP_THRESHOLD (0x1c00*SIZE_ALIGN)
27#define DONTCARE 16
28#define RECLAIM 163840
29
30#define CHUNK_SIZE(c) ((c)->csize & -2)
31#define CHUNK_PSIZE(c) ((c)->psize & -2)
32#define PREV_CHUNK(c) ((struct chunk *)((char *)(c) - CHUNK_PSIZE(c)))
33#define NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CHUNK_SIZE(c)))
34#define MEM_TO_CHUNK(p) (struct chunk *)((char *)(p) - OVERHEAD)
35#define CHUNK_TO_MEM(c) (void *)((char *)(c) + OVERHEAD)
36#define BIN_TO_CHUNK(i) (MEM_TO_CHUNK(&mal.bins[i].head))
37
38#define C_INUSE ((size_t)1)
39
40#define IS_MMAPPED(c) !((c)->csize & (C_INUSE))
41
42hidden void __bin_chunk(struct chunk *);
43
44hidden extern int __malloc_replaced;
45
46#endif
lib/libc/musl/src/internal/shgetc.c+1-1
......@@ -32,6 +32,6 @@ int __shgetc(FILE *f)
3232 else
3333 f->shend = f->rend;
3434 f->shcnt = f->buf - f->rpos + cnt;
35 if (f->rpos[-1] != c) f->rpos[-1] = c;
35 if (f->rpos <= f->buf) f->rpos[-1] = c;
3636 return c;
3737}
lib/libc/musl/src/internal/stdio_impl.h-2
......@@ -60,8 +60,6 @@ hidden size_t __stdout_write(FILE *, const unsigned char *, size_t);
6060hidden off_t __stdio_seek(FILE *, off_t, int);
6161hidden int __stdio_close(FILE *);
6262
63hidden size_t __string_read(FILE *, unsigned char *, size_t);
64
6563hidden int __toread(FILE *);
6664hidden int __towrite(FILE *);
6765
lib/libc/musl/src/internal/version.h+1-1
......@@ -1 +1 @@
1#define VERSION "1.2.0"
1#define VERSION "1.2.1"
lib/libc/musl/src/ipc/msgctl.c+10
......@@ -9,6 +9,14 @@
99
1010int msgctl(int q, int cmd, struct msqid_ds *buf)
1111{
12#if IPC_TIME64
13 struct msqid_ds out, *orig;
14 if (cmd&IPC_TIME64) {
15 out = (struct msqid_ds){0};
16 orig = buf;
17 buf = &out;
18 }
19#endif
1220#ifdef SYSCALL_IPC_BROKEN_MODE
1321 struct msqid_ds tmp;
1422 if (cmd == IPC_SET) {
......@@ -32,6 +40,8 @@ int msgctl(int q, int cmd, struct msqid_ds *buf)
3240#endif
3341#if IPC_TIME64
3442 if (r >= 0 && (cmd&IPC_TIME64)) {
43 buf = orig;
44 *buf = out;
3545 IPC_HILO(buf, msg_stime);
3646 IPC_HILO(buf, msg_rtime);
3747 IPC_HILO(buf, msg_ctime);
lib/libc/musl/src/ipc/semctl.c+10
......@@ -28,6 +28,14 @@ int semctl(int id, int num, int cmd, ...)
2828 arg = va_arg(ap, union semun);
2929 va_end(ap);
3030 }
31#if IPC_TIME64
32 struct semid_ds out, *orig;
33 if (cmd&IPC_TIME64) {
34 out = (struct semid_ds){0};
35 orig = arg.buf;
36 arg.buf = &out;
37 }
38#endif
3139#ifdef SYSCALL_IPC_BROKEN_MODE
3240 struct semid_ds tmp;
3341 if (cmd == IPC_SET) {
......@@ -51,6 +59,8 @@ int semctl(int id, int num, int cmd, ...)
5159#endif
5260#if IPC_TIME64
5361 if (r >= 0 && (cmd&IPC_TIME64)) {
62 arg.buf = orig;
63 *arg.buf = out;
5464 IPC_HILO(arg.buf, sem_otime);
5565 IPC_HILO(arg.buf, sem_ctime);
5666 }
lib/libc/musl/src/ipc/shmctl.c+10
......@@ -9,6 +9,14 @@
99
1010int shmctl(int id, int cmd, struct shmid_ds *buf)
1111{
12#if IPC_TIME64
13 struct shmid_ds out, *orig;
14 if (cmd&IPC_TIME64) {
15 out = (struct shmid_ds){0};
16 orig = buf;
17 buf = &out;
18 }
19#endif
1220#ifdef SYSCALL_IPC_BROKEN_MODE
1321 struct shmid_ds tmp;
1422 if (cmd == IPC_SET) {
......@@ -32,6 +40,8 @@ int shmctl(int id, int cmd, struct shmid_ds *buf)
3240#endif
3341#if IPC_TIME64
3442 if (r >= 0 && (cmd&IPC_TIME64)) {
43 buf = orig;
44 *buf = out;
3545 IPC_HILO(buf, shm_atime);
3646 IPC_HILO(buf, shm_dtime);
3747 IPC_HILO(buf, shm_ctime);
lib/libc/musl/src/linux/clock_adjtime.c+46-49
......@@ -38,55 +38,52 @@ int clock_adjtime (clockid_t clock_id, struct timex *utx)
3838{
3939 int r = -ENOSYS;
4040#ifdef SYS_clock_adjtime64
41 if (SYS_clock_adjtime == SYS_clock_adjtime64 ||
42 (utx->modes & ADJ_SETOFFSET) && !IS32BIT(utx->time.tv_sec)) {
43 struct ktimex64 ktx = {
44 .modes = utx->modes,
45 .offset = utx->offset,
46 .freq = utx->freq,
47 .maxerror = utx->maxerror,
48 .esterror = utx->esterror,
49 .status = utx->status,
50 .constant = utx->constant,
51 .precision = utx->precision,
52 .tolerance = utx->tolerance,
53 .time_sec = utx->time.tv_sec,
54 .time_usec = utx->time.tv_usec,
55 .tick = utx->tick,
56 .ppsfreq = utx->ppsfreq,
57 .jitter = utx->jitter,
58 .shift = utx->shift,
59 .stabil = utx->stabil,
60 .jitcnt = utx->jitcnt,
61 .calcnt = utx->calcnt,
62 .errcnt = utx->errcnt,
63 .stbcnt = utx->stbcnt,
64 .tai = utx->tai,
65 };
66 r = __syscall(SYS_clock_adjtime, clock_id, &ktx);
67 if (r>=0) {
68 utx->modes = ktx.modes;
69 utx->offset = ktx.offset;
70 utx->freq = ktx.freq;
71 utx->maxerror = ktx.maxerror;
72 utx->esterror = ktx.esterror;
73 utx->status = ktx.status;
74 utx->constant = ktx.constant;
75 utx->precision = ktx.precision;
76 utx->tolerance = ktx.tolerance;
77 utx->time.tv_sec = ktx.time_sec;
78 utx->time.tv_usec = ktx.time_usec;
79 utx->tick = ktx.tick;
80 utx->ppsfreq = ktx.ppsfreq;
81 utx->jitter = ktx.jitter;
82 utx->shift = ktx.shift;
83 utx->stabil = ktx.stabil;
84 utx->jitcnt = ktx.jitcnt;
85 utx->calcnt = ktx.calcnt;
86 utx->errcnt = ktx.errcnt;
87 utx->stbcnt = ktx.stbcnt;
88 utx->tai = ktx.tai;
89 }
41 struct ktimex64 ktx = {
42 .modes = utx->modes,
43 .offset = utx->offset,
44 .freq = utx->freq,
45 .maxerror = utx->maxerror,
46 .esterror = utx->esterror,
47 .status = utx->status,
48 .constant = utx->constant,
49 .precision = utx->precision,
50 .tolerance = utx->tolerance,
51 .time_sec = utx->time.tv_sec,
52 .time_usec = utx->time.tv_usec,
53 .tick = utx->tick,
54 .ppsfreq = utx->ppsfreq,
55 .jitter = utx->jitter,
56 .shift = utx->shift,
57 .stabil = utx->stabil,
58 .jitcnt = utx->jitcnt,
59 .calcnt = utx->calcnt,
60 .errcnt = utx->errcnt,
61 .stbcnt = utx->stbcnt,
62 .tai = utx->tai,
63 };
64 r = __syscall(SYS_clock_adjtime64, clock_id, &ktx);
65 if (r>=0) {
66 utx->modes = ktx.modes;
67 utx->offset = ktx.offset;
68 utx->freq = ktx.freq;
69 utx->maxerror = ktx.maxerror;
70 utx->esterror = ktx.esterror;
71 utx->status = ktx.status;
72 utx->constant = ktx.constant;
73 utx->precision = ktx.precision;
74 utx->tolerance = ktx.tolerance;
75 utx->time.tv_sec = ktx.time_sec;
76 utx->time.tv_usec = ktx.time_usec;
77 utx->tick = ktx.tick;
78 utx->ppsfreq = ktx.ppsfreq;
79 utx->jitter = ktx.jitter;
80 utx->shift = ktx.shift;
81 utx->stabil = ktx.stabil;
82 utx->jitcnt = ktx.jitcnt;
83 utx->calcnt = ktx.calcnt;
84 utx->errcnt = ktx.errcnt;
85 utx->stbcnt = ktx.stbcnt;
86 utx->tai = ktx.tai;
9087 }
9188 if (SYS_clock_adjtime == SYS_clock_adjtime64 || r!=-ENOSYS)
9289 return __syscall_ret(r);
lib/libc/musl/src/malloc/DESIGN deleted-22
......@@ -1,22 +0,0 @@
1
2
3In principle, this memory allocator is roughly equivalent to Doug
4Lea's dlmalloc with fine-grained locking.
5
6
7
8malloc:
9
10Uses a freelist binned by chunk size, with a bitmap to optimize
11searching for the smallest non-empty bin which can satisfy an
12allocation. If no free chunks are available, it creates a new chunk of
13the requested size and attempts to merge it with any existing free
14chunk immediately below the newly created chunk.
15
16Whether the chunk was obtained from a bin or newly created, it's
17likely to be larger than the requested allocation. malloc always
18finishes its work by passing the new chunk to realloc, which will
19split it into two chunks and free the tail portion.
20
21
22
lib/libc/musl/src/malloc/aligned_alloc.c deleted-7
......@@ -1,7 +0,0 @@
1#include <stdlib.h>
2#include "malloc_impl.h"
3
4void *aligned_alloc(size_t align, size_t len)
5{
6 return __memalign(align, len);
7}
lib/libc/musl/src/malloc/calloc.c created+45
......@@ -0,0 +1,45 @@
1#include <stdlib.h>
2#include <stdint.h>
3#include <string.h>
4#include <errno.h>
5#include "dynlink.h"
6
7static size_t mal0_clear(char *p, size_t n)
8{
9 const size_t pagesz = 4096; /* arbitrary */
10 if (n < pagesz) return n;
11#ifdef __GNUC__
12 typedef uint64_t __attribute__((__may_alias__)) T;
13#else
14 typedef unsigned char T;
15#endif
16 char *pp = p + n;
17 size_t i = (uintptr_t)pp & (pagesz - 1);
18 for (;;) {
19 pp = memset(pp - i, 0, i);
20 if (pp - p < pagesz) return pp - p;
21 for (i = pagesz; i; i -= 2*sizeof(T), pp -= 2*sizeof(T))
22 if (((T *)pp)[-1] | ((T *)pp)[-2])
23 break;
24 }
25}
26
27static int allzerop(void *p)
28{
29 return 0;
30}
31weak_alias(allzerop, __malloc_allzerop);
32
33void *calloc(size_t m, size_t n)
34{
35 if (n && m > (size_t)-1/n) {
36 errno = ENOMEM;
37 return 0;
38 }
39 n *= m;
40 void *p = malloc(n);
41 if (!p || (!__malloc_replaced && __malloc_allzerop(p)))
42 return p;
43 n = mal0_clear(p, n);
44 return memset(p, 0, n);
45}
lib/libc/musl/src/malloc/expand_heap.c deleted-71
......@@ -1,71 +0,0 @@
1#include <limits.h>
2#include <stdint.h>
3#include <errno.h>
4#include <sys/mman.h>
5#include "libc.h"
6#include "syscall.h"
7#include "malloc_impl.h"
8
9/* This function returns true if the interval [old,new]
10 * intersects the 'len'-sized interval below &libc.auxv
11 * (interpreted as the main-thread stack) or below &b
12 * (the current stack). It is used to defend against
13 * buggy brk implementations that can cross the stack. */
14
15static int traverses_stack_p(uintptr_t old, uintptr_t new)
16{
17 const uintptr_t len = 8<<20;
18 uintptr_t a, b;
19
20 b = (uintptr_t)libc.auxv;
21 a = b > len ? b-len : 0;
22 if (new>a && old<b) return 1;
23
24 b = (uintptr_t)&b;
25 a = b > len ? b-len : 0;
26 if (new>a && old<b) return 1;
27
28 return 0;
29}
30
31/* Expand the heap in-place if brk can be used, or otherwise via mmap,
32 * using an exponential lower bound on growth by mmap to make
33 * fragmentation asymptotically irrelevant. The size argument is both
34 * an input and an output, since the caller needs to know the size
35 * allocated, which will be larger than requested due to page alignment
36 * and mmap minimum size rules. The caller is responsible for locking
37 * to prevent concurrent calls. */
38
39void *__expand_heap(size_t *pn)
40{
41 static uintptr_t brk;
42 static unsigned mmap_step;
43 size_t n = *pn;
44
45 if (n > SIZE_MAX/2 - PAGE_SIZE) {
46 errno = ENOMEM;
47 return 0;
48 }
49 n += -n & PAGE_SIZE-1;
50
51 if (!brk) {
52 brk = __syscall(SYS_brk, 0);
53 brk += -brk & PAGE_SIZE-1;
54 }
55
56 if (n < SIZE_MAX-brk && !traverses_stack_p(brk, brk+n)
57 && __syscall(SYS_brk, brk+n)==brk+n) {
58 *pn = n;
59 brk += n;
60 return (void *)(brk-n);
61 }
62
63 size_t min = (size_t)PAGE_SIZE << mmap_step/2;
64 if (n < min) n = min;
65 void *area = __mmap(0, n, PROT_READ|PROT_WRITE,
66 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
67 if (area == MAP_FAILED) return 0;
68 *pn = n;
69 mmap_step++;
70 return area;
71}
lib/libc/musl/src/malloc/lite_malloc.c+72-28
......@@ -2,58 +2,102 @@
22#include <stdint.h>
33#include <limits.h>
44#include <errno.h>
5#include <sys/mman.h>
6#include "libc.h"
57#include "lock.h"
6#include "malloc_impl.h"
8#include "syscall.h"
79
810#define ALIGN 16
911
12/* This function returns true if the interval [old,new]
13 * intersects the 'len'-sized interval below &libc.auxv
14 * (interpreted as the main-thread stack) or below &b
15 * (the current stack). It is used to defend against
16 * buggy brk implementations that can cross the stack. */
17
18static int traverses_stack_p(uintptr_t old, uintptr_t new)
19{
20 const uintptr_t len = 8<<20;
21 uintptr_t a, b;
22
23 b = (uintptr_t)libc.auxv;
24 a = b > len ? b-len : 0;
25 if (new>a && old<b) return 1;
26
27 b = (uintptr_t)&b;
28 a = b > len ? b-len : 0;
29 if (new>a && old<b) return 1;
30
31 return 0;
32}
33
1034static void *__simple_malloc(size_t n)
1135{
12 static char *cur, *end;
36 static uintptr_t brk, cur, end;
1337 static volatile int lock[1];
14 size_t align=1, pad;
38 static unsigned mmap_step;
39 size_t align=1;
1540 void *p;
1641
42 if (n > SIZE_MAX/2) {
43 errno = ENOMEM;
44 return 0;
45 }
46
1747 if (!n) n++;
1848 while (align<n && align<ALIGN)
1949 align += align;
2050
2151 LOCK(lock);
2252
23 pad = -(uintptr_t)cur & align-1;
24
25 if (n <= SIZE_MAX/2 + ALIGN) n += pad;
53 cur += -cur & align-1;
2654
2755 if (n > end-cur) {
28 size_t m = n;
29 char *new = __expand_heap(&m);
30 if (!new) {
31 UNLOCK(lock);
32 return 0;
56 size_t req = n - (end-cur) + PAGE_SIZE-1 & -PAGE_SIZE;
57
58 if (!cur) {
59 brk = __syscall(SYS_brk, 0);
60 brk += -brk & PAGE_SIZE-1;
61 cur = end = brk;
3362 }
34 if (new != end) {
35 cur = new;
36 n -= pad;
37 pad = 0;
63
64 if (brk == end && req < SIZE_MAX-brk
65 && !traverses_stack_p(brk, brk+req)
66 && __syscall(SYS_brk, brk+req)==brk+req) {
67 brk = end += req;
68 } else {
69 int new_area = 0;
70 req = n + PAGE_SIZE-1 & -PAGE_SIZE;
71 /* Only make a new area rather than individual mmap
72 * if wasted space would be over 1/8 of the map. */
73 if (req-n > req/8) {
74 /* Geometric area size growth up to 64 pages,
75 * bounding waste by 1/8 of the area. */
76 size_t min = PAGE_SIZE<<(mmap_step/2);
77 if (min-n > end-cur) {
78 if (req < min) {
79 req = min;
80 if (mmap_step < 12)
81 mmap_step++;
82 }
83 new_area = 1;
84 }
85 }
86 void *mem = __mmap(0, req, PROT_READ|PROT_WRITE,
87 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
88 if (mem == MAP_FAILED || !new_area) {
89 UNLOCK(lock);
90 return mem==MAP_FAILED ? 0 : mem;
91 }
92 cur = (uintptr_t)mem;
93 end = cur + req;
3894 }
39 end = new + m;
4095 }
4196
42 p = cur + pad;
97 p = (void *)cur;
4398 cur += n;
4499 UNLOCK(lock);
45100 return p;
46101}
47102
48103weak_alias(__simple_malloc, malloc);
49
50static void *__simple_calloc(size_t m, size_t n)
51{
52 if (n && m > (size_t)-1/n) {
53 errno = ENOMEM;
54 return 0;
55 }
56 return __simple_malloc(n * m);
57}
58
59weak_alias(__simple_calloc, calloc);
lib/libc/musl/src/malloc/malloc.c deleted-548
......@@ -1,548 +0,0 @@
1#define _GNU_SOURCE
2#include <stdlib.h>
3#include <string.h>
4#include <limits.h>
5#include <stdint.h>
6#include <errno.h>
7#include <sys/mman.h>
8#include "libc.h"
9#include "atomic.h"
10#include "pthread_impl.h"
11#include "malloc_impl.h"
12
13#if defined(__GNUC__) && defined(__PIC__)
14#define inline inline __attribute__((always_inline))
15#endif
16
17static struct {
18 volatile uint64_t binmap;
19 struct bin bins[64];
20 volatile int free_lock[2];
21} mal;
22
23int __malloc_replaced;
24
25/* Synchronization tools */
26
27static inline void lock(volatile int *lk)
28{
29 if (libc.threads_minus_1)
30 while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1);
31}
32
33static inline void unlock(volatile int *lk)
34{
35 if (lk[0]) {
36 a_store(lk, 0);
37 if (lk[1]) __wake(lk, 1, 1);
38 }
39}
40
41static inline void lock_bin(int i)
42{
43 lock(mal.bins[i].lock);
44 if (!mal.bins[i].head)
45 mal.bins[i].head = mal.bins[i].tail = BIN_TO_CHUNK(i);
46}
47
48static inline void unlock_bin(int i)
49{
50 unlock(mal.bins[i].lock);
51}
52
53static int first_set(uint64_t x)
54{
55#if 1
56 return a_ctz_64(x);
57#else
58 static const char debruijn64[64] = {
59 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
60 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
61 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
62 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
63 };
64 static const char debruijn32[32] = {
65 0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
66 31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
67 };
68 if (sizeof(long) < 8) {
69 uint32_t y = x;
70 if (!y) {
71 y = x>>32;
72 return 32 + debruijn32[(y&-y)*0x076be629 >> 27];
73 }
74 return debruijn32[(y&-y)*0x076be629 >> 27];
75 }
76 return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
77#endif
78}
79
80static const unsigned char bin_tab[60] = {
81 32,33,34,35,36,36,37,37,38,38,39,39,
82 40,40,40,40,41,41,41,41,42,42,42,42,43,43,43,43,
83 44,44,44,44,44,44,44,44,45,45,45,45,45,45,45,45,
84 46,46,46,46,46,46,46,46,47,47,47,47,47,47,47,47,
85};
86
87static int bin_index(size_t x)
88{
89 x = x / SIZE_ALIGN - 1;
90 if (x <= 32) return x;
91 if (x < 512) return bin_tab[x/8-4];
92 if (x > 0x1c00) return 63;
93 return bin_tab[x/128-4] + 16;
94}
95
96static int bin_index_up(size_t x)
97{
98 x = x / SIZE_ALIGN - 1;
99 if (x <= 32) return x;
100 x--;
101 if (x < 512) return bin_tab[x/8-4] + 1;
102 return bin_tab[x/128-4] + 17;
103}
104
105#if 0
106void __dump_heap(int x)
107{
108 struct chunk *c;
109 int i;
110 for (c = (void *)mal.heap; CHUNK_SIZE(c); c = NEXT_CHUNK(c))
111 fprintf(stderr, "base %p size %zu (%d) flags %d/%d\n",
112 c, CHUNK_SIZE(c), bin_index(CHUNK_SIZE(c)),
113 c->csize & 15,
114 NEXT_CHUNK(c)->psize & 15);
115 for (i=0; i<64; i++) {
116 if (mal.bins[i].head != BIN_TO_CHUNK(i) && mal.bins[i].head) {
117 fprintf(stderr, "bin %d: %p\n", i, mal.bins[i].head);
118 if (!(mal.binmap & 1ULL<<i))
119 fprintf(stderr, "missing from binmap!\n");
120 } else if (mal.binmap & 1ULL<<i)
121 fprintf(stderr, "binmap wrongly contains %d!\n", i);
122 }
123}
124#endif
125
126static struct chunk *expand_heap(size_t n)
127{
128 static int heap_lock[2];
129 static void *end;
130 void *p;
131 struct chunk *w;
132
133 /* The argument n already accounts for the caller's chunk
134 * overhead needs, but if the heap can't be extended in-place,
135 * we need room for an extra zero-sized sentinel chunk. */
136 n += SIZE_ALIGN;
137
138 lock(heap_lock);
139
140 p = __expand_heap(&n);
141 if (!p) {
142 unlock(heap_lock);
143 return 0;
144 }
145
146 /* If not just expanding existing space, we need to make a
147 * new sentinel chunk below the allocated space. */
148 if (p != end) {
149 /* Valid/safe because of the prologue increment. */
150 n -= SIZE_ALIGN;
151 p = (char *)p + SIZE_ALIGN;
152 w = MEM_TO_CHUNK(p);
153 w->psize = 0 | C_INUSE;
154 }
155
156 /* Record new heap end and fill in footer. */
157 end = (char *)p + n;
158 w = MEM_TO_CHUNK(end);
159 w->psize = n | C_INUSE;
160 w->csize = 0 | C_INUSE;
161
162 /* Fill in header, which may be new or may be replacing a
163 * zero-size sentinel header at the old end-of-heap. */
164 w = MEM_TO_CHUNK(p);
165 w->csize = n | C_INUSE;
166
167 unlock(heap_lock);
168
169 return w;
170}
171
172static int adjust_size(size_t *n)
173{
174 /* Result of pointer difference must fit in ptrdiff_t. */
175 if (*n-1 > PTRDIFF_MAX - SIZE_ALIGN - PAGE_SIZE) {
176 if (*n) {
177 errno = ENOMEM;
178 return -1;
179 } else {
180 *n = SIZE_ALIGN;
181 return 0;
182 }
183 }
184 *n = (*n + OVERHEAD + SIZE_ALIGN - 1) & SIZE_MASK;
185 return 0;
186}
187
188static void unbin(struct chunk *c, int i)
189{
190 if (c->prev == c->next)
191 a_and_64(&mal.binmap, ~(1ULL<<i));
192 c->prev->next = c->next;
193 c->next->prev = c->prev;
194 c->csize |= C_INUSE;
195 NEXT_CHUNK(c)->psize |= C_INUSE;
196}
197
198static int alloc_fwd(struct chunk *c)
199{
200 int i;
201 size_t k;
202 while (!((k=c->csize) & C_INUSE)) {
203 i = bin_index(k);
204 lock_bin(i);
205 if (c->csize == k) {
206 unbin(c, i);
207 unlock_bin(i);
208 return 1;
209 }
210 unlock_bin(i);
211 }
212 return 0;
213}
214
215static int alloc_rev(struct chunk *c)
216{
217 int i;
218 size_t k;
219 while (!((k=c->psize) & C_INUSE)) {
220 i = bin_index(k);
221 lock_bin(i);
222 if (c->psize == k) {
223 unbin(PREV_CHUNK(c), i);
224 unlock_bin(i);
225 return 1;
226 }
227 unlock_bin(i);
228 }
229 return 0;
230}
231
232
233/* pretrim - trims a chunk _prior_ to removing it from its bin.
234 * Must be called with i as the ideal bin for size n, j the bin
235 * for the _free_ chunk self, and bin j locked. */
236static int pretrim(struct chunk *self, size_t n, int i, int j)
237{
238 size_t n1;
239 struct chunk *next, *split;
240
241 /* We cannot pretrim if it would require re-binning. */
242 if (j < 40) return 0;
243 if (j < i+3) {
244 if (j != 63) return 0;
245 n1 = CHUNK_SIZE(self);
246 if (n1-n <= MMAP_THRESHOLD) return 0;
247 } else {
248 n1 = CHUNK_SIZE(self);
249 }
250 if (bin_index(n1-n) != j) return 0;
251
252 next = NEXT_CHUNK(self);
253 split = (void *)((char *)self + n);
254
255 split->prev = self->prev;
256 split->next = self->next;
257 split->prev->next = split;
258 split->next->prev = split;
259 split->psize = n | C_INUSE;
260 split->csize = n1-n;
261 next->psize = n1-n;
262 self->csize = n | C_INUSE;
263 return 1;
264}
265
266static void trim(struct chunk *self, size_t n)
267{
268 size_t n1 = CHUNK_SIZE(self);
269 struct chunk *next, *split;
270
271 if (n >= n1 - DONTCARE) return;
272
273 next = NEXT_CHUNK(self);
274 split = (void *)((char *)self + n);
275
276 split->psize = n | C_INUSE;
277 split->csize = n1-n | C_INUSE;
278 next->psize = n1-n | C_INUSE;
279 self->csize = n | C_INUSE;
280
281 __bin_chunk(split);
282}
283
284void *malloc(size_t n)
285{
286 struct chunk *c;
287 int i, j;
288
289 if (adjust_size(&n) < 0) return 0;
290
291 if (n > MMAP_THRESHOLD) {
292 size_t len = n + OVERHEAD + PAGE_SIZE - 1 & -PAGE_SIZE;
293 char *base = __mmap(0, len, PROT_READ|PROT_WRITE,
294 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
295 if (base == (void *)-1) return 0;
296 c = (void *)(base + SIZE_ALIGN - OVERHEAD);
297 c->csize = len - (SIZE_ALIGN - OVERHEAD);
298 c->psize = SIZE_ALIGN - OVERHEAD;
299 return CHUNK_TO_MEM(c);
300 }
301
302 i = bin_index_up(n);
303 for (;;) {
304 uint64_t mask = mal.binmap & -(1ULL<<i);
305 if (!mask) {
306 c = expand_heap(n);
307 if (!c) return 0;
308 if (alloc_rev(c)) {
309 struct chunk *x = c;
310 c = PREV_CHUNK(c);
311 NEXT_CHUNK(x)->psize = c->csize =
312 x->csize + CHUNK_SIZE(c);
313 }
314 break;
315 }
316 j = first_set(mask);
317 lock_bin(j);
318 c = mal.bins[j].head;
319 if (c != BIN_TO_CHUNK(j)) {
320 if (!pretrim(c, n, i, j)) unbin(c, j);
321 unlock_bin(j);
322 break;
323 }
324 unlock_bin(j);
325 }
326
327 /* Now patch up in case we over-allocated */
328 trim(c, n);
329
330 return CHUNK_TO_MEM(c);
331}
332
333static size_t mal0_clear(char *p, size_t pagesz, size_t n)
334{
335#ifdef __GNUC__
336 typedef uint64_t __attribute__((__may_alias__)) T;
337#else
338 typedef unsigned char T;
339#endif
340 char *pp = p + n;
341 size_t i = (uintptr_t)pp & (pagesz - 1);
342 for (;;) {
343 pp = memset(pp - i, 0, i);
344 if (pp - p < pagesz) return pp - p;
345 for (i = pagesz; i; i -= 2*sizeof(T), pp -= 2*sizeof(T))
346 if (((T *)pp)[-1] | ((T *)pp)[-2])
347 break;
348 }
349}
350
351void *calloc(size_t m, size_t n)
352{
353 if (n && m > (size_t)-1/n) {
354 errno = ENOMEM;
355 return 0;
356 }
357 n *= m;
358 void *p = malloc(n);
359 if (!p) return p;
360 if (!__malloc_replaced) {
361 if (IS_MMAPPED(MEM_TO_CHUNK(p)))
362 return p;
363 if (n >= PAGE_SIZE)
364 n = mal0_clear(p, PAGE_SIZE, n);
365 }
366 return memset(p, 0, n);
367}
368
369void *realloc(void *p, size_t n)
370{
371 struct chunk *self, *next;
372 size_t n0, n1;
373 void *new;
374
375 if (!p) return malloc(n);
376
377 if (adjust_size(&n) < 0) return 0;
378
379 self = MEM_TO_CHUNK(p);
380 n1 = n0 = CHUNK_SIZE(self);
381
382 if (IS_MMAPPED(self)) {
383 size_t extra = self->psize;
384 char *base = (char *)self - extra;
385 size_t oldlen = n0 + extra;
386 size_t newlen = n + extra;
387 /* Crash on realloc of freed chunk */
388 if (extra & 1) a_crash();
389 if (newlen < PAGE_SIZE && (new = malloc(n-OVERHEAD))) {
390 n0 = n;
391 goto copy_free_ret;
392 }
393 newlen = (newlen + PAGE_SIZE-1) & -PAGE_SIZE;
394 if (oldlen == newlen) return p;
395 base = __mremap(base, oldlen, newlen, MREMAP_MAYMOVE);
396 if (base == (void *)-1)
397 goto copy_realloc;
398 self = (void *)(base + extra);
399 self->csize = newlen - extra;
400 return CHUNK_TO_MEM(self);
401 }
402
403 next = NEXT_CHUNK(self);
404
405 /* Crash on corrupted footer (likely from buffer overflow) */
406 if (next->psize != self->csize) a_crash();
407
408 /* Merge adjacent chunks if we need more space. This is not
409 * a waste of time even if we fail to get enough space, because our
410 * subsequent call to free would otherwise have to do the merge. */
411 if (n > n1 && alloc_fwd(next)) {
412 n1 += CHUNK_SIZE(next);
413 next = NEXT_CHUNK(next);
414 }
415 /* FIXME: find what's wrong here and reenable it..? */
416 if (0 && n > n1 && alloc_rev(self)) {
417 self = PREV_CHUNK(self);
418 n1 += CHUNK_SIZE(self);
419 }
420 self->csize = n1 | C_INUSE;
421 next->psize = n1 | C_INUSE;
422
423 /* If we got enough space, split off the excess and return */
424 if (n <= n1) {
425 //memmove(CHUNK_TO_MEM(self), p, n0-OVERHEAD);
426 trim(self, n);
427 return CHUNK_TO_MEM(self);
428 }
429
430copy_realloc:
431 /* As a last resort, allocate a new chunk and copy to it. */
432 new = malloc(n-OVERHEAD);
433 if (!new) return 0;
434copy_free_ret:
435 memcpy(new, p, n0-OVERHEAD);
436 free(CHUNK_TO_MEM(self));
437 return new;
438}
439
440void __bin_chunk(struct chunk *self)
441{
442 struct chunk *next = NEXT_CHUNK(self);
443 size_t final_size, new_size, size;
444 int reclaim=0;
445 int i;
446
447 final_size = new_size = CHUNK_SIZE(self);
448
449 /* Crash on corrupted footer (likely from buffer overflow) */
450 if (next->psize != self->csize) a_crash();
451
452 for (;;) {
453 if (self->psize & next->csize & C_INUSE) {
454 self->csize = final_size | C_INUSE;
455 next->psize = final_size | C_INUSE;
456 i = bin_index(final_size);
457 lock_bin(i);
458 lock(mal.free_lock);
459 if (self->psize & next->csize & C_INUSE)
460 break;
461 unlock(mal.free_lock);
462 unlock_bin(i);
463 }
464
465 if (alloc_rev(self)) {
466 self = PREV_CHUNK(self);
467 size = CHUNK_SIZE(self);
468 final_size += size;
469 if (new_size+size > RECLAIM && (new_size+size^size) > size)
470 reclaim = 1;
471 }
472
473 if (alloc_fwd(next)) {
474 size = CHUNK_SIZE(next);
475 final_size += size;
476 if (new_size+size > RECLAIM && (new_size+size^size) > size)
477 reclaim = 1;
478 next = NEXT_CHUNK(next);
479 }
480 }
481
482 if (!(mal.binmap & 1ULL<<i))
483 a_or_64(&mal.binmap, 1ULL<<i);
484
485 self->csize = final_size;
486 next->psize = final_size;
487 unlock(mal.free_lock);
488
489 self->next = BIN_TO_CHUNK(i);
490 self->prev = mal.bins[i].tail;
491 self->next->prev = self;
492 self->prev->next = self;
493
494 /* Replace middle of large chunks with fresh zero pages */
495 if (reclaim) {
496 uintptr_t a = (uintptr_t)self + SIZE_ALIGN+PAGE_SIZE-1 & -PAGE_SIZE;
497 uintptr_t b = (uintptr_t)next - SIZE_ALIGN & -PAGE_SIZE;
498#if 1
499 __madvise((void *)a, b-a, MADV_DONTNEED);
500#else
501 __mmap((void *)a, b-a, PROT_READ|PROT_WRITE,
502 MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
503#endif
504 }
505
506 unlock_bin(i);
507}
508
509static void unmap_chunk(struct chunk *self)
510{
511 size_t extra = self->psize;
512 char *base = (char *)self - extra;
513 size_t len = CHUNK_SIZE(self) + extra;
514 /* Crash on double free */
515 if (extra & 1) a_crash();
516 __munmap(base, len);
517}
518
519void free(void *p)
520{
521 if (!p) return;
522
523 struct chunk *self = MEM_TO_CHUNK(p);
524
525 if (IS_MMAPPED(self))
526 unmap_chunk(self);
527 else
528 __bin_chunk(self);
529}
530
531void __malloc_donate(char *start, char *end)
532{
533 size_t align_start_up = (SIZE_ALIGN-1) & (-(uintptr_t)start - OVERHEAD);
534 size_t align_end_down = (SIZE_ALIGN-1) & (uintptr_t)end;
535
536 /* Getting past this condition ensures that the padding for alignment
537 * and header overhead will not overflow and will leave a nonzero
538 * multiple of SIZE_ALIGN bytes between start and end. */
539 if (end - start <= OVERHEAD + align_start_up + align_end_down)
540 return;
541 start += align_start_up + OVERHEAD;
542 end -= align_end_down;
543
544 struct chunk *c = MEM_TO_CHUNK(start), *n = MEM_TO_CHUNK(end);
545 c->psize = n->csize = C_INUSE;
546 c->csize = n->psize = C_INUSE | (end-start);
547 __bin_chunk(c);
548}
lib/libc/musl/src/malloc/malloc_usable_size.c deleted-9
......@@ -1,9 +0,0 @@
1#include <malloc.h>
2#include "malloc_impl.h"
3
4hidden void *(*const __realloc_dep)(void *, size_t) = realloc;
5
6size_t malloc_usable_size(void *p)
7{
8 return p ? CHUNK_SIZE(MEM_TO_CHUNK(p)) - OVERHEAD : 0;
9}
lib/libc/musl/src/malloc/mallocng/aligned_alloc.c created+57
......@@ -0,0 +1,57 @@
1#include <stdlib.h>
2#include <errno.h>
3#include "meta.h"
4
5void *aligned_alloc(size_t align, size_t len)
6{
7 if ((align & -align) != align) {
8 errno = EINVAL;
9 return 0;
10 }
11
12 if (len > SIZE_MAX - align || align >= (1ULL<<31)*UNIT) {
13 errno = ENOMEM;
14 return 0;
15 }
16
17 if (DISABLE_ALIGNED_ALLOC) {
18 errno = ENOMEM;
19 return 0;
20 }
21
22 if (align <= UNIT) align = UNIT;
23
24 unsigned char *p = malloc(len + align - UNIT);
25 struct meta *g = get_meta(p);
26 int idx = get_slot_index(p);
27 size_t stride = get_stride(g);
28 unsigned char *start = g->mem->storage + stride*idx;
29 unsigned char *end = g->mem->storage + stride*(idx+1) - IB;
30 size_t adj = -(uintptr_t)p & (align-1);
31
32 if (!adj) {
33 set_size(p, end, len);
34 return p;
35 }
36 p += adj;
37 uint32_t offset = (size_t)(p-g->mem->storage)/UNIT;
38 if (offset <= 0xffff) {
39 *(uint16_t *)(p-2) = offset;
40 p[-4] = 0;
41 } else {
42 // use a 32-bit offset if 16-bit doesn't fit. for this,
43 // 16-bit field must be zero, [-4] byte nonzero.
44 *(uint16_t *)(p-2) = 0;
45 *(uint32_t *)(p-8) = offset;
46 p[-4] = 1;
47 }
48 p[-3] = idx;
49 set_size(p, end, len);
50 // store offset to aligned enframing. this facilitates cycling
51 // offset and also iteration of heap for debugging/measurement.
52 // for extreme overalignment it won't fit but these are classless
53 // allocations anyway.
54 *(uint16_t *)(start - 2) = (size_t)(p-start)/UNIT;
55 start[-3] = 7<<5;
56 return p;
57}
lib/libc/musl/src/malloc/mallocng/donate.c created+39
......@@ -0,0 +1,39 @@
1#include <stdlib.h>
2#include <stdint.h>
3#include <limits.h>
4#include <string.h>
5#include <sys/mman.h>
6#include <errno.h>
7
8#include "meta.h"
9
10static void donate(unsigned char *base, size_t len)
11{
12 uintptr_t a = (uintptr_t)base;
13 uintptr_t b = a + len;
14 a += -a & (UNIT-1);
15 b -= b & (UNIT-1);
16 memset(base, 0, len);
17 for (int sc=47; sc>0 && b>a; sc-=4) {
18 if (b-a < (size_classes[sc]+1)*UNIT) continue;
19 struct meta *m = alloc_meta();
20 m->avail_mask = 0;
21 m->freed_mask = 1;
22 m->mem = (void *)a;
23 m->mem->meta = m;
24 m->last_idx = 0;
25 m->freeable = 0;
26 m->sizeclass = sc;
27 m->maplen = 0;
28 *((unsigned char *)m->mem+UNIT-4) = 0;
29 *((unsigned char *)m->mem+UNIT-3) = 255;
30 m->mem->storage[size_classes[sc]*UNIT-4] = 0;
31 queue(&ctx.active[sc], m);
32 a += (size_classes[sc]+1)*UNIT;
33 }
34}
35
36void __malloc_donate(char *start, char *end)
37{
38 donate((void *)start, end-start);
39}
lib/libc/musl/src/malloc/mallocng/free.c created+143
......@@ -0,0 +1,143 @@
1#define _BSD_SOURCE
2#include <stdlib.h>
3#include <sys/mman.h>
4
5#include "meta.h"
6
7struct mapinfo {
8 void *base;
9 size_t len;
10};
11
12static struct mapinfo nontrivial_free(struct meta *, int);
13
14static struct mapinfo free_group(struct meta *g)
15{
16 struct mapinfo mi = { 0 };
17 int sc = g->sizeclass;
18 if (sc < 48) {
19 ctx.usage_by_class[sc] -= g->last_idx+1;
20 }
21 if (g->maplen) {
22 step_seq();
23 record_seq(sc);
24 mi.base = g->mem;
25 mi.len = g->maplen*4096UL;
26 } else {
27 void *p = g->mem;
28 struct meta *m = get_meta(p);
29 int idx = get_slot_index(p);
30 g->mem->meta = 0;
31 // not checking size/reserved here; it's intentionally invalid
32 mi = nontrivial_free(m, idx);
33 }
34 free_meta(g);
35 return mi;
36}
37
38static int okay_to_free(struct meta *g)
39{
40 int sc = g->sizeclass;
41
42 if (!g->freeable) return 0;
43
44 // always free individual mmaps not suitable for reuse
45 if (sc >= 48 || get_stride(g) < UNIT*size_classes[sc])
46 return 1;
47
48 // always free groups allocated inside another group's slot
49 // since recreating them should not be expensive and they
50 // might be blocking freeing of a much larger group.
51 if (!g->maplen) return 1;
52
53 // if there is another non-full group, free this one to
54 // consolidate future allocations, reduce fragmentation.
55 if (g->next != g) return 1;
56
57 // free any group in a size class that's not bouncing
58 if (!is_bouncing(sc)) return 1;
59
60 size_t cnt = g->last_idx+1;
61 size_t usage = ctx.usage_by_class[sc];
62
63 // if usage is high enough that a larger count should be
64 // used, free the low-count group so a new one will be made.
65 if (9*cnt <= usage && cnt < 20)
66 return 1;
67
68 // otherwise, keep the last group in a bouncing class.
69 return 0;
70}
71
72static struct mapinfo nontrivial_free(struct meta *g, int i)
73{
74 uint32_t self = 1u<<i;
75 int sc = g->sizeclass;
76 uint32_t mask = g->freed_mask | g->avail_mask;
77
78 if (mask+self == (2u<<g->last_idx)-1 && okay_to_free(g)) {
79 // any multi-slot group is necessarily on an active list
80 // here, but single-slot groups might or might not be.
81 if (g->next) {
82 assert(sc < 48);
83 int activate_new = (ctx.active[sc]==g);
84 dequeue(&ctx.active[sc], g);
85 if (activate_new && ctx.active[sc])
86 activate_group(ctx.active[sc]);
87 }
88 return free_group(g);
89 } else if (!mask) {
90 assert(sc < 48);
91 // might still be active if there were no allocations
92 // after last available slot was taken.
93 if (ctx.active[sc] != g) {
94 queue(&ctx.active[sc], g);
95 }
96 }
97 a_or(&g->freed_mask, self);
98 return (struct mapinfo){ 0 };
99}
100
101void free(void *p)
102{
103 if (!p) return;
104
105 struct meta *g = get_meta(p);
106 int idx = get_slot_index(p);
107 size_t stride = get_stride(g);
108 unsigned char *start = g->mem->storage + stride*idx;
109 unsigned char *end = start + stride - IB;
110 get_nominal_size(p, end);
111 uint32_t self = 1u<<idx, all = (2u<<g->last_idx)-1;
112 ((unsigned char *)p)[-3] = 255;
113 // invalidate offset to group header, and cycle offset of
114 // used region within slot if current offset is zero.
115 *(uint16_t *)((char *)p-2) = 0;
116
117 // release any whole pages contained in the slot to be freed
118 // unless it's a single-slot group that will be unmapped.
119 if (((uintptr_t)(start-1) ^ (uintptr_t)end) >= 2*PGSZ && g->last_idx) {
120 unsigned char *base = start + (-(uintptr_t)start & (PGSZ-1));
121 size_t len = (end-base) & -PGSZ;
122 if (len) madvise(base, len, MADV_FREE);
123 }
124
125 // atomic free without locking if this is neither first or last slot
126 for (;;) {
127 uint32_t freed = g->freed_mask;
128 uint32_t avail = g->avail_mask;
129 uint32_t mask = freed | avail;
130 assert(!(mask&self));
131 if (!freed || mask+self==all) break;
132 if (!MT)
133 g->freed_mask = freed+self;
134 else if (a_cas(&g->freed_mask, freed, freed+self)!=freed)
135 continue;
136 return;
137 }
138
139 wrlock();
140 struct mapinfo mi = nontrivial_free(g, idx);
141 unlock();
142 if (mi.len) munmap(mi.base, mi.len);
143}
lib/libc/musl/src/malloc/mallocng/glue.h created+77
......@@ -0,0 +1,77 @@
1#ifndef MALLOC_GLUE_H
2#define MALLOC_GLUE_H
3
4#include <stdint.h>
5#include <sys/mman.h>
6#include <pthread.h>
7#include <unistd.h>
8#include <elf.h>
9#include <string.h>
10#include "atomic.h"
11#include "syscall.h"
12#include "libc.h"
13#include "lock.h"
14#include "dynlink.h"
15
16// use macros to appropriately namespace these.
17#define size_classes __malloc_size_classes
18#define ctx __malloc_context
19#define alloc_meta __malloc_alloc_meta
20#define is_allzero __malloc_allzerop
21#define dump_heap __dump_heap
22
23#if USE_REAL_ASSERT
24#include <assert.h>
25#else
26#undef assert
27#define assert(x) do { if (!(x)) a_crash(); } while(0)
28#endif
29
30#define brk(p) ((uintptr_t)__syscall(SYS_brk, p))
31
32#define mmap __mmap
33#define madvise __madvise
34#define mremap __mremap
35
36#define DISABLE_ALIGNED_ALLOC (__malloc_replaced && !__aligned_alloc_replaced)
37
38static inline uint64_t get_random_secret()
39{
40 uint64_t secret = (uintptr_t)&secret * 1103515245;
41 for (size_t i=0; libc.auxv[i]; i+=2)
42 if (libc.auxv[i]==AT_RANDOM)
43 memcpy(&secret, (char *)libc.auxv[i+1]+8, sizeof secret);
44 return secret;
45}
46
47#ifndef PAGESIZE
48#define PAGESIZE PAGE_SIZE
49#endif
50
51#define MT (libc.need_locks)
52
53#define RDLOCK_IS_EXCLUSIVE 1
54
55__attribute__((__visibility__("hidden")))
56extern int __malloc_lock[1];
57
58#define LOCK_OBJ_DEF \
59int __malloc_lock[1];
60
61static inline void rdlock()
62{
63 if (MT) LOCK(__malloc_lock);
64}
65static inline void wrlock()
66{
67 if (MT) LOCK(__malloc_lock);
68}
69static inline void unlock()
70{
71 UNLOCK(__malloc_lock);
72}
73static inline void upgradelock()
74{
75}
76
77#endif
lib/libc/musl/src/malloc/mallocng/malloc.c created+387
......@@ -0,0 +1,387 @@
1#include <stdlib.h>
2#include <stdint.h>
3#include <limits.h>
4#include <string.h>
5#include <sys/mman.h>
6#include <errno.h>
7
8#include "meta.h"
9
10LOCK_OBJ_DEF;
11
12const uint16_t size_classes[] = {
13 1, 2, 3, 4, 5, 6, 7, 8,
14 9, 10, 12, 15,
15 18, 20, 25, 31,
16 36, 42, 50, 63,
17 72, 84, 102, 127,
18 146, 170, 204, 255,
19 292, 340, 409, 511,
20 584, 682, 818, 1023,
21 1169, 1364, 1637, 2047,
22 2340, 2730, 3276, 4095,
23 4680, 5460, 6552, 8191,
24};
25
26static const uint8_t small_cnt_tab[][3] = {
27 { 30, 30, 30 },
28 { 31, 15, 15 },
29 { 20, 10, 10 },
30 { 31, 15, 7 },
31 { 25, 12, 6 },
32 { 21, 10, 5 },
33 { 18, 8, 4 },
34 { 31, 15, 7 },
35 { 28, 14, 6 },
36};
37
38static const uint8_t med_cnt_tab[4] = { 28, 24, 20, 32 };
39
40struct malloc_context ctx = { 0 };
41
42struct meta *alloc_meta(void)
43{
44 struct meta *m;
45 unsigned char *p;
46 if (!ctx.init_done) {
47#ifndef PAGESIZE
48 ctx.pagesize = get_page_size();
49#endif
50 ctx.secret = get_random_secret();
51 ctx.init_done = 1;
52 }
53 size_t pagesize = PGSZ;
54 if (pagesize < 4096) pagesize = 4096;
55 if ((m = dequeue_head(&ctx.free_meta_head))) return m;
56 if (!ctx.avail_meta_count) {
57 int need_unprotect = 1;
58 if (!ctx.avail_meta_area_count && ctx.brk!=-1) {
59 uintptr_t new = ctx.brk + pagesize;
60 int need_guard = 0;
61 if (!ctx.brk) {
62 need_guard = 1;
63 ctx.brk = brk(0);
64 // some ancient kernels returned _ebss
65 // instead of next page as initial brk.
66 ctx.brk += -ctx.brk & (pagesize-1);
67 new = ctx.brk + 2*pagesize;
68 }
69 if (brk(new) != new) {
70 ctx.brk = -1;
71 } else {
72 if (need_guard) mmap((void *)ctx.brk, pagesize,
73 PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
74 ctx.brk = new;
75 ctx.avail_meta_areas = (void *)(new - pagesize);
76 ctx.avail_meta_area_count = pagesize>>12;
77 need_unprotect = 0;
78 }
79 }
80 if (!ctx.avail_meta_area_count) {
81 size_t n = 2UL << ctx.meta_alloc_shift;
82 p = mmap(0, n*pagesize, PROT_NONE,
83 MAP_PRIVATE|MAP_ANON, -1, 0);
84 if (p==MAP_FAILED) return 0;
85 ctx.avail_meta_areas = p + pagesize;
86 ctx.avail_meta_area_count = (n-1)*(pagesize>>12);
87 ctx.meta_alloc_shift++;
88 }
89 p = ctx.avail_meta_areas;
90 if ((uintptr_t)p & (pagesize-1)) need_unprotect = 0;
91 if (need_unprotect)
92 if (mprotect(p, pagesize, PROT_READ|PROT_WRITE)
93 && errno != ENOSYS)
94 return 0;
95 ctx.avail_meta_area_count--;
96 ctx.avail_meta_areas = p + 4096;
97 if (ctx.meta_area_tail) {
98 ctx.meta_area_tail->next = (void *)p;
99 } else {
100 ctx.meta_area_head = (void *)p;
101 }
102 ctx.meta_area_tail = (void *)p;
103 ctx.meta_area_tail->check = ctx.secret;
104 ctx.avail_meta_count = ctx.meta_area_tail->nslots
105 = (4096-sizeof(struct meta_area))/sizeof *m;
106 ctx.avail_meta = ctx.meta_area_tail->slots;
107 }
108 ctx.avail_meta_count--;
109 m = ctx.avail_meta++;
110 m->prev = m->next = 0;
111 return m;
112}
113
114static uint32_t try_avail(struct meta **pm)
115{
116 struct meta *m = *pm;
117 uint32_t first;
118 if (!m) return 0;
119 uint32_t mask = m->avail_mask;
120 if (!mask) {
121 if (!m) return 0;
122 if (!m->freed_mask) {
123 dequeue(pm, m);
124 m = *pm;
125 if (!m) return 0;
126 } else {
127 m = m->next;
128 *pm = m;
129 }
130
131 mask = m->freed_mask;
132
133 // skip fully-free group unless it's the only one
134 // or it's a permanently non-freeable group
135 if (mask == (2u<<m->last_idx)-1 && m->freeable) {
136 m = m->next;
137 *pm = m;
138 mask = m->freed_mask;
139 }
140
141 // activate more slots in a not-fully-active group
142 // if needed, but only as a last resort. prefer using
143 // any other group with free slots. this avoids
144 // touching & dirtying as-yet-unused pages.
145 if (!(mask & ((2u<<m->mem->active_idx)-1))) {
146 if (m->next != m) {
147 m = m->next;
148 *pm = m;
149 } else {
150 int cnt = m->mem->active_idx + 2;
151 int size = size_classes[m->sizeclass]*UNIT;
152 int span = UNIT + size*cnt;
153 // activate up to next 4k boundary
154 while ((span^(span+size-1)) < 4096) {
155 cnt++;
156 span += size;
157 }
158 if (cnt > m->last_idx+1)
159 cnt = m->last_idx+1;
160 m->mem->active_idx = cnt-1;
161 }
162 }
163 mask = activate_group(m);
164 assert(mask);
165 decay_bounces(m->sizeclass);
166 }
167 first = mask&-mask;
168 m->avail_mask = mask-first;
169 return first;
170}
171
172static int alloc_slot(int, size_t);
173
174static struct meta *alloc_group(int sc, size_t req)
175{
176 size_t size = UNIT*size_classes[sc];
177 int i = 0, cnt;
178 unsigned char *p;
179 struct meta *m = alloc_meta();
180 if (!m) return 0;
181 size_t usage = ctx.usage_by_class[sc];
182 size_t pagesize = PGSZ;
183 int active_idx;
184 if (sc < 9) {
185 while (i<2 && 4*small_cnt_tab[sc][i] > usage)
186 i++;
187 cnt = small_cnt_tab[sc][i];
188 } else {
189 // lookup max number of slots fitting in power-of-two size
190 // from a table, along with number of factors of two we
191 // can divide out without a remainder or reaching 1.
192 cnt = med_cnt_tab[sc&3];
193
194 // reduce cnt to avoid excessive eagar allocation.
195 while (!(cnt&1) && 4*cnt > usage)
196 cnt >>= 1;
197
198 // data structures don't support groups whose slot offsets
199 // in units don't fit in 16 bits.
200 while (size*cnt >= 65536*UNIT)
201 cnt >>= 1;
202 }
203
204 // If we selected a count of 1 above but it's not sufficient to use
205 // mmap, increase to 2. Then it might be; if not it will nest.
206 if (cnt==1 && size*cnt+UNIT <= pagesize/2) cnt = 2;
207
208 // All choices of size*cnt are "just below" a power of two, so anything
209 // larger than half the page size should be allocated as whole pages.
210 if (size*cnt+UNIT > pagesize/2) {
211 // check/update bounce counter to start/increase retention
212 // of freed maps, and inhibit use of low-count, odd-size
213 // small mappings and single-slot groups if activated.
214 int nosmall = is_bouncing(sc);
215 account_bounce(sc);
216 step_seq();
217
218 // since the following count reduction opportunities have
219 // an absolute memory usage cost, don't overdo them. count
220 // coarse usage as part of usage.
221 if (!(sc&1) && sc<32) usage += ctx.usage_by_class[sc+1];
222
223 // try to drop to a lower count if the one found above
224 // increases usage by more than 25%. these reduced counts
225 // roughly fill an integral number of pages, just not a
226 // power of two, limiting amount of unusable space.
227 if (4*cnt > usage && !nosmall) {
228 if (0);
229 else if ((sc&3)==1 && size*cnt>8*pagesize) cnt = 2;
230 else if ((sc&3)==2 && size*cnt>4*pagesize) cnt = 3;
231 else if ((sc&3)==0 && size*cnt>8*pagesize) cnt = 3;
232 else if ((sc&3)==0 && size*cnt>2*pagesize) cnt = 5;
233 }
234 size_t needed = size*cnt + UNIT;
235 needed += -needed & (pagesize-1);
236
237 // produce an individually-mmapped allocation if usage is low,
238 // bounce counter hasn't triggered, and either it saves memory
239 // or it avoids eagar slot allocation without wasting too much.
240 if (!nosmall && cnt<=7) {
241 req += IB + UNIT;
242 req += -req & (pagesize-1);
243 if (req<size+UNIT || (req>=4*pagesize && 2*cnt>usage)) {
244 cnt = 1;
245 needed = req;
246 }
247 }
248
249 p = mmap(0, needed, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
250 if (p==MAP_FAILED) {
251 free_meta(m);
252 return 0;
253 }
254 m->maplen = needed>>12;
255 ctx.mmap_counter++;
256 active_idx = (4096-UNIT)/size-1;
257 if (active_idx > cnt-1) active_idx = cnt-1;
258 if (active_idx < 0) active_idx = 0;
259 } else {
260 int j = size_to_class(UNIT+cnt*size-IB);
261 int idx = alloc_slot(j, UNIT+cnt*size-IB);
262 if (idx < 0) {
263 free_meta(m);
264 return 0;
265 }
266 struct meta *g = ctx.active[j];
267 p = enframe(g, idx, UNIT*size_classes[j]-IB, ctx.mmap_counter);
268 m->maplen = 0;
269 p[-3] = (p[-3]&31) | (6<<5);
270 for (int i=0; i<=cnt; i++)
271 p[UNIT+i*size-4] = 0;
272 active_idx = cnt-1;
273 }
274 ctx.usage_by_class[sc] += cnt;
275 m->avail_mask = (2u<<active_idx)-1;
276 m->freed_mask = (2u<<(cnt-1))-1 - m->avail_mask;
277 m->mem = (void *)p;
278 m->mem->meta = m;
279 m->mem->active_idx = active_idx;
280 m->last_idx = cnt-1;
281 m->freeable = 1;
282 m->sizeclass = sc;
283 return m;
284}
285
286static int alloc_slot(int sc, size_t req)
287{
288 uint32_t first = try_avail(&ctx.active[sc]);
289 if (first) return a_ctz_32(first);
290
291 struct meta *g = alloc_group(sc, req);
292 if (!g) return -1;
293
294 g->avail_mask--;
295 queue(&ctx.active[sc], g);
296 return 0;
297}
298
299void *malloc(size_t n)
300{
301 if (size_overflows(n)) return 0;
302 struct meta *g;
303 uint32_t mask, first;
304 int sc;
305 int idx;
306 int ctr;
307
308 if (n >= MMAP_THRESHOLD) {
309 size_t needed = n + IB + UNIT;
310 void *p = mmap(0, needed, PROT_READ|PROT_WRITE,
311 MAP_PRIVATE|MAP_ANON, -1, 0);
312 if (p==MAP_FAILED) return 0;
313 wrlock();
314 step_seq();
315 g = alloc_meta();
316 if (!g) {
317 unlock();
318 munmap(p, needed);
319 return 0;
320 }
321 g->mem = p;
322 g->mem->meta = g;
323 g->last_idx = 0;
324 g->freeable = 1;
325 g->sizeclass = 63;
326 g->maplen = (needed+4095)/4096;
327 g->avail_mask = g->freed_mask = 0;
328 // use a global counter to cycle offset in
329 // individually-mmapped allocations.
330 ctx.mmap_counter++;
331 idx = 0;
332 goto success;
333 }
334
335 sc = size_to_class(n);
336
337 rdlock();
338 g = ctx.active[sc];
339
340 // use coarse size classes initially when there are not yet
341 // any groups of desired size. this allows counts of 2 or 3
342 // to be allocated at first rather than having to start with
343 // 7 or 5, the min counts for even size classes.
344 if (!g && sc>=4 && sc<32 && sc!=6 && !(sc&1) && !ctx.usage_by_class[sc]) {
345 size_t usage = ctx.usage_by_class[sc|1];
346 // if a new group may be allocated, count it toward
347 // usage in deciding if we can use coarse class.
348 if (!ctx.active[sc|1] || (!ctx.active[sc|1]->avail_mask
349 && !ctx.active[sc|1]->freed_mask))
350 usage += 3;
351 if (usage <= 12)
352 sc |= 1;
353 g = ctx.active[sc];
354 }
355
356 for (;;) {
357 mask = g ? g->avail_mask : 0;
358 first = mask&-mask;
359 if (!first) break;
360 if (RDLOCK_IS_EXCLUSIVE || !MT)
361 g->avail_mask = mask-first;
362 else if (a_cas(&g->avail_mask, mask, mask-first)!=mask)
363 continue;
364 idx = a_ctz_32(first);
365 goto success;
366 }
367 upgradelock();
368
369 idx = alloc_slot(sc, n);
370 if (idx < 0) {
371 unlock();
372 return 0;
373 }
374 g = ctx.active[sc];
375
376success:
377 ctr = ctx.mmap_counter;
378 unlock();
379 return enframe(g, idx, n, ctr);
380}
381
382int is_allzero(void *p)
383{
384 struct meta *g = get_meta(p);
385 return g->sizeclass >= 48 ||
386 get_stride(g) < UNIT*size_classes[g->sizeclass];
387}
lib/libc/musl/src/malloc/mallocng/malloc_usable_size.c created+12
......@@ -0,0 +1,12 @@
1#include <stdlib.h>
2#include "meta.h"
3
4size_t malloc_usable_size(void *p)
5{
6 struct meta *g = get_meta(p);
7 int idx = get_slot_index(p);
8 size_t stride = get_stride(g);
9 unsigned char *start = g->mem->storage + stride*idx;
10 unsigned char *end = start + stride - IB;
11 return get_nominal_size(p, end);
12}
lib/libc/musl/src/malloc/mallocng/meta.h created+288
......@@ -0,0 +1,288 @@
1#ifndef MALLOC_META_H
2#define MALLOC_META_H
3
4#include <stdint.h>
5#include <errno.h>
6#include <limits.h>
7#include "glue.h"
8
9__attribute__((__visibility__("hidden")))
10extern const uint16_t size_classes[];
11
12#define MMAP_THRESHOLD 131052
13
14#define UNIT 16
15#define IB 4
16
17struct group {
18 struct meta *meta;
19 unsigned char active_idx:5;
20 char pad[UNIT - sizeof(struct meta *) - 1];
21 unsigned char storage[];
22};
23
24struct meta {
25 struct meta *prev, *next;
26 struct group *mem;
27 volatile int avail_mask, freed_mask;
28 uintptr_t last_idx:5;
29 uintptr_t freeable:1;
30 uintptr_t sizeclass:6;
31 uintptr_t maplen:8*sizeof(uintptr_t)-12;
32};
33
34struct meta_area {
35 uint64_t check;
36 struct meta_area *next;
37 int nslots;
38 struct meta slots[];
39};
40
41struct malloc_context {
42 uint64_t secret;
43#ifndef PAGESIZE
44 size_t pagesize;
45#endif
46 int init_done;
47 unsigned mmap_counter;
48 struct meta *free_meta_head;
49 struct meta *avail_meta;
50 size_t avail_meta_count, avail_meta_area_count, meta_alloc_shift;
51 struct meta_area *meta_area_head, *meta_area_tail;
52 unsigned char *avail_meta_areas;
53 struct meta *active[48];
54 size_t usage_by_class[48];
55 uint8_t unmap_seq[32], bounces[32];
56 uint8_t seq;
57 uintptr_t brk;
58};
59
60__attribute__((__visibility__("hidden")))
61extern struct malloc_context ctx;
62
63#ifdef PAGESIZE
64#define PGSZ PAGESIZE
65#else
66#define PGSZ ctx.pagesize
67#endif
68
69__attribute__((__visibility__("hidden")))
70struct meta *alloc_meta(void);
71
72__attribute__((__visibility__("hidden")))
73int is_allzero(void *);
74
75static inline void queue(struct meta **phead, struct meta *m)
76{
77 assert(!m->next);
78 assert(!m->prev);
79 if (*phead) {
80 struct meta *head = *phead;
81 m->next = head;
82 m->prev = head->prev;
83 m->next->prev = m->prev->next = m;
84 } else {
85 m->prev = m->next = m;
86 *phead = m;
87 }
88}
89
90static inline void dequeue(struct meta **phead, struct meta *m)
91{
92 if (m->next != m) {
93 m->prev->next = m->next;
94 m->next->prev = m->prev;
95 if (*phead == m) *phead = m->next;
96 } else {
97 *phead = 0;
98 }
99 m->prev = m->next = 0;
100}
101
102static inline struct meta *dequeue_head(struct meta **phead)
103{
104 struct meta *m = *phead;
105 if (m) dequeue(phead, m);
106 return m;
107}
108
109static inline void free_meta(struct meta *m)
110{
111 *m = (struct meta){0};
112 queue(&ctx.free_meta_head, m);
113}
114
115static inline uint32_t activate_group(struct meta *m)
116{
117 assert(!m->avail_mask);
118 uint32_t mask, act = (2u<<m->mem->active_idx)-1;
119 do mask = m->freed_mask;
120 while (a_cas(&m->freed_mask, mask, mask&~act)!=mask);
121 return m->avail_mask = mask & act;
122}
123
124static inline int get_slot_index(const unsigned char *p)
125{
126 return p[-3] & 31;
127}
128
129static inline struct meta *get_meta(const unsigned char *p)
130{
131 assert(!((uintptr_t)p & 15));
132 int offset = *(const uint16_t *)(p - 2);
133 int index = get_slot_index(p);
134 if (p[-4]) {
135 assert(!offset);
136 offset = *(uint32_t *)(p - 8);
137 assert(offset > 0xffff);
138 }
139 const struct group *base = (const void *)(p - UNIT*offset - UNIT);
140 const struct meta *meta = base->meta;
141 assert(meta->mem == base);
142 assert(index <= meta->last_idx);
143 assert(!(meta->avail_mask & (1u<<index)));
144 assert(!(meta->freed_mask & (1u<<index)));
145 const struct meta_area *area = (void *)((uintptr_t)meta & -4096);
146 assert(area->check == ctx.secret);
147 if (meta->sizeclass < 48) {
148 assert(offset >= size_classes[meta->sizeclass]*index);
149 assert(offset < size_classes[meta->sizeclass]*(index+1));
150 } else {
151 assert(meta->sizeclass == 63);
152 }
153 if (meta->maplen) {
154 assert(offset <= meta->maplen*4096UL/UNIT - 1);
155 }
156 return (struct meta *)meta;
157}
158
159static inline size_t get_nominal_size(const unsigned char *p, const unsigned char *end)
160{
161 size_t reserved = p[-3] >> 5;
162 if (reserved >= 5) {
163 assert(reserved == 5);
164 reserved = *(const uint32_t *)(end-4);
165 assert(reserved >= 5);
166 assert(!end[-5]);
167 }
168 assert(reserved <= end-p);
169 assert(!*(end-reserved));
170 // also check the slot's overflow byte
171 assert(!*end);
172 return end-reserved-p;
173}
174
175static inline size_t get_stride(const struct meta *g)
176{
177 if (!g->last_idx && g->maplen) {
178 return g->maplen*4096UL - UNIT;
179 } else {
180 return UNIT*size_classes[g->sizeclass];
181 }
182}
183
184static inline void set_size(unsigned char *p, unsigned char *end, size_t n)
185{
186 int reserved = end-p-n;
187 if (reserved) end[-reserved] = 0;
188 if (reserved >= 5) {
189 *(uint32_t *)(end-4) = reserved;
190 end[-5] = 0;
191 reserved = 5;
192 }
193 p[-3] = (p[-3]&31) + (reserved<<5);
194}
195
196static inline void *enframe(struct meta *g, int idx, size_t n, int ctr)
197{
198 size_t stride = get_stride(g);
199 size_t slack = (stride-IB-n)/UNIT;
200 unsigned char *p = g->mem->storage + stride*idx;
201 unsigned char *end = p+stride-IB;
202 // cycle offset within slot to increase interval to address
203 // reuse, facilitate trapping double-free.
204 int off = (p[-3] ? *(uint16_t *)(p-2) + 1 : ctr) & 255;
205 assert(!p[-4]);
206 if (off > slack) {
207 size_t m = slack;
208 m |= m>>1; m |= m>>2; m |= m>>4;
209 off &= m;
210 if (off > slack) off -= slack+1;
211 assert(off <= slack);
212 }
213 if (off) {
214 // store offset in unused header at offset zero
215 // if enframing at non-zero offset.
216 *(uint16_t *)(p-2) = off;
217 p[-3] = 7<<5;
218 p += UNIT*off;
219 // for nonzero offset there is no permanent check
220 // byte, so make one.
221 p[-4] = 0;
222 }
223 *(uint16_t *)(p-2) = (size_t)(p-g->mem->storage)/UNIT;
224 p[-3] = idx;
225 set_size(p, end, n);
226 return p;
227}
228
229static inline int size_to_class(size_t n)
230{
231 n = (n+IB-1)>>4;
232 if (n<10) return n;
233 n++;
234 int i = (28-a_clz_32(n))*4 + 8;
235 if (n>size_classes[i+1]) i+=2;
236 if (n>size_classes[i]) i++;
237 return i;
238}
239
240static inline int size_overflows(size_t n)
241{
242 if (n >= SIZE_MAX/2 - 4096) {
243 errno = ENOMEM;
244 return 1;
245 }
246 return 0;
247}
248
249static inline void step_seq(void)
250{
251 if (ctx.seq==255) {
252 for (int i=0; i<32; i++) ctx.unmap_seq[i] = 0;
253 ctx.seq = 1;
254 } else {
255 ctx.seq++;
256 }
257}
258
259static inline void record_seq(int sc)
260{
261 if (sc-7U < 32) ctx.unmap_seq[sc-7] = ctx.seq;
262}
263
264static inline void account_bounce(int sc)
265{
266 if (sc-7U < 32) {
267 int seq = ctx.unmap_seq[sc-7];
268 if (seq && ctx.seq-seq < 10) {
269 if (ctx.bounces[sc-7]+1 < 100)
270 ctx.bounces[sc-7]++;
271 else
272 ctx.bounces[sc-7] = 150;
273 }
274 }
275}
276
277static inline void decay_bounces(int sc)
278{
279 if (sc-7U < 32 && ctx.bounces[sc-7])
280 ctx.bounces[sc-7]--;
281}
282
283static inline int is_bouncing(int sc)
284{
285 return (sc-7U < 32 && ctx.bounces[sc-7] >= 100);
286}
287
288#endif
lib/libc/musl/src/malloc/mallocng/realloc.c created+51
......@@ -0,0 +1,51 @@
1#define _GNU_SOURCE
2#include <stdlib.h>
3#include <sys/mman.h>
4#include <string.h>
5#include "meta.h"
6
7void *realloc(void *p, size_t n)
8{
9 if (!p) return malloc(n);
10 if (size_overflows(n)) return 0;
11
12 struct meta *g = get_meta(p);
13 int idx = get_slot_index(p);
14 size_t stride = get_stride(g);
15 unsigned char *start = g->mem->storage + stride*idx;
16 unsigned char *end = start + stride - IB;
17 size_t old_size = get_nominal_size(p, end);
18 size_t avail_size = end-(unsigned char *)p;
19 void *new;
20
21 // only resize in-place if size class matches
22 if (n <= avail_size && n<MMAP_THRESHOLD
23 && size_to_class(n)+1 >= g->sizeclass) {
24 set_size(p, end, n);
25 return p;
26 }
27
28 // use mremap if old and new size are both mmap-worthy
29 if (g->sizeclass>=48 && n>=MMAP_THRESHOLD) {
30 assert(g->sizeclass==63);
31 size_t base = (unsigned char *)p-start;
32 size_t needed = (n + base + UNIT + IB + 4095) & -4096;
33 new = g->maplen*4096UL == needed ? g->mem :
34 mremap(g->mem, g->maplen*4096UL, needed, MREMAP_MAYMOVE);
35 if (new!=MAP_FAILED) {
36 g->mem = new;
37 g->maplen = needed/4096;
38 p = g->mem->storage + base;
39 end = g->mem->storage + (needed - UNIT) - IB;
40 *end = 0;
41 set_size(p, end, n);
42 return p;
43 }
44 }
45
46 new = malloc(n);
47 if (!new) return 0;
48 memcpy(new, p, n < old_size ? n : old_size);
49 free(p);
50 return new;
51}
lib/libc/musl/src/malloc/memalign.c+3-50
......@@ -1,54 +1,7 @@
1#define _BSD_SOURCE
12#include <stdlib.h>
2#include <stdint.h>
3#include <errno.h>
4#include "malloc_impl.h"
53
6void *__memalign(size_t align, size_t len)
4void *memalign(size_t align, size_t len)
75{
8 unsigned char *mem, *new;
9
10 if ((align & -align) != align) {
11 errno = EINVAL;
12 return 0;
13 }
14
15 if (len > SIZE_MAX - align || __malloc_replaced) {
16 errno = ENOMEM;
17 return 0;
18 }
19
20 if (align <= SIZE_ALIGN)
21 return malloc(len);
22
23 if (!(mem = malloc(len + align-1)))
24 return 0;
25
26 new = (void *)((uintptr_t)mem + align-1 & -align);
27 if (new == mem) return mem;
28
29 struct chunk *c = MEM_TO_CHUNK(mem);
30 struct chunk *n = MEM_TO_CHUNK(new);
31
32 if (IS_MMAPPED(c)) {
33 /* Apply difference between aligned and original
34 * address to the "extra" field of mmapped chunk. */
35 n->psize = c->psize + (new-mem);
36 n->csize = c->csize - (new-mem);
37 return new;
38 }
39
40 struct chunk *t = NEXT_CHUNK(c);
41
42 /* Split the allocated chunk into two chunks. The aligned part
43 * that will be used has the size in its footer reduced by the
44 * difference between the aligned and original addresses, and
45 * the resulting size copied to its header. A new header and
46 * footer are written for the split-off part to be freed. */
47 n->psize = c->csize = C_INUSE | (new-mem);
48 n->csize = t->psize -= new-mem;
49
50 __bin_chunk(c);
51 return new;
6 return aligned_alloc(align, len);
527}
53
54weak_alias(__memalign, memalign);
lib/libc/musl/src/malloc/posix_memalign.c+1-2
......@@ -1,11 +1,10 @@
11#include <stdlib.h>
22#include <errno.h>
3#include "malloc_impl.h"
43
54int posix_memalign(void **res, size_t align, size_t len)
65{
76 if (align < sizeof(void *)) return EINVAL;
8 void *mem = __memalign(align, len);
7 void *mem = aligned_alloc(align, len);
98 if (!mem) return errno;
109 *res = mem;
1110 return 0;
lib/libc/musl/src/malloc/replaced.c created+4
......@@ -0,0 +1,4 @@
1#include "dynlink.h"
2
3int __malloc_replaced;
4int __aligned_alloc_replaced;
lib/libc/musl/src/math/__expo2.c+3-2
......@@ -5,12 +5,13 @@ static const int k = 2043;
55static const double kln2 = 0x1.62066151add8bp+10;
66
77/* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */
8double __expo2(double x)
8double __expo2(double x, double sign)
99{
1010 double scale;
1111
1212 /* note that k is odd and scale*scale overflows */
1313 INSERT_WORDS(scale, (uint32_t)(0x3ff + k/2) << 20, 0);
1414 /* exp(x - k ln2) * 2**(k-1) */
15 return exp(x - kln2) * scale * scale;
15 /* in directed rounding correct sign before rounding or overflow is important */
16 return exp(x - kln2) * (sign * scale) * scale;
1617}
lib/libc/musl/src/math/__expo2f.c+3-2
......@@ -5,12 +5,13 @@ static const int k = 235;
55static const float kln2 = 0x1.45c778p+7f;
66
77/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */
8float __expo2f(float x)
8float __expo2f(float x, float sign)
99{
1010 float scale;
1111
1212 /* note that k is odd and scale*scale overflows */
1313 SET_FLOAT_WORD(scale, (uint32_t)(0x7f + k/2) << 23);
1414 /* exp(x - k ln2) * 2**(k-1) */
15 return expf(x - kln2) * scale * scale;
15 /* in directed rounding correct sign before rounding or overflow is important */
16 return expf(x - kln2) * (sign * scale) * scale;
1617}
lib/libc/musl/src/math/__rem_pio2.c+14-1
......@@ -36,6 +36,7 @@
3636 */
3737static const double
3838toint = 1.5/EPS,
39pio4 = 0x1.921fb54442d18p-1,
3940invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
4041pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
4142pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
......@@ -117,11 +118,23 @@ int __rem_pio2(double x, double *y)
117118 }
118119 if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
119120medium:
120 /* rint(x/(pi/2)), Assume round-to-nearest. */
121 /* rint(x/(pi/2)) */
121122 fn = (double_t)x*invpio2 + toint - toint;
122123 n = (int32_t)fn;
123124 r = x - fn*pio2_1;
124125 w = fn*pio2_1t; /* 1st round, good to 85 bits */
126 /* Matters with directed rounding. */
127 if (predict_false(r - w < -pio4)) {
128 n--;
129 fn--;
130 r = x - fn*pio2_1;
131 w = fn*pio2_1t;
132 } else if (predict_false(r - w > pio4)) {
133 n++;
134 fn++;
135 r = x - fn*pio2_1;
136 w = fn*pio2_1t;
137 }
125138 y[0] = r - w;
126139 u.f = y[0];
127140 ey = u.i>>52 & 0x7ff;
lib/libc/musl/src/math/__rem_pio2f.c+12-1
......@@ -35,6 +35,7 @@
3535 */
3636static const double
3737toint = 1.5/EPS,
38pio4 = 0x1.921fb6p-1,
3839invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
3940pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
4041pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
......@@ -50,10 +51,20 @@ int __rem_pio2f(float x, double *y)
5051 ix = u.i & 0x7fffffff;
5152 /* 25+53 bit pi is good enough for medium size */
5253 if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */
53 /* Use a specialized rint() to get fn. Assume round-to-nearest. */
54 /* Use a specialized rint() to get fn. */
5455 fn = (double_t)x*invpio2 + toint - toint;
5556 n = (int32_t)fn;
5657 *y = x - fn*pio2_1 - fn*pio2_1t;
58 /* Matters with directed rounding. */
59 if (predict_false(*y < -pio4)) {
60 n--;
61 fn--;
62 *y = x - fn*pio2_1 - fn*pio2_1t;
63 } else if (predict_false(*y > pio4)) {
64 n++;
65 fn++;
66 *y = x - fn*pio2_1 - fn*pio2_1t;
67 }
5768 return n;
5869 }
5970 if(ix>=0x7f800000) { /* x is inf or NaN */
lib/libc/musl/src/math/__rem_pio2l.c+15-1
......@@ -44,6 +44,7 @@ pio2_1 = 1.57079632679597125389e+00, /* 0x3FF921FB, 0x54444000 */
4444pio2_2 = -1.07463465549783099519e-12, /* -0x12e7b967674000.0p-92 */
4545pio2_3 = 6.36831716351370313614e-25; /* 0x18a2e037074000.0p-133 */
4646static const long double
47pio4 = 0x1.921fb54442d1846ap-1L,
4748invpio2 = 6.36619772367581343076e-01L, /* 0xa2f9836e4e44152a.0p-64 */
4849pio2_1t = -1.07463465549719416346e-12L, /* -0x973dcb3b399d747f.0p-103 */
4950pio2_2t = 6.36831716351095013979e-25L, /* 0xc51701b839a25205.0p-144 */
......@@ -57,6 +58,7 @@ pio2_3t = -2.75299651904407171810e-37L; /* -0xbb5bf6c7ddd660ce.0p-185 */
5758#define NX 5
5859#define NY 3
5960static const long double
61pio4 = 0x1.921fb54442d18469898cc51701b8p-1L,
6062invpio2 = 6.3661977236758134307553505349005747e-01L, /* 0x145f306dc9c882a53f84eafa3ea6a.0p-113 */
6163pio2_1 = 1.5707963267948966192292994253909555e+00L, /* 0x1921fb54442d18469800000000000.0p-112 */
6264pio2_1t = 2.0222662487959507323996846200947577e-21L, /* 0x13198a2e03707344a4093822299f3.0p-181 */
......@@ -76,11 +78,23 @@ int __rem_pio2l(long double x, long double *y)
7678 u.f = x;
7779 ex = u.i.se & 0x7fff;
7880 if (SMALL(u)) {
79 /* rint(x/(pi/2)), Assume round-to-nearest. */
81 /* rint(x/(pi/2)) */
8082 fn = x*invpio2 + toint - toint;
8183 n = QUOBITS(fn);
8284 r = x-fn*pio2_1;
8385 w = fn*pio2_1t; /* 1st round good to 102/180 bits (ld80/ld128) */
86 /* Matters with directed rounding. */
87 if (predict_false(r - w < -pio4)) {
88 n--;
89 fn--;
90 r = x - fn*pio2_1;
91 w = fn*pio2_1t;
92 } else if (predict_false(r - w > pio4)) {
93 n++;
94 fn++;
95 r = x - fn*pio2_1;
96 w = fn*pio2_1t;
97 }
8498 y[0] = r-w;
8599 u.f = y[0];
86100 ey = u.i.se & 0x7fff;
lib/libc/musl/src/math/cosh.c+1-1
......@@ -35,6 +35,6 @@ double cosh(double x)
3535
3636 /* |x| > log(DBL_MAX) or nan */
3737 /* note: the result is stored to handle overflow */
38 t = __expo2(x);
38 t = __expo2(x, 1.0);
3939 return t;
4040}
lib/libc/musl/src/math/coshf.c+1-1
......@@ -28,6 +28,6 @@ float coshf(float x)
2828 }
2929
3030 /* |x| > log(FLT_MAX) or nan */
31 t = __expo2f(x);
31 t = __expo2f(x, 1.0f);
3232 return t;
3333}
lib/libc/musl/src/math/i386/fabs.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3double fabs(double x)
4{
5 __asm__ ("fabs" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/i386/fabs.s deleted-6
......@@ -1,6 +0,0 @@
1.global fabs
2.type fabs,@function
3fabs:
4 fldl 4(%esp)
5 fabs
6 ret
lib/libc/musl/src/math/i386/fabsf.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3float fabsf(float x)
4{
5 __asm__ ("fabs" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/i386/fabsf.s deleted-6
......@@ -1,6 +0,0 @@
1.global fabsf
2.type fabsf,@function
3fabsf:
4 flds 4(%esp)
5 fabs
6 ret
lib/libc/musl/src/math/i386/fabsl.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3long double fabsl(long double x)
4{
5 __asm__ ("fabs" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/i386/fabsl.s deleted-6
......@@ -1,6 +0,0 @@
1.global fabsl
2.type fabsl,@function
3fabsl:
4 fldt 4(%esp)
5 fabs
6 ret
lib/libc/musl/src/math/i386/fmod.c created+10
......@@ -0,0 +1,10 @@
1#include <math.h>
2
3double fmod(double x, double y)
4{
5 unsigned short fpsr;
6 // fprem does not introduce excess precision into x
7 do __asm__ ("fprem; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
8 while (fpsr & 0x400);
9 return x;
10}
lib/libc/musl/src/math/i386/fmod.s deleted-11
......@@ -1,11 +0,0 @@
1.global fmod
2.type fmod,@function
3fmod:
4 fldl 12(%esp)
5 fldl 4(%esp)
61: fprem
7 fnstsw %ax
8 sahf
9 jp 1b
10 fstp %st(1)
11 ret
lib/libc/musl/src/math/i386/fmodf.c created+10
......@@ -0,0 +1,10 @@
1#include <math.h>
2
3float fmodf(float x, float y)
4{
5 unsigned short fpsr;
6 // fprem does not introduce excess precision into x
7 do __asm__ ("fprem; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
8 while (fpsr & 0x400);
9 return x;
10}
lib/libc/musl/src/math/i386/fmodf.s deleted-11
......@@ -1,11 +0,0 @@
1.global fmodf
2.type fmodf,@function
3fmodf:
4 flds 8(%esp)
5 flds 4(%esp)
61: fprem
7 fnstsw %ax
8 sahf
9 jp 1b
10 fstp %st(1)
11 ret
lib/libc/musl/src/math/i386/fmodl.c created+9
......@@ -0,0 +1,9 @@
1#include <math.h>
2
3long double fmodl(long double x, long double y)
4{
5 unsigned short fpsr;
6 do __asm__ ("fprem; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
7 while (fpsr & 0x400);
8 return x;
9}
lib/libc/musl/src/math/i386/fmodl.s deleted-11
......@@ -1,11 +0,0 @@
1.global fmodl
2.type fmodl,@function
3fmodl:
4 fldt 16(%esp)
5 fldt 4(%esp)
61: fprem
7 fnstsw %ax
8 sahf
9 jp 1b
10 fstp %st(1)
11 ret
lib/libc/musl/src/math/i386/llrint.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long long llrint(double x)
4{
5 long long r;
6 __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
7 return r;
8}
lib/libc/musl/src/math/i386/llrint.s deleted-8
......@@ -1,8 +0,0 @@
1.global llrint
2.type llrint,@function
3llrint:
4 fldl 4(%esp)
5 fistpll 4(%esp)
6 mov 4(%esp),%eax
7 mov 8(%esp),%edx
8 ret
lib/libc/musl/src/math/i386/llrintf.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long long llrintf(float x)
4{
5 long long r;
6 __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
7 return r;
8}
lib/libc/musl/src/math/i386/llrintf.s deleted-9
......@@ -1,9 +0,0 @@
1.global llrintf
2.type llrintf,@function
3llrintf:
4 sub $8,%esp
5 flds 12(%esp)
6 fistpll (%esp)
7 pop %eax
8 pop %edx
9 ret
lib/libc/musl/src/math/i386/llrintl.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long long llrintl(long double x)
4{
5 long long r;
6 __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
7 return r;
8}
lib/libc/musl/src/math/i386/llrintl.s deleted-8
......@@ -1,8 +0,0 @@
1.global llrintl
2.type llrintl,@function
3llrintl:
4 fldt 4(%esp)
5 fistpll 4(%esp)
6 mov 4(%esp),%eax
7 mov 8(%esp),%edx
8 ret
lib/libc/musl/src/math/i386/lrint.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long lrint(double x)
4{
5 long r;
6 __asm__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
7 return r;
8}
lib/libc/musl/src/math/i386/lrint.s deleted-7
......@@ -1,7 +0,0 @@
1.global lrint
2.type lrint,@function
3lrint:
4 fldl 4(%esp)
5 fistpl 4(%esp)
6 mov 4(%esp),%eax
7 ret
lib/libc/musl/src/math/i386/lrintf.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long lrintf(float x)
4{
5 long r;
6 __asm__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
7 return r;
8}
lib/libc/musl/src/math/i386/lrintf.s deleted-7
......@@ -1,7 +0,0 @@
1.global lrintf
2.type lrintf,@function
3lrintf:
4 flds 4(%esp)
5 fistpl 4(%esp)
6 mov 4(%esp),%eax
7 ret
lib/libc/musl/src/math/i386/lrintl.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long lrintl(long double x)
4{
5 long r;
6 __asm__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
7 return r;
8}
lib/libc/musl/src/math/i386/lrintl.s deleted-7
......@@ -1,7 +0,0 @@
1.global lrintl
2.type lrintl,@function
3lrintl:
4 fldt 4(%esp)
5 fistpl 4(%esp)
6 mov 4(%esp),%eax
7 ret
lib/libc/musl/src/math/i386/remainder.c created+12
......@@ -0,0 +1,12 @@
1#include <math.h>
2
3double remainder(double x, double y)
4{
5 unsigned short fpsr;
6 // fprem1 does not introduce excess precision into x
7 do __asm__ ("fprem1; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
8 while (fpsr & 0x400);
9 return x;
10}
11
12weak_alias(remainder, drem);
lib/libc/musl/src/math/i386/remainder.s deleted-14
......@@ -1,14 +0,0 @@
1.global remainder
2.type remainder,@function
3remainder:
4.weak drem
5.type drem,@function
6drem:
7 fldl 12(%esp)
8 fldl 4(%esp)
91: fprem1
10 fnstsw %ax
11 sahf
12 jp 1b
13 fstp %st(1)
14 ret
lib/libc/musl/src/math/i386/remainderf.c created+12
......@@ -0,0 +1,12 @@
1#include <math.h>
2
3float remainderf(float x, float y)
4{
5 unsigned short fpsr;
6 // fprem1 does not introduce excess precision into x
7 do __asm__ ("fprem1; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
8 while (fpsr & 0x400);
9 return x;
10}
11
12weak_alias(remainderf, dremf);
lib/libc/musl/src/math/i386/remainderf.s deleted-14
......@@ -1,14 +0,0 @@
1.global remainderf
2.type remainderf,@function
3remainderf:
4.weak dremf
5.type dremf,@function
6dremf:
7 flds 8(%esp)
8 flds 4(%esp)
91: fprem1
10 fnstsw %ax
11 sahf
12 jp 1b
13 fstp %st(1)
14 ret
lib/libc/musl/src/math/i386/remainderl.c created+9
......@@ -0,0 +1,9 @@
1#include <math.h>
2
3long double remainderl(long double x, long double y)
4{
5 unsigned short fpsr;
6 do __asm__ ("fprem1; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
7 while (fpsr & 0x400);
8 return x;
9}
lib/libc/musl/src/math/i386/remainderl.s deleted-11
......@@ -1,11 +0,0 @@
1.global remainderl
2.type remainderl,@function
3remainderl:
4 fldt 16(%esp)
5 fldt 4(%esp)
61: fprem1
7 fnstsw %ax
8 sahf
9 jp 1b
10 fstp %st(1)
11 ret
lib/libc/musl/src/math/i386/rint.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3double rint(double x)
4{
5 __asm__ ("frndint" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/i386/rint.s deleted-6
......@@ -1,6 +0,0 @@
1.global rint
2.type rint,@function
3rint:
4 fldl 4(%esp)
5 frndint
6 ret
lib/libc/musl/src/math/i386/rintf.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3float rintf(float x)
4{
5 __asm__ ("frndint" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/i386/rintf.s deleted-6
......@@ -1,6 +0,0 @@
1.global rintf
2.type rintf,@function
3rintf:
4 flds 4(%esp)
5 frndint
6 ret
lib/libc/musl/src/math/i386/rintl.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3long double rintl(long double x)
4{
5 __asm__ ("frndint" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/i386/rintl.s deleted-6
......@@ -1,6 +0,0 @@
1.global rintl
2.type rintl,@function
3rintl:
4 fldt 4(%esp)
5 frndint
6 ret
lib/libc/musl/src/math/i386/sqrt.c created+15
......@@ -0,0 +1,15 @@
1#include "libm.h"
2
3double sqrt(double x)
4{
5 union ldshape ux;
6 unsigned fpsr;
7 __asm__ ("fsqrt; fnstsw %%ax": "=t"(ux.f), "=a"(fpsr) : "0"(x));
8 if ((ux.i.m & 0x7ff) != 0x400)
9 return (double)ux.f;
10 /* Rounding to double would have encountered an exact halfway case.
11 Adjust mantissa downwards if fsqrt rounded up, else upwards.
12 (result of fsqrt could not have been exact) */
13 ux.i.m ^= (fpsr & 0x200) + 0x300;
14 return (double)ux.f;
15}
lib/libc/musl/src/math/i386/sqrt.s deleted-21
......@@ -1,21 +0,0 @@
1.global sqrt
2.type sqrt,@function
3sqrt: fldl 4(%esp)
4 fsqrt
5 fnstsw %ax
6 sub $12,%esp
7 fld %st(0)
8 fstpt (%esp)
9 mov (%esp),%ecx
10 and $0x7ff,%ecx
11 cmp $0x400,%ecx
12 jnz 1f
13 and $0x200,%eax
14 sub $0x100,%eax
15 sub %eax,(%esp)
16 fstp %st(0)
17 fldt (%esp)
181: add $12,%esp
19 fstpl 4(%esp)
20 fldl 4(%esp)
21 ret
lib/libc/musl/src/math/i386/sqrtf.c created+12
......@@ -0,0 +1,12 @@
1#include <math.h>
2
3float sqrtf(float x)
4{
5 long double t;
6 /* The long double result has sufficient precision so that
7 * second rounding to float still keeps the returned value
8 * correctly rounded, see Pierre Roux, "Innocuous Double
9 * Rounding of Basic Arithmetic Operations". */
10 __asm__ ("fsqrt" : "=t"(t) : "0"(x));
11 return (float)t;
12}
lib/libc/musl/src/math/i386/sqrtf.s deleted-7
......@@ -1,7 +0,0 @@
1.global sqrtf
2.type sqrtf,@function
3sqrtf: flds 4(%esp)
4 fsqrt
5 fstps 4(%esp)
6 flds 4(%esp)
7 ret
lib/libc/musl/src/math/i386/sqrtl.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3long double sqrtl(long double x)
4{
5 __asm__ ("fsqrt" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/i386/sqrtl.s deleted-5
......@@ -1,5 +0,0 @@
1.global sqrtl
2.type sqrtl,@function
3sqrtl: fldt 4(%esp)
4 fsqrt
5 ret
lib/libc/musl/src/math/m68k/sqrtl.c created+15
......@@ -0,0 +1,15 @@
1#include <math.h>
2
3#if __HAVE_68881__
4
5long double sqrtl(long double x)
6{
7 __asm__ ("fsqrt.x %1,%0" : "=f"(x) : "fm"(x));
8 return x;
9}
10
11#else
12
13#include "../sqrtl.c"
14
15#endif
lib/libc/musl/src/math/sinh.c+1-1
......@@ -34,6 +34,6 @@ double sinh(double x)
3434
3535 /* |x| > log(DBL_MAX) or nan */
3636 /* note: the result is stored to handle overflow */
37 t = 2*h*__expo2(absx);
37 t = __expo2(absx, 2*h);
3838 return t;
3939}
lib/libc/musl/src/math/sinhf.c+1-1
......@@ -26,6 +26,6 @@ float sinhf(float x)
2626 }
2727
2828 /* |x| > logf(FLT_MAX) or nan */
29 t = 2*h*__expo2f(absx);
29 t = __expo2f(absx, 2*h);
3030 return t;
3131}
lib/libc/musl/src/math/x86_64/fabs.c created+10
......@@ -0,0 +1,10 @@
1#include <math.h>
2
3double fabs(double x)
4{
5 double t;
6 __asm__ ("pcmpeqd %0, %0" : "=x"(t)); // t = ~0
7 __asm__ ("psrlq $1, %0" : "+x"(t)); // t >>= 1
8 __asm__ ("andps %1, %0" : "+x"(x) : "x"(t)); // x &= t
9 return x;
10}
lib/libc/musl/src/math/x86_64/fabs.s deleted-9
......@@ -1,9 +0,0 @@
1.global fabs
2.type fabs,@function
3fabs:
4 xor %eax,%eax
5 dec %rax
6 shr %rax
7 movq %rax,%xmm1
8 andpd %xmm1,%xmm0
9 ret
lib/libc/musl/src/math/x86_64/fabsf.c created+10
......@@ -0,0 +1,10 @@
1#include <math.h>
2
3float fabsf(float x)
4{
5 float t;
6 __asm__ ("pcmpeqd %0, %0" : "=x"(t)); // t = ~0
7 __asm__ ("psrld $1, %0" : "+x"(t)); // t >>= 1
8 __asm__ ("andps %1, %0" : "+x"(x) : "x"(t)); // x &= t
9 return x;
10}
lib/libc/musl/src/math/x86_64/fabsf.s deleted-7
......@@ -1,7 +0,0 @@
1.global fabsf
2.type fabsf,@function
3fabsf:
4 mov $0x7fffffff,%eax
5 movq %rax,%xmm1
6 andps %xmm1,%xmm0
7 ret
lib/libc/musl/src/math/x86_64/fabsl.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3long double fabsl(long double x)
4{
5 __asm__ ("fabs" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/x86_64/fabsl.s deleted-6
......@@ -1,6 +0,0 @@
1.global fabsl
2.type fabsl,@function
3fabsl:
4 fldt 8(%rsp)
5 fabs
6 ret
lib/libc/musl/src/math/x86_64/fmodl.c created+9
......@@ -0,0 +1,9 @@
1#include <math.h>
2
3long double fmodl(long double x, long double y)
4{
5 unsigned short fpsr;
6 do __asm__ ("fprem; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
7 while (fpsr & 0x400);
8 return x;
9}
lib/libc/musl/src/math/x86_64/fmodl.s deleted-11
......@@ -1,11 +0,0 @@
1.global fmodl
2.type fmodl,@function
3fmodl:
4 fldt 24(%rsp)
5 fldt 8(%rsp)
61: fprem
7 fnstsw %ax
8 testb $4,%ah
9 jnz 1b
10 fstp %st(1)
11 ret
lib/libc/musl/src/math/x86_64/llrint.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long long llrint(double x)
4{
5 long long r;
6 __asm__ ("cvtsd2si %1, %0" : "=r"(r) : "x"(x));
7 return r;
8}
lib/libc/musl/src/math/x86_64/llrint.s deleted-5
......@@ -1,5 +0,0 @@
1.global llrint
2.type llrint,@function
3llrint:
4 cvtsd2si %xmm0,%rax
5 ret
lib/libc/musl/src/math/x86_64/llrintf.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long long llrintf(float x)
4{
5 long long r;
6 __asm__ ("cvtss2si %1, %0" : "=r"(r) : "x"(x));
7 return r;
8}
lib/libc/musl/src/math/x86_64/llrintf.s deleted-5
......@@ -1,5 +0,0 @@
1.global llrintf
2.type llrintf,@function
3llrintf:
4 cvtss2si %xmm0,%rax
5 ret
lib/libc/musl/src/math/x86_64/llrintl.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long long llrintl(long double x)
4{
5 long long r;
6 __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
7 return r;
8}
lib/libc/musl/src/math/x86_64/llrintl.s deleted-7
......@@ -1,7 +0,0 @@
1.global llrintl
2.type llrintl,@function
3llrintl:
4 fldt 8(%rsp)
5 fistpll 8(%rsp)
6 mov 8(%rsp),%rax
7 ret
lib/libc/musl/src/math/x86_64/lrint.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long lrint(double x)
4{
5 long r;
6 __asm__ ("cvtsd2si %1, %0" : "=r"(r) : "x"(x));
7 return r;
8}
lib/libc/musl/src/math/x86_64/lrint.s deleted-5
......@@ -1,5 +0,0 @@
1.global lrint
2.type lrint,@function
3lrint:
4 cvtsd2si %xmm0,%rax
5 ret
lib/libc/musl/src/math/x86_64/lrintf.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long lrintf(float x)
4{
5 long r;
6 __asm__ ("cvtss2si %1, %0" : "=r"(r) : "x"(x));
7 return r;
8}
lib/libc/musl/src/math/x86_64/lrintf.s deleted-5
......@@ -1,5 +0,0 @@
1.global lrintf
2.type lrintf,@function
3lrintf:
4 cvtss2si %xmm0,%rax
5 ret
lib/libc/musl/src/math/x86_64/lrintl.c created+8
......@@ -0,0 +1,8 @@
1#include <math.h>
2
3long lrintl(long double x)
4{
5 long r;
6 __asm__ ("fistpll %0" : "=m"(r) : "t"(x) : "st");
7 return r;
8}
lib/libc/musl/src/math/x86_64/lrintl.s deleted-7
......@@ -1,7 +0,0 @@
1.global lrintl
2.type lrintl,@function
3lrintl:
4 fldt 8(%rsp)
5 fistpll 8(%rsp)
6 mov 8(%rsp),%rax
7 ret
lib/libc/musl/src/math/x86_64/remainderl.c created+9
......@@ -0,0 +1,9 @@
1#include <math.h>
2
3long double remainderl(long double x, long double y)
4{
5 unsigned short fpsr;
6 do __asm__ ("fprem1; fnstsw %%ax" : "+t"(x), "=a"(fpsr) : "u"(y));
7 while (fpsr & 0x400);
8 return x;
9}
lib/libc/musl/src/math/x86_64/remainderl.s deleted-11
......@@ -1,11 +0,0 @@
1.global remainderl
2.type remainderl,@function
3remainderl:
4 fldt 24(%rsp)
5 fldt 8(%rsp)
61: fprem1
7 fnstsw %ax
8 testb $4,%ah
9 jnz 1b
10 fstp %st(1)
11 ret
lib/libc/musl/src/math/x86_64/remquol.c created+32
......@@ -0,0 +1,32 @@
1#include <math.h>
2
3long double remquol(long double x, long double y, int *quo)
4{
5 signed char *cx = (void *)&x, *cy = (void *)&y;
6 /* By ensuring that addresses of x and y cannot be discarded,
7 * this empty asm guides GCC into representing extraction of
8 * their sign bits as memory loads rather than making x and y
9 * not-address-taken internally and using bitfield operations,
10 * which in the end wouldn't work out, as extraction from FPU
11 * registers needs to go through memory anyway. This way GCC
12 * should manage to use incoming stack slots without spills. */
13 __asm__ ("" :: "X"(cx), "X"(cy));
14
15 long double t = x;
16 unsigned fpsr;
17 do __asm__ ("fprem1; fnstsw %%ax" : "+t"(t), "=a"(fpsr) : "u"(y));
18 while (fpsr & 0x400);
19 /* C0, C1, C3 flags in x87 status word carry low bits of quotient:
20 * 15 14 13 12 11 10 9 8
21 * . C3 . . . C2 C1 C0
22 * . b1 . . . 0 b0 b2 */
23 unsigned char i = fpsr >> 8;
24 i = i>>4 | i<<4;
25 /* i[5:2] is now {b0 b2 ? b1}. Retrieve {0 b2 b1 b0} via
26 * in-register table lookup. */
27 unsigned qbits = 0x7575313164642020 >> (i & 60);
28 qbits &= 7;
29
30 *quo = (cx[9]^cy[9]) < 0 ? -qbits : qbits;
31 return t;
32}
lib/libc/musl/src/math/x86_64/rintl.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3long double rintl(long double x)
4{
5 __asm__ ("frndint" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/x86_64/rintl.s deleted-6
......@@ -1,6 +0,0 @@
1.global rintl
2.type rintl,@function
3rintl:
4 fldt 8(%rsp)
5 frndint
6 ret
lib/libc/musl/src/math/x86_64/sqrt.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3double sqrt(double x)
4{
5 __asm__ ("sqrtsd %1, %0" : "=x"(x) : "x"(x));
6 return x;
7}
lib/libc/musl/src/math/x86_64/sqrt.s deleted-4
......@@ -1,4 +0,0 @@
1.global sqrt
2.type sqrt,@function
3sqrt: sqrtsd %xmm0, %xmm0
4 ret
lib/libc/musl/src/math/x86_64/sqrtf.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3float sqrtf(float x)
4{
5 __asm__ ("sqrtss %1, %0" : "=x"(x) : "x"(x));
6 return x;
7}
lib/libc/musl/src/math/x86_64/sqrtf.s deleted-4
......@@ -1,4 +0,0 @@
1.global sqrtf
2.type sqrtf,@function
3sqrtf: sqrtss %xmm0, %xmm0
4 ret
lib/libc/musl/src/math/x86_64/sqrtl.c created+7
......@@ -0,0 +1,7 @@
1#include <math.h>
2
3long double sqrtl(long double x)
4{
5 __asm__ ("fsqrt" : "+t"(x));
6 return x;
7}
lib/libc/musl/src/math/x86_64/sqrtl.s deleted-5
......@@ -1,5 +0,0 @@
1.global sqrtl
2.type sqrtl,@function
3sqrtl: fldt 8(%rsp)
4 fsqrt
5 ret
lib/libc/musl/src/misc/getentropy.c+1-1
......@@ -6,7 +6,7 @@
66
77int getentropy(void *buffer, size_t len)
88{
9 int cs, ret;
9 int cs, ret = 0;
1010 char *pos = buffer;
1111
1212 if (len > 256) {
lib/libc/musl/src/misc/nftw.c+18-4
......@@ -1,5 +1,6 @@
11#include <ftw.h>
22#include <dirent.h>
3#include <fcntl.h>
34#include <sys/stat.h>
45#include <errno.h>
56#include <unistd.h>
......@@ -26,6 +27,8 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
2627 struct history new;
2728 int type;
2829 int r;
30 int dfd;
31 int err;
2932 struct FTW lev;
3033
3134 if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
......@@ -34,8 +37,7 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
3437 else if (errno != EACCES) return -1;
3538 else type = FTW_NS;
3639 } else if (S_ISDIR(st.st_mode)) {
37 if (access(path, R_OK) < 0) type = FTW_DNR;
38 else if (flags & FTW_DEPTH) type = FTW_DP;
40 if (flags & FTW_DEPTH) type = FTW_DP;
3941 else type = FTW_D;
4042 } else if (S_ISLNK(st.st_mode)) {
4143 if (flags & FTW_PHYS) type = FTW_SL;
......@@ -63,6 +65,13 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
6365 lev.base = k;
6466 }
6567
68 if (type == FTW_D || type == FTW_DP) {
69 dfd = open(path, O_RDONLY);
70 err = errno;
71 if (dfd < 0 && err == EACCES) type = FTW_DNR;
72 if (!fd_limit) close(dfd);
73 }
74
6675 if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
6776 return r;
6877
......@@ -71,7 +80,11 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
7180 return 0;
7281
7382 if ((type == FTW_D || type == FTW_DP) && fd_limit) {
74 DIR *d = opendir(path);
83 if (dfd < 0) {
84 errno = err;
85 return -1;
86 }
87 DIR *d = fdopendir(dfd);
7588 if (d) {
7689 struct dirent *de;
7790 while ((de = readdir(d))) {
......@@ -92,7 +105,8 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
92105 }
93106 }
94107 closedir(d);
95 } else if (errno != EACCES) {
108 } else {
109 close(dfd);
96110 return -1;
97111 }
98112 }
lib/libc/musl/src/network/getnameinfo.c+1
......@@ -158,6 +158,7 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
158158 unsigned char query[18+PTR_MAX], reply[512];
159159 int qlen = __res_mkquery(0, ptr, 1, RR_PTR,
160160 0, 0, 0, query, sizeof query);
161 query[3] = 0; /* don't need AD flag */
161162 int rlen = __res_send(query, qlen, reply, sizeof reply);
162163 buf[0] = 0;
163164 if (rlen > 0)
lib/libc/musl/src/network/lookup_name.c+8-4
......@@ -149,6 +149,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
149149 0, 0, 0, qbuf[nq], sizeof *qbuf);
150150 if (qlens[nq] == -1)
151151 return EAI_NONAME;
152 qbuf[nq][3] = 0; /* don't need AD flag */
152153 nq++;
153154 }
154155 }
......@@ -156,14 +157,17 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
156157 if (__res_msend_rc(nq, qp, qlens, ap, alens, sizeof *abuf, conf) < 0)
157158 return EAI_SYSTEM;
158159
160 for (i=0; i<nq; i++) {
161 if (alens[i] < 4 || (abuf[i][3] & 15) == 2) return EAI_AGAIN;
162 if ((abuf[i][3] & 15) == 3) return 0;
163 if ((abuf[i][3] & 15) != 0) return EAI_FAIL;
164 }
165
159166 for (i=0; i<nq; i++)
160167 __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx);
161168
162169 if (ctx.cnt) return ctx.cnt;
163 if (alens[0] < 4 || (abuf[0][3] & 15) == 2) return EAI_AGAIN;
164 if ((abuf[0][3] & 15) == 0) return EAI_NONAME;
165 if ((abuf[0][3] & 15) == 3) return 0;
166 return EAI_FAIL;
170 return EAI_NONAME;
167171}
168172
169173static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family)
lib/libc/musl/src/network/res_mkquery.c+1
......@@ -20,6 +20,7 @@ int __res_mkquery(int op, const char *dname, int class, int type,
2020 /* Construct query template - ID will be filled later */
2121 memset(q, 0, n);
2222 q[2] = op*8 + 1;
23 q[3] = 32; /* AD */
2324 q[5] = 1;
2425 memcpy((char *)q+13, dname, l);
2526 for (i=13; q[i]; i=j+1) {
lib/libc/musl/src/network/res_send.c+1-1
......@@ -3,7 +3,7 @@
33int __res_send(const unsigned char *msg, int msglen, unsigned char *answer, int anslen)
44{
55 int r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
6 return r<0 ? r : anslen;
6 return r<0 || !anslen ? -1 : anslen;
77}
88
99weak_alias(__res_send, res_send);
lib/libc/musl/src/network/socket.c+5-5
......@@ -5,17 +5,17 @@
55
66int socket(int domain, int type, int protocol)
77{
8 int s = socketcall(socket, domain, type, protocol, 0, 0, 0);
9 if (s<0 && (errno==EINVAL || errno==EPROTONOSUPPORT)
8 int s = __socketcall(socket, domain, type, protocol, 0, 0, 0);
9 if ((s==-EINVAL || s==-EPROTONOSUPPORT)
1010 && (type&(SOCK_CLOEXEC|SOCK_NONBLOCK))) {
11 s = socketcall(socket, domain,
11 s = __socketcall(socket, domain,
1212 type & ~(SOCK_CLOEXEC|SOCK_NONBLOCK),
1313 protocol, 0, 0, 0);
14 if (s < 0) return s;
14 if (s < 0) return __syscall_ret(s);
1515 if (type & SOCK_CLOEXEC)
1616 __syscall(SYS_fcntl, s, F_SETFD, FD_CLOEXEC);
1717 if (type & SOCK_NONBLOCK)
1818 __syscall(SYS_fcntl, s, F_SETFL, O_NONBLOCK);
1919 }
20 return s;
20 return __syscall_ret(s);
2121}
lib/libc/musl/src/process/fork.c+1
......@@ -30,6 +30,7 @@ pid_t fork(void)
3030 self->next = self->prev = self;
3131 __thread_list_lock = 0;
3232 libc.threads_minus_1 = 0;
33 if (libc.need_locks) libc.need_locks = -1;
3334 }
3435 __restore_sigs(&set);
3536 __fork_handler(!ret);
lib/libc/musl/src/stdio/__string_read.c deleted-16
......@@ -1,16 +0,0 @@
1#include "stdio_impl.h"
2#include <string.h>
3
4size_t __string_read(FILE *f, unsigned char *buf, size_t len)
5{
6 char *src = f->cookie;
7 size_t k = len+256;
8 char *end = memchr(src, 0, k);
9 if (end) k = end-src;
10 if (k < len) len = k;
11 memcpy(buf, src, len);
12 f->rpos = (void *)(src+len);
13 f->rend = (void *)(src+k);
14 f->cookie = src+k;
15 return len;
16}
lib/libc/musl/src/stdio/fmemopen.c+3-3
......@@ -2,6 +2,7 @@
22#include <errno.h>
33#include <string.h>
44#include <stdlib.h>
5#include <stddef.h>
56#include <inttypes.h>
67#include "libc.h"
78
......@@ -95,18 +96,17 @@ FILE *fmemopen(void *restrict buf, size_t size, const char *restrict mode)
9596
9697 f = malloc(sizeof *f + (buf?0:size));
9798 if (!f) return 0;
98 memset(&f->f, 0, sizeof f->f);
99 memset(f, 0, offsetof(struct mem_FILE, buf));
99100 f->f.cookie = &f->c;
100101 f->f.fd = -1;
101102 f->f.lbf = EOF;
102103 f->f.buf = f->buf + UNGET;
103104 f->f.buf_size = sizeof f->buf - UNGET;
104105 if (!buf) {
105 buf = f->buf2;;
106 buf = f->buf2;
106107 memset(buf, 0, size);
107108 }
108109
109 memset(&f->c, 0, sizeof f->c);
110110 f->c.buf = buf;
111111 f->c.size = size;
112112 f->c.mode = *mode;
lib/libc/musl/src/stdio/vdprintf.c+1-6
......@@ -1,14 +1,9 @@
11#include "stdio_impl.h"
22
3static size_t wrap_write(FILE *f, const unsigned char *buf, size_t len)
4{
5 return __stdio_write(f, buf, len);
6}
7
83int vdprintf(int fd, const char *restrict fmt, va_list ap)
94{
105 FILE f = {
11 .fd = fd, .lbf = EOF, .write = wrap_write,
6 .fd = fd, .lbf = EOF, .write = __stdio_write,
127 .buf = (void *)fmt, .buf_size = 0,
138 .lock = -1
149 };
lib/libc/musl/src/stdio/vfscanf.c+4-1
......@@ -57,7 +57,7 @@ int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
5757{
5858 int width;
5959 int size;
60 int alloc;
60 int alloc = 0;
6161 int base;
6262 const unsigned char *p;
6363 int c, t;
......@@ -76,6 +76,9 @@ int vfscanf(FILE *restrict f, const char *restrict fmt, va_list ap)
7676
7777 FLOCK(f);
7878
79 if (!f->rpos) __toread(f);
80 if (!f->rpos) goto input_fail;
81
7982 for (p=(const unsigned char *)fmt; *p; p++) {
8083
8184 alloc = 0;
lib/libc/musl/src/stdio/vsscanf.c+13-3
......@@ -1,15 +1,25 @@
11#include "stdio_impl.h"
2#include <string.h>
23
3static size_t do_read(FILE *f, unsigned char *buf, size_t len)
4static size_t string_read(FILE *f, unsigned char *buf, size_t len)
45{
5 return __string_read(f, buf, len);
6 char *src = f->cookie;
7 size_t k = len+256;
8 char *end = memchr(src, 0, k);
9 if (end) k = end-src;
10 if (k < len) len = k;
11 memcpy(buf, src, len);
12 f->rpos = (void *)(src+len);
13 f->rend = (void *)(src+k);
14 f->cookie = src+k;
15 return len;
616}
717
818int vsscanf(const char *restrict s, const char *restrict fmt, va_list ap)
919{
1020 FILE f = {
1121 .buf = (void *)s, .cookie = (void *)s,
12 .read = do_read, .lock = -1
22 .read = string_read, .lock = -1
1323 };
1424 return vfscanf(&f, fmt, ap);
1525}
lib/libc/musl/src/stdlib/wcstod.c+1-2
......@@ -33,8 +33,7 @@ static long double wcstox(const wchar_t *s, wchar_t **p, int prec)
3333 unsigned char buf[64];
3434 FILE f = {0};
3535 f.flags = 0;
36 f.rpos = f.rend = 0;
37 f.buf = buf + 4;
36 f.rpos = f.rend = f.buf = buf + 4;
3837 f.buf_size = sizeof buf - 4;
3938 f.lock = -1;
4039 f.read = do_read;
lib/libc/musl/src/stdlib/wcstol.c+1-2
......@@ -35,8 +35,7 @@ static unsigned long long wcstox(const wchar_t *s, wchar_t **p, int base, unsign
3535 unsigned char buf[64];
3636 FILE f = {0};
3737 f.flags = 0;
38 f.rpos = f.rend = 0;
39 f.buf = buf + 4;
38 f.rpos = f.rend = f.buf = buf + 4;
4039 f.buf_size = sizeof buf - 4;
4140 f.lock = -1;
4241 f.read = do_read;
lib/libc/musl/src/string/aarch64/memcpy.S created+186
......@@ -0,0 +1,186 @@
1/*
2 * memcpy - copy memory area
3 *
4 * Copyright (c) 2012-2020, Arm Limited.
5 * SPDX-License-Identifier: MIT
6 */
7
8/* Assumptions:
9 *
10 * ARMv8-a, AArch64, unaligned accesses.
11 *
12 */
13
14#define dstin x0
15#define src x1
16#define count x2
17#define dst x3
18#define srcend x4
19#define dstend x5
20#define A_l x6
21#define A_lw w6
22#define A_h x7
23#define B_l x8
24#define B_lw w8
25#define B_h x9
26#define C_l x10
27#define C_lw w10
28#define C_h x11
29#define D_l x12
30#define D_h x13
31#define E_l x14
32#define E_h x15
33#define F_l x16
34#define F_h x17
35#define G_l count
36#define G_h dst
37#define H_l src
38#define H_h srcend
39#define tmp1 x14
40
41/* This implementation of memcpy uses unaligned accesses and branchless
42 sequences to keep the code small, simple and improve performance.
43
44 Copies are split into 3 main cases: small copies of up to 32 bytes, medium
45 copies of up to 128 bytes, and large copies. The overhead of the overlap
46 check is negligible since it is only required for large copies.
47
48 Large copies use a software pipelined loop processing 64 bytes per iteration.
49 The destination pointer is 16-byte aligned to minimize unaligned accesses.
50 The loop tail is handled by always copying 64 bytes from the end.
51*/
52
53.global memcpy
54.type memcpy,%function
55memcpy:
56 add srcend, src, count
57 add dstend, dstin, count
58 cmp count, 128
59 b.hi .Lcopy_long
60 cmp count, 32
61 b.hi .Lcopy32_128
62
63 /* Small copies: 0..32 bytes. */
64 cmp count, 16
65 b.lo .Lcopy16
66 ldp A_l, A_h, [src]
67 ldp D_l, D_h, [srcend, -16]
68 stp A_l, A_h, [dstin]
69 stp D_l, D_h, [dstend, -16]
70 ret
71
72 /* Copy 8-15 bytes. */
73.Lcopy16:
74 tbz count, 3, .Lcopy8
75 ldr A_l, [src]
76 ldr A_h, [srcend, -8]
77 str A_l, [dstin]
78 str A_h, [dstend, -8]
79 ret
80
81 .p2align 3
82 /* Copy 4-7 bytes. */
83.Lcopy8:
84 tbz count, 2, .Lcopy4
85 ldr A_lw, [src]
86 ldr B_lw, [srcend, -4]
87 str A_lw, [dstin]
88 str B_lw, [dstend, -4]
89 ret
90
91 /* Copy 0..3 bytes using a branchless sequence. */
92.Lcopy4:
93 cbz count, .Lcopy0
94 lsr tmp1, count, 1
95 ldrb A_lw, [src]
96 ldrb C_lw, [srcend, -1]
97 ldrb B_lw, [src, tmp1]
98 strb A_lw, [dstin]
99 strb B_lw, [dstin, tmp1]
100 strb C_lw, [dstend, -1]
101.Lcopy0:
102 ret
103
104 .p2align 4
105 /* Medium copies: 33..128 bytes. */
106.Lcopy32_128:
107 ldp A_l, A_h, [src]
108 ldp B_l, B_h, [src, 16]
109 ldp C_l, C_h, [srcend, -32]
110 ldp D_l, D_h, [srcend, -16]
111 cmp count, 64
112 b.hi .Lcopy128
113 stp A_l, A_h, [dstin]
114 stp B_l, B_h, [dstin, 16]
115 stp C_l, C_h, [dstend, -32]
116 stp D_l, D_h, [dstend, -16]
117 ret
118
119 .p2align 4
120 /* Copy 65..128 bytes. */
121.Lcopy128:
122 ldp E_l, E_h, [src, 32]
123 ldp F_l, F_h, [src, 48]
124 cmp count, 96
125 b.ls .Lcopy96
126 ldp G_l, G_h, [srcend, -64]
127 ldp H_l, H_h, [srcend, -48]
128 stp G_l, G_h, [dstend, -64]
129 stp H_l, H_h, [dstend, -48]
130.Lcopy96:
131 stp A_l, A_h, [dstin]
132 stp B_l, B_h, [dstin, 16]
133 stp E_l, E_h, [dstin, 32]
134 stp F_l, F_h, [dstin, 48]
135 stp C_l, C_h, [dstend, -32]
136 stp D_l, D_h, [dstend, -16]
137 ret
138
139 .p2align 4
140 /* Copy more than 128 bytes. */
141.Lcopy_long:
142
143 /* Copy 16 bytes and then align dst to 16-byte alignment. */
144
145 ldp D_l, D_h, [src]
146 and tmp1, dstin, 15
147 bic dst, dstin, 15
148 sub src, src, tmp1
149 add count, count, tmp1 /* Count is now 16 too large. */
150 ldp A_l, A_h, [src, 16]
151 stp D_l, D_h, [dstin]
152 ldp B_l, B_h, [src, 32]
153 ldp C_l, C_h, [src, 48]
154 ldp D_l, D_h, [src, 64]!
155 subs count, count, 128 + 16 /* Test and readjust count. */
156 b.ls .Lcopy64_from_end
157
158.Lloop64:
159 stp A_l, A_h, [dst, 16]
160 ldp A_l, A_h, [src, 16]
161 stp B_l, B_h, [dst, 32]
162 ldp B_l, B_h, [src, 32]
163 stp C_l, C_h, [dst, 48]
164 ldp C_l, C_h, [src, 48]
165 stp D_l, D_h, [dst, 64]!
166 ldp D_l, D_h, [src, 64]!
167 subs count, count, 64
168 b.hi .Lloop64
169
170 /* Write the last iteration and copy 64 bytes from the end. */
171.Lcopy64_from_end:
172 ldp E_l, E_h, [srcend, -64]
173 stp A_l, A_h, [dst, 16]
174 ldp A_l, A_h, [srcend, -48]
175 stp B_l, B_h, [dst, 32]
176 ldp B_l, B_h, [srcend, -32]
177 stp C_l, C_h, [dst, 48]
178 ldp C_l, C_h, [srcend, -16]
179 stp D_l, D_h, [dst, 64]
180 stp E_l, E_h, [dstend, -64]
181 stp A_l, A_h, [dstend, -48]
182 stp B_l, B_h, [dstend, -32]
183 stp C_l, C_h, [dstend, -16]
184 ret
185
186.size memcpy,.-memcpy
lib/libc/musl/src/string/aarch64/memset.S created+115
......@@ -0,0 +1,115 @@
1/*
2 * memset - fill memory with a constant byte
3 *
4 * Copyright (c) 2012-2020, Arm Limited.
5 * SPDX-License-Identifier: MIT
6 */
7
8/* Assumptions:
9 *
10 * ARMv8-a, AArch64, Advanced SIMD, unaligned accesses.
11 *
12 */
13
14#define dstin x0
15#define val x1
16#define valw w1
17#define count x2
18#define dst x3
19#define dstend x4
20#define zva_val x5
21
22.global memset
23.type memset,%function
24memset:
25
26 dup v0.16B, valw
27 add dstend, dstin, count
28
29 cmp count, 96
30 b.hi .Lset_long
31 cmp count, 16
32 b.hs .Lset_medium
33 mov val, v0.D[0]
34
35 /* Set 0..15 bytes. */
36 tbz count, 3, 1f
37 str val, [dstin]
38 str val, [dstend, -8]
39 ret
40 nop
411: tbz count, 2, 2f
42 str valw, [dstin]
43 str valw, [dstend, -4]
44 ret
452: cbz count, 3f
46 strb valw, [dstin]
47 tbz count, 1, 3f
48 strh valw, [dstend, -2]
493: ret
50
51 /* Set 17..96 bytes. */
52.Lset_medium:
53 str q0, [dstin]
54 tbnz count, 6, .Lset96
55 str q0, [dstend, -16]
56 tbz count, 5, 1f
57 str q0, [dstin, 16]
58 str q0, [dstend, -32]
591: ret
60
61 .p2align 4
62 /* Set 64..96 bytes. Write 64 bytes from the start and
63 32 bytes from the end. */
64.Lset96:
65 str q0, [dstin, 16]
66 stp q0, q0, [dstin, 32]
67 stp q0, q0, [dstend, -32]
68 ret
69
70 .p2align 4
71.Lset_long:
72 and valw, valw, 255
73 bic dst, dstin, 15
74 str q0, [dstin]
75 cmp count, 160
76 ccmp valw, 0, 0, hs
77 b.ne .Lno_zva
78
79#ifndef SKIP_ZVA_CHECK
80 mrs zva_val, dczid_el0
81 and zva_val, zva_val, 31
82 cmp zva_val, 4 /* ZVA size is 64 bytes. */
83 b.ne .Lno_zva
84#endif
85 str q0, [dst, 16]
86 stp q0, q0, [dst, 32]
87 bic dst, dst, 63
88 sub count, dstend, dst /* Count is now 64 too large. */
89 sub count, count, 128 /* Adjust count and bias for loop. */
90
91 .p2align 4
92.Lzva_loop:
93 add dst, dst, 64
94 dc zva, dst
95 subs count, count, 64
96 b.hi .Lzva_loop
97 stp q0, q0, [dstend, -64]
98 stp q0, q0, [dstend, -32]
99 ret
100
101.Lno_zva:
102 sub count, dstend, dst /* Count is 16 too large. */
103 sub dst, dst, 16 /* Dst is biased by -32. */
104 sub count, count, 64 + 16 /* Adjust count and bias for loop. */
105.Lno_zva_loop:
106 stp q0, q0, [dst, 32]
107 stp q0, q0, [dst, 64]!
108 subs count, count, 64
109 b.hi .Lno_zva_loop
110 stp q0, q0, [dstend, -64]
111 stp q0, q0, [dstend, -32]
112 ret
113
114.size memset,.-memset
115
lib/libc/musl/src/string/arm/memcpy.S created+479
......@@ -0,0 +1,479 @@
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29
30/*
31 * Optimized memcpy() for ARM.
32 *
33 * note that memcpy() always returns the destination pointer,
34 * so we have to preserve R0.
35 */
36
37/*
38 * This file has been modified from the original for use in musl libc.
39 * The main changes are: addition of .type memcpy,%function to make the
40 * code safely callable from thumb mode, adjusting the return
41 * instructions to be compatible with pre-thumb ARM cpus, removal of
42 * prefetch code that is not compatible with older cpus and support for
43 * building as thumb 2 and big-endian.
44 */
45
46.syntax unified
47
48.global memcpy
49.type memcpy,%function
50memcpy:
51 /* The stack must always be 64-bits aligned to be compliant with the
52 * ARM ABI. Since we have to save R0, we might as well save R4
53 * which we can use for better pipelining of the reads below
54 */
55 .fnstart
56 .save {r0, r4, lr}
57 stmfd sp!, {r0, r4, lr}
58 /* Making room for r5-r11 which will be spilled later */
59 .pad #28
60 sub sp, sp, #28
61
62 /* it simplifies things to take care of len<4 early */
63 cmp r2, #4
64 blo copy_last_3_and_return
65
66 /* compute the offset to align the source
67 * offset = (4-(src&3))&3 = -src & 3
68 */
69 rsb r3, r1, #0
70 ands r3, r3, #3
71 beq src_aligned
72
73 /* align source to 32 bits. We need to insert 2 instructions between
74 * a ldr[b|h] and str[b|h] because byte and half-word instructions
75 * stall 2 cycles.
76 */
77 movs r12, r3, lsl #31
78 sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
79 ldrbmi r3, [r1], #1
80 ldrbcs r4, [r1], #1
81 ldrbcs r12,[r1], #1
82 strbmi r3, [r0], #1
83 strbcs r4, [r0], #1
84 strbcs r12,[r0], #1
85
86src_aligned:
87
88 /* see if src and dst are aligned together (congruent) */
89 eor r12, r0, r1
90 tst r12, #3
91 bne non_congruent
92
93 /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
94 * frame. Don't update sp.
95 */
96 stmea sp, {r5-r11}
97
98 /* align the destination to a cache-line */
99 rsb r3, r0, #0
100 ands r3, r3, #0x1C
101 beq congruent_aligned32
102 cmp r3, r2
103 andhi r3, r2, #0x1C
104
105 /* conditionnaly copies 0 to 7 words (length in r3) */
106 movs r12, r3, lsl #28
107 ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
108 ldmmi r1!, {r8, r9} /* 8 bytes */
109 stmcs r0!, {r4, r5, r6, r7}
110 stmmi r0!, {r8, r9}
111 tst r3, #0x4
112 ldrne r10,[r1], #4 /* 4 bytes */
113 strne r10,[r0], #4
114 sub r2, r2, r3
115
116congruent_aligned32:
117 /*
118 * here source is aligned to 32 bytes.
119 */
120
121cached_aligned32:
122 subs r2, r2, #32
123 blo less_than_32_left
124
125 /*
126 * We preload a cache-line up to 64 bytes ahead. On the 926, this will
127 * stall only until the requested world is fetched, but the linefill
128 * continues in the the background.
129 * While the linefill is going, we write our previous cache-line
130 * into the write-buffer (which should have some free space).
131 * When the linefill is done, the writebuffer will
132 * start dumping its content into memory
133 *
134 * While all this is going, we then load a full cache line into
135 * 8 registers, this cache line should be in the cache by now
136 * (or partly in the cache).
137 *
138 * This code should work well regardless of the source/dest alignment.
139 *
140 */
141
142 /* Align the preload register to a cache-line because the cpu does
143 * "critical word first" (the first word requested is loaded first).
144 */
145 @ bic r12, r1, #0x1F
146 @ add r12, r12, #64
147
1481: ldmia r1!, { r4-r11 }
149 subs r2, r2, #32
150
151 /*
152 * NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
153 * for ARM9 preload will not be safely guarded by the preceding subs.
154 * When it is safely guarded the only possibility to have SIGSEGV here
155 * is because the caller overstates the length.
156 */
157 @ ldrhi r3, [r12], #32 /* cheap ARM9 preload */
158 stmia r0!, { r4-r11 }
159 bhs 1b
160
161 add r2, r2, #32
162
163less_than_32_left:
164 /*
165 * less than 32 bytes left at this point (length in r2)
166 */
167
168 /* skip all this if there is nothing to do, which should
169 * be a common case (if not executed the code below takes
170 * about 16 cycles)
171 */
172 tst r2, #0x1F
173 beq 1f
174
175 /* conditionnaly copies 0 to 31 bytes */
176 movs r12, r2, lsl #28
177 ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
178 ldmmi r1!, {r8, r9} /* 8 bytes */
179 stmcs r0!, {r4, r5, r6, r7}
180 stmmi r0!, {r8, r9}
181 movs r12, r2, lsl #30
182 ldrcs r3, [r1], #4 /* 4 bytes */
183 ldrhmi r4, [r1], #2 /* 2 bytes */
184 strcs r3, [r0], #4
185 strhmi r4, [r0], #2
186 tst r2, #0x1
187 ldrbne r3, [r1] /* last byte */
188 strbne r3, [r0]
189
190 /* we're done! restore everything and return */
1911: ldmfd sp!, {r5-r11}
192 ldmfd sp!, {r0, r4, lr}
193 bx lr
194
195 /********************************************************************/
196
197non_congruent:
198 /*
199 * here source is aligned to 4 bytes
200 * but destination is not.
201 *
202 * in the code below r2 is the number of bytes read
203 * (the number of bytes written is always smaller, because we have
204 * partial words in the shift queue)
205 */
206 cmp r2, #4
207 blo copy_last_3_and_return
208
209 /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
210 * frame. Don't update sp.
211 */
212 stmea sp, {r5-r11}
213
214 /* compute shifts needed to align src to dest */
215 rsb r5, r0, #0
216 and r5, r5, #3 /* r5 = # bytes in partial words */
217 mov r12, r5, lsl #3 /* r12 = right */
218 rsb lr, r12, #32 /* lr = left */
219
220 /* read the first word */
221 ldr r3, [r1], #4
222 sub r2, r2, #4
223
224 /* write a partial word (0 to 3 bytes), such that destination
225 * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
226 */
227 movs r5, r5, lsl #31
228
229#if __ARMEB__
230 movmi r3, r3, ror #24
231 strbmi r3, [r0], #1
232 movcs r3, r3, ror #24
233 strbcs r3, [r0], #1
234 movcs r3, r3, ror #24
235 strbcs r3, [r0], #1
236#else
237 strbmi r3, [r0], #1
238 movmi r3, r3, lsr #8
239 strbcs r3, [r0], #1
240 movcs r3, r3, lsr #8
241 strbcs r3, [r0], #1
242 movcs r3, r3, lsr #8
243#endif
244
245 cmp r2, #4
246 blo partial_word_tail
247
248#if __ARMEB__
249 mov r3, r3, lsr r12
250 mov r3, r3, lsl r12
251#endif
252
253 /* Align destination to 32 bytes (cache line boundary) */
2541: tst r0, #0x1c
255 beq 2f
256 ldr r5, [r1], #4
257 sub r2, r2, #4
258#if __ARMEB__
259 mov r4, r5, lsr lr
260 orr r4, r4, r3
261 mov r3, r5, lsl r12
262#else
263 mov r4, r5, lsl lr
264 orr r4, r4, r3
265 mov r3, r5, lsr r12
266#endif
267 str r4, [r0], #4
268 cmp r2, #4
269 bhs 1b
270 blo partial_word_tail
271
272 /* copy 32 bytes at a time */
2732: subs r2, r2, #32
274 blo less_than_thirtytwo
275
276 /* Use immediate mode for the shifts, because there is an extra cycle
277 * for register shifts, which could account for up to 50% of
278 * performance hit.
279 */
280
281 cmp r12, #24
282 beq loop24
283 cmp r12, #8
284 beq loop8
285
286loop16:
287 ldr r12, [r1], #4
2881: mov r4, r12
289 ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
290 subs r2, r2, #32
291 ldrhs r12, [r1], #4
292#if __ARMEB__
293 orr r3, r3, r4, lsr #16
294 mov r4, r4, lsl #16
295 orr r4, r4, r5, lsr #16
296 mov r5, r5, lsl #16
297 orr r5, r5, r6, lsr #16
298 mov r6, r6, lsl #16
299 orr r6, r6, r7, lsr #16
300 mov r7, r7, lsl #16
301 orr r7, r7, r8, lsr #16
302 mov r8, r8, lsl #16
303 orr r8, r8, r9, lsr #16
304 mov r9, r9, lsl #16
305 orr r9, r9, r10, lsr #16
306 mov r10, r10, lsl #16
307 orr r10, r10, r11, lsr #16
308 stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
309 mov r3, r11, lsl #16
310#else
311 orr r3, r3, r4, lsl #16
312 mov r4, r4, lsr #16
313 orr r4, r4, r5, lsl #16
314 mov r5, r5, lsr #16
315 orr r5, r5, r6, lsl #16
316 mov r6, r6, lsr #16
317 orr r6, r6, r7, lsl #16
318 mov r7, r7, lsr #16
319 orr r7, r7, r8, lsl #16
320 mov r8, r8, lsr #16
321 orr r8, r8, r9, lsl #16
322 mov r9, r9, lsr #16
323 orr r9, r9, r10, lsl #16
324 mov r10, r10, lsr #16
325 orr r10, r10, r11, lsl #16
326 stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
327 mov r3, r11, lsr #16
328#endif
329 bhs 1b
330 b less_than_thirtytwo
331
332loop8:
333 ldr r12, [r1], #4
3341: mov r4, r12
335 ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
336 subs r2, r2, #32
337 ldrhs r12, [r1], #4
338#if __ARMEB__
339 orr r3, r3, r4, lsr #24
340 mov r4, r4, lsl #8
341 orr r4, r4, r5, lsr #24
342 mov r5, r5, lsl #8
343 orr r5, r5, r6, lsr #24
344 mov r6, r6, lsl #8
345 orr r6, r6, r7, lsr #24
346 mov r7, r7, lsl #8
347 orr r7, r7, r8, lsr #24
348 mov r8, r8, lsl #8
349 orr r8, r8, r9, lsr #24
350 mov r9, r9, lsl #8
351 orr r9, r9, r10, lsr #24
352 mov r10, r10, lsl #8
353 orr r10, r10, r11, lsr #24
354 stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
355 mov r3, r11, lsl #8
356#else
357 orr r3, r3, r4, lsl #24
358 mov r4, r4, lsr #8
359 orr r4, r4, r5, lsl #24
360 mov r5, r5, lsr #8
361 orr r5, r5, r6, lsl #24
362 mov r6, r6, lsr #8
363 orr r6, r6, r7, lsl #24
364 mov r7, r7, lsr #8
365 orr r7, r7, r8, lsl #24
366 mov r8, r8, lsr #8
367 orr r8, r8, r9, lsl #24
368 mov r9, r9, lsr #8
369 orr r9, r9, r10, lsl #24
370 mov r10, r10, lsr #8
371 orr r10, r10, r11, lsl #24
372 stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
373 mov r3, r11, lsr #8
374#endif
375 bhs 1b
376 b less_than_thirtytwo
377
378loop24:
379 ldr r12, [r1], #4
3801: mov r4, r12
381 ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
382 subs r2, r2, #32
383 ldrhs r12, [r1], #4
384#if __ARMEB__
385 orr r3, r3, r4, lsr #8
386 mov r4, r4, lsl #24
387 orr r4, r4, r5, lsr #8
388 mov r5, r5, lsl #24
389 orr r5, r5, r6, lsr #8
390 mov r6, r6, lsl #24
391 orr r6, r6, r7, lsr #8
392 mov r7, r7, lsl #24
393 orr r7, r7, r8, lsr #8
394 mov r8, r8, lsl #24
395 orr r8, r8, r9, lsr #8
396 mov r9, r9, lsl #24
397 orr r9, r9, r10, lsr #8
398 mov r10, r10, lsl #24
399 orr r10, r10, r11, lsr #8
400 stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
401 mov r3, r11, lsl #24
402#else
403 orr r3, r3, r4, lsl #8
404 mov r4, r4, lsr #24
405 orr r4, r4, r5, lsl #8
406 mov r5, r5, lsr #24
407 orr r5, r5, r6, lsl #8
408 mov r6, r6, lsr #24
409 orr r6, r6, r7, lsl #8
410 mov r7, r7, lsr #24
411 orr r7, r7, r8, lsl #8
412 mov r8, r8, lsr #24
413 orr r8, r8, r9, lsl #8
414 mov r9, r9, lsr #24
415 orr r9, r9, r10, lsl #8
416 mov r10, r10, lsr #24
417 orr r10, r10, r11, lsl #8
418 stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
419 mov r3, r11, lsr #24
420#endif
421 bhs 1b
422
423less_than_thirtytwo:
424 /* copy the last 0 to 31 bytes of the source */
425 rsb r12, lr, #32 /* we corrupted r12, recompute it */
426 add r2, r2, #32
427 cmp r2, #4
428 blo partial_word_tail
429
4301: ldr r5, [r1], #4
431 sub r2, r2, #4
432#if __ARMEB__
433 mov r4, r5, lsr lr
434 orr r4, r4, r3
435 mov r3, r5, lsl r12
436#else
437 mov r4, r5, lsl lr
438 orr r4, r4, r3
439 mov r3, r5, lsr r12
440#endif
441 str r4, [r0], #4
442 cmp r2, #4
443 bhs 1b
444
445partial_word_tail:
446 /* we have a partial word in the input buffer */
447 movs r5, lr, lsl #(31-3)
448#if __ARMEB__
449 movmi r3, r3, ror #24
450 strbmi r3, [r0], #1
451 movcs r3, r3, ror #24
452 strbcs r3, [r0], #1
453 movcs r3, r3, ror #24
454 strbcs r3, [r0], #1
455#else
456 strbmi r3, [r0], #1
457 movmi r3, r3, lsr #8
458 strbcs r3, [r0], #1
459 movcs r3, r3, lsr #8
460 strbcs r3, [r0], #1
461#endif
462
463 /* Refill spilled registers from the stack. Don't update sp. */
464 ldmfd sp, {r5-r11}
465
466copy_last_3_and_return:
467 movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
468 ldrbmi r2, [r1], #1
469 ldrbcs r3, [r1], #1
470 ldrbcs r12,[r1]
471 strbmi r2, [r0], #1
472 strbcs r3, [r0], #1
473 strbcs r12,[r0]
474
475 /* we're done! restore sp and spilled registers and return */
476 add sp, sp, #28
477 ldmfd sp!, {r0, r4, lr}
478 bx lr
479
lib/libc/musl/src/string/arm/memcpy.c deleted-3
......@@ -1,3 +0,0 @@
1#if __ARMEB__
2#include "../memcpy.c"
3#endif
lib/libc/musl/src/string/arm/memcpy_le.S deleted-386
......@@ -1,386 +0,0 @@
1#if !__ARMEB__
2
3/*
4 * Copyright (C) 2008 The Android Open Source Project
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31
32/*
33 * Optimized memcpy() for ARM.
34 *
35 * note that memcpy() always returns the destination pointer,
36 * so we have to preserve R0.
37 */
38
39/*
40 * This file has been modified from the original for use in musl libc.
41 * The main changes are: addition of .type memcpy,%function to make the
42 * code safely callable from thumb mode, adjusting the return
43 * instructions to be compatible with pre-thumb ARM cpus, removal of
44 * prefetch code that is not compatible with older cpus and support for
45 * building as thumb 2.
46 */
47
48.syntax unified
49
50.global memcpy
51.type memcpy,%function
52memcpy:
53 /* The stack must always be 64-bits aligned to be compliant with the
54 * ARM ABI. Since we have to save R0, we might as well save R4
55 * which we can use for better pipelining of the reads below
56 */
57 .fnstart
58 .save {r0, r4, lr}
59 stmfd sp!, {r0, r4, lr}
60 /* Making room for r5-r11 which will be spilled later */
61 .pad #28
62 sub sp, sp, #28
63
64 /* it simplifies things to take care of len<4 early */
65 cmp r2, #4
66 blo copy_last_3_and_return
67
68 /* compute the offset to align the source
69 * offset = (4-(src&3))&3 = -src & 3
70 */
71 rsb r3, r1, #0
72 ands r3, r3, #3
73 beq src_aligned
74
75 /* align source to 32 bits. We need to insert 2 instructions between
76 * a ldr[b|h] and str[b|h] because byte and half-word instructions
77 * stall 2 cycles.
78 */
79 movs r12, r3, lsl #31
80 sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
81 ldrbmi r3, [r1], #1
82 ldrbcs r4, [r1], #1
83 ldrbcs r12,[r1], #1
84 strbmi r3, [r0], #1
85 strbcs r4, [r0], #1
86 strbcs r12,[r0], #1
87
88src_aligned:
89
90 /* see if src and dst are aligned together (congruent) */
91 eor r12, r0, r1
92 tst r12, #3
93 bne non_congruent
94
95 /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
96 * frame. Don't update sp.
97 */
98 stmea sp, {r5-r11}
99
100 /* align the destination to a cache-line */
101 rsb r3, r0, #0
102 ands r3, r3, #0x1C
103 beq congruent_aligned32
104 cmp r3, r2
105 andhi r3, r2, #0x1C
106
107 /* conditionnaly copies 0 to 7 words (length in r3) */
108 movs r12, r3, lsl #28
109 ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
110 ldmmi r1!, {r8, r9} /* 8 bytes */
111 stmcs r0!, {r4, r5, r6, r7}
112 stmmi r0!, {r8, r9}
113 tst r3, #0x4
114 ldrne r10,[r1], #4 /* 4 bytes */
115 strne r10,[r0], #4
116 sub r2, r2, r3
117
118congruent_aligned32:
119 /*
120 * here source is aligned to 32 bytes.
121 */
122
123cached_aligned32:
124 subs r2, r2, #32
125 blo less_than_32_left
126
127 /*
128 * We preload a cache-line up to 64 bytes ahead. On the 926, this will
129 * stall only until the requested world is fetched, but the linefill
130 * continues in the the background.
131 * While the linefill is going, we write our previous cache-line
132 * into the write-buffer (which should have some free space).
133 * When the linefill is done, the writebuffer will
134 * start dumping its content into memory
135 *
136 * While all this is going, we then load a full cache line into
137 * 8 registers, this cache line should be in the cache by now
138 * (or partly in the cache).
139 *
140 * This code should work well regardless of the source/dest alignment.
141 *
142 */
143
144 /* Align the preload register to a cache-line because the cpu does
145 * "critical word first" (the first word requested is loaded first).
146 */
147 @ bic r12, r1, #0x1F
148 @ add r12, r12, #64
149
1501: ldmia r1!, { r4-r11 }
151 subs r2, r2, #32
152
153 /*
154 * NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
155 * for ARM9 preload will not be safely guarded by the preceding subs.
156 * When it is safely guarded the only possibility to have SIGSEGV here
157 * is because the caller overstates the length.
158 */
159 @ ldrhi r3, [r12], #32 /* cheap ARM9 preload */
160 stmia r0!, { r4-r11 }
161 bhs 1b
162
163 add r2, r2, #32
164
165less_than_32_left:
166 /*
167 * less than 32 bytes left at this point (length in r2)
168 */
169
170 /* skip all this if there is nothing to do, which should
171 * be a common case (if not executed the code below takes
172 * about 16 cycles)
173 */
174 tst r2, #0x1F
175 beq 1f
176
177 /* conditionnaly copies 0 to 31 bytes */
178 movs r12, r2, lsl #28
179 ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
180 ldmmi r1!, {r8, r9} /* 8 bytes */
181 stmcs r0!, {r4, r5, r6, r7}
182 stmmi r0!, {r8, r9}
183 movs r12, r2, lsl #30
184 ldrcs r3, [r1], #4 /* 4 bytes */
185 ldrhmi r4, [r1], #2 /* 2 bytes */
186 strcs r3, [r0], #4
187 strhmi r4, [r0], #2
188 tst r2, #0x1
189 ldrbne r3, [r1] /* last byte */
190 strbne r3, [r0]
191
192 /* we're done! restore everything and return */
1931: ldmfd sp!, {r5-r11}
194 ldmfd sp!, {r0, r4, lr}
195 bx lr
196
197 /********************************************************************/
198
199non_congruent:
200 /*
201 * here source is aligned to 4 bytes
202 * but destination is not.
203 *
204 * in the code below r2 is the number of bytes read
205 * (the number of bytes written is always smaller, because we have
206 * partial words in the shift queue)
207 */
208 cmp r2, #4
209 blo copy_last_3_and_return
210
211 /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
212 * frame. Don't update sp.
213 */
214 stmea sp, {r5-r11}
215
216 /* compute shifts needed to align src to dest */
217 rsb r5, r0, #0
218 and r5, r5, #3 /* r5 = # bytes in partial words */
219 mov r12, r5, lsl #3 /* r12 = right */
220 rsb lr, r12, #32 /* lr = left */
221
222 /* read the first word */
223 ldr r3, [r1], #4
224 sub r2, r2, #4
225
226 /* write a partial word (0 to 3 bytes), such that destination
227 * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
228 */
229 movs r5, r5, lsl #31
230 strbmi r3, [r0], #1
231 movmi r3, r3, lsr #8
232 strbcs r3, [r0], #1
233 movcs r3, r3, lsr #8
234 strbcs r3, [r0], #1
235 movcs r3, r3, lsr #8
236
237 cmp r2, #4
238 blo partial_word_tail
239
240 /* Align destination to 32 bytes (cache line boundary) */
2411: tst r0, #0x1c
242 beq 2f
243 ldr r5, [r1], #4
244 sub r2, r2, #4
245 mov r4, r5, lsl lr
246 orr r4, r4, r3
247 mov r3, r5, lsr r12
248 str r4, [r0], #4
249 cmp r2, #4
250 bhs 1b
251 blo partial_word_tail
252
253 /* copy 32 bytes at a time */
2542: subs r2, r2, #32
255 blo less_than_thirtytwo
256
257 /* Use immediate mode for the shifts, because there is an extra cycle
258 * for register shifts, which could account for up to 50% of
259 * performance hit.
260 */
261
262 cmp r12, #24
263 beq loop24
264 cmp r12, #8
265 beq loop8
266
267loop16:
268 ldr r12, [r1], #4
2691: mov r4, r12
270 ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
271 subs r2, r2, #32
272 ldrhs r12, [r1], #4
273 orr r3, r3, r4, lsl #16
274 mov r4, r4, lsr #16
275 orr r4, r4, r5, lsl #16
276 mov r5, r5, lsr #16
277 orr r5, r5, r6, lsl #16
278 mov r6, r6, lsr #16
279 orr r6, r6, r7, lsl #16
280 mov r7, r7, lsr #16
281 orr r7, r7, r8, lsl #16
282 mov r8, r8, lsr #16
283 orr r8, r8, r9, lsl #16
284 mov r9, r9, lsr #16
285 orr r9, r9, r10, lsl #16
286 mov r10, r10, lsr #16
287 orr r10, r10, r11, lsl #16
288 stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
289 mov r3, r11, lsr #16
290 bhs 1b
291 b less_than_thirtytwo
292
293loop8:
294 ldr r12, [r1], #4
2951: mov r4, r12
296 ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
297 subs r2, r2, #32
298 ldrhs r12, [r1], #4
299 orr r3, r3, r4, lsl #24
300 mov r4, r4, lsr #8
301 orr r4, r4, r5, lsl #24
302 mov r5, r5, lsr #8
303 orr r5, r5, r6, lsl #24
304 mov r6, r6, lsr #8
305 orr r6, r6, r7, lsl #24
306 mov r7, r7, lsr #8
307 orr r7, r7, r8, lsl #24
308 mov r8, r8, lsr #8
309 orr r8, r8, r9, lsl #24
310 mov r9, r9, lsr #8
311 orr r9, r9, r10, lsl #24
312 mov r10, r10, lsr #8
313 orr r10, r10, r11, lsl #24
314 stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
315 mov r3, r11, lsr #8
316 bhs 1b
317 b less_than_thirtytwo
318
319loop24:
320 ldr r12, [r1], #4
3211: mov r4, r12
322 ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
323 subs r2, r2, #32
324 ldrhs r12, [r1], #4
325 orr r3, r3, r4, lsl #8
326 mov r4, r4, lsr #24
327 orr r4, r4, r5, lsl #8
328 mov r5, r5, lsr #24
329 orr r5, r5, r6, lsl #8
330 mov r6, r6, lsr #24
331 orr r6, r6, r7, lsl #8
332 mov r7, r7, lsr #24
333 orr r7, r7, r8, lsl #8
334 mov r8, r8, lsr #24
335 orr r8, r8, r9, lsl #8
336 mov r9, r9, lsr #24
337 orr r9, r9, r10, lsl #8
338 mov r10, r10, lsr #24
339 orr r10, r10, r11, lsl #8
340 stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
341 mov r3, r11, lsr #24
342 bhs 1b
343
344less_than_thirtytwo:
345 /* copy the last 0 to 31 bytes of the source */
346 rsb r12, lr, #32 /* we corrupted r12, recompute it */
347 add r2, r2, #32
348 cmp r2, #4
349 blo partial_word_tail
350
3511: ldr r5, [r1], #4
352 sub r2, r2, #4
353 mov r4, r5, lsl lr
354 orr r4, r4, r3
355 mov r3, r5, lsr r12
356 str r4, [r0], #4
357 cmp r2, #4
358 bhs 1b
359
360partial_word_tail:
361 /* we have a partial word in the input buffer */
362 movs r5, lr, lsl #(31-3)
363 strbmi r3, [r0], #1
364 movmi r3, r3, lsr #8
365 strbcs r3, [r0], #1
366 movcs r3, r3, lsr #8
367 strbcs r3, [r0], #1
368
369 /* Refill spilled registers from the stack. Don't update sp. */
370 ldmfd sp, {r5-r11}
371
372copy_last_3_and_return:
373 movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
374 ldrbmi r2, [r1], #1
375 ldrbcs r3, [r1], #1
376 ldrbcs r12,[r1]
377 strbmi r2, [r0], #1
378 strbcs r3, [r0], #1
379 strbcs r12,[r0]
380
381 /* we're done! restore sp and spilled registers and return */
382 add sp, sp, #28
383 ldmfd sp!, {r0, r4, lr}
384 bx lr
385
386#endif
lib/libc/musl/src/string/memccpy.c+1-1
......@@ -29,6 +29,6 @@ void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
2929#endif
3030 for (; n && (*d=*s)!=c; n--, s++, d++);
3131tail:
32 if (n && *s==c) return d+1;
32 if (n) return d+1;
3333 return 0;
3434}
lib/libc/musl/src/string/memmem.c+4-4
......@@ -12,8 +12,8 @@ static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned cha
1212
1313static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
1414{
15 uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
16 uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
15 uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
16 uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
1717 for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8)
1818 if (hw == nw) return (char *)h-3;
1919 return hw == nw ? (char *)h-3 : 0;
......@@ -21,8 +21,8 @@ static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned c
2121
2222static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
2323{
24 uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
25 uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
24 uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
25 uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
2626 for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++)
2727 if (hw == nw) return (char *)h-4;
2828 return hw == nw ? (char *)h-4 : 0;
lib/libc/musl/src/string/strsignal.c+10
......@@ -31,7 +31,11 @@ static const char map[] = {
3131 [SIGPIPE] = 13,
3232 [SIGALRM] = 14,
3333 [SIGTERM] = 15,
34#if defined(SIGSTKFLT)
3435 [SIGSTKFLT] = 16,
36#elif defined(SIGEMT)
37 [SIGEMT] = 16,
38#endif
3539 [SIGCHLD] = 17,
3640 [SIGCONT] = 18,
3741 [SIGSTOP] = 19,
......@@ -70,7 +74,13 @@ static const char strings[] =
7074 "Broken pipe\0"
7175 "Alarm clock\0"
7276 "Terminated\0"
77#if defined(SIGSTKFLT)
7378 "Stack fault\0"
79#elif defined(SIGEMT)
80 "Emulator trap\0"
81#else
82 "Unknown signal\0"
83#endif
7484 "Child process status\0"
7585 "Continued\0"
7686 "Stopped (signal)\0"
lib/libc/musl/src/string/strstr.c+4-4
......@@ -10,16 +10,16 @@ static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
1010
1111static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
1212{
13 uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
14 uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
13 uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
14 uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
1515 for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
1616 return *h ? (char *)h-2 : 0;
1717}
1818
1919static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
2020{
21 uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
22 uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
21 uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
22 uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
2323 for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
2424 return *h ? (char *)h-3 : 0;
2525}
lib/libc/musl/src/thread/__lock.c+3-1
......@@ -18,9 +18,11 @@
1818
1919void __lock(volatile int *l)
2020{
21 if (!libc.threads_minus_1) return;
21 int need_locks = libc.need_locks;
22 if (!need_locks) return;
2223 /* fast path: INT_MIN for the lock, +1 for the congestion */
2324 int current = a_cas(l, 0, INT_MIN + 1);
25 if (need_locks < 0) libc.need_locks = 0;
2426 if (!current) return;
2527 /* A first spin loop, for medium congestion. */
2628 for (unsigned i = 0; i < 10; ++i) {
lib/libc/musl/src/thread/pthread_create.c+19-15
......@@ -72,12 +72,13 @@ _Noreturn void __pthread_exit(void *result)
7272 /* Access to target the exiting thread with syscalls that use
7373 * its kernel tid is controlled by killlock. For detached threads,
7474 * any use past this point would have undefined behavior, but for
75 * joinable threads it's a valid usage that must be handled. */
75 * joinable threads it's a valid usage that must be handled.
76 * Signals must be blocked since pthread_kill must be AS-safe. */
77 __block_app_sigs(&set);
7678 LOCK(self->killlock);
7779
78 /* The thread list lock must be AS-safe, and thus requires
79 * application signals to be blocked before it can be taken. */
80 __block_app_sigs(&set);
80 /* The thread list lock must be AS-safe, and thus depends on
81 * application signals being blocked above. */
8182 __tl_lock();
8283
8384 /* If this is the only thread in the list, don't proceed with
......@@ -85,19 +86,12 @@ _Noreturn void __pthread_exit(void *result)
8586 * signal state to prepare for exit to call atexit handlers. */
8687 if (self->next == self) {
8788 __tl_unlock();
88 __restore_sigs(&set);
8989 UNLOCK(self->killlock);
90 __restore_sigs(&set);
9091 exit(0);
9192 }
9293
93 /* At this point we are committed to thread termination. Unlink
94 * the thread from the list. This change will not be visible
95 * until the lock is released, which only happens after SYS_exit
96 * has been called, via the exit futex address pointing at the lock. */
97 libc.threads_minus_1--;
98 self->next->prev = self->prev;
99 self->prev->next = self->next;
100 self->prev = self->next = self;
94 /* At this point we are committed to thread termination. */
10195
10296 /* Process robust list in userspace to handle non-pshared mutexes
10397 * and the detached thread case where the robust list head will
......@@ -121,6 +115,16 @@ _Noreturn void __pthread_exit(void *result)
121115 __do_orphaned_stdio_locks();
122116 __dl_thread_cleanup();
123117
118 /* Last, unlink thread from the list. This change will not be visible
119 * until the lock is released, which only happens after SYS_exit
120 * has been called, via the exit futex address pointing at the lock.
121 * This needs to happen after any possible calls to LOCK() that might
122 * skip locking if process appears single-threaded. */
123 if (!--libc.threads_minus_1) libc.need_locks = -1;
124 self->next->prev = self->prev;
125 self->prev->next = self->next;
126 self->prev = self->next = self;
127
124128 /* This atomic potentially competes with a concurrent pthread_detach
125129 * call; the loser is responsible for freeing thread resources. */
126130 int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);
......@@ -336,7 +340,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
336340 ~(1UL<<((SIGCANCEL-1)%(8*sizeof(long))));
337341
338342 __tl_lock();
339 libc.threads_minus_1++;
343 if (!libc.threads_minus_1++) libc.need_locks = 1;
340344 ret = __clone((c11 ? start_c11 : start), stack, flags, args, &new->tid, TP_ADJ(new), &__thread_list_lock);
341345
342346 /* All clone failures translate to EAGAIN. If explicit scheduling
......@@ -360,7 +364,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
360364 new->next->prev = new;
361365 new->prev->next = new;
362366 } else {
363 libc.threads_minus_1--;
367 if (!--libc.threads_minus_1) libc.need_locks = 0;
364368 }
365369 __tl_unlock();
366370 __restore_sigs(&set);
lib/libc/musl/src/thread/pthread_getschedparam.c+3
......@@ -4,6 +4,8 @@
44int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param *restrict param)
55{
66 int r;
7 sigset_t set;
8 __block_app_sigs(&set);
79 LOCK(t->killlock);
810 if (!t->tid) {
911 r = ESRCH;
......@@ -14,5 +16,6 @@ int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param
1416 }
1517 }
1618 UNLOCK(t->killlock);
19 __restore_sigs(&set);
1720 return r;
1821}
lib/libc/musl/src/thread/pthread_kill.c+6
......@@ -4,9 +4,15 @@
44int pthread_kill(pthread_t t, int sig)
55{
66 int r;
7 sigset_t set;
8 /* Block not just app signals, but internal ones too, since
9 * pthread_kill is used to implement pthread_cancel, which
10 * must be async-cancel-safe. */
11 __block_all_sigs(&set);
712 LOCK(t->killlock);
813 r = t->tid ? -__syscall(SYS_tkill, t->tid, sig)
914 : (sig+0U >= _NSIG ? EINVAL : 0);
1015 UNLOCK(t->killlock);
16 __restore_sigs(&set);
1117 return r;
1218}
lib/libc/musl/src/thread/pthread_setschedparam.c+3
......@@ -4,8 +4,11 @@
44int pthread_setschedparam(pthread_t t, int policy, const struct sched_param *param)
55{
66 int r;
7 sigset_t set;
8 __block_app_sigs(&set);
79 LOCK(t->killlock);
810 r = !t->tid ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param);
911 UNLOCK(t->killlock);
12 __restore_sigs(&set);
1013 return r;
1114}
lib/libc/musl/src/thread/pthread_setschedprio.c+3
......@@ -4,8 +4,11 @@
44int pthread_setschedprio(pthread_t t, int prio)
55{
66 int r;
7 sigset_t set;
8 __block_app_sigs(&set);
79 LOCK(t->killlock);
810 r = !t->tid ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio);
911 UNLOCK(t->killlock);
12 __restore_sigs(&set);
1013 return r;
1114}
lib/libc/musl/src/time/__tz.c+6-6
......@@ -86,15 +86,15 @@ static void getname(char *d, const char **p)
8686 int i;
8787 if (**p == '<') {
8888 ++*p;
89 for (i=0; (*p)[i]!='>' && i<TZNAME_MAX; i++)
90 d[i] = (*p)[i];
91 ++*p;
89 for (i=0; (*p)[i] && (*p)[i]!='>'; i++)
90 if (i<TZNAME_MAX) d[i] = (*p)[i];
91 if ((*p)[i]) ++*p;
9292 } else {
93 for (i=0; ((*p)[i]|32)-'a'<26U && i<TZNAME_MAX; i++)
94 d[i] = (*p)[i];
93 for (i=0; ((*p)[i]|32)-'a'<26U; i++)
94 if (i<TZNAME_MAX) d[i] = (*p)[i];
9595 }
9696 *p += i;
97 d[i] = 0;
97 d[i<TZNAME_MAX?i:TZNAME_MAX] = 0;
9898}
9999
100100#define VEC(...) ((const unsigned char[]){__VA_ARGS__})
src/musl.zig+49-43
......@@ -656,13 +656,17 @@ const src_files = [_][]const u8{
656656 "musl/src/locale/uselocale.c",
657657 "musl/src/locale/wcscoll.c",
658658 "musl/src/locale/wcsxfrm.c",
659 "musl/src/malloc/aligned_alloc.c",
660 "musl/src/malloc/expand_heap.c",
659 "musl/src/malloc/calloc.c",
661660 "musl/src/malloc/lite_malloc.c",
662 "musl/src/malloc/malloc.c",
663 "musl/src/malloc/malloc_usable_size.c",
661 "musl/src/malloc/mallocng/aligned_alloc.c",
662 "musl/src/malloc/mallocng/donate.c",
663 "musl/src/malloc/mallocng/free.c",
664 "musl/src/malloc/mallocng/malloc.c",
665 "musl/src/malloc/mallocng/malloc_usable_size.c",
666 "musl/src/malloc/mallocng/realloc.c",
664667 "musl/src/malloc/memalign.c",
665668 "musl/src/malloc/posix_memalign.c",
669 "musl/src/malloc/replaced.c",
666670 "musl/src/math/__cos.c",
667671 "musl/src/math/__cosdf.c",
668672 "musl/src/math/__cosl.c",
......@@ -834,23 +838,23 @@ const src_files = [_][]const u8{
834838 "musl/src/math/i386/exp_ld.s",
835839 "musl/src/math/i386/expl.s",
836840 "musl/src/math/i386/expm1l.s",
837 "musl/src/math/i386/fabs.s",
838 "musl/src/math/i386/fabsf.s",
839 "musl/src/math/i386/fabsl.s",
841 "musl/src/math/i386/fabs.c",
842 "musl/src/math/i386/fabsf.c",
843 "musl/src/math/i386/fabsl.c",
840844 "musl/src/math/i386/floor.s",
841845 "musl/src/math/i386/floorf.s",
842846 "musl/src/math/i386/floorl.s",
843 "musl/src/math/i386/fmod.s",
844 "musl/src/math/i386/fmodf.s",
845 "musl/src/math/i386/fmodl.s",
847 "musl/src/math/i386/fmod.c",
848 "musl/src/math/i386/fmodf.c",
849 "musl/src/math/i386/fmodl.c",
846850 "musl/src/math/i386/hypot.s",
847851 "musl/src/math/i386/hypotf.s",
848852 "musl/src/math/i386/ldexp.s",
849853 "musl/src/math/i386/ldexpf.s",
850854 "musl/src/math/i386/ldexpl.s",
851 "musl/src/math/i386/llrint.s",
852 "musl/src/math/i386/llrintf.s",
853 "musl/src/math/i386/llrintl.s",
855 "musl/src/math/i386/llrint.c",
856 "musl/src/math/i386/llrintf.c",
857 "musl/src/math/i386/llrintl.c",
854858 "musl/src/math/i386/log.s",
855859 "musl/src/math/i386/log10.s",
856860 "musl/src/math/i386/log10f.s",
......@@ -863,27 +867,27 @@ const src_files = [_][]const u8{
863867 "musl/src/math/i386/log2l.s",
864868 "musl/src/math/i386/logf.s",
865869 "musl/src/math/i386/logl.s",
866 "musl/src/math/i386/lrint.s",
867 "musl/src/math/i386/lrintf.s",
868 "musl/src/math/i386/lrintl.s",
869 "musl/src/math/i386/remainder.s",
870 "musl/src/math/i386/remainderf.s",
871 "musl/src/math/i386/remainderl.s",
870 "musl/src/math/i386/lrint.c",
871 "musl/src/math/i386/lrintf.c",
872 "musl/src/math/i386/lrintl.c",
873 "musl/src/math/i386/remainder.c",
874 "musl/src/math/i386/remainderf.c",
875 "musl/src/math/i386/remainderl.c",
872876 "musl/src/math/i386/remquo.s",
873877 "musl/src/math/i386/remquof.s",
874878 "musl/src/math/i386/remquol.s",
875 "musl/src/math/i386/rint.s",
876 "musl/src/math/i386/rintf.s",
877 "musl/src/math/i386/rintl.s",
879 "musl/src/math/i386/rint.c",
880 "musl/src/math/i386/rintf.c",
881 "musl/src/math/i386/rintl.c",
878882 "musl/src/math/i386/scalbln.s",
879883 "musl/src/math/i386/scalblnf.s",
880884 "musl/src/math/i386/scalblnl.s",
881885 "musl/src/math/i386/scalbn.s",
882886 "musl/src/math/i386/scalbnf.s",
883887 "musl/src/math/i386/scalbnl.s",
884 "musl/src/math/i386/sqrt.s",
885 "musl/src/math/i386/sqrtf.s",
886 "musl/src/math/i386/sqrtl.s",
888 "musl/src/math/i386/sqrt.c",
889 "musl/src/math/i386/sqrtf.c",
890 "musl/src/math/i386/sqrtl.c",
887891 "musl/src/math/i386/trunc.s",
888892 "musl/src/math/i386/truncf.s",
889893 "musl/src/math/i386/truncl.s",
......@@ -935,6 +939,7 @@ const src_files = [_][]const u8{
935939 "musl/src/math/lround.c",
936940 "musl/src/math/lroundf.c",
937941 "musl/src/math/lroundl.c",
942 "musl/src/math/m68k/sqrtl.c",
938943 "musl/src/math/mips/fabs.c",
939944 "musl/src/math/mips/fabsf.c",
940945 "musl/src/math/mips/sqrt.c",
......@@ -1113,28 +1118,29 @@ const src_files = [_][]const u8{
11131118 "musl/src/math/x86_64/exp2l.s",
11141119 "musl/src/math/x86_64/expl.s",
11151120 "musl/src/math/x86_64/expm1l.s",
1116 "musl/src/math/x86_64/fabs.s",
1117 "musl/src/math/x86_64/fabsf.s",
1118 "musl/src/math/x86_64/fabsl.s",
1121 "musl/src/math/x86_64/fabs.c",
1122 "musl/src/math/x86_64/fabsf.c",
1123 "musl/src/math/x86_64/fabsl.c",
11191124 "musl/src/math/x86_64/floorl.s",
11201125 "musl/src/math/x86_64/fma.c",
11211126 "musl/src/math/x86_64/fmaf.c",
1122 "musl/src/math/x86_64/fmodl.s",
1123 "musl/src/math/x86_64/llrint.s",
1124 "musl/src/math/x86_64/llrintf.s",
1125 "musl/src/math/x86_64/llrintl.s",
1127 "musl/src/math/x86_64/fmodl.c",
1128 "musl/src/math/x86_64/llrint.c",
1129 "musl/src/math/x86_64/llrintf.c",
1130 "musl/src/math/x86_64/llrintl.c",
11261131 "musl/src/math/x86_64/log10l.s",
11271132 "musl/src/math/x86_64/log1pl.s",
11281133 "musl/src/math/x86_64/log2l.s",
11291134 "musl/src/math/x86_64/logl.s",
1130 "musl/src/math/x86_64/lrint.s",
1131 "musl/src/math/x86_64/lrintf.s",
1132 "musl/src/math/x86_64/lrintl.s",
1133 "musl/src/math/x86_64/remainderl.s",
1134 "musl/src/math/x86_64/rintl.s",
1135 "musl/src/math/x86_64/sqrt.s",
1136 "musl/src/math/x86_64/sqrtf.s",
1137 "musl/src/math/x86_64/sqrtl.s",
1135 "musl/src/math/x86_64/lrint.c",
1136 "musl/src/math/x86_64/lrintf.c",
1137 "musl/src/math/x86_64/lrintl.c",
1138 "musl/src/math/x86_64/remainderl.c",
1139 "musl/src/math/x86_64/remquol.c",
1140 "musl/src/math/x86_64/rintl.c",
1141 "musl/src/math/x86_64/sqrt.c",
1142 "musl/src/math/x86_64/sqrtf.c",
1143 "musl/src/math/x86_64/sqrtl.c",
11381144 "musl/src/math/x86_64/truncl.s",
11391145 "musl/src/misc/a64l.c",
11401146 "musl/src/misc/basename.c",
......@@ -1528,7 +1534,6 @@ const src_files = [_][]const u8{
15281534 "musl/src/stdio/__stdio_seek.c",
15291535 "musl/src/stdio/__stdio_write.c",
15301536 "musl/src/stdio/__stdout_write.c",
1531 "musl/src/stdio/__string_read.c",
15321537 "musl/src/stdio/__toread.c",
15331538 "musl/src/stdio/__towrite.c",
15341539 "musl/src/stdio/__uflow.c",
......@@ -1654,10 +1659,11 @@ const src_files = [_][]const u8{
16541659 "musl/src/stdlib/strtol.c",
16551660 "musl/src/stdlib/wcstod.c",
16561661 "musl/src/stdlib/wcstol.c",
1662 "musl/src/string/aarch64/memcpy.S",
1663 "musl/src/string/aarch64/memset.S",
16571664 "musl/src/string/arm/__aeabi_memcpy.s",
16581665 "musl/src/string/arm/__aeabi_memset.s",
1659 "musl/src/string/arm/memcpy.c",
1660 "musl/src/string/arm/memcpy_le.S",
1666 "musl/src/string/arm/memcpy.S",
16611667 "musl/src/string/bcmp.c",
16621668 "musl/src/string/bcopy.c",
16631669 "musl/src/string/bzero.c",