mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
Polyfill IPv6 on non-Linux
This commit is contained in:
parent
b73e35c6fa
commit
0547eabcd6
10 changed files with 185 additions and 78 deletions
|
@ -18,7 +18,6 @@
|
|||
#define in_addr_t uint32_t
|
||||
#define in_addr_t uint32_t
|
||||
#define in_port_t uint16_t
|
||||
#define in_port_t uint16_t
|
||||
#define ino_t uint64_t
|
||||
#define key_t int32_t
|
||||
#define loff_t int64_t
|
||||
|
|
|
@ -38,6 +38,12 @@ OpenBSD Sorting (BSD-3)\\n\
|
|||
Copyright 1993 The Regents of the University of California\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
#define SWAPTYPE_BYTEV 1
|
||||
#define SWAPTYPE_INTV 2
|
||||
#define SWAPTYPE_LONGV 3
|
||||
#define SWAPTYPE_INT 4
|
||||
#define SWAPTYPE_LONG 5
|
||||
|
||||
#define CMPPAR int (*cmp)(const void *, const void *, void *),void *arg
|
||||
#define CMPARG cmp, arg
|
||||
#define CMP(a, b) cmp(a, b, arg)
|
||||
|
@ -46,30 +52,6 @@ asm(".include \"libc/disclaimer.inc\"");
|
|||
static inline char *med3(char *, char *, char *, CMPPAR);
|
||||
static inline void swapfunc(char *, char *, size_t, int);
|
||||
|
||||
/*
|
||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
||||
*
|
||||
* This version differs from Bentley & McIlroy in the following ways:
|
||||
* 1. The partition value is swapped into a[0] instead of being
|
||||
* stored out of line.
|
||||
*
|
||||
* 2. The swap function can swap 32-bit aligned elements on 64-bit
|
||||
* platforms instead of swapping them as byte-aligned.
|
||||
*
|
||||
* 3. It uses David Musser's introsort algorithm to fall back to
|
||||
* heapsort(3) when the recursion depth reaches 2*lg(n + 1).
|
||||
* This avoids quicksort's quadratic behavior for pathological
|
||||
* input without appreciably changing the average run time.
|
||||
*
|
||||
* 4. Tail recursion is eliminated when sorting the larger of two
|
||||
* subpartitions to save stack space.
|
||||
*/
|
||||
#define SWAPTYPE_BYTEV 1
|
||||
#define SWAPTYPE_INTV 2
|
||||
#define SWAPTYPE_LONGV 3
|
||||
#define SWAPTYPE_INT 4
|
||||
#define SWAPTYPE_LONG 5
|
||||
|
||||
#define TYPE_ALIGNED(TYPE, a, es) \
|
||||
(((char *)a - (char *)0) % sizeof(TYPE) == 0 && es % sizeof(TYPE) == 0)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/struct/sockaddr.internal.h"
|
||||
#include "libc/sock/struct/sockaddr6-bsd.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -41,6 +42,21 @@ int sockaddr2bsd(const void *addr, uint32_t addrsize,
|
|||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else if (((struct sockaddr *)addr)->sa_family == AF_INET6) {
|
||||
if (addrsize >= sizeof(struct sockaddr_in6)) {
|
||||
out_addr->sin6.sin6_len = 0;
|
||||
out_addr->sin6.sin6_family = AF_INET6;
|
||||
out_addr->sin6.sin6_port = ((struct sockaddr_in6 *)addr)->sin6_port;
|
||||
out_addr->sin6.sin6_flowinfo =
|
||||
((struct sockaddr_in6 *)addr)->sin6_flowinfo;
|
||||
out_addr->sin6.sin6_addr = ((struct sockaddr_in6 *)addr)->sin6_addr;
|
||||
out_addr->sin6.sin6_scope_id =
|
||||
((struct sockaddr_in6 *)addr)->sin6_scope_id;
|
||||
*out_addrsize = sizeof(struct sockaddr_in6_bsd);
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
} else if (((struct sockaddr *)addr)->sa_family == AF_UNIX) {
|
||||
famsize = sizeof(((struct sockaddr_un *)addr)->sun_family);
|
||||
if (addrsize >= famsize &&
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/struct/sockaddr.internal.h"
|
||||
#include "libc/sock/struct/sockaddr6-bsd.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -42,6 +43,16 @@ void sockaddr2linux(const union sockaddr_storage_bsd *addr, uint32_t addrsize,
|
|||
out_addr->sin.sin_addr = addr->sin.sin_addr;
|
||||
*inout_addrsize = sizeof(struct sockaddr_in);
|
||||
}
|
||||
} else if (addr->sa.sa_family == AF_INET6) {
|
||||
if (addrsize >= sizeof(struct sockaddr_in6_bsd) &&
|
||||
size >= sizeof(struct sockaddr_in6)) {
|
||||
out_addr->sin6.sin6_family = AF_INET6;
|
||||
out_addr->sin6.sin6_port = addr->sin6.sin6_port;
|
||||
out_addr->sin6.sin6_addr = addr->sin6.sin6_addr;
|
||||
out_addr->sin6.sin6_flowinfo = addr->sin6.sin6_flowinfo;
|
||||
out_addr->sin6.sin6_scope_id = addr->sin6.sin6_scope_id;
|
||||
*inout_addrsize = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
} else if (addr->sa.sa_family == AF_UNIX) {
|
||||
if (addrsize >=
|
||||
sizeof(addr->sun.sun_len) + sizeof(addr->sun.sun_family) &&
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR_INTERNAL_H_
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/sock/struct/sockaddr.h"
|
||||
#include "libc/sock/struct/sockaddr6-bsd.internal.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
@ -29,12 +30,14 @@ struct sockaddr_un_bsd {
|
|||
union sockaddr_storage_bsd {
|
||||
struct sockaddr_bsd sa;
|
||||
struct sockaddr_in_bsd sin;
|
||||
struct sockaddr_in6_bsd sin6;
|
||||
struct sockaddr_un_bsd sun;
|
||||
};
|
||||
|
||||
union sockaddr_storage_linux {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr_un sun;
|
||||
};
|
||||
|
||||
|
|
18
libc/sock/struct/sockaddr6-bsd.internal.h
Normal file
18
libc/sock/struct/sockaddr6-bsd.internal.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR6_BSD_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR6_BSD_INTERNAL_H_
|
||||
#include "libc/sock/struct/sockaddr6.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct sockaddr_in6_bsd {
|
||||
uint8_t sin6_len;
|
||||
uint8_t sin6_family;
|
||||
uint16_t sin6_port;
|
||||
uint32_t sin6_flowinfo;
|
||||
struct in6_addr sin6_addr;
|
||||
uint32_t sin6_scope_id;
|
||||
};
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR6_BSD_INTERNAL_H_ */
|
|
@ -17,47 +17,22 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
forceinline void longsorter(long *x, size_t n, size_t t) {
|
||||
long a, b, c;
|
||||
size_t i, p, q;
|
||||
for (p = t; p > 0; p >>= 1) {
|
||||
for (i = 0; i < n - p; ++i) {
|
||||
if (!(i & p)) {
|
||||
a = x[i + 0];
|
||||
b = x[i + p];
|
||||
if (a > b) c = a, a = b, b = c;
|
||||
x[i + 0] = a;
|
||||
x[i + p] = b;
|
||||
}
|
||||
}
|
||||
for (q = t; q > p; q >>= 1) {
|
||||
for (i = 0; i < n - q; ++i) {
|
||||
if (!(i & p)) {
|
||||
a = x[i + p];
|
||||
b = x[i + q];
|
||||
if (a > b) c = a, a = b, b = c;
|
||||
x[i + p] = a;
|
||||
x[i + q] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void longsorter(long *A, size_t n) {
|
||||
long t, p;
|
||||
size_t i, j;
|
||||
if (n < 2) return;
|
||||
for (p = A[n / 2], i = 0, j = n - 1;; i++, j--) {
|
||||
while (A[i] < p) i++;
|
||||
while (A[j] > p) j--;
|
||||
if (i >= j) break;
|
||||
t = A[i];
|
||||
A[i] = A[j];
|
||||
A[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
static microarchitecture("avx2") optimizespeed noasan
|
||||
void longsort_avx2(long *x, size_t n, size_t t) {
|
||||
longsorter(x, n, t);
|
||||
}
|
||||
|
||||
static optimizesize noasan void longsort_pure(long *x, size_t n, size_t t) {
|
||||
longsorter(x, n, t);
|
||||
longsorter(A, i);
|
||||
longsorter(A + i, n - i);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,21 +42,9 @@ static optimizesize noasan void longsort_pure(long *x, size_t n, size_t t) {
|
|||
* -Lord Capulet
|
||||
*
|
||||
*/
|
||||
void longsort(long *x, size_t n) {
|
||||
size_t t, m;
|
||||
if (IsAsan()) {
|
||||
if (__builtin_mul_overflow(n, sizeof(long), &m)) m = -1;
|
||||
__asan_verify(x, m);
|
||||
}
|
||||
if (n > 1) {
|
||||
t = 1ul << bsrl(n - 1);
|
||||
if (!IsTiny() && X86_HAVE(AVX2)) {
|
||||
longsort_avx2(x, n, t);
|
||||
} else {
|
||||
longsort_pure(x, n, t);
|
||||
}
|
||||
}
|
||||
void longsort(long *A, size_t n) {
|
||||
longsorter(A, n);
|
||||
if (n > 1000) {
|
||||
STRACE("longsort(%p, %'zu)", x, n);
|
||||
STRACE("longsort(%p, %'zu)", A, n);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue