未验证 提交 4f795bf7 编写于 作者: O openharmony_ci 提交者: Gitee

!841 feat:a核musl升级至v1.2.3

Merge pull request !841 from zhangdengyu/muslUpdate0303
文件模式从 100644 更改为 100755
...@@ -24,11 +24,6 @@ struct in_addr inet_makeaddr(in_addr_t, in_addr_t); ...@@ -24,11 +24,6 @@ struct in_addr inet_makeaddr(in_addr_t, in_addr_t);
in_addr_t inet_lnaof(struct in_addr); in_addr_t inet_lnaof(struct in_addr);
in_addr_t inet_netof(struct in_addr); in_addr_t inet_netof(struct in_addr);
#undef INET_ADDRSTRLEN
#undef INET6_ADDRSTRLEN
#define INET_ADDRSTRLEN 16
#define INET6_ADDRSTRLEN 46
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -64,7 +64,9 @@ int isascii(int); ...@@ -64,7 +64,9 @@ int isascii(int);
int toascii(int); int toascii(int);
#define _tolower(a) ((a)|0x20) #define _tolower(a) ((a)|0x20)
#define _toupper(a) ((a)&0x5f) #define _toupper(a) ((a)&0x5f)
#ifndef __cplusplus
#define isascii(a) (0 ? isascii(a) : (unsigned)(a) < 128) #define isascii(a) (0 ? isascii(a) : (unsigned)(a) < 128)
#endif
#endif #endif
......
...@@ -7,7 +7,9 @@ extern "C" { ...@@ -7,7 +7,9 @@ extern "C" {
#include <features.h> #include <features.h>
#ifdef __cplusplus #if __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0L #define NULL 0L
#else #else
#define NULL ((void*)0) #define NULL ((void*)0)
......
...@@ -59,12 +59,14 @@ ...@@ -59,12 +59,14 @@
#define ETH_P_PREAUTH 0x88C7 #define ETH_P_PREAUTH 0x88C7
#define ETH_P_TIPC 0x88CA #define ETH_P_TIPC 0x88CA
#define ETH_P_LLDP 0x88CC #define ETH_P_LLDP 0x88CC
#define ETH_P_MRP 0x88E3
#define ETH_P_MACSEC 0x88E5 #define ETH_P_MACSEC 0x88E5
#define ETH_P_8021AH 0x88E7 #define ETH_P_8021AH 0x88E7
#define ETH_P_MVRP 0x88F5 #define ETH_P_MVRP 0x88F5
#define ETH_P_1588 0x88F7 #define ETH_P_1588 0x88F7
#define ETH_P_NCSI 0x88F8 #define ETH_P_NCSI 0x88F8
#define ETH_P_PRP 0x88FB #define ETH_P_PRP 0x88FB
#define ETH_P_CFM 0x8902
#define ETH_P_FCOE 0x8906 #define ETH_P_FCOE 0x8906
#define ETH_P_TDLS 0x890D #define ETH_P_TDLS 0x890D
#define ETH_P_FIP 0x8914 #define ETH_P_FIP 0x8914
......
...@@ -48,6 +48,7 @@ struct ipv6_mreq { ...@@ -48,6 +48,7 @@ struct ipv6_mreq {
#define INADDR_BROADCAST ((in_addr_t) 0xffffffff) #define INADDR_BROADCAST ((in_addr_t) 0xffffffff)
#define INADDR_NONE ((in_addr_t) 0xffffffff) #define INADDR_NONE ((in_addr_t) 0xffffffff)
#define INADDR_LOOPBACK ((in_addr_t) 0x7f000001) #define INADDR_LOOPBACK ((in_addr_t) 0x7f000001)
#define INADDR_DUMMY ((in_addr_t) 0xc0000008)
#define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000) #define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000)
#define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001) #define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001)
...@@ -60,8 +61,6 @@ struct ipv6_mreq { ...@@ -60,8 +61,6 @@ struct ipv6_mreq {
extern const struct in6_addr in6addr_any, in6addr_loopback; extern const struct in6_addr in6addr_any, in6addr_loopback;
#undef INET_ADDRSTRLEN
#undef INET6_ADDRSTRLEN
#define INET_ADDRSTRLEN 16 #define INET_ADDRSTRLEN 16
#define INET6_ADDRSTRLEN 46 #define INET6_ADDRSTRLEN 46
...@@ -103,8 +102,10 @@ uint16_t ntohs(uint16_t); ...@@ -103,8 +102,10 @@ uint16_t ntohs(uint16_t);
#define IPPROTO_MH 135 #define IPPROTO_MH 135
#define IPPROTO_UDPLITE 136 #define IPPROTO_UDPLITE 136
#define IPPROTO_MPLS 137 #define IPPROTO_MPLS 137
#define IPPROTO_ETHERNET 143
#define IPPROTO_RAW 255 #define IPPROTO_RAW 255
#define IPPROTO_MAX 256 #define IPPROTO_MPTCP 262
#define IPPROTO_MAX 263
#define IN6_IS_ADDR_UNSPECIFIED(a) \ #define IN6_IS_ADDR_UNSPECIFIED(a) \
(((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \ (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \
...@@ -202,6 +203,7 @@ uint16_t ntohs(uint16_t); ...@@ -202,6 +203,7 @@ uint16_t ntohs(uint16_t);
#define IP_CHECKSUM 23 #define IP_CHECKSUM 23
#define IP_BIND_ADDRESS_NO_PORT 24 #define IP_BIND_ADDRESS_NO_PORT 24
#define IP_RECVFRAGSIZE 25 #define IP_RECVFRAGSIZE 25
#define IP_RECVERR_RFC4884 26
#define IP_MULTICAST_IF 32 #define IP_MULTICAST_IF 32
#define IP_MULTICAST_TTL 33 #define IP_MULTICAST_TTL 33
#define IP_MULTICAST_LOOP 34 #define IP_MULTICAST_LOOP 34
......
...@@ -78,6 +78,10 @@ enum { ...@@ -78,6 +78,10 @@ enum {
TCP_NLA_DSACK_DUPS, TCP_NLA_DSACK_DUPS,
TCP_NLA_REORD_SEEN, TCP_NLA_REORD_SEEN,
TCP_NLA_SRTT, TCP_NLA_SRTT,
TCP_NLA_TIMEOUT_REHASH,
TCP_NLA_BYTES_NOTSENT,
TCP_NLA_EDT,
TCP_NLA_TTL,
}; };
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
...@@ -181,6 +185,13 @@ struct tcphdr { ...@@ -181,6 +185,13 @@ struct tcphdr {
#define TCP_CA_Recovery 3 #define TCP_CA_Recovery 3
#define TCP_CA_Loss 4 #define TCP_CA_Loss 4
enum tcp_fastopen_client_fail {
TFO_STATUS_UNSPEC,
TFO_COOKIE_UNAVAILABLE,
TFO_DATA_NOT_ACKED,
TFO_SYN_RETRANSMITTED,
};
struct tcp_info { struct tcp_info {
uint8_t tcpi_state; uint8_t tcpi_state;
uint8_t tcpi_ca_state; uint8_t tcpi_ca_state;
...@@ -189,7 +200,7 @@ struct tcp_info { ...@@ -189,7 +200,7 @@ struct tcp_info {
uint8_t tcpi_backoff; uint8_t tcpi_backoff;
uint8_t tcpi_options; uint8_t tcpi_options;
uint8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; uint8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
uint8_t tcpi_delivery_rate_app_limited : 1; uint8_t tcpi_delivery_rate_app_limited : 1, tcpi_fastopen_client_fail : 2;
uint32_t tcpi_rto; uint32_t tcpi_rto;
uint32_t tcpi_ato; uint32_t tcpi_ato;
uint32_t tcpi_snd_mss; uint32_t tcpi_snd_mss;
...@@ -240,14 +251,15 @@ struct tcp_info { ...@@ -240,14 +251,15 @@ struct tcp_info {
#define TCP_MD5SIG_MAXKEYLEN 80 #define TCP_MD5SIG_MAXKEYLEN 80
#define TCP_MD5SIG_FLAG_PREFIX 1 #define TCP_MD5SIG_FLAG_PREFIX 0x1
#define TCP_MD5SIG_FLAG_IFINDEX 0x2
struct tcp_md5sig { struct tcp_md5sig {
struct sockaddr_storage tcpm_addr; struct sockaddr_storage tcpm_addr;
uint8_t tcpm_flags; uint8_t tcpm_flags;
uint8_t tcpm_prefixlen; uint8_t tcpm_prefixlen;
uint16_t tcpm_keylen; uint16_t tcpm_keylen;
uint32_t __tcpm_pad; int tcpm_ifindex;
uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN];
}; };
...@@ -271,10 +283,21 @@ struct tcp_repair_window { ...@@ -271,10 +283,21 @@ struct tcp_repair_window {
uint32_t rcv_wup; uint32_t rcv_wup;
}; };
#define TCP_RECEIVE_ZEROCOPY_FLAG_TLB_CLEAN_HINT 0x1
struct tcp_zerocopy_receive { struct tcp_zerocopy_receive {
uint64_t address; uint64_t address;
uint32_t length; uint32_t length;
uint32_t recv_skip_hint; uint32_t recv_skip_hint;
uint32_t inq;
int32_t err;
uint64_t copybuf_address;
int32_t copybuf_len;
uint32_t flags;
uint64_t msg_control;
uint64_t msg_controllen;
uint32_t msg_flags;
uint32_t reserved;
}; };
#endif #endif
......
...@@ -145,6 +145,9 @@ typedef struct pthread_cond { ...@@ -145,6 +145,9 @@ typedef struct pthread_cond {
#define PTHREAD_BARRIER_SERIAL_THREAD (-1) #define PTHREAD_BARRIER_SERIAL_THREAD (-1)
#define PTHREAD_NULL ((pthread_t)0)
int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict); int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict);
int pthread_detach(pthread_t); int pthread_detach(pthread_t);
void pthread_exit(void *); void pthread_exit(void *);
...@@ -267,6 +270,7 @@ int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *); ...@@ -267,6 +270,7 @@ int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *);
int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *); int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *);
int pthread_getattr_np(pthread_t, pthread_attr_t *); int pthread_getattr_np(pthread_t, pthread_attr_t *);
int pthread_setname_np(pthread_t, const char *); int pthread_setname_np(pthread_t, const char *);
int pthread_getname_np(pthread_t, char *, size_t);
int pthread_getattr_default_np(pthread_attr_t *); int pthread_getattr_default_np(pthread_attr_t *);
int pthread_setattr_default_np(const pthread_attr_t *); int pthread_setattr_default_np(const pthread_attr_t *);
int pthread_tryjoin_np(pthread_t, void **); int pthread_tryjoin_np(pthread_t, void **);
......
...@@ -79,6 +79,8 @@ typedef struct sigaltstack stack_t; ...@@ -79,6 +79,8 @@ typedef struct sigaltstack stack_t;
#define SEGV_ACCERR 2 #define SEGV_ACCERR 2
#define SEGV_BNDERR 3 #define SEGV_BNDERR 3
#define SEGV_PKUERR 4 #define SEGV_PKUERR 4
#define SEGV_MTEAERR 8
#define SEGV_MTESERR 9
#define BUS_ADRALN 1 #define BUS_ADRALN 1
#define BUS_ADRERR 2 #define BUS_ADRERR 2
...@@ -144,17 +146,31 @@ struct sigaction { ...@@ -144,17 +146,31 @@ struct sigaction {
#define sa_handler sa_sigactionhandler.sa_handler #define sa_handler sa_sigactionhandler.sa_handler
#define sa_sigaction sa_sigactionhandler.sa_sigaction #define sa_sigaction sa_sigactionhandler.sa_sigaction
#define SA_UNSUPPORTED 0x00000400
#define SA_EXPOSE_TAGBITS 0x00000800
struct sigevent { struct sigevent {
union sigval sigev_value; union sigval sigev_value;
int sigev_signo; int sigev_signo;
int sigev_notify; int sigev_notify;
void (*sigev_notify_function)(union sigval); union {
void *sigev_notify_attributes; char __pad[64 - 2*sizeof(int) - sizeof(union sigval)];
pid_t sigev_notify_thread_id;
struct {
void (*sigev_notify_function)(union sigval);
pthread_attr_t *sigev_notify_attributes;
} __sev_thread;
} __sev_fields;
}; };
#define sigev_notify_thread_id __sev_fields.sigev_notify_thread_id
#define sigev_notify_function __sev_fields.__sev_thread.sigev_notify_function
#define sigev_notify_attributes __sev_fields.__sev_thread.sigev_notify_attributes
#define SIGEV_SIGNAL 0 #define SIGEV_SIGNAL 0
#define SIGEV_NONE 1 #define SIGEV_NONE 1
#define SIGEV_THREAD 2 #define SIGEV_THREAD 2
#define SIGEV_THREAD_ID 4
#define SIGRTMIN 35 #define SIGRTMIN 35
#define SIGRTMAX (_NSIG - 1) #define SIGRTMAX (_NSIG - 1)
...@@ -186,6 +202,9 @@ void (*sigset(int, void (*)(int)))(int); ...@@ -186,6 +202,9 @@ void (*sigset(int, void (*)(int)))(int);
#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) #if defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
#define NSIG _NSIG #define NSIG _NSIG
typedef void (*sig_t)(int); typedef void (*sig_t)(int);
#define SYS_SECCOMP 1
#define SYS_USER_DISPATCH 2
#endif #endif
#ifdef _GNU_SOURCE #ifdef _GNU_SOURCE
......
#ifndef _STDDEF_H #ifndef _STDDEF_H
#define _STDDEF_H #define _STDDEF_H
#ifdef __cplusplus #if __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0L #define NULL 0L
#else #else
#define NULL ((void*)0) #define NULL ((void*)0)
......
...@@ -25,7 +25,9 @@ extern "C" { ...@@ -25,7 +25,9 @@ extern "C" {
#include <bits/alltypes.h> #include <bits/alltypes.h>
#ifdef __cplusplus #if __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0L #define NULL 0L
#else #else
#define NULL ((void*)0) #define NULL ((void*)0)
......
...@@ -7,7 +7,9 @@ extern "C" { ...@@ -7,7 +7,9 @@ extern "C" {
#include <features.h> #include <features.h>
#ifdef __cplusplus #if __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0L #define NULL 0L
#else #else
#define NULL ((void*)0) #define NULL ((void*)0)
...@@ -146,6 +148,8 @@ int getloadavg(double *, int); ...@@ -146,6 +148,8 @@ int getloadavg(double *, int);
int clearenv(void); int clearenv(void);
#define WCOREDUMP(s) ((s) & 0x80) #define WCOREDUMP(s) ((s) & 0x80)
#define WIFCONTINUED(s) ((s) == 0xffff) #define WIFCONTINUED(s) ((s) == 0xffff)
void *reallocarray (void *, size_t, size_t);
void qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *);
#endif #endif
#ifdef _GNU_SOURCE #ifdef _GNU_SOURCE
......
...@@ -7,7 +7,9 @@ extern "C" { ...@@ -7,7 +7,9 @@ extern "C" {
#include <features.h> #include <features.h>
#ifdef __cplusplus #if __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0L #define NULL 0L
#else #else
#define NULL ((void*)0) #define NULL ((void*)0)
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
extern "C" { extern "C" {
#endif #endif
#define __NEED_struct_winsize
#include <bits/alltypes.h> #include <bits/alltypes.h>
#include <bits/ioctl.h> #include <bits/ioctl.h>
......
...@@ -42,6 +42,7 @@ extern "C" { ...@@ -42,6 +42,7 @@ extern "C" {
#define MAP_HUGE_SHIFT 26 #define MAP_HUGE_SHIFT 26
#define MAP_HUGE_MASK 0x3f #define MAP_HUGE_MASK 0x3f
#define MAP_HUGE_16KB (14 << 26)
#define MAP_HUGE_64KB (16 << 26) #define MAP_HUGE_64KB (16 << 26)
#define MAP_HUGE_512KB (19 << 26) #define MAP_HUGE_512KB (19 << 26)
#define MAP_HUGE_1MB (20 << 26) #define MAP_HUGE_1MB (20 << 26)
...@@ -104,6 +105,7 @@ extern "C" { ...@@ -104,6 +105,7 @@ extern "C" {
#ifdef _GNU_SOURCE #ifdef _GNU_SOURCE
#define MREMAP_MAYMOVE 1 #define MREMAP_MAYMOVE 1
#define MREMAP_FIXED 2 #define MREMAP_FIXED 2
#define MREMAP_DONTUNMAP 4
#define MLOCK_ONFAULT 0x01 #define MLOCK_ONFAULT 0x01
......
...@@ -31,6 +31,7 @@ extern "C" { ...@@ -31,6 +31,7 @@ extern "C" {
#define MS_REMOUNT 32 #define MS_REMOUNT 32
#define MS_MANDLOCK 64 #define MS_MANDLOCK 64
#define MS_DIRSYNC 128 #define MS_DIRSYNC 128
#define MS_NOSYMFOLLOW 256
#define MS_NOATIME 1024 #define MS_NOATIME 1024
#define MS_NODIRATIME 2048 #define MS_NODIRATIME 2048
#define MS_BIND 4096 #define MS_BIND 4096
......
...@@ -157,6 +157,25 @@ struct prctl_mm_map { ...@@ -157,6 +157,25 @@ struct prctl_mm_map {
#define PR_SET_TAGGED_ADDR_CTRL 55 #define PR_SET_TAGGED_ADDR_CTRL 55
#define PR_GET_TAGGED_ADDR_CTRL 56 #define PR_GET_TAGGED_ADDR_CTRL 56
#define PR_TAGGED_ADDR_ENABLE (1UL << 0) #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
#define PR_MTE_TCF_SHIFT 1
#define PR_MTE_TCF_NONE (0UL << 1)
#define PR_MTE_TCF_SYNC (1UL << 1)
#define PR_MTE_TCF_ASYNC (2UL << 1)
#define PR_MTE_TCF_MASK (3UL << 1)
#define PR_MTE_TAG_SHIFT 3
#define PR_MTE_TAG_MASK (0xffffUL << 3)
#define PR_SET_IO_FLUSHER 57
#define PR_GET_IO_FLUSHER 58
#define PR_SET_SYSCALL_USER_DISPATCH 59
#define PR_SYS_DISPATCH_OFF 0
#define PR_SYS_DISPATCH_ON 1
#define SYSCALL_DISPATCH_FILTER_ALLOW 0
#define SYSCALL_DISPATCH_FILTER_BLOCK 1
#define PR_PAC_SET_ENABLED_KEYS 60
#define PR_PAC_GET_ENABLED_KEYS 61
int prctl (int, ...); int prctl (int, ...);
......
...@@ -289,6 +289,8 @@ struct linger { ...@@ -289,6 +289,8 @@ struct linger {
#define SCM_TXTIME SO_TXTIME #define SCM_TXTIME SO_TXTIME
#define SO_BINDTOIFINDEX 62 #define SO_BINDTOIFINDEX 62
#define SO_DETACH_REUSEPORT_BPF 68 #define SO_DETACH_REUSEPORT_BPF 68
#define SO_PREFER_BUSY_POLL 69
#define SO_BUSY_POLL_BUDGET 70
#ifndef SOL_SOCKET #ifndef SOL_SOCKET
#define SOL_SOCKET 1 #define SOL_SOCKET 1
......
...@@ -8,6 +8,7 @@ extern "C" { ...@@ -8,6 +8,7 @@ extern "C" {
#include <features.h> #include <features.h>
#define __NEED_pid_t #define __NEED_pid_t
#define __NEED_struct_winsize
#include <bits/alltypes.h> #include <bits/alltypes.h>
...@@ -27,6 +28,9 @@ int cfsetispeed (struct termios *, speed_t); ...@@ -27,6 +28,9 @@ int cfsetispeed (struct termios *, speed_t);
int tcgetattr (int, struct termios *); int tcgetattr (int, struct termios *);
int tcsetattr (int, int, const struct termios *); int tcsetattr (int, int, const struct termios *);
int tcgetwinsize (int, struct winsize *);
int tcsetwinsize (int, const struct winsize *);
int tcsendbreak (int, int); int tcsendbreak (int, int);
int tcdrain (int); int tcdrain (int);
int tcflush (int, int); int tcflush (int, int);
......
...@@ -7,7 +7,9 @@ extern "C" { ...@@ -7,7 +7,9 @@ extern "C" {
#include <features.h> #include <features.h>
#ifdef __cplusplus #if __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0L #define NULL 0L
#else #else
#define NULL ((void*)0) #define NULL ((void*)0)
......
...@@ -14,8 +14,12 @@ extern "C" { ...@@ -14,8 +14,12 @@ extern "C" {
#define SEEK_SET 0 #define SEEK_SET 0
#define SEEK_CUR 1 #define SEEK_CUR 1
#define SEEK_END 2 #define SEEK_END 2
#define SEEK_DATA 3
#define SEEK_HOLE 4
#ifdef __cplusplus #if __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0L #define NULL 0L
#else #else
#define NULL ((void*)0) #define NULL ((void*)0)
...@@ -81,6 +85,7 @@ unsigned alarm(unsigned); ...@@ -81,6 +85,7 @@ unsigned alarm(unsigned);
unsigned sleep(unsigned); unsigned sleep(unsigned);
pid_t fork(void); pid_t fork(void);
pid_t _Fork(void);
int execve(const char *, char *const [], char *const []); int execve(const char *, char *const [], char *const []);
int execv(const char *, char *const []); int execv(const char *, char *const []);
int execle(const char *, const char *, ...); int execle(const char *, const char *, ...);
...@@ -189,6 +194,7 @@ int syncfs(int); ...@@ -189,6 +194,7 @@ int syncfs(int);
int euidaccess(const char *, int); int euidaccess(const char *, int);
int eaccess(const char *, int); int eaccess(const char *, int);
ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned); ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned);
pid_t gettid(void);
#endif #endif
#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
......
...@@ -38,7 +38,9 @@ extern "C" { ...@@ -38,7 +38,9 @@ extern "C" {
#define WCHAR_MIN (-1-0x7fffffff+L'\0') #define WCHAR_MIN (-1-0x7fffffff+L'\0')
#endif #endif
#ifdef __cplusplus #if __cplusplus >= 201103L
#define NULL nullptr
#elif defined(__cplusplus)
#define NULL 0L #define NULL 0L
#else #else
#define NULL ((void*)0) #define NULL ((void*)0)
......
...@@ -63,6 +63,7 @@ MUSL_SRC_COMMON = [ ...@@ -63,6 +63,7 @@ MUSL_SRC_COMMON = [
"$MUSLPORTINGDIR/src/math/__math_divzero.c", "$MUSLPORTINGDIR/src/math/__math_divzero.c",
"$MUSLPORTINGDIR/src/math/__math_divzerof.c", "$MUSLPORTINGDIR/src/math/__math_divzerof.c",
"$MUSLPORTINGDIR/src/math/__math_invalid.c", "$MUSLPORTINGDIR/src/math/__math_invalid.c",
"$MUSLPORTINGDIR/src/math/__math_invalidl.c",
"$MUSLPORTINGDIR/src/math/__math_invalidf.c", "$MUSLPORTINGDIR/src/math/__math_invalidf.c",
"$MUSLPORTINGDIR/src/math/__math_oflow.c", "$MUSLPORTINGDIR/src/math/__math_oflow.c",
"$MUSLPORTINGDIR/src/math/__math_oflowf.c", "$MUSLPORTINGDIR/src/math/__math_oflowf.c",
...@@ -267,6 +268,7 @@ MUSL_SRC_COMMON = [ ...@@ -267,6 +268,7 @@ MUSL_SRC_COMMON = [
"$MUSLPORTINGDIR/src/math/sinhl.c", "$MUSLPORTINGDIR/src/math/sinhl.c",
"$MUSLPORTINGDIR/src/math/sinl.c", "$MUSLPORTINGDIR/src/math/sinl.c",
"$MUSLPORTINGDIR/src/math/sqrt.c", "$MUSLPORTINGDIR/src/math/sqrt.c",
"$MUSLPORTINGDIR/src/math/sqrt_data.c",
"$MUSLPORTINGDIR/src/math/sqrtf.c", "$MUSLPORTINGDIR/src/math/sqrtf.c",
"$MUSLPORTINGDIR/src/math/sqrtl.c", "$MUSLPORTINGDIR/src/math/sqrtl.c",
"$MUSLPORTINGDIR/src/math/tan.c", "$MUSLPORTINGDIR/src/math/tan.c",
......
/* This file is sorted such that 'errors' which represent exceptional /* The first entry is a catch-all for codes not enumerated here.
* conditions under which a correct program may fail come first, followed * This file is included multiple times to declare and define a structure
* by messages that indicate an incorrect program or system failure. The * with these messages, and then to define a lookup table translating
* macro E() along with double-inclusion is used to ensure that ordering * error codes to offsets of corresponding fields in the structure. */
* of the strings remains synchronized. */
E(0, "No error information")
E(EILSEQ, "Illegal byte sequence") E(EILSEQ, "Illegal byte sequence")
E(EDOM, "Domain error") E(EDOM, "Domain error")
...@@ -101,5 +102,7 @@ E(EDQUOT, "Quota exceeded") ...@@ -101,5 +102,7 @@ E(EDQUOT, "Quota exceeded")
E(ENOMEDIUM, "No medium found") E(ENOMEDIUM, "No medium found")
E(EMEDIUMTYPE, "Wrong medium type") E(EMEDIUMTYPE, "Wrong medium type")
E(EMULTIHOP, "Multihop attempted") E(EMULTIHOP, "Multihop attempted")
E(ENOKEY, "Required key not available")
E(0, "No error information") E(EKEYEXPIRED, "Key has expired")
E(EKEYREVOKED, "Key has been revoked")
E(EKEYREJECTED, "Key was rejected by service")
#include <errno.h> #include <errno.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#include "locale_impl.h" #include "locale_impl.h"
#define E(a,b) ((unsigned char)a), static const struct errmsgstr_t {
static const unsigned char errid[] = { #define E(n, s) char str##n[sizeof(s)];
#include "__strerror.h" #include "__strerror.h"
#undef E
} errmsgstr = {
#define E(n, s) s,
#include "__strerror.h"
#undef E
}; };
#undef E static const unsigned short errmsgidx[] = {
#define E(a,b) b "\0" #define E(n, s) [n] = offsetof(struct errmsgstr_t, str##n),
static const char errmsg[] =
#include "__strerror.h" #include "__strerror.h"
; #undef E
};
char *__strerror_l(int e, locale_t loc) char *__strerror_l(int e, locale_t loc)
{ {
const char *s; const char *s;
int i;
for (i=0; errid[i] && errid[i] != e; i++); if (e >= sizeof errmsgidx / sizeof *errmsgidx) e = 0;
for (s=errmsg; i; s++, i--) for (; *s; s++); s = (char *)&errmsgstr + errmsgidx[e];
return (char *)s; return (char *)s;
} }
......
...@@ -8,7 +8,6 @@ extern char **__environ; ...@@ -8,7 +8,6 @@ extern char **__environ;
hidden int __dup3(int, int, int); hidden int __dup3(int, int, int);
hidden int __mkostemps(char *, int, int); hidden int __mkostemps(char *, int, int);
hidden int __execvpe(const char *, char *const *, char *const *); hidden int __execvpe(const char *, char *const *, char *const *);
hidden int __aio_close(int);
hidden off_t __lseek(int, off_t, int); hidden off_t __lseek(int, off_t, int);
#endif #endif
...@@ -315,4 +315,19 @@ static inline int a_clz_64(uint64_t x) ...@@ -315,4 +315,19 @@ static inline int a_clz_64(uint64_t x)
} }
#endif #endif
#ifndef a_clz_32
#define a_clz_32 a_clz_32
static inline int a_clz_32(uint32_t x)
{
x >>= 1;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x++;
return 31-a_ctz_32(x);
}
#endif
#endif #endif
...@@ -236,13 +236,13 @@ hidden int __rem_pio2(double,double*); ...@@ -236,13 +236,13 @@ hidden int __rem_pio2(double,double*);
hidden double __sin(double,double,int); hidden double __sin(double,double,int);
hidden double __cos(double,double); hidden double __cos(double,double);
hidden double __tan(double,double,int); hidden double __tan(double,double,int);
hidden double __expo2(double); hidden double __expo2(double,double);
hidden int __rem_pio2f(float,double*); hidden int __rem_pio2f(float,double*);
hidden float __sindf(double); hidden float __sindf(double);
hidden float __cosdf(double); hidden float __cosdf(double);
hidden float __tandf(double,int); hidden float __tandf(double,int);
hidden float __expo2f(float); hidden float __expo2f(float,float);
hidden int __rem_pio2l(long double, long double *); hidden int __rem_pio2l(long double, long double *);
hidden long double __sinl(long double, long double, int); hidden long double __sinl(long double, long double, int);
...@@ -267,5 +267,8 @@ hidden double __math_uflow(uint32_t); ...@@ -267,5 +267,8 @@ hidden double __math_uflow(uint32_t);
hidden double __math_oflow(uint32_t); hidden double __math_oflow(uint32_t);
hidden double __math_divzero(uint32_t); hidden double __math_divzero(uint32_t);
hidden double __math_invalid(double); hidden double __math_invalid(double);
#if LDBL_MANT_DIG != DBL_MANT_DIG
hidden long double __math_invalidl(long double);
#endif
#endif #endif
...@@ -15,6 +15,8 @@ struct __locale_map { ...@@ -15,6 +15,8 @@ struct __locale_map {
const struct __locale_map *next; const struct __locale_map *next;
}; };
extern hidden volatile int __locale_lock[1];
extern hidden const struct __locale_map __c_dot_utf8; extern hidden const struct __locale_map __c_dot_utf8;
extern hidden const struct __locale_struct __c_locale; extern hidden const struct __locale_struct __c_locale;
extern hidden const struct __locale_struct __c_dot_utf8_locale; extern hidden const struct __locale_struct __c_dot_utf8_locale;
......
...@@ -9,16 +9,12 @@ ...@@ -9,16 +9,12 @@
#include "atomic.h" #include "atomic.h"
enum { enum {
DT_EXITING = 0, DT_EXITED = 0,
DT_EXITING,
DT_JOINABLE, DT_JOINABLE,
DT_DETACHED, DT_DETACHED,
}; };
struct __timer {
int timerid;
pthread_t thread;
};
#define __SU (sizeof(size_t)/sizeof(int)) #define __SU (sizeof(size_t)/sizeof(int))
#define _a_stacksize __u.__s[0] #define _a_stacksize __u.__s[0]
...@@ -51,14 +47,22 @@ struct __timer { ...@@ -51,14 +47,22 @@ struct __timer {
#define _b_waiters2 __u.__vi[4] #define _b_waiters2 __u.__vi[4]
#define _b_inst __u.__p[3] #define _b_inst __u.__p[3]
#ifndef CANARY #ifndef TP_OFFSET
#define CANARY canary #define TP_OFFSET 0
#endif #endif
#ifndef DTP_OFFSET #ifndef DTP_OFFSET
#define DTP_OFFSET 0 #define DTP_OFFSET 0
#endif #endif
#ifdef TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + TP_OFFSET)
#define __pthread_self() ((pthread_t)(__get_tp() - sizeof(struct __pthread) - TP_OFFSET))
#else
#define TP_ADJ(p) (p)
#define __pthread_self() ((pthread_t)__get_tp())
#endif
#ifndef tls_mod_off_t #ifndef tls_mod_off_t
#define tls_mod_off_t size_t #define tls_mod_off_t size_t
#endif #endif
...@@ -92,7 +96,6 @@ hidden int __pthread_key_delete_impl(pthread_key_t); ...@@ -92,7 +96,6 @@ hidden int __pthread_key_delete_impl(pthread_key_t);
extern hidden volatile size_t __pthread_tsd_size; extern hidden volatile size_t __pthread_tsd_size;
extern hidden void *__pthread_tsd_main[]; extern hidden void *__pthread_tsd_main[];
extern hidden volatile int __aio_fut;
extern hidden volatile int __eintr_valid_flag; extern hidden volatile int __eintr_valid_flag;
hidden int __clone(int (*)(void *), void *, int, void *, ...); hidden int __clone(int (*)(void *), void *, int, void *, ...);
...@@ -115,6 +118,8 @@ hidden void __tl_sync(pthread_t); ...@@ -115,6 +118,8 @@ hidden void __tl_sync(pthread_t);
extern hidden volatile int __thread_list_lock; extern hidden volatile int __thread_list_lock;
extern hidden volatile int __abort_lock[1];
extern hidden unsigned __default_stacksize; extern hidden unsigned __default_stacksize;
extern hidden unsigned __default_guardsize; extern hidden unsigned __default_guardsize;
......
...@@ -32,6 +32,6 @@ int __shgetc(FILE *f) ...@@ -32,6 +32,6 @@ int __shgetc(FILE *f)
else else
f->shend = f->rend; f->shend = f->rend;
f->shcnt = f->buf - f->rpos + cnt; f->shcnt = f->buf - f->rpos + cnt;
if (f->rpos[-1] != c) f->rpos[-1] = c; if (f->rpos <= f->buf) f->rpos[-1] = c;
return c; return c;
} }
...@@ -56,8 +56,6 @@ hidden size_t __stdout_write(FILE *, const unsigned char *, size_t); ...@@ -56,8 +56,6 @@ hidden size_t __stdout_write(FILE *, const unsigned char *, size_t);
hidden off_t __stdio_seek(FILE *, off_t, int); hidden off_t __stdio_seek(FILE *, off_t, int);
hidden int __stdio_close(FILE *); hidden int __stdio_close(FILE *);
hidden size_t __string_read(FILE *, unsigned char *, size_t);
hidden int __toread(FILE *); hidden int __toread(FILE *);
hidden int __towrite(FILE *); hidden int __towrite(FILE *);
......
...@@ -5,12 +5,13 @@ static const int k = 2043; ...@@ -5,12 +5,13 @@ static const int k = 2043;
static const double kln2 = 0x1.62066151add8bp+10; static const double kln2 = 0x1.62066151add8bp+10;
/* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */ /* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */
double __expo2(double x) double __expo2(double x, double sign)
{ {
double scale; double scale;
/* note that k is odd and scale*scale overflows */ /* note that k is odd and scale*scale overflows */
INSERT_WORDS(scale, (uint32_t)(0x3ff + k/2) << 20, 0); INSERT_WORDS(scale, (uint32_t)(0x3ff + k/2) << 20, 0);
/* exp(x - k ln2) * 2**(k-1) */ /* exp(x - k ln2) * 2**(k-1) */
return exp(x - kln2) * scale * scale; /* in directed rounding correct sign before rounding or overflow is important */
return exp(x - kln2) * (sign * scale) * scale;
} }
...@@ -5,12 +5,13 @@ static const int k = 235; ...@@ -5,12 +5,13 @@ static const int k = 235;
static const float kln2 = 0x1.45c778p+7f; static const float kln2 = 0x1.45c778p+7f;
/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */ /* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */
float __expo2f(float x) float __expo2f(float x, float sign)
{ {
float scale; float scale;
/* note that k is odd and scale*scale overflows */ /* note that k is odd and scale*scale overflows */
SET_FLOAT_WORD(scale, (uint32_t)(0x7f + k/2) << 23); SET_FLOAT_WORD(scale, (uint32_t)(0x7f + k/2) << 23);
/* exp(x - k ln2) * 2**(k-1) */ /* exp(x - k ln2) * 2**(k-1) */
return expf(x - kln2) * scale * scale; /* in directed rounding correct sign before rounding or overflow is important */
return expf(x - kln2) * (sign * scale) * scale;
} }
#include <float.h>
#include "libm.h"
#if LDBL_MANT_DIG != DBL_MANT_DIG
long double __math_invalidl(long double x)
{
return (x - x) / (x - x);
}
#endif
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
*/ */
static const double static const double
toint = 1.5/EPS, toint = 1.5/EPS,
pio4 = 0x1.921fb54442d18p-1,
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
...@@ -117,11 +118,23 @@ int __rem_pio2(double x, double *y) ...@@ -117,11 +118,23 @@ int __rem_pio2(double x, double *y)
} }
if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
medium: medium:
/* rint(x/(pi/2)), Assume round-to-nearest. */ /* rint(x/(pi/2)) */
fn = (double_t)x*invpio2 + toint - toint; fn = (double_t)x*invpio2 + toint - toint;
n = (int32_t)fn; n = (int32_t)fn;
r = x - fn*pio2_1; r = x - fn*pio2_1;
w = fn*pio2_1t; /* 1st round, good to 85 bits */ w = fn*pio2_1t; /* 1st round, good to 85 bits */
/* Matters with directed rounding. */
if (predict_false(r - w < -pio4)) {
n--;
fn--;
r = x - fn*pio2_1;
w = fn*pio2_1t;
} else if (predict_false(r - w > pio4)) {
n++;
fn++;
r = x - fn*pio2_1;
w = fn*pio2_1t;
}
y[0] = r - w; y[0] = r - w;
u.f = y[0]; u.f = y[0];
ey = u.i>>52 & 0x7ff; ey = u.i>>52 & 0x7ff;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
*/ */
static const double static const double
toint = 1.5/EPS, toint = 1.5/EPS,
pio4 = 0x1.921fb6p-1,
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */ pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */ pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
...@@ -50,10 +51,20 @@ int __rem_pio2f(float x, double *y) ...@@ -50,10 +51,20 @@ int __rem_pio2f(float x, double *y)
ix = u.i & 0x7fffffff; ix = u.i & 0x7fffffff;
/* 25+53 bit pi is good enough for medium size */ /* 25+53 bit pi is good enough for medium size */
if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */ if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */
/* Use a specialized rint() to get fn. Assume round-to-nearest. */ /* Use a specialized rint() to get fn. */
fn = (double_t)x*invpio2 + toint - toint; fn = (double_t)x*invpio2 + toint - toint;
n = (int32_t)fn; n = (int32_t)fn;
*y = x - fn*pio2_1 - fn*pio2_1t; *y = x - fn*pio2_1 - fn*pio2_1t;
/* Matters with directed rounding. */
if (predict_false(*y < -pio4)) {
n--;
fn--;
*y = x - fn*pio2_1 - fn*pio2_1t;
} else if (predict_false(*y > pio4)) {
n++;
fn++;
*y = x - fn*pio2_1 - fn*pio2_1t;
}
return n; return n;
} }
if(ix>=0x7f800000) { /* x is inf or NaN */ if(ix>=0x7f800000) { /* x is inf or NaN */
......
...@@ -44,6 +44,7 @@ pio2_1 = 1.57079632679597125389e+00, /* 0x3FF921FB, 0x54444000 */ ...@@ -44,6 +44,7 @@ pio2_1 = 1.57079632679597125389e+00, /* 0x3FF921FB, 0x54444000 */
pio2_2 = -1.07463465549783099519e-12, /* -0x12e7b967674000.0p-92 */ pio2_2 = -1.07463465549783099519e-12, /* -0x12e7b967674000.0p-92 */
pio2_3 = 6.36831716351370313614e-25; /* 0x18a2e037074000.0p-133 */ pio2_3 = 6.36831716351370313614e-25; /* 0x18a2e037074000.0p-133 */
static const long double static const long double
pio4 = 0x1.921fb54442d1846ap-1L,
invpio2 = 6.36619772367581343076e-01L, /* 0xa2f9836e4e44152a.0p-64 */ invpio2 = 6.36619772367581343076e-01L, /* 0xa2f9836e4e44152a.0p-64 */
pio2_1t = -1.07463465549719416346e-12L, /* -0x973dcb3b399d747f.0p-103 */ pio2_1t = -1.07463465549719416346e-12L, /* -0x973dcb3b399d747f.0p-103 */
pio2_2t = 6.36831716351095013979e-25L, /* 0xc51701b839a25205.0p-144 */ pio2_2t = 6.36831716351095013979e-25L, /* 0xc51701b839a25205.0p-144 */
...@@ -57,6 +58,7 @@ pio2_3t = -2.75299651904407171810e-37L; /* -0xbb5bf6c7ddd660ce.0p-185 */ ...@@ -57,6 +58,7 @@ pio2_3t = -2.75299651904407171810e-37L; /* -0xbb5bf6c7ddd660ce.0p-185 */
#define NX 5 #define NX 5
#define NY 3 #define NY 3
static const long double static const long double
pio4 = 0x1.921fb54442d18469898cc51701b8p-1L,
invpio2 = 6.3661977236758134307553505349005747e-01L, /* 0x145f306dc9c882a53f84eafa3ea6a.0p-113 */ invpio2 = 6.3661977236758134307553505349005747e-01L, /* 0x145f306dc9c882a53f84eafa3ea6a.0p-113 */
pio2_1 = 1.5707963267948966192292994253909555e+00L, /* 0x1921fb54442d18469800000000000.0p-112 */ pio2_1 = 1.5707963267948966192292994253909555e+00L, /* 0x1921fb54442d18469800000000000.0p-112 */
pio2_1t = 2.0222662487959507323996846200947577e-21L, /* 0x13198a2e03707344a4093822299f3.0p-181 */ pio2_1t = 2.0222662487959507323996846200947577e-21L, /* 0x13198a2e03707344a4093822299f3.0p-181 */
...@@ -76,11 +78,23 @@ int __rem_pio2l(long double x, long double *y) ...@@ -76,11 +78,23 @@ int __rem_pio2l(long double x, long double *y)
u.f = x; u.f = x;
ex = u.i.se & 0x7fff; ex = u.i.se & 0x7fff;
if (SMALL(u)) { if (SMALL(u)) {
/* rint(x/(pi/2)), Assume round-to-nearest. */ /* rint(x/(pi/2)) */
fn = x*invpio2 + toint - toint; fn = x*invpio2 + toint - toint;
n = QUOBITS(fn); n = QUOBITS(fn);
r = x-fn*pio2_1; r = x-fn*pio2_1;
w = fn*pio2_1t; /* 1st round good to 102/180 bits (ld80/ld128) */ w = fn*pio2_1t; /* 1st round good to 102/180 bits (ld80/ld128) */
/* Matters with directed rounding. */
if (predict_false(r - w < -pio4)) {
n--;
fn--;
r = x - fn*pio2_1;
w = fn*pio2_1t;
} else if (predict_false(r - w > pio4)) {
n++;
fn++;
r = x - fn*pio2_1;
w = fn*pio2_1t;
}
y[0] = r-w; y[0] = r-w;
u.f = y[0]; u.f = y[0];
ey = u.i.se & 0x7fff; ey = u.i.se & 0x7fff;
......
...@@ -15,12 +15,12 @@ float acoshf(float x) ...@@ -15,12 +15,12 @@ float acoshf(float x)
uint32_t a = u.i & 0x7fffffff; uint32_t a = u.i & 0x7fffffff;
if (a < 0x3f800000+(1<<23)) if (a < 0x3f800000+(1<<23))
/* |x| < 2, invalid if x < 1 or nan */ /* |x| < 2, invalid if x < 1 */
/* up to 2ulp error in [1,1.125] */ /* up to 2ulp error in [1,1.125] */
return log1pf(x-1 + sqrtf((x-1)*(x-1)+2*(x-1))); return log1pf(x-1 + sqrtf((x-1)*(x-1)+2*(x-1)));
if (a < 0x3f800000+(12<<23)) if (u.i < 0x3f800000+(12<<23))
/* |x| < 0x1p12 */ /* 2 <= x < 0x1p12 */
return logf(2*x - 1/(x+sqrtf(x*x-1))); return logf(2*x - 1/(x+sqrtf(x*x-1)));
/* x >= 0x1p12 */ /* x >= 0x1p12 or x <= -2 or nan */
return logf(x) + 0.693147180559945309417232121458176568f; return logf(x) + 0.693147180559945309417232121458176568f;
} }
#include <math.h> #include <math.h>
#if __ARM_PCS_VFP #if __ARM_PCS_VFP && __ARM_FP&8
double fabs(double x) double fabs(double x)
{ {
......
#include <math.h> #include <math.h>
#if __ARM_PCS_VFP || (__VFP_FP__ && !__SOFTFP__) #if (__ARM_PCS_VFP || (__VFP_FP__ && !__SOFTFP__)) && (__ARM_FP&8)
double sqrt(double x) double sqrt(double x)
{ {
......
...@@ -35,6 +35,6 @@ double cosh(double x) ...@@ -35,6 +35,6 @@ double cosh(double x)
/* |x| > log(DBL_MAX) or nan */ /* |x| > log(DBL_MAX) or nan */
/* note: the result is stored to handle overflow */ /* note: the result is stored to handle overflow */
t = __expo2(x); t = __expo2(x, 1.0);
return t; return t;
} }
...@@ -28,6 +28,6 @@ float coshf(float x) ...@@ -28,6 +28,6 @@ float coshf(float x)
} }
/* |x| > log(FLT_MAX) or nan */ /* |x| > log(FLT_MAX) or nan */
t = __expo2f(x); t = __expo2f(x, 1.0f);
return t; return t;
} }
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "libm.h" #include "libm.h"
static const float static const float
o_threshold = 8.8721679688e+01, /* 0x42b17180 */
ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */ invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */
...@@ -41,7 +40,7 @@ float expm1f(float x) ...@@ -41,7 +40,7 @@ float expm1f(float x)
return x; return x;
if (sign) if (sign)
return -1; return -1;
if (x > o_threshold) { if (hx > 0x42b17217) { /* x > log(FLT_MAX) */
x *= 0x1p127f; x *= 0x1p127f;
return x; return x;
} }
......
...@@ -77,17 +77,16 @@ float fmaf(float x, float y, float z) ...@@ -77,17 +77,16 @@ float fmaf(float x, float y, float z)
* If result is inexact, and exactly halfway between two float values, * If result is inexact, and exactly halfway between two float values,
* we need to adjust the low-order bit in the direction of the error. * we need to adjust the low-order bit in the direction of the error.
*/ */
#ifdef FE_TOWARDZERO double err;
fesetround(FE_TOWARDZERO); int neg = u.i >> 63;
#endif if (neg == (z > xy))
volatile double vxy = xy; /* XXX work around gcc CSE bug */ err = xy - result + z;
double adjusted_result = vxy + z; else
fesetround(FE_TONEAREST); err = z - result + xy;
if (result == adjusted_result) { if (neg == (err < 0))
u.f = adjusted_result;
u.i++; u.i++;
adjusted_result = u.f; else
} u.i--;
z = adjusted_result; z = u.f;
return z; return z;
} }
...@@ -34,6 +34,6 @@ double sinh(double x) ...@@ -34,6 +34,6 @@ double sinh(double x)
/* |x| > log(DBL_MAX) or nan */ /* |x| > log(DBL_MAX) or nan */
/* note: the result is stored to handle overflow */ /* note: the result is stored to handle overflow */
t = 2*h*__expo2(absx); t = __expo2(absx, 2*h);
return t; return t;
} }
...@@ -26,6 +26,6 @@ float sinhf(float x) ...@@ -26,6 +26,6 @@ float sinhf(float x)
} }
/* |x| > logf(FLT_MAX) or nan */ /* |x| > logf(FLT_MAX) or nan */
t = 2*h*__expo2f(absx); t = __expo2f(absx, 2*h);
return t; return t;
} }
/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */ #include <stdint.h>
/* #include <math.h>
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* sqrt(x)
* Return correctly rounded sqrt.
* ------------------------------------------
* | Use the hardware sqrt if you have one |
* ------------------------------------------
* Method:
* Bit by bit method using integer arithmetic. (Slow, but portable)
* 1. Normalization
* Scale x to y in [1,4) with even powers of 2:
* find an integer k such that 1 <= (y=x*2^(2k)) < 4, then
* sqrt(x) = 2^k * sqrt(y)
* 2. Bit by bit computation
* Let q = sqrt(y) truncated to i bit after binary point (q = 1),
* i 0
* i+1 2
* s = 2*q , and y = 2 * ( y - q ). (1)
* i i i i
*
* To compute q from q , one checks whether
* i+1 i
*
* -(i+1) 2
* (q + 2 ) <= y. (2)
* i
* -(i+1)
* If (2) is false, then q = q ; otherwise q = q + 2 .
* i+1 i i+1 i
*
* With some algebric manipulation, it is not difficult to see
* that (2) is equivalent to
* -(i+1)
* s + 2 <= y (3)
* i i
*
* The advantage of (3) is that s and y can be computed by
* i i
* the following recurrence formula:
* if (3) is false
*
* s = s , y = y ; (4)
* i+1 i i+1 i
*
* otherwise,
* -i -(i+1)
* s = s + 2 , y = y - s - 2 (5)
* i+1 i i+1 i i
*
* One may easily use induction to prove (4) and (5).
* Note. Since the left hand side of (3) contain only i+2 bits,
* it does not necessary to do a full (53-bit) comparison
* in (3).
* 3. Final rounding
* After generating the 53 bits result, we compute one more bit.
* Together with the remainder, we can decide whether the
* result is exact, bigger than 1/2ulp, or less than 1/2ulp
* (it will never equal to 1/2ulp).
* The rounding mode can be detected by checking whether
* huge + tiny is equal to huge, and whether huge - tiny is
* equal to huge for some floating point number "huge" and "tiny".
*
* Special cases:
* sqrt(+-0) = +-0 ... exact
* sqrt(inf) = inf
* sqrt(-ve) = NaN ... with invalid signal
* sqrt(NaN) = NaN ... with invalid signal for signaling NaN
*/
#include "libm.h" #include "libm.h"
#include "sqrt_data.h"
static const double tiny = 1.0e-300; #define FENV_SUPPORT 1
double sqrt(double x) /* returns a*b*2^-32 - e, with error 0 <= e < 1. */
static inline uint32_t mul32(uint32_t a, uint32_t b)
{ {
double z; return (uint64_t)a*b >> 32;
int32_t sign = (int)0x80000000; }
int32_t ix0,s0,q,m,t,i;
uint32_t r,t1,s1,ix1,q1;
EXTRACT_WORDS(ix0, ix1, x); /* returns a*b*2^-64 - e, with error 0 <= e < 3. */
static inline uint64_t mul64(uint64_t a, uint64_t b)
{
uint64_t ahi = a>>32;
uint64_t alo = a&0xffffffff;
uint64_t bhi = b>>32;
uint64_t blo = b&0xffffffff;
return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32);
}
/* take care of Inf and NaN */ double sqrt(double x)
if ((ix0&0x7ff00000) == 0x7ff00000) { {
return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ uint64_t ix, top, m;
}
/* take care of zero */
if (ix0 <= 0) {
if (((ix0&~sign)|ix1) == 0)
return x; /* sqrt(+-0) = +-0 */
if (ix0 < 0)
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
}
/* normalize x */
m = ix0>>20;
if (m == 0) { /* subnormal x */
while (ix0 == 0) {
m -= 21;
ix0 |= (ix1>>11);
ix1 <<= 21;
}
for (i=0; (ix0&0x00100000) == 0; i++)
ix0<<=1;
m -= i - 1;
ix0 |= ix1>>(32-i);
ix1 <<= i;
}
m -= 1023; /* unbias exponent */
ix0 = (ix0&0x000fffff)|0x00100000;
if (m & 1) { /* odd m, double x to make it even */
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
}
m >>= 1; /* m = [m/2] */
/* generate sqrt(x) bit by bit */
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
r = 0x00200000; /* r = moving bit from right to left */
while (r != 0) {
t = s0 + r;
if (t <= ix0) {
s0 = t + r;
ix0 -= t;
q += r;
}
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
r >>= 1;
}
r = sign; /* special case handling. */
while (r != 0) { ix = asuint64(x);
t1 = s1 + r; top = ix >> 52;
t = s0; if (predict_false(top - 0x001 >= 0x7ff - 0x001)) {
if (t < ix0 || (t == ix0 && t1 <= ix1)) { /* x < 0x1p-1022 or inf or nan. */
s1 = t1 + r; if (ix * 2 == 0)
if ((t1&sign) == sign && (s1&sign) == 0) return x;
s0++; if (ix == 0x7ff0000000000000)
ix0 -= t; return x;
if (ix1 < t1) if (ix > 0x7ff0000000000000)
ix0--; return __math_invalid(x);
ix1 -= t1; /* x is subnormal, normalize it. */
q1 += r; ix = asuint64(x * 0x1p52);
} top = ix >> 52;
ix0 += ix0 + ((ix1&sign)>>31); top -= 52;
ix1 += ix1;
r >>= 1;
} }
/* use floating add to find out rounding direction */ /* argument reduction:
if ((ix0|ix1) != 0) { x = 4^e m; with integer e, and m in [1, 4)
z = 1.0 - tiny; /* raise inexact flag */ m: fixed point representation [2.62]
if (z >= 1.0) { 2^e is the exponent part of the result. */
z = 1.0 + tiny; int even = top & 1;
if (q1 == (uint32_t)0xffffffff) { m = (ix << 11) | 0x8000000000000000;
q1 = 0; if (even) m >>= 1;
q++; top = (top + 0x3ff) >> 1;
} else if (z > 1.0) {
if (q1 == (uint32_t)0xfffffffe) /* approximate r ~ 1/sqrt(m) and s ~ sqrt(m) when m in [1,4)
q++;
q1 += 2; initial estimate:
} else 7bit table lookup (1bit exponent and 6bit significand).
q1 += q1 & 1;
} iterative approximation:
using 2 goldschmidt iterations with 32bit int arithmetics
and a final iteration with 64bit int arithmetics.
details:
the relative error (e = r0 sqrt(m)-1) of a linear estimate
(r0 = a m + b) is |e| < 0.085955 ~ 0x1.6p-4 at best,
a table lookup is faster and needs one less iteration
6 bit lookup table (128b) gives |e| < 0x1.f9p-8
7 bit lookup table (256b) gives |e| < 0x1.fdp-9
for single and double prec 6bit is enough but for quad
prec 7bit is needed (or modified iterations). to avoid
one more iteration >=13bit table would be needed (16k).
a newton-raphson iteration for r is
w = r*r
u = 3 - m*w
r = r*u/2
can use a goldschmidt iteration for s at the end or
s = m*r
first goldschmidt iteration is
s = m*r
u = 3 - s*r
r = r*u/2
s = s*u/2
next goldschmidt iteration is
u = 3 - s*r
r = r*u/2
s = s*u/2
and at the end r is not computed only s.
they use the same amount of operations and converge at the
same quadratic rate, i.e. if
r1 sqrt(m) - 1 = e, then
r2 sqrt(m) - 1 = -3/2 e^2 - 1/2 e^3
the advantage of goldschmidt is that the mul for s and r
are independent (computed in parallel), however it is not
"self synchronizing": it only uses the input m in the
first iteration so rounding errors accumulate. at the end
or when switching to larger precision arithmetics rounding
errors dominate so the first iteration should be used.
the fixed point representations are
m: 2.30 r: 0.32, s: 2.30, d: 2.30, u: 2.30, three: 2.30
and after switching to 64 bit
m: 2.62 r: 0.64, s: 2.62, d: 2.62, u: 2.62, three: 2.62 */
static const uint64_t three = 0xc0000000;
uint64_t r, s, d, u, i;
i = (ix >> 46) % 128;
r = (uint32_t)__rsqrt_tab[i] << 16;
/* |r sqrt(m) - 1| < 0x1.fdp-9 */
s = mul32(m>>32, r);
/* |s/sqrt(m) - 1| < 0x1.fdp-9 */
d = mul32(s, r);
u = three - d;
r = mul32(r, u) << 1;
/* |r sqrt(m) - 1| < 0x1.7bp-16 */
s = mul32(s, u) << 1;
/* |s/sqrt(m) - 1| < 0x1.7bp-16 */
d = mul32(s, r);
u = three - d;
r = mul32(r, u) << 1;
/* |r sqrt(m) - 1| < 0x1.3704p-29 (measured worst-case) */
r = r << 32;
s = mul64(m, r);
d = mul64(s, r);
u = (three<<32) - d;
s = mul64(s, u); /* repr: 3.61 */
/* -0x1p-57 < s - sqrt(m) < 0x1.8001p-61 */
s = (s - 2) >> 9; /* repr: 12.52 */
/* -0x1.09p-52 < s - sqrt(m) < -0x1.fffcp-63 */
/* s < sqrt(m) < s + 0x1.09p-52,
compute nearest rounded result:
the nearest result to 52 bits is either s or s+0x1p-52,
we can decide by comparing (2^52 s + 0.5)^2 to 2^104 m. */
uint64_t d0, d1, d2;
double y, t;
d0 = (m << 42) - s*s;
d1 = s - d0;
d2 = d1 + s + 1;
s += d1 >> 63;
s &= 0x000fffffffffffff;
s |= top << 52;
y = asdouble(s);
if (FENV_SUPPORT) {
/* handle rounding modes and inexact exception:
only (s+1)^2 == 2^42 m case is exact otherwise
add a tiny value to cause the fenv effects. */
uint64_t tiny = predict_false(d2==0) ? 0 : 0x0010000000000000;
tiny |= (d1^d2) & 0x8000000000000000;
t = asdouble(tiny);
y = eval_as_double(y + t);
} }
ix0 = (q>>1) + 0x3fe00000; return y;
ix1 = q1>>1;
if (q&1)
ix1 |= sign;
INSERT_WORDS(z, ix0 + ((uint32_t)m << 20), ix1);
return z;
} }
#include "sqrt_data.h"
const uint16_t __rsqrt_tab[128] = {
0xb451,0xb2f0,0xb196,0xb044,0xaef9,0xadb6,0xac79,0xab43,
0xaa14,0xa8eb,0xa7c8,0xa6aa,0xa592,0xa480,0xa373,0xa26b,
0xa168,0xa06a,0x9f70,0x9e7b,0x9d8a,0x9c9d,0x9bb5,0x9ad1,
0x99f0,0x9913,0x983a,0x9765,0x9693,0x95c4,0x94f8,0x9430,
0x936b,0x92a9,0x91ea,0x912e,0x9075,0x8fbe,0x8f0a,0x8e59,
0x8daa,0x8cfe,0x8c54,0x8bac,0x8b07,0x8a64,0x89c4,0x8925,
0x8889,0x87ee,0x8756,0x86c0,0x862b,0x8599,0x8508,0x8479,
0x83ec,0x8361,0x82d8,0x8250,0x81c9,0x8145,0x80c2,0x8040,
0xff02,0xfd0e,0xfb25,0xf947,0xf773,0xf5aa,0xf3ea,0xf234,
0xf087,0xeee3,0xed47,0xebb3,0xea27,0xe8a3,0xe727,0xe5b2,
0xe443,0xe2dc,0xe17a,0xe020,0xdecb,0xdd7d,0xdc34,0xdaf1,
0xd9b3,0xd87b,0xd748,0xd61a,0xd4f1,0xd3cd,0xd2ad,0xd192,
0xd07b,0xcf69,0xce5b,0xcd51,0xcc4a,0xcb48,0xca4a,0xc94f,
0xc858,0xc764,0xc674,0xc587,0xc49d,0xc3b7,0xc2d4,0xc1f4,
0xc116,0xc03c,0xbf65,0xbe90,0xbdbe,0xbcef,0xbc23,0xbb59,
0xba91,0xb9cc,0xb90a,0xb84a,0xb78c,0xb6d0,0xb617,0xb560,
};
#ifndef _SQRT_DATA_H
#define _SQRT_DATA_H
#include <features.h>
#include <stdint.h>
/* if x in [1,2): i = (int)(64*x);
if x in [2,4): i = (int)(32*x-64);
__rsqrt_tab[i]*2^-16 is estimating 1/sqrt(x) with small relative error:
|__rsqrt_tab[i]*0x1p-16*sqrt(x) - 1| < -0x1.fdp-9 < 2^-8 */
extern hidden const uint16_t __rsqrt_tab[128];
#endif
/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrtf.c */ #include <stdint.h>
/* #include <math.h>
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
*/
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#include "libm.h" #include "libm.h"
#include "sqrt_data.h"
static const float tiny = 1.0e-30; #define FENV_SUPPORT 1
float sqrtf(float x) static inline uint32_t mul32(uint32_t a, uint32_t b)
{ {
float z; return (uint64_t)a*b >> 32;
int32_t sign = (int)0x80000000; }
int32_t ix,s,q,m,t,i;
uint32_t r;
GET_FLOAT_WORD(ix, x); /* see sqrt.c for more detailed comments. */
/* take care of Inf and NaN */ float sqrtf(float x)
if ((ix&0x7f800000) == 0x7f800000) {
return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ uint32_t ix, m, m1, m0, even, ey;
/* take care of zero */ ix = asuint(x);
if (ix <= 0) { if (predict_false(ix - 0x00800000 >= 0x7f800000 - 0x00800000)) {
if ((ix&~sign) == 0) /* x < 0x1p-126 or inf or nan. */
return x; /* sqrt(+-0) = +-0 */ if (ix * 2 == 0)
if (ix < 0) return x;
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ if (ix == 0x7f800000)
} return x;
/* normalize x */ if (ix > 0x7f800000)
m = ix>>23; return __math_invalidf(x);
if (m == 0) { /* subnormal x */ /* x is subnormal, normalize it. */
for (i = 0; (ix&0x00800000) == 0; i++) ix = asuint(x * 0x1p23f);
ix<<=1; ix -= 23 << 23;
m -= i - 1;
} }
m -= 127; /* unbias exponent */
ix = (ix&0x007fffff)|0x00800000;
if (m&1) /* odd m, double x to make it even */
ix += ix;
m >>= 1; /* m = [m/2] */
/* generate sqrt(x) bit by bit */ /* x = 4^e m; with int e and m in [1, 4). */
ix += ix; even = ix & 0x00800000;
q = s = 0; /* q = sqrt(x) */ m1 = (ix << 8) | 0x80000000;
r = 0x01000000; /* r = moving bit from right to left */ m0 = (ix << 7) & 0x7fffffff;
m = even ? m0 : m1;
while (r != 0) { /* 2^e is the exponent part of the return value. */
t = s + r; ey = ix >> 1;
if (t <= ix) { ey += 0x3f800000 >> 1;
s = t+r; ey &= 0x7f800000;
ix -= t;
q += r; /* compute r ~ 1/sqrt(m), s ~ sqrt(m) with 2 goldschmidt iterations. */
} static const uint32_t three = 0xc0000000;
ix += ix; uint32_t r, s, d, u, i;
r >>= 1; i = (ix >> 17) % 128;
} r = (uint32_t)__rsqrt_tab[i] << 16;
/* |r*sqrt(m) - 1| < 0x1p-8 */
s = mul32(m, r);
/* |s/sqrt(m) - 1| < 0x1p-8 */
d = mul32(s, r);
u = three - d;
r = mul32(r, u) << 1;
/* |r*sqrt(m) - 1| < 0x1.7bp-16 */
s = mul32(s, u) << 1;
/* |s/sqrt(m) - 1| < 0x1.7bp-16 */
d = mul32(s, r);
u = three - d;
s = mul32(s, u);
/* -0x1.03p-28 < s/sqrt(m) - 1 < 0x1.fp-31 */
s = (s - 1)>>6;
/* s < sqrt(m) < s + 0x1.08p-23 */
/* use floating add to find out rounding direction */ /* compute nearest rounded result. */
if (ix != 0) { uint32_t d0, d1, d2;
z = 1.0f - tiny; /* raise inexact flag */ float y, t;
if (z >= 1.0f) { d0 = (m << 16) - s*s;
z = 1.0f + tiny; d1 = s - d0;
if (z > 1.0f) d2 = d1 + s + 1;
q += 2; s += d1 >> 31;
else s &= 0x007fffff;
q += q & 1; s |= ey;
} y = asfloat(s);
if (FENV_SUPPORT) {
/* handle rounding and inexact exception. */
uint32_t tiny = predict_false(d2==0) ? 0 : 0x01000000;
tiny |= (d1^d2) & 0x80000000;
t = asfloat(tiny);
y = eval_as_float(y + t);
} }
ix = (q>>1) + 0x3f000000; return y;
SET_FLOAT_WORD(z, ix + ((uint32_t)m << 23));
return z;
} }
#include <stdint.h>
#include <math.h> #include <math.h>
#include <float.h>
#include "libm.h"
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
long double sqrtl(long double x) long double sqrtl(long double x)
{ {
/* FIXME: implement in C, this is for LDBL_MANT_DIG == 64 only */
return sqrt(x); return sqrt(x);
} }
#elif (LDBL_MANT_DIG == 113 || LDBL_MANT_DIG == 64) && LDBL_MAX_EXP == 16384
#include "sqrt_data.h"
#define FENV_SUPPORT 1
typedef struct {
uint64_t hi;
uint64_t lo;
} u128;
/* top: 16 bit sign+exponent, x: significand. */
static inline long double mkldbl(uint64_t top, u128 x)
{
union ldshape u;
#if LDBL_MANT_DIG == 113
u.i2.hi = x.hi;
u.i2.lo = x.lo;
u.i2.hi &= 0x0000ffffffffffff;
u.i2.hi |= top << 48;
#elif LDBL_MANT_DIG == 64
u.i.se = top;
u.i.m = x.lo;
/* force the top bit on non-zero (and non-subnormal) results. */
if (top & 0x7fff)
u.i.m |= 0x8000000000000000;
#endif
return u.f;
}
/* return: top 16 bit is sign+exp and following bits are the significand. */
static inline u128 asu128(long double x)
{
union ldshape u = {.f=x};
u128 r;
#if LDBL_MANT_DIG == 113
r.hi = u.i2.hi;
r.lo = u.i2.lo;
#elif LDBL_MANT_DIG == 64
r.lo = u.i.m<<49;
/* ignore the top bit: pseudo numbers are not handled. */
r.hi = u.i.m>>15;
r.hi &= 0x0000ffffffffffff;
r.hi |= (uint64_t)u.i.se << 48;
#endif
return r;
}
/* returns a*b*2^-32 - e, with error 0 <= e < 1. */
static inline uint32_t mul32(uint32_t a, uint32_t b)
{
return (uint64_t)a*b >> 32;
}
/* returns a*b*2^-64 - e, with error 0 <= e < 3. */
static inline uint64_t mul64(uint64_t a, uint64_t b)
{
uint64_t ahi = a>>32;
uint64_t alo = a&0xffffffff;
uint64_t bhi = b>>32;
uint64_t blo = b&0xffffffff;
return ahi*bhi + (ahi*blo >> 32) + (alo*bhi >> 32);
}
static inline u128 add64(u128 a, uint64_t b)
{
u128 r;
r.lo = a.lo + b;
r.hi = a.hi;
if (r.lo < a.lo)
r.hi++;
return r;
}
static inline u128 add128(u128 a, u128 b)
{
u128 r;
r.lo = a.lo + b.lo;
r.hi = a.hi + b.hi;
if (r.lo < a.lo)
r.hi++;
return r;
}
static inline u128 sub64(u128 a, uint64_t b)
{
u128 r;
r.lo = a.lo - b;
r.hi = a.hi;
if (a.lo < b)
r.hi--;
return r;
}
static inline u128 sub128(u128 a, u128 b)
{
u128 r;
r.lo = a.lo - b.lo;
r.hi = a.hi - b.hi;
if (a.lo < b.lo)
r.hi--;
return r;
}
/* a<<n, 0 <= n <= 127 */
static inline u128 lsh(u128 a, int n)
{
if (n == 0)
return a;
if (n >= 64) {
a.hi = a.lo<<(n-64);
a.lo = 0;
} else {
a.hi = (a.hi<<n) | (a.lo>>(64-n));
a.lo = a.lo<<n;
}
return a;
}
/* a>>n, 0 <= n <= 127 */
static inline u128 rsh(u128 a, int n)
{
if (n == 0)
return a;
if (n >= 64) {
a.lo = a.hi>>(n-64);
a.hi = 0;
} else {
a.lo = (a.lo>>n) | (a.hi<<(64-n));
a.hi = a.hi>>n;
}
return a;
}
/* returns a*b exactly. */
static inline u128 mul64_128(uint64_t a, uint64_t b)
{
u128 r;
uint64_t ahi = a>>32;
uint64_t alo = a&0xffffffff;
uint64_t bhi = b>>32;
uint64_t blo = b&0xffffffff;
uint64_t lo1 = ((ahi*blo)&0xffffffff) + ((alo*bhi)&0xffffffff) + (alo*blo>>32);
uint64_t lo2 = (alo*blo)&0xffffffff;
r.hi = ahi*bhi + (ahi*blo>>32) + (alo*bhi>>32) + (lo1>>32);
r.lo = (lo1<<32) + lo2;
return r;
}
/* returns a*b*2^-128 - e, with error 0 <= e < 7. */
static inline u128 mul128(u128 a, u128 b)
{
u128 hi = mul64_128(a.hi, b.hi);
uint64_t m1 = mul64(a.hi, b.lo);
uint64_t m2 = mul64(a.lo, b.hi);
return add64(add64(hi, m1), m2);
}
/* returns a*b % 2^128. */
static inline u128 mul128_tail(u128 a, u128 b)
{
u128 lo = mul64_128(a.lo, b.lo);
lo.hi += a.hi*b.lo + a.lo*b.hi;
return lo;
}
/* see sqrt.c for detailed comments. */
long double sqrtl(long double x)
{
u128 ix, ml;
uint64_t top;
ix = asu128(x);
top = ix.hi >> 48;
if (predict_false(top - 0x0001 >= 0x7fff - 0x0001)) {
/* x < 0x1p-16382 or inf or nan. */
if (2*ix.hi == 0 && ix.lo == 0)
return x;
if (ix.hi == 0x7fff000000000000 && ix.lo == 0)
return x;
if (top >= 0x7fff)
return __math_invalidl(x);
/* x is subnormal, normalize it. */
ix = asu128(x * 0x1p112);
top = ix.hi >> 48;
top -= 112;
}
/* x = 4^e m; with int e and m in [1, 4) */
int even = top & 1;
ml = lsh(ix, 15);
ml.hi |= 0x8000000000000000;
if (even) ml = rsh(ml, 1);
top = (top + 0x3fff) >> 1;
/* r ~ 1/sqrt(m) */
static const uint64_t three = 0xc0000000;
uint64_t r, s, d, u, i;
i = (ix.hi >> 42) % 128;
r = (uint32_t)__rsqrt_tab[i] << 16;
/* |r sqrt(m) - 1| < 0x1p-8 */
s = mul32(ml.hi>>32, r);
d = mul32(s, r);
u = three - d;
r = mul32(u, r) << 1;
/* |r sqrt(m) - 1| < 0x1.7bp-16, switch to 64bit */
r = r<<32;
s = mul64(ml.hi, r);
d = mul64(s, r);
u = (three<<32) - d;
r = mul64(u, r) << 1;
/* |r sqrt(m) - 1| < 0x1.a5p-31 */
s = mul64(u, s) << 1;
d = mul64(s, r);
u = (three<<32) - d;
r = mul64(u, r) << 1;
/* |r sqrt(m) - 1| < 0x1.c001p-59, switch to 128bit */
static const u128 threel = {.hi=three<<32, .lo=0};
u128 rl, sl, dl, ul;
rl.hi = r;
rl.lo = 0;
sl = mul128(ml, rl);
dl = mul128(sl, rl);
ul = sub128(threel, dl);
sl = mul128(ul, sl); /* repr: 3.125 */
/* -0x1p-116 < s - sqrt(m) < 0x3.8001p-125 */
sl = rsh(sub64(sl, 4), 125-(LDBL_MANT_DIG-1));
/* s < sqrt(m) < s + 1 ULP + tiny */
long double y;
u128 d2, d1, d0;
d0 = sub128(lsh(ml, 2*(LDBL_MANT_DIG-1)-126), mul128_tail(sl,sl));
d1 = sub128(sl, d0);
d2 = add128(add64(sl, 1), d1);
sl = add64(sl, d1.hi >> 63);
y = mkldbl(top, sl);
if (FENV_SUPPORT) {
/* handle rounding modes and inexact exception. */
top = predict_false((d2.hi|d2.lo)==0) ? 0 : 1;
top |= ((d1.hi^d2.hi)&0x8000000000000000) >> 48;
y += mkldbl(top, (u128){0});
}
return y;
}
#else
#error unsupported long double format
#endif
#include "stdio_impl.h" #include "stdio_impl.h"
#include <unistd.h> #include <unistd.h>
int __stdio_close(FILE *f) int __stdio_close(FILE *f)
{ {
return close(f->fd); return close(f->fd);
......
#include "stdio_impl.h" #include "stdio_impl.h"
#include <errno.h>
int __fseeko_unlocked(FILE *f, off_t off, int whence) int __fseeko_unlocked(FILE *f, off_t off, int whence)
{ {
/* Fail immediately for invalid whence argument. */
if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END) {
errno = EINVAL;
return -1;
}
/* Adjust relative offset for unread data in buffer, if any. */ /* Adjust relative offset for unread data in buffer, if any. */
if (whence == SEEK_CUR && f->rend) off -= f->rend - f->rpos; if (whence == SEEK_CUR && f->rend) off -= f->rend - f->rpos;
...@@ -20,7 +27,7 @@ int __fseeko_unlocked(FILE *f, off_t off, int whence) ...@@ -20,7 +27,7 @@ int __fseeko_unlocked(FILE *f, off_t off, int whence)
/* If seek succeeded, file is seekable and we discard read buffer. */ /* If seek succeeded, file is seekable and we discard read buffer. */
f->rpos = f->rend = 0; f->rpos = f->rend = 0;
f->flags &= ~F_EOF; f->flags &= ~F_EOF;
return 0; return 0;
} }
......
...@@ -28,10 +28,3 @@ long double strtold(const char *restrict s, char **restrict p) ...@@ -28,10 +28,3 @@ long double strtold(const char *restrict s, char **restrict p)
{ {
return strtox(s, p, 2); return strtox(s, p, 2);
} }
weak_alias(strtof, strtof_l);
weak_alias(strtod, strtod_l);
weak_alias(strtold, strtold_l);
weak_alias(strtof, __strtof_l);
weak_alias(strtod, __strtod_l);
weak_alias(strtold, __strtold_l);
...@@ -10,16 +10,16 @@ static char *twobyte_strstr(const unsigned char *h, const unsigned char *n) ...@@ -10,16 +10,16 @@ static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
static char *threebyte_strstr(const unsigned char *h, const unsigned char *n) static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
{ {
uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8; uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8; uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8); for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
return *h ? (char *)h-2 : 0; return *h ? (char *)h-2 : 0;
} }
static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n) static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
{ {
uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
for (h+=3; *h && hw != nw; hw = hw<<8 | *++h); for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
return *h ? (char *)h-3 : 0; return *h ? (char *)h-3 : 0;
} }
...@@ -96,7 +96,7 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n) ...@@ -96,7 +96,7 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
for (;;) { for (;;) {
/* Update incremental end-of-haystack pointer */ /* Update incremental end-of-haystack pointer */
if (z-h < l) { if (z-h < l) {
/* Fast estimate for MIN(l,63) */ /* Fast estimate for MAX(l,63) */
size_t grow = l | 63; size_t grow = l | 63;
const unsigned char *z2 = memchr(z, 0, grow); const unsigned char *z2 = memchr(z, 0, grow);
if (z2) { if (z2) {
......
...@@ -82,22 +82,20 @@ static size_t scan_trans(long long t, int local, size_t *alt) ...@@ -82,22 +82,20 @@ static size_t scan_trans(long long t, int local, size_t *alt)
n = (index-trans)>>scale; n = (index-trans)>>scale;
if (a == n-1) return -1; if (a == n-1) return -1;
if (a == 0) { if (a == 0) {
x = zi_read32(trans + (a<<scale)); x = zi_read32(trans);
if (scale == 3) x = x<<32 | zi_read32(trans + (a<<scale) + 4); if (scale == 3) x = x<<32 | zi_read32(trans + 4);
else x = (int32_t)x; else x = (int32_t)x;
if (local) off = (int32_t)zi_read32(types + 6 * index[a-1]); /* Find the lowest non-DST type, or 0 if none. */
size_t j = 0;
for (size_t i=abbrevs-types; i; i-=6) {
if (!types[i-6+4]) j = i-6;
}
if (local) off = (int32_t)zi_read32(types + j);
/* If t is before first transition, use the above-found type
* and the index-zero (after transition) type as the alt. */
if (t - off < (int64_t)x) { if (t - off < (int64_t)x) {
for (a=0; a<(abbrevs-types)/6; a++) { if (alt) *alt = index[0];
if (types[6*a+4] != types[4]) break; return j/6;
}
if (a == (abbrevs-types)/6) a = 0;
if (types[6*a+4]) {
*alt = a;
return 0;
} else {
*alt = 0;
return a;
}
} }
} }
......
...@@ -372,6 +372,16 @@ ...@@ -372,6 +372,16 @@
#define __NR_fspick 433 #define __NR_fspick 433
#define __NR_pidfd_open 434 #define __NR_pidfd_open 434
#define __NR_clone3 435 #define __NR_clone3 435
#define __NR_close_range 436
#define __NR_openat2 437
#define __NR_pidfd_getfd 438
#define __NR_faccessat2 439
#define __NR_process_madvise 440
#define __NR_epoll_pwait2 441
#define __NR_mount_setattr 442
#define __NR_landlock_create_ruleset 444
#define __NR_landlock_add_rule 445
#define __NR_landlock_restrict_self 446
/* OHOS customized syscalls, not compatible with ARM EABI */ /* OHOS customized syscalls, not compatible with ARM EABI */
#define __NR_OHOS_BEGIN 500 #define __NR_OHOS_BEGIN 500
......
#if 0
#if ((__ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \ #if ((__ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \
|| __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7 || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
static inline pthread_t __pthread_self() static inline uintptr_t __get_tp()
{ {
char *p; uintptr_t tp;
__asm__ ( "mrc p15,0,%0,c13,c0,3" : "=r"(p) ); __asm__ ( "mrc p15,0,%0,c13,c0,3" : "=r"(tp) );
return (void *)(p-sizeof(struct pthread)); return tp;
} }
#else #else
...@@ -17,21 +16,19 @@ static inline pthread_t __pthread_self() ...@@ -17,21 +16,19 @@ static inline pthread_t __pthread_self()
#define BLX "blx" #define BLX "blx"
#endif #endif
static inline pthread_t __pthread_self() static inline uintptr_t __get_tp()
{ {
extern hidden uintptr_t __a_gettp_ptr; extern hidden uintptr_t __a_gettp_ptr;
register uintptr_t p __asm__("r0"); register uintptr_t tp __asm__("r0");
__asm__ ( BLX " %1" : "=r"(p) : "r"(__a_gettp_ptr) : "cc", "lr" ); __asm__ ( BLX " %1" : "=r"(tp) : "r"(__a_gettp_ptr) : "cc", "lr" );
return (void *)(p-sizeof(struct pthread)); return tp;
} }
#endif #endif
#else
extern pthread_t __pthread_self(); extern pthread_t __pthread_self();
#endif
#define TLS_ABOVE_TP #define TLS_ABOVE_TP
#define GAP_ABOVE_TP 8 #define GAP_ABOVE_TP 8
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
#define MC_PC arm_pc #define MC_PC arm_pc
#define _GNU_SOURCE #define _GNU_SOURCE
#define SYSCALL_NO_TLS 1 #define SYSCALL_NO_TLS 1
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
...@@ -21,9 +20,14 @@ ...@@ -21,9 +20,14 @@
#include <semaphore.h> #include <semaphore.h>
#include <sys/membarrier.h> #include <sys/membarrier.h>
#include "pthread_impl.h" #include "pthread_impl.h"
#include "fork_impl.h"
#include "libc.h" #include "libc.h"
#include "dynlink.h" #include "dynlink.h"
#include "malloc_impl.h"
#define malloc __libc_malloc
#define calloc __libc_calloc
#define realloc __libc_realloc
#define free __libc_free
static void error(const char *, ...); static void error(const char *, ...);
...@@ -77,7 +81,7 @@ struct dso { ...@@ -77,7 +81,7 @@ struct dso {
struct dso **deps, *needed_by; struct dso **deps, *needed_by;
size_t ndeps_direct; size_t ndeps_direct;
size_t next_dep; size_t next_dep;
int ctor_visitor; pthread_t ctor_visitor;
char *rpath_orig, *rpath; char *rpath_orig, *rpath;
struct tls_module tls; struct tls_module tls;
size_t tls_id; size_t tls_id;
...@@ -413,8 +417,6 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri ...@@ -413,8 +417,6 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
} }
switch(type) { switch(type) {
case REL_NONE:
break;
case REL_OFFSET: case REL_OFFSET:
addend -= (size_t)reloc_addr; addend -= (size_t)reloc_addr;
case REL_SYMBOLIC: case REL_SYMBOLIC:
...@@ -557,10 +559,25 @@ static void reclaim_gaps(struct dso *dso) ...@@ -557,10 +559,25 @@ static void reclaim_gaps(struct dso *dso)
} }
} }
static ssize_t read_loop(int fd, void *p, size_t n)
{
for (size_t i=0; i<n; ) {
ssize_t l = read(fd, (char *)p+i, n-i);
if (l<0) {
if (errno==EINTR) continue;
else return -1;
}
if (l==0) return i;
i += l;
}
return n;
}
static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off) static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off)
{ {
static int no_map_fixed; static int no_map_fixed;
char *q; char *q;
if (!n) return p;
if (!no_map_fixed) { if (!no_map_fixed) {
q = mmap(p, n, prot, flags|MAP_FIXED, fd, off); q = mmap(p, n, prot, flags|MAP_FIXED, fd, off);
if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL) if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL)
...@@ -1076,13 +1093,18 @@ static struct dso *load_library(const char *name, struct dso *needed_by) ...@@ -1076,13 +1093,18 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
snprintf(etc_ldso_path, sizeof etc_ldso_path, snprintf(etc_ldso_path, sizeof etc_ldso_path,
"%.*s/etc/ld-musl-" LDSO_ARCH ".path", "%.*s/etc/ld-musl-" LDSO_ARCH ".path",
(int)prefix_len, prefix); (int)prefix_len, prefix);
FILE *f = fopen(etc_ldso_path, "rbe"); fd = open(etc_ldso_path, O_RDONLY|O_CLOEXEC);
if (f) { if (fd>=0) {
if (getdelim(&sys_path, (size_t[1]){0}, 0, f) <= 0) { size_t n = 0;
if (!fstat(fd, &st)) n = st.st_size;
if ((sys_path = malloc(n+1)))
sys_path[n] = 0;
if (!sys_path || read_loop(fd, sys_path, n)<0) {
free(sys_path); free(sys_path);
sys_path = ""; sys_path = "";
} }
fclose(f); close(fd);
} else if (errno != ENOENT) { } else if (errno != ENOENT) {
sys_path = ""; sys_path = "";
} }
...@@ -1259,7 +1281,7 @@ static void extend_bfs_deps(struct dso *p) ...@@ -1259,7 +1281,7 @@ static void extend_bfs_deps(struct dso *p)
struct dso *dep = p->deps[i]; struct dso *dep = p->deps[i];
for (j=cnt=0; j<dep->ndeps_direct; j++) for (j=cnt=0; j<dep->ndeps_direct; j++)
if (!dep->deps[j]->mark) cnt++; if (!dep->deps[j]->mark) cnt++;
tmp = no_realloc ? tmp = no_realloc ?
malloc(sizeof(*tmp) * (ndeps_all+cnt+1)) : malloc(sizeof(*tmp) * (ndeps_all+cnt+1)) :
realloc(p->deps, sizeof(*tmp) * (ndeps_all+cnt+1)); realloc(p->deps, sizeof(*tmp) * (ndeps_all+cnt+1));
if (!tmp) { if (!tmp) {
...@@ -1397,7 +1419,7 @@ void __libc_exit_fini() ...@@ -1397,7 +1419,7 @@ void __libc_exit_fini()
{ {
struct dso *p; struct dso *p;
size_t dyn[DYN_CNT]; size_t dyn[DYN_CNT];
int self = __pthread_self()->tid; pthread_t self = __pthread_self();
/* Take both locks before setting shutting_down, so that /* Take both locks before setting shutting_down, so that
* either lock is sufficient to read its value. The lock * either lock is sufficient to read its value. The lock
...@@ -1423,6 +1445,17 @@ void __libc_exit_fini() ...@@ -1423,6 +1445,17 @@ void __libc_exit_fini()
} }
} }
void __ldso_atfork(int who)
{
if (who<0) {
pthread_rwlock_wrlock(&lock);
pthread_mutex_lock(&init_fini_lock);
} else {
pthread_mutex_unlock(&init_fini_lock);
pthread_rwlock_unlock(&lock);
}
}
static struct dso **queue_ctors(struct dso *dso) static struct dso **queue_ctors(struct dso *dso)
{ {
size_t cnt, qpos, spos, i; size_t cnt, qpos, spos, i;
...@@ -1481,6 +1514,13 @@ static struct dso **queue_ctors(struct dso *dso) ...@@ -1481,6 +1514,13 @@ static struct dso **queue_ctors(struct dso *dso)
} }
queue[qpos] = 0; queue[qpos] = 0;
for (i=0; i<qpos; i++) queue[i]->mark = 0; for (i=0; i<qpos; i++) queue[i]->mark = 0;
for (i=0; i<qpos; i++)
if (queue[i]->ctor_visitor && queue[i]->ctor_visitor->tid < 0) {
error("State of %s is inconsistent due to multithreaded fork\n",
queue[i]->name);
free(queue);
if (runtime) longjmp(*rtld_fail, 1);
}
return queue; return queue;
} }
...@@ -1489,7 +1529,7 @@ static void do_init_fini(struct dso **queue) ...@@ -1489,7 +1529,7 @@ static void do_init_fini(struct dso **queue)
{ {
struct dso *p; struct dso *p;
size_t dyn[DYN_CNT], i; size_t dyn[DYN_CNT], i;
int self = __pthread_self()->tid; pthread_t self = __pthread_self();
pthread_mutex_lock(&init_fini_lock); pthread_mutex_lock(&init_fini_lock);
for (i=0; (p=queue[i]); i++) { for (i=0; (p=queue[i]); i++) {
...@@ -1498,7 +1538,7 @@ static void do_init_fini(struct dso **queue) ...@@ -1498,7 +1538,7 @@ static void do_init_fini(struct dso **queue)
if (p->ctor_visitor || p->constructed) if (p->ctor_visitor || p->constructed)
continue; continue;
p->ctor_visitor = self; p->ctor_visitor = self;
decode_vec(p->dynv, dyn, DYN_CNT); decode_vec(p->dynv, dyn, DYN_CNT);
if (dyn[0] & ((1<<DT_FINI) | (1<<DT_FINI_ARRAY))) { if (dyn[0] & ((1<<DT_FINI) | (1<<DT_FINI_ARRAY))) {
p->fini_next = fini_head; p->fini_next = fini_head;
...@@ -1598,7 +1638,7 @@ static void install_new_tls(void) ...@@ -1598,7 +1638,7 @@ static void install_new_tls(void)
/* Install new dtv for each thread. */ /* Install new dtv for each thread. */
for (j=0, td=self; !j || td!=self; j++, td=td->next) { for (j=0, td=self; !j || td!=self; j++, td=td->next) {
td->dtv = td->dtv_copy = newdtv[j]; td->dtv = newdtv[j];
} }
__tl_unlock(); __tl_unlock();
...@@ -1609,7 +1649,7 @@ static void install_new_tls(void) ...@@ -1609,7 +1649,7 @@ static void install_new_tls(void)
* following stage 2 and stage 3 functions via primitive symbolic lookup * following stage 2 and stage 3 functions via primitive symbolic lookup
* since it does not have access to their addresses to begin with. */ * since it does not have access to their addresses to begin with. */
/* Stage 2 of the dynamic linker is called after relative relocations /* Stage 2 of the dynamic linker is called after relative relocations
* have been processed. It can make function calls to static functions * have been processed. It can make function calls to static functions
* and access string literals and static data, but cannot use extern * and access string literals and static data, but cannot use extern
* symbols. Its job is to perform symbolic relocations on the dynamic * symbols. Its job is to perform symbolic relocations on the dynamic
...@@ -1815,7 +1855,7 @@ void __dls3(size_t *sp, size_t *auxv) ...@@ -1815,7 +1855,7 @@ void __dls3(size_t *sp, size_t *auxv)
dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno)); dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno));
_exit(1); _exit(1);
} }
Ehdr *ehdr = (void *)map_library(fd, &app); Ehdr *ehdr = map_library(fd, &app);
if (!ehdr) { if (!ehdr) {
dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]); dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]);
_exit(1); _exit(1);
...@@ -1961,6 +2001,8 @@ void __dls3(size_t *sp, size_t *auxv) ...@@ -1961,6 +2001,8 @@ void __dls3(size_t *sp, size_t *auxv)
* possibility of incomplete replacement. */ * possibility of incomplete replacement. */
if (find_sym(head, "malloc", 1).dso != &ldso) if (find_sym(head, "malloc", 1).dso != &ldso)
__malloc_replaced = 1; __malloc_replaced = 1;
if (find_sym(head, "aligned_alloc", 1).dso != &ldso)
__aligned_alloc_replaced = 1;
/* Switch to runtime mode: any further failures in the dynamic /* Switch to runtime mode: any further failures in the dynamic
* linker are a reportable failure rather than a fatal startup * linker are a reportable failure rather than a fatal startup
...@@ -1971,7 +2013,7 @@ void __dls3(size_t *sp, size_t *auxv) ...@@ -1971,7 +2013,7 @@ void __dls3(size_t *sp, size_t *auxv)
debug.bp = dl_debug_state; debug.bp = dl_debug_state;
debug.head = head; debug.head = head;
debug.base = ldso.base; debug.base = ldso.base;
debug.state = 0; debug.state = RT_CONSISTENT;
_dl_debug_state(); _dl_debug_state();
if (replace_argv0) argv[0] = replace_argv0; if (replace_argv0) argv[0] = replace_argv0;
...@@ -2030,6 +2072,9 @@ void *dlopen(const char *file, int mode) ...@@ -2030,6 +2072,9 @@ void *dlopen(const char *file, int mode)
pthread_rwlock_wrlock(&lock); pthread_rwlock_wrlock(&lock);
__inhibit_ptc(); __inhibit_ptc();
debug.state = RT_ADD;
_dl_debug_state();
p = 0; p = 0;
if (shutting_down) { if (shutting_down) {
error("Cannot dlopen while program is exiting."); error("Cannot dlopen while program is exiting.");
...@@ -2089,8 +2134,9 @@ void *dlopen(const char *file, int mode) ...@@ -2089,8 +2134,9 @@ void *dlopen(const char *file, int mode)
load_deps(p); load_deps(p);
extend_bfs_deps(p); extend_bfs_deps(p);
pthread_mutex_lock(&init_fini_lock); pthread_mutex_lock(&init_fini_lock);
if (!p->constructed) ctor_queue = queue_ctors(p); int constructed = p->constructed;
pthread_mutex_unlock(&init_fini_lock); pthread_mutex_unlock(&init_fini_lock);
if (!constructed) ctor_queue = queue_ctors(p);
if (!p->relocated && (mode & RTLD_LAZY)) { if (!p->relocated && (mode & RTLD_LAZY)) {
prepare_lazy(p); prepare_lazy(p);
for (i=0; p->deps[i]; i++) for (i=0; p->deps[i]; i++)
...@@ -2122,9 +2168,10 @@ void *dlopen(const char *file, int mode) ...@@ -2122,9 +2168,10 @@ void *dlopen(const char *file, int mode)
update_tls_size(); update_tls_size();
if (tls_cnt != orig_tls_cnt) if (tls_cnt != orig_tls_cnt)
install_new_tls(); install_new_tls();
_dl_debug_state();
orig_tail = tail; orig_tail = tail;
end: end:
debug.state = RT_CONSISTENT;
_dl_debug_state();
__release_ptc(); __release_ptc();
if (p) gencnt++; if (p) gencnt++;
pthread_rwlock_unlock(&lock); pthread_rwlock_unlock(&lock);
...@@ -2318,7 +2365,8 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void ...@@ -2318,7 +2365,8 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void
info.dlpi_adds = gencnt; info.dlpi_adds = gencnt;
info.dlpi_subs = 0; info.dlpi_subs = 0;
info.dlpi_tls_modid = current->tls_id; info.dlpi_tls_modid = current->tls_id;
info.dlpi_tls_data = current->tls.image; info.dlpi_tls_data = !current->tls_id ? 0 :
__tls_get_addr((tls_mod_off_t[]){current->tls_id,0});
ret = (callback)(&info, sizeof (info), data); ret = (callback)(&info, sizeof (info), data);
......
...@@ -10,6 +10,12 @@ ...@@ -10,6 +10,12 @@
#include "syscall.h" #include "syscall.h"
#include "atomic.h" #include "atomic.h"
#include "pthread_impl.h" #include "pthread_impl.h"
#include "aio_impl.h"
#define malloc __libc_malloc
#define calloc __libc_calloc
#define realloc __libc_realloc
#define free __libc_free
/* The following is a threads-based implementation of AIO with minimal /* The following is a threads-based implementation of AIO with minimal
* dependence on implementation details. Most synchronization is * dependence on implementation details. Most synchronization is
...@@ -71,6 +77,9 @@ static struct aio_queue *****map; ...@@ -71,6 +77,9 @@ static struct aio_queue *****map;
static volatile int aio_fd_cnt; static volatile int aio_fd_cnt;
volatile int __aio_fut; volatile int __aio_fut;
static size_t io_thread_stack_size;
#define MAX(a,b) ((a)>(b) ? (a) : (b))
static struct aio_queue *__aio_get_queue(int fd, int need) static struct aio_queue *__aio_get_queue(int fd, int need)
{ {
if (fd < 0) { if (fd < 0) {
...@@ -85,6 +94,10 @@ static struct aio_queue *__aio_get_queue(int fd, int need) ...@@ -85,6 +94,10 @@ static struct aio_queue *__aio_get_queue(int fd, int need)
pthread_rwlock_unlock(&maplock); pthread_rwlock_unlock(&maplock);
if (fcntl(fd, F_GETFD) < 0) return 0; if (fcntl(fd, F_GETFD) < 0) return 0;
pthread_rwlock_wrlock(&maplock); pthread_rwlock_wrlock(&maplock);
if (!io_thread_stack_size) {
unsigned long val = __getauxval(AT_MINSIGSTKSZ);
io_thread_stack_size = MAX(MINSIGSTKSZ+2048, val+512);
}
if (!map) map = calloc(sizeof *map, (-1U/2+1)>>24); if (!map) map = calloc(sizeof *map, (-1U/2+1)>>24);
if (!map) goto out; if (!map) goto out;
if (!map[a]) map[a] = calloc(sizeof **map, 256); if (!map[a]) map[a] = calloc(sizeof **map, 256);
...@@ -254,21 +267,12 @@ static void *io_thread_func(void *ctx) ...@@ -254,21 +267,12 @@ static void *io_thread_func(void *ctx)
} }
at.ret = ret; at.ret = ret;
at.err = ret<0 ? errno : 0; at.err = ret<0 ? errno : 0;
pthread_cleanup_pop(1); pthread_cleanup_pop(1);
return 0; return 0;
} }
static size_t io_thread_stack_size = MINSIGSTKSZ+2048;
static pthread_once_t init_stack_size_once;
static void init_stack_size()
{
unsigned long val = __getauxval(AT_MINSIGSTKSZ);
if (val > MINSIGSTKSZ) io_thread_stack_size = val + 512;
}
static int submit(struct aiocb *cb, int op) static int submit(struct aiocb *cb, int op)
{ {
int ret = 0; int ret = 0;
...@@ -294,7 +298,6 @@ static int submit(struct aiocb *cb, int op) ...@@ -294,7 +298,6 @@ static int submit(struct aiocb *cb, int op)
else else
pthread_attr_init(&a); pthread_attr_init(&a);
} else { } else {
pthread_once(&init_stack_size_once, init_stack_size);
pthread_attr_init(&a); pthread_attr_init(&a);
pthread_attr_setstacksize(&a, io_thread_stack_size); pthread_attr_setstacksize(&a, io_thread_stack_size);
pthread_attr_setguardsize(&a, 0); pthread_attr_setguardsize(&a, 0);
...@@ -399,6 +402,20 @@ int __aio_close(int fd) ...@@ -399,6 +402,20 @@ int __aio_close(int fd)
return fd; return fd;
} }
void __aio_atfork(int who)
{
if (who<0) {
pthread_rwlock_rdlock(&maplock);
return;
}
if (who>0 && map) for (int a=0; a<(-1U/2+1)>>24; a++)
if (map[a]) for (int b=0; b<256; b++)
if (map[a][b]) for (int c=0; c<256; c++)
if (map[a][b][c]) for (int d=0; d<256; d++)
map[a][b][c][d] = 0;
pthread_rwlock_unlock(&maplock);
}
weak_alias(aio_cancel, aio_cancel64); weak_alias(aio_cancel, aio_cancel64);
weak_alias(aio_error, aio_error64); weak_alias(aio_error, aio_error64);
weak_alias(aio_fsync, aio_fsync64); weak_alias(aio_fsync, aio_fsync64);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <unsupported_api.h> #include <unsupported_api.h>
#include "atomic.h" #include "atomic.h"
#include "pthread_impl.h" #include "pthread_impl.h"
#include "aio_impl.h"
int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts) int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts)
{ {
......
...@@ -36,7 +36,6 @@ int __init_tp(void *p) ...@@ -36,7 +36,6 @@ int __init_tp(void *p)
int r = __set_thread_area(TP_ADJ(p)); int r = __set_thread_area(TP_ADJ(p));
if (r < 0) return -1; if (r < 0) return -1;
if (!r) libc.can_do_threads = 1; if (!r) libc.can_do_threads = 1;
libc.threads_minus_1 = 1;
libc.threaded = 0; libc.threaded = 0;
td->self = td; td->self = td;
td->detach_state = DT_JOINABLE; td->detach_state = DT_JOINABLE;
...@@ -100,7 +99,7 @@ void *__copy_tls(unsigned char *mem) ...@@ -100,7 +99,7 @@ void *__copy_tls(unsigned char *mem)
} }
#endif #endif
dtv[0] = libc.tls_cnt; dtv[0] = libc.tls_cnt;
td->dtv = td->dtv_copy = dtv; td->dtv = dtv;
return td; return td;
} }
......
...@@ -69,7 +69,8 @@ weak_alias(libc_start_init, __libc_start_init); ...@@ -69,7 +69,8 @@ weak_alias(libc_start_init, __libc_start_init);
typedef int lsm2_fn(int (*)(int,char **,char **), int, char **); typedef int lsm2_fn(int (*)(int,char **,char **), int, char **);
static lsm2_fn libc_start_main_stage2; static lsm2_fn libc_start_main_stage2;
int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv) int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv,
void (*init_dummy)(), void(*fini_dummy)(), void(*ldso_dummy)())
{ {
char **envp = argv+argc+1; char **envp = argv+argc+1;
......
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#include "lock.h" #include "lock.h"
#include "ksigaction.h" #include "ksigaction.h"
hidden volatile int __abort_lock[1];
_Noreturn void abort(void) _Noreturn void abort(void)
{ {
sigset_t set, pending; sigset_t set, pending;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "libc.h" #include "libc.h"
#include <bits/errno.h> #include <bits/errno.h>
pthread_mutex_t __exit_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t __exit_mutex = PTHREAD_MUTEX_INITIALIZER;
static void dummy() static void dummy()
{ {
......
...@@ -18,10 +18,11 @@ struct tls_module { ...@@ -18,10 +18,11 @@ struct tls_module {
}; };
struct __libc { struct __libc {
int can_do_threads; char can_do_threads;
int threaded; char threaded;
int secure; char secure;
volatile int threads_minus_1; volatile signed char need_locks;
int threads_minus_1;
size_t *auxv; size_t *auxv;
struct tls_module *tls_head; struct tls_module *tls_head;
size_t tls_size, tls_align, tls_cnt; size_t tls_size, tls_align, tls_cnt;
......
...@@ -11,16 +11,25 @@ ...@@ -11,16 +11,25 @@
#include "atomic.h" #include "atomic.h"
#include "futex.h" #include "futex.h"
#include "pthread_arch.h"
#define pthread __pthread #define pthread __pthread
struct pthread { struct pthread {
/* Part 1 -- these fields may be external or /* Part 1 -- these fields may be external or
* internal (accessed via asm) ABI. Do not change. */ * internal (accessed via asm) ABI. Do not change. */
struct pthread *self; struct pthread *self;
#ifndef TLS_ABOVE_TP
uintptr_t *dtv; uintptr_t *dtv;
#endif
struct pthread *prev, *next; /* non-ABI */ struct pthread *prev, *next; /* non-ABI */
uintptr_t sysinfo; uintptr_t sysinfo;
uintptr_t canary, canary2; #ifndef TLS_ABOVE_TP
#ifdef CANARY_PAD
uintptr_t canary_pad;
#endif
uintptr_t canary;
#endif
/* Part 2 -- implementation details, non-ABI. */ /* Part 2 -- implementation details, non-ABI. */
int tid; int tid;
...@@ -43,6 +52,7 @@ struct pthread { ...@@ -43,6 +52,7 @@ struct pthread {
long off; long off;
volatile void *volatile pending; volatile void *volatile pending;
} robust_list; } robust_list;
int h_errno_val;
volatile int timer_id; volatile int timer_id;
locale_t locale; locale_t locale;
volatile int killlock[1]; volatile int killlock[1];
...@@ -51,21 +61,19 @@ struct pthread { ...@@ -51,21 +61,19 @@ struct pthread {
/* Part 3 -- the positions of these fields relative to /* Part 3 -- the positions of these fields relative to
* the end of the structure is external and internal ABI. */ * the end of the structure is external and internal ABI. */
uintptr_t canary_at_end; #ifdef TLS_ABOVE_TP
uintptr_t *dtv_copy; uintptr_t canary;
uintptr_t *dtv;
#endif
}; };
enum { enum {
DT_EXITING = 0, DT_EXITED = 0,
DT_EXITING,
DT_JOINABLE, DT_JOINABLE,
DT_DETACHED, DT_DETACHED,
}; };
struct __timer {
int timerid;
pthread_t thread;
};
#define __SU (sizeof(size_t)/sizeof(int)) #define __SU (sizeof(size_t)/sizeof(int))
#define _a_stacksize __u.__s[0] #define _a_stacksize __u.__s[0]
...@@ -98,16 +106,20 @@ struct __timer { ...@@ -98,16 +106,20 @@ struct __timer {
#define _b_waiters2 __u.__vi[4] #define _b_waiters2 __u.__vi[4]
#define _b_inst __u.__p[3] #define _b_inst __u.__p[3]
#include "pthread_arch.h" #ifndef TP_OFFSET
#define TP_OFFSET 0
#ifndef CANARY
#define CANARY canary
#endif #endif
#ifndef DTP_OFFSET #ifndef DTP_OFFSET
#define DTP_OFFSET 0 #define DTP_OFFSET 0
#endif #endif
#ifdef TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + TP_OFFSET)
#else
#define TP_ADJ(p) (p)
#endif
#ifndef tls_mod_off_t #ifndef tls_mod_off_t
#define tls_mod_off_t size_t #define tls_mod_off_t size_t
#endif #endif
...@@ -141,7 +153,6 @@ hidden int __pthread_key_delete_impl(pthread_key_t); ...@@ -141,7 +153,6 @@ hidden int __pthread_key_delete_impl(pthread_key_t);
extern hidden volatile size_t __pthread_tsd_size; extern hidden volatile size_t __pthread_tsd_size;
extern hidden void *__pthread_tsd_main[]; extern hidden void *__pthread_tsd_main[];
extern hidden volatile int __aio_fut;
extern hidden volatile int __eintr_valid_flag; extern hidden volatile int __eintr_valid_flag;
hidden int __clone(int (*)(void *), void *, int, void *, ...); hidden int __clone(int (*)(void *), void *, int, void *, ...);
...@@ -177,6 +188,8 @@ hidden void __tl_sync(pthread_t); ...@@ -177,6 +188,8 @@ hidden void __tl_sync(pthread_t);
extern hidden volatile int __thread_list_lock; extern hidden volatile int __thread_list_lock;
extern hidden volatile int __abort_lock[1];
extern hidden unsigned __default_stacksize; extern hidden unsigned __default_stacksize;
extern hidden unsigned __default_guardsize; extern hidden unsigned __default_guardsize;
......
...@@ -11,6 +11,14 @@ ...@@ -11,6 +11,14 @@
int msgctl(int q, int cmd, struct msqid_ds *buf) int msgctl(int q, int cmd, struct msqid_ds *buf)
{ {
#if IPC_TIME64
struct msqid_ds out, *orig;
if (cmd&IPC_TIME64) {
out = (struct msqid_ds){0};
orig = buf;
buf = &out;
}
#endif
unsupported_api(__FUNCTION__); unsupported_api(__FUNCTION__);
#ifdef SYSCALL_IPC_BROKEN_MODE #ifdef SYSCALL_IPC_BROKEN_MODE
struct msqid_ds tmp; struct msqid_ds tmp;
...@@ -35,6 +43,8 @@ int msgctl(int q, int cmd, struct msqid_ds *buf) ...@@ -35,6 +43,8 @@ int msgctl(int q, int cmd, struct msqid_ds *buf)
#endif #endif
#if IPC_TIME64 #if IPC_TIME64
if (r >= 0 && (cmd&IPC_TIME64)) { if (r >= 0 && (cmd&IPC_TIME64)) {
buf = orig;
*buf = out;
IPC_HILO(buf, msg_stime); IPC_HILO(buf, msg_stime);
IPC_HILO(buf, msg_rtime); IPC_HILO(buf, msg_rtime);
IPC_HILO(buf, msg_ctime); IPC_HILO(buf, msg_ctime);
......
...@@ -31,6 +31,14 @@ int semctl(int id, int num, int cmd, ...) ...@@ -31,6 +31,14 @@ int semctl(int id, int num, int cmd, ...)
arg = va_arg(ap, union semun); arg = va_arg(ap, union semun);
va_end(ap); va_end(ap);
} }
#if IPC_TIME64
struct semid_ds out, *orig;
if (cmd&IPC_TIME64) {
out = (struct semid_ds){0};
orig = arg.buf;
arg.buf = &out;
}
#endif
#ifdef SYSCALL_IPC_BROKEN_MODE #ifdef SYSCALL_IPC_BROKEN_MODE
struct semid_ds tmp; struct semid_ds tmp;
if (cmd == IPC_SET) { if (cmd == IPC_SET) {
...@@ -54,6 +62,8 @@ int semctl(int id, int num, int cmd, ...) ...@@ -54,6 +62,8 @@ int semctl(int id, int num, int cmd, ...)
#endif #endif
#if IPC_TIME64 #if IPC_TIME64
if (r >= 0 && (cmd&IPC_TIME64)) { if (r >= 0 && (cmd&IPC_TIME64)) {
arg.buf = orig;
*arg.buf = out;
IPC_HILO(arg.buf, sem_otime); IPC_HILO(arg.buf, sem_otime);
IPC_HILO(arg.buf, sem_ctime); IPC_HILO(arg.buf, sem_ctime);
} }
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
#include <unsupported_api.h> #include <unsupported_api.h>
#include "locale_impl.h" #include "locale_impl.h"
#define malloc undef
#define calloc undef
#define realloc undef
#define free __libc_free
void freelocale(locale_t l) void freelocale(locale_t l)
{ {
unsupported_api(__FUNCTION__); unsupported_api(__FUNCTION__);
......
...@@ -9,6 +9,11 @@ ...@@ -9,6 +9,11 @@
#include "atomic.h" #include "atomic.h"
#include "pthread_impl.h" #include "pthread_impl.h"
#include "malloc_impl.h" #include "malloc_impl.h"
#include "fork_impl.h"
#define malloc __libc_malloc_impl
#define realloc __libc_realloc
#define free __libc_free
#if defined(__GNUC__) && defined(__PIC__) #if defined(__GNUC__) && defined(__PIC__)
#define inline inline __attribute__((always_inline)) #define inline inline __attribute__((always_inline))
...@@ -17,17 +22,18 @@ ...@@ -17,17 +22,18 @@
static struct { static struct {
volatile uint64_t binmap; volatile uint64_t binmap;
struct bin bins[64]; struct bin bins[64];
volatile int free_lock[2]; volatile int split_merge_lock[2];
} mal; } mal;
int __malloc_replaced;
/* Synchronization tools */ /* Synchronization tools */
static inline void lock(volatile int *lk) static inline void lock(volatile int *lk)
{ {
if (libc.threads_minus_1) int need_locks = libc.need_locks;
if (need_locks) {
while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1); while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1);
if (need_locks < 0) libc.need_locks = 0;
}
} }
static inline void unlock(volatile int *lk) static inline void unlock(volatile int *lk)
...@@ -123,9 +129,72 @@ void __dump_heap(int x) ...@@ -123,9 +129,72 @@ void __dump_heap(int x)
} }
#endif #endif
/* This function returns true if the interval [old,new]
* intersects the 'len'-sized interval below &libc.auxv
* (interpreted as the main-thread stack) or below &b
* (the current stack). It is used to defend against
* buggy brk implementations that can cross the stack. */
static int traverses_stack_p(uintptr_t old, uintptr_t new)
{
const uintptr_t len = 8<<20;
uintptr_t a, b;
b = (uintptr_t)libc.auxv;
a = b > len ? b-len : 0;
if (new>a && old<b) return 1;
b = (uintptr_t)&b;
a = b > len ? b-len : 0;
if (new>a && old<b) return 1;
return 0;
}
/* Expand the heap in-place if brk can be used, or otherwise via mmap,
* using an exponential lower bound on growth by mmap to make
* fragmentation asymptotically irrelevant. The size argument is both
* an input and an output, since the caller needs to know the size
* allocated, which will be larger than requested due to page alignment
* and mmap minimum size rules. The caller is responsible for locking
* to prevent concurrent calls. */
static void *__expand_heap(size_t *pn)
{
static uintptr_t brk;
static unsigned mmap_step;
size_t n = *pn;
if (n > SIZE_MAX/2 - PAGE_SIZE) {
errno = ENOMEM;
return 0;
}
n += -n & PAGE_SIZE-1;
if (!brk) {
brk = __syscall(SYS_brk, 0);
brk += -brk & PAGE_SIZE-1;
}
if (n < SIZE_MAX-brk && !traverses_stack_p(brk, brk+n)
&& __syscall(SYS_brk, brk+n)==brk+n) {
*pn = n;
brk += n;
return (void *)(brk-n);
}
size_t min = (size_t)PAGE_SIZE << mmap_step/2;
if (n < min) n = min;
void *area = __mmap(0, n, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (area == MAP_FAILED) return 0;
*pn = n;
mmap_step++;
return area;
}
static struct chunk *expand_heap(size_t n) static struct chunk *expand_heap(size_t n)
{ {
static int heap_lock[2];
static void *end; static void *end;
void *p; void *p;
struct chunk *w; struct chunk *w;
...@@ -135,13 +204,8 @@ static struct chunk *expand_heap(size_t n) ...@@ -135,13 +204,8 @@ static struct chunk *expand_heap(size_t n)
* we need room for an extra zero-sized sentinel chunk. */ * we need room for an extra zero-sized sentinel chunk. */
n += SIZE_ALIGN; n += SIZE_ALIGN;
lock(heap_lock);
p = __expand_heap(&n); p = __expand_heap(&n);
if (!p) { if (!p) return 0;
unlock(heap_lock);
return 0;
}
/* If not just expanding existing space, we need to make a /* If not just expanding existing space, we need to make a
* new sentinel chunk below the allocated space. */ * new sentinel chunk below the allocated space. */
...@@ -164,8 +228,6 @@ static struct chunk *expand_heap(size_t n) ...@@ -164,8 +228,6 @@ static struct chunk *expand_heap(size_t n)
w = MEM_TO_CHUNK(p); w = MEM_TO_CHUNK(p);
w->csize = n | C_INUSE; w->csize = n | C_INUSE;
unlock(heap_lock);
return w; return w;
} }
...@@ -195,96 +257,44 @@ static void unbin(struct chunk *c, int i) ...@@ -195,96 +257,44 @@ static void unbin(struct chunk *c, int i)
NEXT_CHUNK(c)->psize |= C_INUSE; NEXT_CHUNK(c)->psize |= C_INUSE;
} }
static int alloc_fwd(struct chunk *c) static void bin_chunk(struct chunk *self, int i)
{ {
int i; self->next = BIN_TO_CHUNK(i);
size_t k; self->prev = mal.bins[i].tail;
while (!((k=c->csize) & C_INUSE)) { self->next->prev = self;
i = bin_index(k); self->prev->next = self;
lock_bin(i); if (self->prev == BIN_TO_CHUNK(i))
if (c->csize == k) { a_or_64(&mal.binmap, 1ULL<<i);
unbin(c, i);
unlock_bin(i);
return 1;
}
unlock_bin(i);
}
return 0;
}
static int alloc_rev(struct chunk *c)
{
int i;
size_t k;
while (!((k=c->psize) & C_INUSE)) {
i = bin_index(k);
lock_bin(i);
if (c->psize == k) {
unbin(PREV_CHUNK(c), i);
unlock_bin(i);
return 1;
}
unlock_bin(i);
}
return 0;
} }
static void trim(struct chunk *self, size_t n)
/* pretrim - trims a chunk _prior_ to removing it from its bin.
* Must be called with i as the ideal bin for size n, j the bin
* for the _free_ chunk self, and bin j locked. */
static int pretrim(struct chunk *self, size_t n, int i, int j)
{ {
size_t n1; size_t n1 = CHUNK_SIZE(self);
struct chunk *next, *split; struct chunk *next, *split;
/* We cannot pretrim if it would require re-binning. */ if (n >= n1 - DONTCARE) return;
if (j < 40) return 0;
if (j < i+3) {
if (j != 63) return 0;
n1 = CHUNK_SIZE(self);
if (n1-n <= MMAP_THRESHOLD) return 0;
} else {
n1 = CHUNK_SIZE(self);
}
if (bin_index(n1-n) != j) return 0;
next = NEXT_CHUNK(self); next = NEXT_CHUNK(self);
split = (void *)((char *)self + n); split = (void *)((char *)self + n);
split->prev = self->prev;
split->next = self->next;
split->prev->next = split;
split->next->prev = split;
split->psize = n | C_INUSE; split->psize = n | C_INUSE;
split->csize = n1-n; split->csize = n1-n;
next->psize = n1-n; next->psize = n1-n;
self->csize = n | C_INUSE; self->csize = n | C_INUSE;
return 1;
}
static void trim(struct chunk *self, size_t n) int i = bin_index(n1-n);
{ lock_bin(i);
size_t n1 = CHUNK_SIZE(self);
struct chunk *next, *split;
if (n >= n1 - DONTCARE) return; bin_chunk(split, i);
next = NEXT_CHUNK(self); unlock_bin(i);
split = (void *)((char *)self + n);
split->psize = n | C_INUSE;
split->csize = n1-n | C_INUSE;
next->psize = n1-n | C_INUSE;
self->csize = n | C_INUSE;
__bin_chunk(split);
} }
void *malloc(size_t n) void *malloc(size_t n)
{ {
struct chunk *c; struct chunk *c;
int i, j; int i, j;
uint64_t mask;
if (adjust_size(&n) < 0) return 0; if (adjust_size(&n) < 0) return 0;
...@@ -300,70 +310,43 @@ void *malloc(size_t n) ...@@ -300,70 +310,43 @@ void *malloc(size_t n)
} }
i = bin_index_up(n); i = bin_index_up(n);
for (;;) { if (i<63 && (mal.binmap & (1ULL<<i))) {
uint64_t mask = mal.binmap & -(1ULL<<i); lock_bin(i);
if (!mask) { c = mal.bins[i].head;
c = expand_heap(n); if (c != BIN_TO_CHUNK(i) && CHUNK_SIZE(c)-n <= DONTCARE) {
if (!c) return 0; unbin(c, i);
if (alloc_rev(c)) { unlock_bin(i);
struct chunk *x = c; return CHUNK_TO_MEM(c);
c = PREV_CHUNK(c);
NEXT_CHUNK(x)->psize = c->csize =
x->csize + CHUNK_SIZE(c);
}
break;
} }
unlock_bin(i);
}
lock(mal.split_merge_lock);
for (mask = mal.binmap & -(1ULL<<i); mask; mask -= (mask&-mask)) {
j = first_set(mask); j = first_set(mask);
lock_bin(j); lock_bin(j);
c = mal.bins[j].head; c = mal.bins[j].head;
if (c != BIN_TO_CHUNK(j)) { if (c != BIN_TO_CHUNK(j)) {
if (!pretrim(c, n, i, j)) unbin(c, j); unbin(c, j);
unlock_bin(j); unlock_bin(j);
break; break;
} }
unlock_bin(j); unlock_bin(j);
} }
if (!mask) {
/* Now patch up in case we over-allocated */ c = expand_heap(n);
if (!c) {
unlock(mal.split_merge_lock);
return 0;
}
}
trim(c, n); trim(c, n);
unlock(mal.split_merge_lock);
return CHUNK_TO_MEM(c); return CHUNK_TO_MEM(c);
} }
static size_t mal0_clear(char *p, size_t pagesz, size_t n) int __malloc_allzerop(void *p)
{ {
#ifdef __GNUC__ return IS_MMAPPED(MEM_TO_CHUNK(p));
typedef uint64_t __attribute__((__may_alias__)) T;
#else
typedef unsigned char T;
#endif
char *pp = p + n;
size_t i = (uintptr_t)pp & (pagesz - 1);
for (;;) {
pp = memset(pp - i, 0, i);
if (pp - p < pagesz) return pp - p;
for (i = pagesz; i; i -= 2*sizeof(T), pp -= 2*sizeof(T))
if (((T *)pp)[-1] | ((T *)pp)[-2])
break;
}
}
void *calloc(size_t m, size_t n)
{
if (n && m > (size_t)-1/n) {
errno = ENOMEM;
return 0;
}
n *= m;
void *p = malloc(n);
if (!p) return p;
if (!__malloc_replaced) {
if (IS_MMAPPED(MEM_TO_CHUNK(p)))
return p;
if (n >= PAGE_SIZE)
n = mal0_clear(p, PAGE_SIZE, n);
}
return memset(p, 0, n);
} }
void *realloc(void *p, size_t n) void *realloc(void *p, size_t n)
...@@ -379,6 +362,8 @@ void *realloc(void *p, size_t n) ...@@ -379,6 +362,8 @@ void *realloc(void *p, size_t n)
self = MEM_TO_CHUNK(p); self = MEM_TO_CHUNK(p);
n1 = n0 = CHUNK_SIZE(self); n1 = n0 = CHUNK_SIZE(self);
if (n<=n0 && n0-n<=DONTCARE) return p;
if (IS_MMAPPED(self)) { if (IS_MMAPPED(self)) {
size_t extra = self->psize; size_t extra = self->psize;
char *base = (char *)self - extra; char *base = (char *)self - extra;
...@@ -405,34 +390,43 @@ void *realloc(void *p, size_t n) ...@@ -405,34 +390,43 @@ void *realloc(void *p, size_t n)
/* Crash on corrupted footer (likely from buffer overflow) */ /* Crash on corrupted footer (likely from buffer overflow) */
if (next->psize != self->csize) a_crash(); if (next->psize != self->csize) a_crash();
/* Merge adjacent chunks if we need more space. This is not if (n < n0) {
* a waste of time even if we fail to get enough space, because our int i = bin_index_up(n);
* subsequent call to free would otherwise have to do the merge. */ int j = bin_index(n0);
if (n > n1 && alloc_fwd(next)) { if (i<j && (mal.binmap & (1ULL << i)))
n1 += CHUNK_SIZE(next); goto copy_realloc;
next = NEXT_CHUNK(next); struct chunk *split = (void *)((char *)self + n);
} self->csize = split->psize = n | C_INUSE;
/* FIXME: find what's wrong here and reenable it..? */ split->csize = next->psize = n0-n | C_INUSE;
if (0 && n > n1 && alloc_rev(self)) { __bin_chunk(split);
self = PREV_CHUNK(self); return CHUNK_TO_MEM(self);
n1 += CHUNK_SIZE(self);
} }
self->csize = n1 | C_INUSE;
next->psize = n1 | C_INUSE;
/* If we got enough space, split off the excess and return */ lock(mal.split_merge_lock);
if (n <= n1) {
//memmove(CHUNK_TO_MEM(self), p, n0-OVERHEAD); size_t nsize = next->csize & C_INUSE ? 0 : CHUNK_SIZE(next);
trim(self, n); if (n0+nsize >= n) {
return CHUNK_TO_MEM(self); int i = bin_index(nsize);
lock_bin(i);
if (!(next->csize & C_INUSE)) {
unbin(next, i);
unlock_bin(i);
next = NEXT_CHUNK(next);
self->csize = next->psize = n0+nsize | C_INUSE;
trim(self, n);
unlock(mal.split_merge_lock);
return CHUNK_TO_MEM(self);
}
unlock_bin(i);
} }
unlock(mal.split_merge_lock);
copy_realloc: copy_realloc:
/* As a last resort, allocate a new chunk and copy to it. */ /* As a last resort, allocate a new chunk and copy to it. */
new = malloc(n-OVERHEAD); new = malloc(n-OVERHEAD);
if (!new) return 0; if (!new) return 0;
copy_free_ret: copy_free_ret:
memcpy(new, p, n0-OVERHEAD); memcpy(new, p, (n<n0 ? n : n0) - OVERHEAD);
free(CHUNK_TO_MEM(self)); free(CHUNK_TO_MEM(self));
return new; return new;
} }
...@@ -440,67 +434,61 @@ copy_free_ret: ...@@ -440,67 +434,61 @@ copy_free_ret:
void __bin_chunk(struct chunk *self) void __bin_chunk(struct chunk *self)
{ {
struct chunk *next = NEXT_CHUNK(self); struct chunk *next = NEXT_CHUNK(self);
size_t final_size, new_size, size;
int reclaim=0;
int i;
final_size = new_size = CHUNK_SIZE(self);
/* Crash on corrupted footer (likely from buffer overflow) */ /* Crash on corrupted footer (likely from buffer overflow) */
if (next->psize != self->csize) a_crash(); if (next->psize != self->csize) a_crash();
for (;;) { lock(mal.split_merge_lock);
if (self->psize & next->csize & C_INUSE) {
self->csize = final_size | C_INUSE;
next->psize = final_size | C_INUSE;
i = bin_index(final_size);
lock_bin(i);
lock(mal.free_lock);
if (self->psize & next->csize & C_INUSE)
break;
unlock(mal.free_lock);
unlock_bin(i);
}
if (alloc_rev(self)) { size_t osize = CHUNK_SIZE(self), size = osize;
self = PREV_CHUNK(self);
size = CHUNK_SIZE(self); /* Since we hold split_merge_lock, only transition from free to
final_size += size; * in-use can race; in-use to free is impossible */
if (new_size+size > RECLAIM && (new_size+size^size) > size) size_t psize = self->psize & C_INUSE ? 0 : CHUNK_PSIZE(self);
reclaim = 1; size_t nsize = next->csize & C_INUSE ? 0 : CHUNK_SIZE(next);
}
if (alloc_fwd(next)) { if (psize) {
size = CHUNK_SIZE(next); int i = bin_index(psize);
final_size += size; lock_bin(i);
if (new_size+size > RECLAIM && (new_size+size^size) > size) if (!(self->psize & C_INUSE)) {
reclaim = 1; struct chunk *prev = PREV_CHUNK(self);
unbin(prev, i);
self = prev;
size += psize;
}
unlock_bin(i);
}
if (nsize) {
int i = bin_index(nsize);
lock_bin(i);
if (!(next->csize & C_INUSE)) {
unbin(next, i);
next = NEXT_CHUNK(next); next = NEXT_CHUNK(next);
size += nsize;
} }
unlock_bin(i);
} }
if (!(mal.binmap & 1ULL<<i)) int i = bin_index(size);
a_or_64(&mal.binmap, 1ULL<<i); lock_bin(i);
self->csize = final_size; self->csize = size;
next->psize = final_size; next->psize = size;
unlock(mal.free_lock); bin_chunk(self, i);
unlock(mal.split_merge_lock);
self->next = BIN_TO_CHUNK(i);
self->prev = mal.bins[i].tail;
self->next->prev = self;
self->prev->next = self;
/* Replace middle of large chunks with fresh zero pages */ /* Replace middle of large chunks with fresh zero pages */
if (reclaim) { if (size > RECLAIM && (size^(size-osize)) > size-osize) {
uintptr_t a = (uintptr_t)self + SIZE_ALIGN+PAGE_SIZE-1 & -PAGE_SIZE; uintptr_t a = (uintptr_t)self + SIZE_ALIGN+PAGE_SIZE-1 & -PAGE_SIZE;
uintptr_t b = (uintptr_t)next - SIZE_ALIGN & -PAGE_SIZE; uintptr_t b = (uintptr_t)next - SIZE_ALIGN & -PAGE_SIZE;
int e = errno;
#if 0 #if 0
__madvise((void *)a, b-a, MADV_DONTNEED); __madvise((void *)a, b-a, MADV_DONTNEED);
#else #else
__mmap((void *)a, b-a, PROT_READ|PROT_WRITE, __mmap((void *)a, b-a, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0); MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
#endif #endif
errno = e;
} }
unlock_bin(i); unlock_bin(i);
...@@ -513,7 +501,9 @@ static void unmap_chunk(struct chunk *self) ...@@ -513,7 +501,9 @@ static void unmap_chunk(struct chunk *self)
size_t len = CHUNK_SIZE(self) + extra; size_t len = CHUNK_SIZE(self) + extra;
/* Crash on double free */ /* Crash on double free */
if (extra & 1) a_crash(); if (extra & 1) a_crash();
int e = errno;
__munmap(base, len); __munmap(base, len);
errno = e;
} }
void free(void *p) void free(void *p)
...@@ -546,3 +536,21 @@ void __malloc_donate(char *start, char *end) ...@@ -546,3 +536,21 @@ void __malloc_donate(char *start, char *end)
c->csize = n->psize = C_INUSE | (end-start); c->csize = n->psize = C_INUSE | (end-start);
__bin_chunk(c); __bin_chunk(c);
} }
void __malloc_atfork(int who)
{
if (who<0) {
lock(mal.split_merge_lock);
for (int i=0; i<64; i++)
lock(mal.bins[i].lock);
} else if (!who) {
for (int i=0; i<64; i++)
unlock(mal.bins[i].lock);
unlock(mal.split_merge_lock);
} else {
for (int i=0; i<64; i++)
mal.bins[i].lock[0] = mal.bins[i].lock[1] = 0;
mal.split_merge_lock[1] = 0;
mal.split_merge_lock[0] = 0;
}
}
#include <ftw.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <pthread.h>
struct history
{
struct history *chain;
dev_t dev;
ino_t ino;
int level;
int base;
};
#undef dirfd
#define dirfd(d) (*(int *)d)
static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags, struct history *h)
{
size_t l = strlen(path), j = l && path[l-1]=='/' ? l-1 : l;
struct stat st;
struct history new;
int type;
int r;
struct FTW lev;
if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
type = FTW_SLN;
else if (errno != EACCES) return -1;
else type = FTW_NS;
} else if (S_ISDIR(st.st_mode)) {
if (access(path, R_OK) < 0) type = FTW_DNR;
else if (flags & FTW_DEPTH) type = FTW_DP;
else type = FTW_D;
} else if (S_ISLNK(st.st_mode)) {
if (flags & FTW_PHYS) type = FTW_SL;
else type = FTW_SLN;
} else {
type = FTW_F;
}
if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev)
return 0;
new.chain = h;
new.dev = st.st_dev;
new.ino = st.st_ino;
new.level = h ? h->level+1 : 0;
new.base = j+1;
lev.level = new.level;
if (h) {
lev.base = h->base;
} else {
size_t k;
for (k=j; k && path[k]=='/'; k--);
for (; k && path[k-1]!='/'; k--);
lev.base = k;
}
if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
return r;
for (; h; h = h->chain)
if (h->dev == st.st_dev && h->ino == st.st_ino)
return 0;
if ((type == FTW_D || type == FTW_DP) && fd_limit) {
DIR *d = opendir(path);
if (d) {
struct dirent *de;
while ((de = readdir(d))) {
if (de->d_name[0] == '.'
&& (!de->d_name[1]
|| (de->d_name[1]=='.'
&& !de->d_name[2]))) continue;
if (strlen(de->d_name) >= PATH_MAX-l) {
errno = ENAMETOOLONG;
closedir(d);
return -1;
}
path[j]='/';
strcpy(path+j+1, de->d_name);
if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) {
closedir(d);
return r;
}
}
closedir(d);
} else if (errno != EACCES) {
return -1;
}
}
path[l] = 0;
if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
return r;
return 0;
}
int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags)
{
int r, cs;
size_t l;
char pathbuf[PATH_MAX+1];
if (fd_limit <= 0) return 0;
l = strlen(path);
if (l > PATH_MAX) {
errno = ENAMETOOLONG;
return -1;
}
memcpy(pathbuf, path, l+1);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
r = do_nftw(pathbuf, fn, fd_limit, flags, NULL);
pthread_setcancelstate(cs, 0);
return r;
}
weak_alias(nftw, nftw64);
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <unsupported_api.h> #include <unsupported_api.h>
#include "lock.h" #include "lock.h"
#include "fork_impl.h"
static volatile int lock[1]; static volatile int lock[1];
static char log_ident[32]; static char log_ident[32];
...@@ -18,6 +19,7 @@ static int log_opt; ...@@ -18,6 +19,7 @@ static int log_opt;
static int log_facility = LOG_USER; static int log_facility = LOG_USER;
static int log_mask = 0xff; static int log_mask = 0xff;
static int log_fd = -1; static int log_fd = -1;
volatile int *const __syslog_lockptr = lock;
int setlogmask(int maskpri) int setlogmask(int maskpri)
{ {
......
...@@ -115,7 +115,7 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags) ...@@ -115,7 +115,7 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags)
_exit(1); _exit(1);
} }
close(p[1]); close(p[1]);
f = fdopen(p[0], "r"); f = fdopen(p[0], "r");
if (!f) { if (!f) {
close(p[0]); close(p[0]);
......
...@@ -70,7 +70,7 @@ static void reverse_hosts(char *buf, const unsigned char *a, unsigned scopeid, i ...@@ -70,7 +70,7 @@ static void reverse_hosts(char *buf, const unsigned char *a, unsigned scopeid, i
if (memcmp(a, iplit.addr, 16) || iplit.scopeid != scopeid) if (memcmp(a, iplit.addr, 16) || iplit.scopeid != scopeid)
continue; continue;
for (; *p && isspace(*p); p++); for (; *p && isspace(*p); p++);
for (z=p; *z && !isspace(*z); z++); for (z=p; *z && !isspace(*z); z++);
*z = 0; *z = 0;
...@@ -115,7 +115,7 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const ...@@ -115,7 +115,7 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const
data, c, 256) <= 0) data, c, 256) <= 0)
*(char *)c = 0; *(char *)c = 0;
return 0; return 0;
} }
int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
...@@ -158,6 +158,7 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl, ...@@ -158,6 +158,7 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
unsigned char query[18+PTR_MAX], reply[512]; unsigned char query[18+PTR_MAX], reply[512];
int qlen = __res_mkquery(0, ptr, 1, RR_PTR, int qlen = __res_mkquery(0, ptr, 1, RR_PTR,
0, 0, 0, query, sizeof query); 0, 0, 0, query, sizeof query);
query[3] = 0; /* don't need AD flag */
int rlen = __res_send(query, qlen, reply, sizeof reply); int rlen = __res_send(query, qlen, reply, sizeof reply);
buf[0] = 0; buf[0] = 0;
if (rlen > 0) if (rlen > 0)
......
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <dlfcn.h>
#include <stdint.h>
#include <stddef.h>
#include "syscall.h"
#if OHOS_PERMISSION_INTERNET
typedef uint8_t (*AllowFunc)(void);
static const char *LIB_NETSYS_CLIENT_NAME = "libnetsys_client.z.so";
static const char *ALLOW_SOCKET_FUNC_NAME = "IsAllowInternet";
/*
* Read a flag from netsys_client, there is only one place to set this flag, is the
* founction named DoStartup in startup_appspawn.
* */
uint8_t is_allow_internet(void)
{
static uint8_t first_time = 1;
static uint8_t allow = 1;
if (!first_time) {
return allow;
}
void *handler = dlopen(LIB_NETSYS_CLIENT_NAME, RTLD_LAZY);
if (handler != NULL) {
AllowFunc func = (AllowFunc)dlsym(handler, ALLOW_SOCKET_FUNC_NAME);
if (func != NULL && func() == 0) {
allow = 0;
}
dlclose(handler);
}
first_time = 0;
return allow;
}
#endif
int socket(int domain, int type, int protocol)
{
#if OHOS_PERMISSION_INTERNET
if ((domain == AF_INET || domain == AF_INET6) && is_allow_internet() == 0) {
errno = EPERM;
return -1;
}
#endif
int s = socketcall(socket, domain, type, protocol, 0, 0, 0);
if (s<0 && (errno==EINVAL || errno==EPROTONOSUPPORT)
&& (type&(SOCK_CLOEXEC|SOCK_NONBLOCK))) {
s = socketcall(socket, domain,
type & ~(SOCK_CLOEXEC|SOCK_NONBLOCK),
protocol, 0, 0, 0);
if (s < 0) return s;
if (type & SOCK_CLOEXEC)
__syscall(SYS_fcntl, s, F_SETFD, FD_CLOEXEC);
if (type & SOCK_NONBLOCK)
__syscall(SYS_fcntl, s, F_SETFL, O_NONBLOCK);
}
return s;
}
#include <sys/socket.h>
#include <byteswap.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include "nscd.h"
static const struct {
short sun_family;
char sun_path[21];
} addr = {
AF_UNIX,
"/var/run/nscd/socket"
};
FILE *__nscd_query(int32_t req, const char *key, int32_t *buf, size_t len, int *swap)
{
size_t i;
int fd;
FILE *f = 0;
int32_t req_buf[REQ_LEN] = {
NSCDVERSION,
req,
strnlen(key,LOGIN_NAME_MAX)+1
};
struct msghdr msg = {
.msg_iov = (struct iovec[]){
{&req_buf, sizeof(req_buf)},
{(char*)key, strlen(key)+1}
},
.msg_iovlen = 2
};
int errno_save = errno;
*swap = 0;
retry:
memset(buf, 0, len);
buf[0] = NSCDVERSION;
fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (fd < 0) return NULL;
if(!(f = fdopen(fd, "r"))) {
close(fd);
return 0;
}
if (req_buf[2] > LOGIN_NAME_MAX)
return f;
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
/* If there isn't a running nscd we simulate a "not found"
* result and the caller is responsible for calling
* fclose on the (unconnected) socket. The value of
* errno must be left unchanged in this case. */
if (errno == EACCES || errno == ECONNREFUSED || errno == ENOENT) {
errno = errno_save;
return f;
}
goto error;
}
if (sendmsg(fd, &msg, MSG_NOSIGNAL) < 0)
goto error;
if (!fread(buf, len, 1, f)) {
/* If the VERSION entry mismatches nscd will disconnect. The
* most likely cause is that the endianness mismatched. So, we
* byteswap and try once more. (if we already swapped, just
* fail out)
*/
if (ferror(f)) goto error;
if (!*swap) {
fclose(f);
for (i = 0; i < sizeof(req_buf)/sizeof(req_buf[0]); i++) {
req_buf[i] = bswap_32(req_buf[i]);
}
*swap = 1;
goto retry;
} else {
errno = EIO;
goto error;
}
}
if (*swap) {
for (i = 0; i < len/sizeof(buf[0]); i++) {
buf[i] = bswap_32(buf[i]);
}
}
/* The first entry in every nscd response is the version number. This
* really shouldn't happen, and is evidence of some form of malformed
* response.
*/
if(buf[0] != NSCDVERSION) {
errno = EIO;
goto error;
}
return f;
error:
fclose(f);
return 0;
}
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include <signal.h> #include <signal.h>
#include "syscall.h" #include "syscall.h"
#include "libc.h" #include "libc.h"
#include "lock.h"
#include "pthread_impl.h" #include "pthread_impl.h"
#include "aio_impl.h"
static void dummy(int x) static void dummy(int x) { }
{ weak_alias(dummy, __aio_atfork);
}
weak_alias(dummy, __fork_handler);
pid_t fork(void) pid_t _Fork(void)
{ {
pid_t ret; pid_t ret;
sigset_t set; sigset_t set;
__fork_handler(-1);
__block_all_sigs(&set); __block_all_sigs(&set);
__aio_atfork(-1);
LOCK(__abort_lock);
#ifdef SYS_fork #ifdef SYS_fork
ret = __syscall(SYS_fork); ret = __syscall(SYS_fork);
#else #else
...@@ -30,10 +29,12 @@ pid_t fork(void) ...@@ -30,10 +29,12 @@ pid_t fork(void)
self->next = self->prev = self; self->next = self->prev = self;
__thread_list_lock = 0; __thread_list_lock = 0;
libc.threads_minus_1 = 0; libc.threads_minus_1 = 0;
if (libc.need_locks) libc.need_locks = -1;
libc.exit = 0; libc.exit = 0;
signal(SIGSYS, arm_do_signal); signal(SIGSYS, arm_do_signal);
} }
UNLOCK(__abort_lock);
__aio_atfork(!ret);
__restore_sigs(&set); __restore_sigs(&set);
__fork_handler(!ret);
return __syscall_ret(ret); return __syscall_ret(ret);
} }
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <unsupported_api.h> #include <unsupported_api.h>
#include "syscall.h" #include "syscall.h"
#include "lock.h"
#include "pthread_impl.h" #include "pthread_impl.h"
#include "fdop.h" #include "fdop.h"
...@@ -172,8 +173,6 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, ...@@ -172,8 +173,6 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
struct args args; struct args args;
unsupported_api(__FUNCTION__); unsupported_api(__FUNCTION__);
if (pipe2(args.p, O_CLOEXEC))
return errno;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
...@@ -184,9 +183,20 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, ...@@ -184,9 +183,20 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
args.envp = envp; args.envp = envp;
pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask); pthread_sigmask(SIG_BLOCK, SIGALL_SET, &args.oldmask);
/* The lock guards both against seeing a SIGABRT disposition change
* by abort and against leaking the pipe fd to fork-without-exec. */
LOCK(__abort_lock);
if (pipe2(args.p, O_CLOEXEC)) {
UNLOCK(__abort_lock);
ec = errno;
goto fail;
}
pid = __clone(child, stack+sizeof stack, pid = __clone(child, stack+sizeof stack,
CLONE_VM|CLONE_VFORK|SIGCHLD, &args); CLONE_VM|CLONE_VFORK|SIGCHLD, &args);
close(args.p[1]); close(args.p[1]);
UNLOCK(__abort_lock);
if (pid > 0) { if (pid > 0) {
if (read(args.p[0], &ec, sizeof ec) != sizeof ec) ec = 0; if (read(args.p[0], &ec, sizeof ec) != sizeof ec) ec = 0;
...@@ -199,6 +209,7 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, ...@@ -199,6 +209,7 @@ int posix_spawn(pid_t *restrict res, const char *restrict path,
if (!ec && res) *res = pid; if (!ec && res) *res = pid;
fail:
pthread_sigmask(SIG_SETMASK, &args.oldmask, 0); pthread_sigmask(SIG_SETMASK, &args.oldmask, 0);
pthread_setcancelstate(cs, 0); pthread_setcancelstate(cs, 0);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, int fd) int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, int fd)
{ {
if (fd < 0) return EBADF;
unsupported_api(__FUNCTION__); unsupported_api(__FUNCTION__);
struct fdop *op = malloc(sizeof *op); struct fdop *op = malloc(sizeof *op);
if (!op) return ENOMEM; if (!op) return ENOMEM;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, int srcfd, int fd) int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, int srcfd, int fd)
{ {
if (srcfd < 0 || fd < 0) return EBADF;
unsupported_api(__FUNCTION__); unsupported_api(__FUNCTION__);
struct fdop *op = malloc(sizeof *op); struct fdop *op = malloc(sizeof *op);
if (!op) return ENOMEM; if (!op) return ENOMEM;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict fa, int fd, const char *restrict path, int flags, mode_t mode) int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict fa, int fd, const char *restrict path, int flags, mode_t mode)
{ {
if (fd < 0) return EBADF;
unsupported_api(__FUNCTION__); unsupported_api(__FUNCTION__);
struct fdop *op = malloc(sizeof *op + strlen(path) + 1); struct fdop *op = malloc(sizeof *op + strlen(path) + 1);
if (!op) return ENOMEM; if (!op) return ENOMEM;
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#define CHECK_BIT(bitmap, pos) ((bitmap & (1u << pos)) ? 1 : 0) #define CHECK_BIT(bitmap, pos) ((bitmap & (1u << pos)) ? 1 : 0)
#define SIG_FLAG_NOIGNORE 1 #define SIG_FLAG_NOIGNORE 1
struct sigactq { struct sigactq {
struct sigaction act; struct sigaction act;
bool ign_flag; bool ign_flag;
...@@ -26,9 +25,6 @@ struct sigactq { ...@@ -26,9 +25,6 @@ struct sigactq {
}; };
typedef struct sigactq sigactq_t; typedef struct sigactq sigactq_t;
typedef void (*sa_sighandler_t)(int); typedef void (*sa_sighandler_t)(int);
typedef struct sigaction sigaction_t; typedef struct sigaction sigaction_t;
...@@ -41,7 +37,6 @@ struct sig_default_act { ...@@ -41,7 +37,6 @@ struct sig_default_act {
sa_sighandler_t action; sa_sighandler_t action;
}; };
static void __sig_core(int signo); static void __sig_core(int signo);
static void __sig_kill(int signo); static void __sig_kill(int signo);
static void __sig_cont(int signo); static void __sig_cont(int signo);
...@@ -276,12 +271,6 @@ void __sig_init(void) ...@@ -276,12 +271,6 @@ void __sig_init(void)
__sig_add_def_action(); __sig_add_def_action();
} }
static volatile int dummy_lock[1] = { 0 };
extern hidden volatile int __abort_lock[1];
weak_alias(dummy_lock, __abort_lock);
static int unmask_done; static int unmask_done;
static unsigned long handler_set[_NSIG/(8*sizeof(long))]; static unsigned long handler_set[_NSIG/(8*sizeof(long))];
...@@ -295,7 +284,6 @@ volatile int __eintr_valid_flag; ...@@ -295,7 +284,6 @@ volatile int __eintr_valid_flag;
int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old) int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old)
{ {
sigaction_t ksa, ksa_old; sigaction_t ksa, ksa_old;
unsigned long set[_NSIG/(8*sizeof(long))];
int r = 0; int r = 0;
if (sa) { if (sa) {
...@@ -321,14 +309,6 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact ...@@ -321,14 +309,6 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact
a_store(&__eintr_valid_flag, 1); a_store(&__eintr_valid_flag, 1);
} }
} }
/* Changing the disposition of SIGABRT to anything but
* SIG_DFL requires a lock, so that it cannot be changed
* while abort is terminating the process after simply
* calling raise(SIGABRT) failed to do so. */
if (sa->sa_handler != SIG_DFL && sig == SIGABRT) {
__block_all_sigs(&set);
LOCK(__abort_lock);
}
ksa.sa_handler = sa->sa_handler; ksa.sa_handler = sa->sa_handler;
ksa.sa_flags = sa->sa_flags | SA_RESTORER; ksa.sa_flags = sa->sa_flags | SA_RESTORER;
ksa.sa_restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore; ksa.sa_restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore;
...@@ -340,10 +320,6 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact ...@@ -340,10 +320,6 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact
} else { } else {
r = __sig_action_opr(sig, (const sigaction_t*)sa?&ksa:0, (sigaction_t*)old?&ksa_old:0); r = __sig_action_opr(sig, (const sigaction_t*)sa?&ksa:0, (sigaction_t*)old?&ksa_old:0);
} }
if (sig == SIGABRT && sa && sa->sa_handler != SIG_DFL) {
UNLOCK(__abort_lock);
__restore_sigs(&set);
}
if (old && !r) { if (old && !r) {
old->sa_handler = ksa_old.sa_handler; old->sa_handler = ksa_old.sa_handler;
old->sa_flags = ksa_old.sa_flags; old->sa_flags = ksa_old.sa_flags;
...@@ -354,11 +330,26 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact ...@@ -354,11 +330,26 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact
int __sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old) int __sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old)
{ {
unsigned long set[_NSIG/(8*sizeof(long))];
if (sig-32U < 3 || sig-1U >= _NSIG-1) { if (sig-32U < 3 || sig-1U >= _NSIG-1) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
return __libc_sigaction(sig, sa, old);
/* Doing anything with the disposition of SIGABRT requires a lock,
* so that it cannot be changed while abort is terminating the
* process and so any change made by abort can't be observed. */
if (sig == SIGABRT) {
__block_all_sigs(&set);
LOCK(__abort_lock);
}
int r = __libc_sigaction(sig, sa, old);
if (sig == SIGABRT) {
UNLOCK(__abort_lock);
__restore_sigs(&set);
}
return r;
} }
weak_alias(__sigaction, sigaction); weak_alias(__sigaction, sigaction);
...@@ -33,25 +33,12 @@ FILE *popen(const char *cmd, const char *mode) ...@@ -33,25 +33,12 @@ FILE *popen(const char *cmd, const char *mode)
__syscall(SYS_close, p[1]); __syscall(SYS_close, p[1]);
return NULL; return NULL;
} }
FLOCK(f);
/* If the child's end of the pipe happens to already be on the final
* fd number to which it will be assigned (either 0 or 1), it must
* be moved to a different fd. Otherwise, there is no safe way to
* remove the close-on-exec flag in the child without also creating
* a file descriptor leak race condition in the parent. */
if (p[1-op] == 1-op) {
int tmp = fcntl(1-op, F_DUPFD_CLOEXEC, 0);
if (tmp < 0) {
e = errno;
goto fail;
}
__syscall(SYS_close, p[1-op]);
p[1-op] = tmp;
}
e = ENOMEM; e = ENOMEM;
if (!posix_spawn_file_actions_init(&fa)) { if (!posix_spawn_file_actions_init(&fa)) {
for (FILE *l = *__ofl_lock(); l; l=l->next)
if (l->pipe_pid && posix_spawn_file_actions_addclose(&fa, l->fd))
goto fail;
if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) { if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) {
if (!(e = posix_spawn(&pid, "/bin/sh", &fa, 0, if (!(e = posix_spawn(&pid, "/bin/sh", &fa, 0,
(char *[]){ "sh", "-c", (char *)cmd, 0 }, __environ))) { (char *[]){ "sh", "-c", (char *)cmd, 0 }, __environ))) {
...@@ -60,13 +47,14 @@ FILE *popen(const char *cmd, const char *mode) ...@@ -60,13 +47,14 @@ FILE *popen(const char *cmd, const char *mode)
if (!strchr(mode, 'e')) if (!strchr(mode, 'e'))
fcntl(p[op], F_SETFD, 0); fcntl(p[op], F_SETFD, 0);
__syscall(SYS_close, p[1-op]); __syscall(SYS_close, p[1-op]);
FUNLOCK(f); __ofl_unlock();
return f; return f;
} }
} }
fail:
__ofl_unlock();
posix_spawn_file_actions_destroy(&fa); posix_spawn_file_actions_destroy(&fa);
} }
fail:
fclose(f); fclose(f);
__syscall(SYS_close, p[1-op]); __syscall(SYS_close, p[1-op]);
......
...@@ -19,15 +19,16 @@ ...@@ -19,15 +19,16 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
#define _BSD_SOURCE
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
typedef int (*cmpfun)(const void *, const void *); typedef int (*cmpfun)(const void *, const void *, void *);
#define MIDDLE_ONE(a, b, c) \ #define MIDDLE_ONE(a, b, c, arg) \
(*cmp)(a, b) < 0 ? \ cmp(a, b, arg) < 0 ? \
((*cmp)(b, c) < 0 ? (b) : ((*cmp)(a, c) < 0 ? (c) : (a))): \ (cmp(b, c, arg) < 0 ? (b) : (cmp(a, c, arg) < 0 ? (c) : (a))): \
((*cmp)(b, c) > 0 ? (b) : ((*cmp)(a, c) < 0 ? (a) : (c))) (cmp(b, c, arg) > 0 ? (b) : (cmp(a, c, arg) < 0 ? (a) : (c)))
#define SWAPN(a, b, n) \ #define SWAPN(a, b, n) \
do { \ do { \
...@@ -42,7 +43,7 @@ typedef int (*cmpfun)(const void *, const void *); ...@@ -42,7 +43,7 @@ typedef int (*cmpfun)(const void *, const void *);
} \ } \
} while (0) } while (0)
void qsort(void *base, size_t nel, size_t width, cmpfun cmp) void __qsort_r(void *base, size_t nel, size_t width, cmpfun cmp, void *arg)
{ {
char *start, *end, *m, *l, *r; char *start, *end, *m, *l, *r;
int i, j, swapflag = 0; int i, j, swapflag = 0;
...@@ -60,7 +61,7 @@ insertqort: ...@@ -60,7 +61,7 @@ insertqort:
for (l = start + width; l <= end; l += width) { for (l = start + width; l <= end; l += width) {
memcpy(temp, l, width); memcpy(temp, l, width);
for (m = l - width; m >= start; m -= width) { for (m = l - width; m >= start; m -= width) {
if ((*cmp)(m, temp) > 0) { if (cmp(m, temp, arg) > 0) {
memcpy((m + width), m, width); memcpy((m + width), m, width);
} else { } else {
break; break;
...@@ -73,7 +74,7 @@ insertqort: ...@@ -73,7 +74,7 @@ insertqort:
// quick sort // quick sort
m = start + (nel >> 1) * width; m = start + (nel >> 1) * width;
m = MIDDLE_ONE(start, m, end); m = MIDDLE_ONE(start, m, end, arg);
if (m != start) { if (m != start) {
SWAPN(start, m, width); SWAPN(start, m, width);
m = start; m = start;
...@@ -82,10 +83,10 @@ insertqort: ...@@ -82,10 +83,10 @@ insertqort:
r = end; r = end;
while (l <= r) { while (l <= r) {
while (l <= r && (*cmp)(l, m) < 0) { while (l <= r && cmp(l, m, arg) < 0) {
l += width; l += width;
} }
while (l <= r && (*cmp)(r, m) >= 0) { while (l <= r && cmp(r, m, arg) >= 0) {
r -= width; r -= width;
} }
if (l < r) { if (l < r) {
...@@ -102,7 +103,7 @@ insertqort: ...@@ -102,7 +103,7 @@ insertqort:
} }
if (m - start > end - m) { if (m - start > end - m) {
qsort(start, (m - start) / width, width, (*cmp)); __qsort_r(start, (m - start) / width, width, cmp, arg);
if (m == end) { if (m == end) {
return; return;
} }
...@@ -110,7 +111,7 @@ insertqort: ...@@ -110,7 +111,7 @@ insertqort:
nel = (end - start) / width + 1; nel = (end - start) / width + 1;
goto loop; goto loop;
} else { } else {
qsort(m + width, (end - m) / width, width, (*cmp)); __qsort_r(m + width, (end - m) / width, width, cmp, arg);
if (m == start) { if (m == start) {
return; return;
} }
...@@ -119,3 +120,5 @@ insertqort: ...@@ -119,3 +120,5 @@ insertqort:
goto loop; goto loop;
} }
} }
weak_alias(__qsort_r, qsort_r);
...@@ -72,7 +72,7 @@ int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restr ...@@ -72,7 +72,7 @@ int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restr
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *restrict protocol) int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *restrict protocol)
{ {
unsupported_api(__FUNCTION__); unsupported_api(__FUNCTION__);
*protocol = PTHREAD_PRIO_NONE; *protocol = a->__attr / 8U % 2;
return 0; return 0;
} }
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict pshared) int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict pshared)
......
...@@ -68,15 +68,29 @@ _Noreturn void __pthread_exit(void *result) ...@@ -68,15 +68,29 @@ _Noreturn void __pthread_exit(void *result)
__pthread_tsd_run_dtors(); __pthread_tsd_run_dtors();
__block_app_sigs(&set);
/* This atomic potentially competes with a concurrent pthread_detach
* call; the loser is responsible for freeing thread resources. */
int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);
if (state==DT_DETACHED && self->map_base) {
/* Since __unmapself bypasses the normal munmap code path,
* explicitly wait for vmlock holders first. This must be
* done before any locks are taken, to avoid lock ordering
* issues that could lead to deadlock. */
__vm_wait();
}
/* Access to target the exiting thread with syscalls that use /* Access to target the exiting thread with syscalls that use
* its kernel tid is controlled by killlock. For detached threads, * its kernel tid is controlled by killlock. For detached threads,
* any use past this point would have undefined behavior, but for * any use past this point would have undefined behavior, but for
* joinable threads it's a valid usage that must be handled. */ * joinable threads it's a valid usage that must be handled.
* Signals must be blocked since pthread_kill must be AS-safe. */
LOCK(self->killlock); LOCK(self->killlock);
/* The thread list lock must be AS-safe, and thus requires /* The thread list lock must be AS-safe, and thus depends on
* application signals to be blocked before it can be taken. */ * application signals being blocked above. */
__block_app_sigs(&set);
__tl_lock(); __tl_lock();
/* If this is the only thread in the list, don't proceed with /* If this is the only thread in the list, don't proceed with
...@@ -84,19 +98,13 @@ _Noreturn void __pthread_exit(void *result) ...@@ -84,19 +98,13 @@ _Noreturn void __pthread_exit(void *result)
* signal state to prepare for exit to call atexit handlers. */ * signal state to prepare for exit to call atexit handlers. */
if (self->next == self) { if (self->next == self) {
__tl_unlock(); __tl_unlock();
__restore_sigs(&set);
UNLOCK(self->killlock); UNLOCK(self->killlock);
self->detach_state = state;
__restore_sigs(&set);
exit(0); exit(0);
} }
/* At this point we are committed to thread termination. Unlink /* At this point we are committed to thread termination. */
* the thread from the list. This change will not be visible
* until the lock is released, which only happens after SYS_exit
* has been called, via the exit futex address pointing at the lock. */
libc.threads_minus_1--;
self->next->prev = self->prev;
self->prev->next = self->next;
self->prev = self->next = self;
/* Process robust list in userspace to handle non-pshared mutexes /* Process robust list in userspace to handle non-pshared mutexes
* and the detached thread case where the robust list head will * and the detached thread case where the robust list head will
...@@ -120,9 +128,16 @@ _Noreturn void __pthread_exit(void *result) ...@@ -120,9 +128,16 @@ _Noreturn void __pthread_exit(void *result)
__do_orphaned_stdio_locks(); __do_orphaned_stdio_locks();
__dl_thread_cleanup(); __dl_thread_cleanup();
/* This atomic potentially competes with a concurrent pthread_detach /* Last, unlink thread from the list. This change will not be visible
* call; the loser is responsible for freeing thread resources. */ * until the lock is released, which only happens after SYS_exit
int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING); * has been called, via the exit futex address pointing at the lock.
* This needs to happen after any possible calls to LOCK() that might
* skip locking if process appears single-threaded. */
if (!--libc.threads_minus_1) libc.need_locks = -1;
self->next->prev = self->prev;
self->prev->next = self->next;
self->prev = self->next = self;
#if 0 #if 0
if (state==DT_DETACHED && self->map_base) { if (state==DT_DETACHED && self->map_base) {
/* Robust list will no longer be valid, and was already /* Robust list will no longer be valid, and was already
...@@ -130,16 +145,13 @@ _Noreturn void __pthread_exit(void *result) ...@@ -130,16 +145,13 @@ _Noreturn void __pthread_exit(void *result)
if (self->robust_list.off) if (self->robust_list.off)
__syscall(SYS_set_robust_list, 0, 3*sizeof(long)); __syscall(SYS_set_robust_list, 0, 3*sizeof(long));
/* Since __unmapself bypasses the normal munmap code path,
* explicitly wait for vmlock holders first. */
__vm_wait();
/* The following call unmaps the thread's stack mapping /* The following call unmaps the thread's stack mapping
* and then exits without touching the stack. */ * and then exits without touching the stack. */
__unmapself(self->map_base, self->map_size); __unmapself(self->map_base, self->map_size);
} }
/* Wake any joiner. */ /* Wake any joiner. */
a_store(&self->detach_state, DT_EXITED);
__wake(&self->detach_state, 1, 1); __wake(&self->detach_state, 1, 1);
#endif #endif
...@@ -314,7 +326,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att ...@@ -314,7 +326,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
new->detach_state = DT_JOINABLE; new->detach_state = DT_JOINABLE;
} }
new->robust_list.head = &new->robust_list.head; new->robust_list.head = &new->robust_list.head;
new->CANARY = self->CANARY; new->canary = self->canary;
new->sysinfo = self->sysinfo; new->sysinfo = self->sysinfo;
/* Setup argument structure for the new thread on its stack. /* Setup argument structure for the new thread on its stack.
...@@ -340,7 +352,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att ...@@ -340,7 +352,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
~(1UL<<((SIGCANCEL-1)%(8*sizeof(long)))); ~(1UL<<((SIGCANCEL-1)%(8*sizeof(long))));
__tl_lock(); __tl_lock();
libc.threads_minus_1++; if (!libc.threads_minus_1++) libc.need_locks = 1;
ret = __thread_clone((c11 ? start_c11 : start), flags, new, stack); ret = __thread_clone((c11 ? start_c11 : start), flags, new, stack);
/* All clone failures translate to EAGAIN. If explicit scheduling /* All clone failures translate to EAGAIN. If explicit scheduling
...@@ -364,7 +376,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att ...@@ -364,7 +376,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
} }
if (ret < 0) { if (ret < 0) {
libc.threads_minus_1--; if (!--libc.threads_minus_1) libc.need_locks = 0;
__tl_unlock(); __tl_unlock();
__restore_sigs(&set); __restore_sigs(&set);
__release_ptc(); __release_ptc();
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param *restrict param) int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param *restrict param)
{ {
int r; int r;
sigset_t set;
__block_app_sigs(&set);
LOCK(t->killlock); LOCK(t->killlock);
if (!t->tid) { if (!t->tid) {
r = ESRCH; r = ESRCH;
...@@ -23,5 +25,6 @@ int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param ...@@ -23,5 +25,6 @@ int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param
} }
} }
UNLOCK(t->killlock); UNLOCK(t->killlock);
__restore_sigs(&set);
return r; return r;
} }
...@@ -2,25 +2,24 @@ ...@@ -2,25 +2,24 @@
#include <unsupported_api.h> #include <unsupported_api.h>
#include "syscall.h" #include "syscall.h"
static pthread_once_t check_pi_once; static volatile int check_pi_result = -1;
static int check_pi_result;
static void check_pi()
{
volatile int lk = 0;
check_pi_result = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0);
}
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int protocol) int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int protocol)
{ {
int r;
unsupported_api(__FUNCTION__); unsupported_api(__FUNCTION__);
switch (protocol) { switch (protocol) {
case PTHREAD_PRIO_NONE: case PTHREAD_PRIO_NONE:
a->__attr &= ~8; a->__attr &= ~8;
return 0; return 0;
case PTHREAD_PRIO_INHERIT: case PTHREAD_PRIO_INHERIT:
pthread_once(&check_pi_once, check_pi); r = check_pi_result;
if (check_pi_result) return check_pi_result; if (r < 0) {
volatile int lk = 0;
r = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0);
a_store(&check_pi_result, r);
}
if (r) return r;
a->__attr |= 8; a->__attr |= 8;
return 0; return 0;
case PTHREAD_PRIO_PROTECT: case PTHREAD_PRIO_PROTECT:
......
...@@ -13,8 +13,11 @@ int pthread_setschedparam(pthread_t t, int policy, const struct sched_param *par ...@@ -13,8 +13,11 @@ int pthread_setschedparam(pthread_t t, int policy, const struct sched_param *par
return EINVAL; return EINVAL;
} }
sigset_t set;
__block_app_sigs(&set);
LOCK(t->killlock); LOCK(t->killlock);
r = !t->tid ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param->sched_priority, MUSL_TYPE_THREAD); r = !t->tid ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param->sched_priority, MUSL_TYPE_THREAD);
UNLOCK(t->killlock); UNLOCK(t->killlock);
__restore_sigs(&set);
return r; return r;
} }
...@@ -9,8 +9,11 @@ int pthread_setschedprio(pthread_t t, int prio) ...@@ -9,8 +9,11 @@ int pthread_setschedprio(pthread_t t, int prio)
return EINVAL; return EINVAL;
} }
sigset_t set;
__block_app_sigs(&set);
LOCK(t->killlock); LOCK(t->killlock);
r = !t->tid ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, prio, MUSL_TYPE_THREAD); r = !t->tid ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, prio, MUSL_TYPE_THREAD);
UNLOCK(t->killlock); UNLOCK(t->killlock);
__restore_sigs(&set);
return r; return r;
} }
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <pthread.h> #include <pthread.h>
#include "lock.h" #include "lock.h"
#include "fork_impl.h"
#define malloc __libc_malloc
#define calloc __libc_calloc
#define realloc undef
#define free undef
static struct { static struct {
ino_t ino; ino_t ino;
...@@ -19,6 +25,7 @@ static struct { ...@@ -19,6 +25,7 @@ static struct {
int refcnt; int refcnt;
} *semtab; } *semtab;
static volatile int lock[1]; static volatile int lock[1];
volatile int *const __sem_open_lockptr = lock;
#define FLAGS (O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK) #define FLAGS (O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK)
...@@ -162,9 +169,12 @@ int sem_close(sem_t *sem) ...@@ -162,9 +169,12 @@ int sem_close(sem_t *sem)
LOCK(lock); LOCK(lock);
for (i=0; i<SEM_NSEMS_MAX && semtab[i].sem != sem; i++); for (i=0; i<SEM_NSEMS_MAX && semtab[i].sem != sem; i++);
if (!--semtab[i].refcnt) { if (!--semtab[i].refcnt) {
semtab[i].sem = 0; UNLOCK(lock);
semtab[i].ino = 0; return 0;
} }
semtab[i].sem = 0;
semtab[i].ino = 0;
UNLOCK(lock); UNLOCK(lock);
munmap(sem, sizeof *sem); munmap(sem, sizeof *sem);
return 0; return 0;
......
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <signal.h>
#include "syscall.h" #include "syscall.h"
#include "libc.h" #include "libc.h"
#include "pthread_impl.h"
struct ctx { struct ctx {
int id, eid, sid; int id, eid, sid;
int nr, err; int nr, ret;
}; };
static void do_setxid(void *p) static void do_setxid(void *p)
{ {
struct ctx *c = p; struct ctx *c = p;
if (c->err>0) return; if (c->ret<0) return;
int ret = -__syscall(c->nr, c->id, c->eid, c->sid); int ret = __syscall(c->nr, c->id, c->eid, c->sid);
if (ret && !c->err) { if (ret && !c->ret) {
/* If one thread fails to set ids after another has already /* If one thread fails to set ids after another has already
* succeeded, forcibly killing the process is the only safe * succeeded, forcibly killing the process is the only safe
* thing to do. State is inconsistent and dangerous. Use * thing to do. State is inconsistent and dangerous. Use
...@@ -22,18 +21,14 @@ static void do_setxid(void *p) ...@@ -22,18 +21,14 @@ static void do_setxid(void *p)
__block_all_sigs(0); __block_all_sigs(0);
__syscall(SYS_kill, __syscall(SYS_getpid), SIGKILL); __syscall(SYS_kill, __syscall(SYS_getpid), SIGKILL);
} }
c->err = ret; c->ret = ret;
} }
int __setxid(int nr, int id, int eid, int sid) int __setxid(int nr, int id, int eid, int sid)
{ {
/* err is initially nonzero so that failure of the first thread does not /* ret is initially nonzero so that failure of the first thread does not
* trigger the safety kill above. */ * trigger the safety kill above. */
struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid, .err = -1 }; struct ctx c = { .nr = nr, .id = id, .eid = eid, .sid = sid, .ret = 1 };
do_setxid(&c); do_setxid(&c);
if (c.err) { return __syscall_ret(c.ret);
if (c.err>0) errno = c.err;
return -1;
}
return 0;
} }
#
# Makefile for musl (requires GNU make)
#
# This is how simple every makefile should be...
# No, I take that back - actually most should be less than half this size.
#
# Use config.mak to override any of the following variables.
# Do not make changes here.
#
srcdir = .
exec_prefix = /usr/local
bindir = $(exec_prefix)/bin
prefix = /usr/local/musl
includedir = $(prefix)/include
libdir = $(prefix)/lib
syslibdir = /lib
MALLOC_DIR = oldmalloc
SRC_DIRS = $(addprefix $(srcdir)/,src/* src/malloc/$(MALLOC_DIR) crt ldso $(COMPAT_SRC_DIRS))
BASE_GLOBS = $(addsuffix /*.c,$(SRC_DIRS))
ARCH_GLOBS = $(addsuffix /$(ARCH)/*.[csS],$(SRC_DIRS))
BASE_SRCS = $(sort $(wildcard $(BASE_GLOBS)))
ARCH_SRCS = $(sort $(wildcard $(ARCH_GLOBS)))
BASE_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(BASE_SRCS)))
ARCH_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(ARCH_SRCS)))
REPLACED_OBJS = $(sort $(subst /$(ARCH)/,/,$(ARCH_OBJS)))
ALL_OBJS = $(addprefix obj/, $(filter-out $(REPLACED_OBJS), $(sort $(BASE_OBJS) $(ARCH_OBJS))))
LIBC_OBJS = $(filter obj/src/%,$(ALL_OBJS)) $(filter obj/compat/%,$(ALL_OBJS))
LDSO_OBJS = $(filter obj/ldso/%,$(ALL_OBJS:%.o=%.lo))
CRT_OBJS = $(filter obj/crt/%,$(ALL_OBJS))
AOBJS = $(LIBC_OBJS)
LOBJS = $(LIBC_OBJS:.o=.lo)
GENH = obj/include/bits/alltypes.h obj/include/bits/syscall.h
GENH_INT = obj/src/internal/version.h
IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/locale_impl.h src/internal/libc.h)
LDFLAGS =
LDFLAGS_AUTO =
LIBCC = -lgcc
CPPFLAGS =
CFLAGS =
CFLAGS_AUTO = -Os -pipe
CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc
CFLAGS_ALL = $(CFLAGS_C99FSE)
CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -I$(srcdir)/arch/generic -Iobj/src/internal -I$(srcdir)/src/include -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include
CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
LDFLAGS_ALL = $(LDFLAGS_AUTO) $(LDFLAGS)
AR = $(CROSS_COMPILE)ar
RANLIB = $(CROSS_COMPILE)ranlib
INSTALL = $(srcdir)/tools/install.sh
ARCH_INCLUDES = $(wildcard $(srcdir)/arch/$(ARCH)/bits/*.h)
GENERIC_INCLUDES = $(wildcard $(srcdir)/arch/generic/bits/*.h)
INCLUDES = $(wildcard $(srcdir)/include/*.h $(srcdir)/include/*/*.h)
ALL_INCLUDES = $(sort $(INCLUDES:$(srcdir)/%=%) $(GENH:obj/%=%) $(ARCH_INCLUDES:$(srcdir)/arch/$(ARCH)/%=include/%) $(GENERIC_INCLUDES:$(srcdir)/arch/generic/%=include/%))
EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv dl
EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a)
CRT_LIBS = $(addprefix lib/,$(notdir $(CRT_OBJS)))
STATIC_LIBS = lib/libc.a
SHARED_LIBS = lib/libc.so
TOOL_LIBS = lib/musl-gcc.specs
ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS)
ALL_TOOLS = obj/musl-gcc
WRAPCC_GCC = gcc
WRAPCC_CLANG = clang
LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1
-include config.mak
-include $(srcdir)/arch/$(ARCH)/arch.mak
ifeq ($(ARCH),)
all:
@echo "Please set ARCH in config.mak before running make."
@exit 1
else
all: $(ALL_LIBS) $(ALL_TOOLS)
OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(GENH) $(GENH_INT))) obj/include)
$(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(ALL_OBJS:%.o=%.lo) $(GENH) $(GENH_INT): | $(OBJ_DIRS)
$(OBJ_DIRS):
mkdir -p $@
obj/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed
sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@
obj/include/bits/syscall.h: $(srcdir)/arch/$(ARCH)/bits/syscall.h.in
cp $< $@
sed -n -e s/__NR_/SYS_/p < $< >> $@
obj/src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git)
printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@
obj/src/internal/version.o obj/src/internal/version.lo: obj/src/internal/version.h
obj/crt/rcrt1.o obj/ldso/dlstart.lo obj/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
obj/crt/crt1.o obj/crt/scrt1.o obj/crt/rcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart.c
obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC
OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%))
$(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3
MEMOPS_OBJS = $(filter %/memcpy.o %/memmove.o %/memcmp.o %/memset.o, $(LIBC_OBJS))
$(MEMOPS_OBJS) $(MEMOPS_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS)
NOSSP_OBJS = $(CRT_OBJS) $(LDSO_OBJS) $(filter \
%/__libc_start_main.o %/__init_tls.o %/__stack_chk_fail.o \
%/__set_thread_area.o %/memset.o %/memcpy.o \
, $(LIBC_OBJS))
$(NOSSP_OBJS) $(NOSSP_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
$(CRT_OBJS): CFLAGS_ALL += -DCRT
$(LOBJS) $(LDSO_OBJS): CFLAGS_ALL += -fPIC
CC_CMD = $(CC) $(CFLAGS_ALL) -c -o $@ $<
# Choose invocation of assembler to be used
ifeq ($(ADD_CFI),yes)
AS_CMD = LC_ALL=C awk -f $(srcdir)/tools/add-cfi.common.awk -f $(srcdir)/tools/add-cfi.$(ARCH).awk $< | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ -
else
AS_CMD = $(CC_CMD)
endif
obj/%.o: $(srcdir)/%.s
$(AS_CMD)
obj/%.o: $(srcdir)/%.S
$(CC_CMD)
obj/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
$(CC_CMD)
obj/%.lo: $(srcdir)/%.s
$(AS_CMD)
obj/%.lo: $(srcdir)/%.S
$(CC_CMD)
obj/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
$(CC_CMD)
lib/libc.so: $(LOBJS) $(LDSO_OBJS)
$(CC) $(CFLAGS_ALL) $(LDFLAGS_ALL) -nostdlib -shared \
-Wl,-e,_dlstart -o $@ $(LOBJS) $(LDSO_OBJS) $(LIBCC)
lib/libc.a: $(AOBJS)
rm -f $@
$(AR) rc $@ $(AOBJS)
$(RANLIB) $@
$(EMPTY_LIBS):
rm -f $@
$(AR) rc $@
lib/%.o: obj/crt/$(ARCH)/%.o
cp $< $@
lib/%.o: obj/crt/%.o
cp $< $@
lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh config.mak
sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@
obj/musl-gcc: config.mak
printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@
chmod +x $@
obj/%-clang: $(srcdir)/tools/%-clang.in config.mak
sed -e 's!@CC@!$(WRAPCC_CLANG)!g' -e 's!@PREFIX@!$(prefix)!g' -e 's!@INCDIR@!$(includedir)!g' -e 's!@LIBDIR@!$(libdir)!g' -e 's!@LDSO@!$(LDSO_PATHNAME)!g' $< > $@
chmod +x $@
$(DESTDIR)$(bindir)/%: obj/%
$(INSTALL) -D $< $@
$(DESTDIR)$(libdir)/%.so: lib/%.so
$(INSTALL) -D -m 755 $< $@
$(DESTDIR)$(libdir)/%: lib/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/generic/bits/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(includedir)/bits/%: obj/include/bits/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(includedir)/%: $(srcdir)/include/%
$(INSTALL) -D -m 644 $< $@
$(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
$(INSTALL) -D -l $(libdir)/libc.so $@ || true
install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DESTDIR)$(LDSO_PATHNAME),)
install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
install-tools: $(ALL_TOOLS:obj/%=$(DESTDIR)$(bindir)/%)
install: install-libs install-headers install-tools
musl-git-%.tar.gz: .git
git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ $(patsubst musl-git-%.tar.gz,%,$@)
musl-%.tar.gz: .git
git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ v$(patsubst musl-%.tar.gz,%,$@)
endif
clean:
rm -rf obj lib
distclean: clean
rm -f config.mak
.PHONY: all clean install install-libs install-headers install-tools
#define _GNU_SOURCE #define _GNU_SOURCE
#define SYSCALL_NO_TLS 1 #define SYSCALL_NO_TLS 1
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
...@@ -21,9 +20,14 @@ ...@@ -21,9 +20,14 @@
#include <semaphore.h> #include <semaphore.h>
#include <sys/membarrier.h> #include <sys/membarrier.h>
#include "pthread_impl.h" #include "pthread_impl.h"
#include "fork_impl.h"
#include "libc.h" #include "libc.h"
#include "dynlink.h" #include "dynlink.h"
#include "malloc_impl.h"
#define malloc __libc_malloc
#define calloc __libc_calloc
#define realloc __libc_realloc
#define free __libc_free
static void error(const char *, ...); static void error(const char *, ...);
...@@ -77,7 +81,7 @@ struct dso { ...@@ -77,7 +81,7 @@ struct dso {
struct dso **deps, *needed_by; struct dso **deps, *needed_by;
size_t ndeps_direct; size_t ndeps_direct;
size_t next_dep; size_t next_dep;
int ctor_visitor; pthread_t ctor_visitor;
char *rpath_orig, *rpath; char *rpath_orig, *rpath;
struct tls_module tls; struct tls_module tls;
size_t tls_id; size_t tls_id;
...@@ -413,8 +417,6 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri ...@@ -413,8 +417,6 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
} }
switch(type) { switch(type) {
case REL_NONE:
break;
case REL_OFFSET: case REL_OFFSET:
addend -= (size_t)reloc_addr; addend -= (size_t)reloc_addr;
case REL_SYMBOLIC: case REL_SYMBOLIC:
...@@ -557,10 +559,25 @@ static void reclaim_gaps(struct dso *dso) ...@@ -557,10 +559,25 @@ static void reclaim_gaps(struct dso *dso)
} }
} }
static ssize_t read_loop(int fd, void *p, size_t n)
{
for (size_t i=0; i<n; ) {
ssize_t l = read(fd, (char *)p+i, n-i);
if (l<0) {
if (errno==EINTR) continue;
else return -1;
}
if (l==0) return i;
i += l;
}
return n;
}
static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off) static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t off)
{ {
static int no_map_fixed; static int no_map_fixed;
char *q; char *q;
if (!n) return p;
if (!no_map_fixed) { if (!no_map_fixed) {
q = mmap(p, n, prot, flags|MAP_FIXED, fd, off); q = mmap(p, n, prot, flags|MAP_FIXED, fd, off);
if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL) if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL)
...@@ -1076,13 +1093,17 @@ static struct dso *load_library(const char *name, struct dso *needed_by) ...@@ -1076,13 +1093,17 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
snprintf(etc_ldso_path, sizeof etc_ldso_path, snprintf(etc_ldso_path, sizeof etc_ldso_path,
"%.*s/etc/ld-musl-" LDSO_ARCH ".path", "%.*s/etc/ld-musl-" LDSO_ARCH ".path",
(int)prefix_len, prefix); (int)prefix_len, prefix);
FILE *f = fopen(etc_ldso_path, "rbe"); fd = open(etc_ldso_path, O_RDONLY|O_CLOEXEC);
if (f) { if (fd>=0) {
if (getdelim(&sys_path, (size_t[1]){0}, 0, f) <= 0) { size_t n = 0;
if (!fstat(fd, &st)) n = st.st_size;
if ((sys_path = malloc(n+1)))
sys_path[n] = 0;
if (!sys_path || read_loop(fd, sys_path, n)<0) {
free(sys_path); free(sys_path);
sys_path = ""; sys_path = "";
} }
fclose(f); close(fd);
} else if (errno != ENOENT) { } else if (errno != ENOENT) {
sys_path = ""; sys_path = "";
} }
...@@ -1259,7 +1280,7 @@ static void extend_bfs_deps(struct dso *p) ...@@ -1259,7 +1280,7 @@ static void extend_bfs_deps(struct dso *p)
struct dso *dep = p->deps[i]; struct dso *dep = p->deps[i];
for (j=cnt=0; j<dep->ndeps_direct; j++) for (j=cnt=0; j<dep->ndeps_direct; j++)
if (!dep->deps[j]->mark) cnt++; if (!dep->deps[j]->mark) cnt++;
tmp = no_realloc ? tmp = no_realloc ?
malloc(sizeof(*tmp) * (ndeps_all+cnt+1)) : malloc(sizeof(*tmp) * (ndeps_all+cnt+1)) :
realloc(p->deps, sizeof(*tmp) * (ndeps_all+cnt+1)); realloc(p->deps, sizeof(*tmp) * (ndeps_all+cnt+1));
if (!tmp) { if (!tmp) {
...@@ -1397,7 +1418,7 @@ void __libc_exit_fini() ...@@ -1397,7 +1418,7 @@ void __libc_exit_fini()
{ {
struct dso *p; struct dso *p;
size_t dyn[DYN_CNT]; size_t dyn[DYN_CNT];
int self = __pthread_self()->tid; pthread_t self = __pthread_self();
/* Take both locks before setting shutting_down, so that /* Take both locks before setting shutting_down, so that
* either lock is sufficient to read its value. The lock * either lock is sufficient to read its value. The lock
...@@ -1423,6 +1444,17 @@ void __libc_exit_fini() ...@@ -1423,6 +1444,17 @@ void __libc_exit_fini()
} }
} }
void __ldso_atfork(int who)
{
if (who<0) {
pthread_rwlock_wrlock(&lock);
pthread_mutex_lock(&init_fini_lock);
} else {
pthread_mutex_unlock(&init_fini_lock);
pthread_rwlock_unlock(&lock);
}
}
static struct dso **queue_ctors(struct dso *dso) static struct dso **queue_ctors(struct dso *dso)
{ {
size_t cnt, qpos, spos, i; size_t cnt, qpos, spos, i;
...@@ -1481,6 +1513,13 @@ static struct dso **queue_ctors(struct dso *dso) ...@@ -1481,6 +1513,13 @@ static struct dso **queue_ctors(struct dso *dso)
} }
queue[qpos] = 0; queue[qpos] = 0;
for (i=0; i<qpos; i++) queue[i]->mark = 0; for (i=0; i<qpos; i++) queue[i]->mark = 0;
for (i=0; i<qpos; i++)
if (queue[i]->ctor_visitor && queue[i]->ctor_visitor->tid < 0) {
error("State of %s is inconsistent due to multithreaded fork\n",
queue[i]->name);
free(queue);
if (runtime) longjmp(*rtld_fail, 1);
}
return queue; return queue;
} }
...@@ -1489,7 +1528,7 @@ static void do_init_fini(struct dso **queue) ...@@ -1489,7 +1528,7 @@ static void do_init_fini(struct dso **queue)
{ {
struct dso *p; struct dso *p;
size_t dyn[DYN_CNT], i; size_t dyn[DYN_CNT], i;
int self = __pthread_self()->tid; pthread_t self = __pthread_self();
pthread_mutex_lock(&init_fini_lock); pthread_mutex_lock(&init_fini_lock);
for (i=0; (p=queue[i]); i++) { for (i=0; (p=queue[i]); i++) {
...@@ -1498,7 +1537,7 @@ static void do_init_fini(struct dso **queue) ...@@ -1498,7 +1537,7 @@ static void do_init_fini(struct dso **queue)
if (p->ctor_visitor || p->constructed) if (p->ctor_visitor || p->constructed)
continue; continue;
p->ctor_visitor = self; p->ctor_visitor = self;
decode_vec(p->dynv, dyn, DYN_CNT); decode_vec(p->dynv, dyn, DYN_CNT);
if (dyn[0] & ((1<<DT_FINI) | (1<<DT_FINI_ARRAY))) { if (dyn[0] & ((1<<DT_FINI) | (1<<DT_FINI_ARRAY))) {
p->fini_next = fini_head; p->fini_next = fini_head;
...@@ -1598,7 +1637,7 @@ static void install_new_tls(void) ...@@ -1598,7 +1637,7 @@ static void install_new_tls(void)
/* Install new dtv for each thread. */ /* Install new dtv for each thread. */
for (j=0, td=self; !j || td!=self; j++, td=td->next) { for (j=0, td=self; !j || td!=self; j++, td=td->next) {
td->dtv = td->dtv_copy = newdtv[j]; td->dtv = newdtv[j];
} }
__tl_unlock(); __tl_unlock();
...@@ -1609,7 +1648,7 @@ static void install_new_tls(void) ...@@ -1609,7 +1648,7 @@ static void install_new_tls(void)
* following stage 2 and stage 3 functions via primitive symbolic lookup * following stage 2 and stage 3 functions via primitive symbolic lookup
* since it does not have access to their addresses to begin with. */ * since it does not have access to their addresses to begin with. */
/* Stage 2 of the dynamic linker is called after relative relocations /* Stage 2 of the dynamic linker is called after relative relocations
* have been processed. It can make function calls to static functions * have been processed. It can make function calls to static functions
* and access string literals and static data, but cannot use extern * and access string literals and static data, but cannot use extern
* symbols. Its job is to perform symbolic relocations on the dynamic * symbols. Its job is to perform symbolic relocations on the dynamic
...@@ -1815,7 +1854,7 @@ void __dls3(size_t *sp, size_t *auxv) ...@@ -1815,7 +1854,7 @@ void __dls3(size_t *sp, size_t *auxv)
dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno)); dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno));
_exit(1); _exit(1);
} }
Ehdr *ehdr = (void *)map_library(fd, &app); Ehdr *ehdr = map_library(fd, &app);
if (!ehdr) { if (!ehdr) {
dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]); dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]);
_exit(1); _exit(1);
...@@ -1961,6 +2000,8 @@ void __dls3(size_t *sp, size_t *auxv) ...@@ -1961,6 +2000,8 @@ void __dls3(size_t *sp, size_t *auxv)
* possibility of incomplete replacement. */ * possibility of incomplete replacement. */
if (find_sym(head, "malloc", 1).dso != &ldso) if (find_sym(head, "malloc", 1).dso != &ldso)
__malloc_replaced = 1; __malloc_replaced = 1;
if (find_sym(head, "aligned_alloc", 1).dso != &ldso)
__aligned_alloc_replaced = 1;
/* Switch to runtime mode: any further failures in the dynamic /* Switch to runtime mode: any further failures in the dynamic
* linker are a reportable failure rather than a fatal startup * linker are a reportable failure rather than a fatal startup
...@@ -1971,7 +2012,7 @@ void __dls3(size_t *sp, size_t *auxv) ...@@ -1971,7 +2012,7 @@ void __dls3(size_t *sp, size_t *auxv)
debug.bp = dl_debug_state; debug.bp = dl_debug_state;
debug.head = head; debug.head = head;
debug.base = ldso.base; debug.base = ldso.base;
debug.state = 0; debug.state = RT_CONSISTENT;
_dl_debug_state(); _dl_debug_state();
if (replace_argv0) argv[0] = replace_argv0; if (replace_argv0) argv[0] = replace_argv0;
...@@ -2030,6 +2071,9 @@ void *dlopen(const char *file, int mode) ...@@ -2030,6 +2071,9 @@ void *dlopen(const char *file, int mode)
pthread_rwlock_wrlock(&lock); pthread_rwlock_wrlock(&lock);
__inhibit_ptc(); __inhibit_ptc();
debug.state = RT_ADD;
_dl_debug_state();
p = 0; p = 0;
if (shutting_down) { if (shutting_down) {
error("Cannot dlopen while program is exiting."); error("Cannot dlopen while program is exiting.");
...@@ -2089,8 +2133,9 @@ void *dlopen(const char *file, int mode) ...@@ -2089,8 +2133,9 @@ void *dlopen(const char *file, int mode)
load_deps(p); load_deps(p);
extend_bfs_deps(p); extend_bfs_deps(p);
pthread_mutex_lock(&init_fini_lock); pthread_mutex_lock(&init_fini_lock);
if (!p->constructed) ctor_queue = queue_ctors(p); int constructed = p->constructed;
pthread_mutex_unlock(&init_fini_lock); pthread_mutex_unlock(&init_fini_lock);
if (!constructed) ctor_queue = queue_ctors(p);
if (!p->relocated && (mode & RTLD_LAZY)) { if (!p->relocated && (mode & RTLD_LAZY)) {
prepare_lazy(p); prepare_lazy(p);
for (i=0; p->deps[i]; i++) for (i=0; p->deps[i]; i++)
...@@ -2122,9 +2167,10 @@ void *dlopen(const char *file, int mode) ...@@ -2122,9 +2167,10 @@ void *dlopen(const char *file, int mode)
update_tls_size(); update_tls_size();
if (tls_cnt != orig_tls_cnt) if (tls_cnt != orig_tls_cnt)
install_new_tls(); install_new_tls();
_dl_debug_state();
orig_tail = tail; orig_tail = tail;
end: end:
debug.state = RT_CONSISTENT;
_dl_debug_state();
__release_ptc(); __release_ptc();
if (p) gencnt++; if (p) gencnt++;
pthread_rwlock_unlock(&lock); pthread_rwlock_unlock(&lock);
...@@ -2318,7 +2364,8 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void ...@@ -2318,7 +2364,8 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void
info.dlpi_adds = gencnt; info.dlpi_adds = gencnt;
info.dlpi_subs = 0; info.dlpi_subs = 0;
info.dlpi_tls_modid = current->tls_id; info.dlpi_tls_modid = current->tls_id;
info.dlpi_tls_data = current->tls.image; info.dlpi_tls_data = !current->tls_id ? 0 :
__tls_get_addr((tls_mod_off_t[]){current->tls_id,0});
ret = (callback)(&info, sizeof (info), data); ret = (callback)(&info, sizeof (info), data);
......
...@@ -70,7 +70,8 @@ weak_alias(libc_start_init, __libc_start_init); ...@@ -70,7 +70,8 @@ weak_alias(libc_start_init, __libc_start_init);
typedef int lsm2_fn(int (*)(int,char **,char **), int, char **); typedef int lsm2_fn(int (*)(int,char **,char **), int, char **);
static lsm2_fn libc_start_main_stage2; static lsm2_fn libc_start_main_stage2;
int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv) int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv,
void (*init_dummy)(), void(*fini_dummy)(), void(*ldso_dummy)())
{ {
char **envp = argv+argc+1; char **envp = argv+argc+1;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include <errno.h> #include <errno.h>
#include "libc.h" #include "libc.h"
#include "pthread_impl.h" #include "pthread_impl.h"
#include "malloc_impl.h" #include "oldmalloc/malloc_impl.h"
static inline void lock(volatile int *lk) static inline void lock(volatile int *lk)
{ {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "libc.h" #include "libc.h"
#include "atomic.h" #include "atomic.h"
#include "pthread_impl.h" #include "pthread_impl.h"
#include "malloc_impl.h" #include "oldmalloc/malloc_impl.h"
#if defined(__GNUC__) && defined(__PIC__) #if defined(__GNUC__) && defined(__PIC__)
#define inline inline __attribute__((always_inline)) #define inline inline __attribute__((always_inline))
......
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include "malloc_impl.h"
#include "dynlink.h"
void *aligned_alloc(size_t align, size_t len)
{
unsigned char *mem, *new;
if ((align & -align) != align) {
errno = EINVAL;
return 0;
}
if (len > SIZE_MAX - align ||
(__malloc_replaced && !__aligned_alloc_replaced)) {
errno = ENOMEM;
return 0;
}
if (align <= SIZE_ALIGN)
return malloc(len);
if (!(mem = malloc(len + align-1)))
return 0;
new = (void *)((uintptr_t)mem + align-1 & -align);
if (new == mem) return mem;
struct chunk *c = MEM_TO_CHUNK(mem);
struct chunk *n = MEM_TO_CHUNK(new);
if (IS_MMAPPED(c)) {
/* Apply difference between aligned and original
* address to the "extra" field of mmapped chunk. */
n->psize = c->psize + (new-mem);
n->csize = c->csize - (new-mem);
return new;
}
struct chunk *t = NEXT_CHUNK(c);
/* Split the allocated chunk into two chunks. The aligned part
* that will be used has the size in its footer reduced by the
* difference between the aligned and original addresses, and
* the resulting size copied to its header. A new header and
* footer are written for the split-off part to be freed. */
n->psize = c->csize = C_INUSE | (new-mem);
n->csize = t->psize -= new-mem;
__bin_chunk(c);
return new;
}
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册