1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
// Xcode's Archive builds with Xcode's Package support struggle with empty .c files
// (https://bugs.swift.org/browse/SR-12939).
void CNIOLinux_i_do_nothing_just_working_around_a_darwin_toolchain_bug(void) {}
#ifdef __linux__
#ifndef _GNU_SOURCE
#error You must define _GNU_SOURCE
#endif
#include <CNIOLinux.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <sys/ioctl.h>
_Static_assert(sizeof(CNIOLinux_mmsghdr) == sizeof(struct mmsghdr),
"sizes of CNIOLinux_mmsghdr and struct mmsghdr differ");
_Static_assert(sizeof(CNIOLinux_in6_pktinfo) == sizeof(struct in6_pktinfo),
"sizes of CNIOLinux_in6_pktinfo and struct in6_pktinfo differ");
int CNIOLinux_sendmmsg(int sockfd, CNIOLinux_mmsghdr *msgvec, unsigned int vlen, int flags) {
// This is technically undefined behaviour, but it's basically fine because these types are the same size, and we
// don't think the compiler is inclined to blow anything up here.
return sendmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags);
}
int CNIOLinux_recvmmsg(int sockfd, CNIOLinux_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) {
// This is technically undefined behaviour, but it's basically fine because these types are the same size, and we
// don't think the compiler is inclined to blow anything up here.
return recvmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags, timeout);
}
int CNIOLinux_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
return accept4(sockfd, addr, addrlen, flags);
}
int CNIOLinux_pthread_setname_np(pthread_t thread, const char *name) {
return pthread_setname_np(thread, name);
}
int CNIOLinux_pthread_getname_np(pthread_t thread, char *name, size_t len) {
#ifdef __ANDROID__
// https://android.googlesource.com/platform/bionic/+/master/libc/bionic/pthread_setname_np.cpp#51
if (thread == pthread_self()) {
return TEMP_FAILURE_RETRY(prctl(PR_GET_NAME, name)) == -1 ? -1 : 0;
}
char comm_name[64];
snprintf(comm_name, sizeof(comm_name), "/proc/self/task/%d/comm", pthread_gettid_np(thread));
int fd = TEMP_FAILURE_RETRY(open(comm_name, O_CLOEXEC | O_RDONLY));
if (fd == -1) return -1;
ssize_t n = TEMP_FAILURE_RETRY(read(fd, name, len));
close(fd);
if (n == -1) return -1;
// The kernel adds a trailing '\n' to the /proc file,
// so this is actually the normal case for short names.
if (n > 0 && name[n - 1] == '\n') {
name[n - 1] = '\0';
return 0;
}
if (n >= 0 && len <= SSIZE_MAX && n == (ssize_t)len) return 1;
name[n] = '\0';
return 0;
#else
return pthread_getname_np(thread, name, len);
#endif
}
int CNIOLinux_pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset) {
#ifdef __ANDROID__
return sched_setaffinity(pthread_gettid_np(thread), cpusetsize, cpuset);
#else
return pthread_setaffinity_np(thread, cpusetsize, cpuset);
#endif
}
int CNIOLinux_pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset) {
#ifdef __ANDROID__
return sched_getaffinity(pthread_gettid_np(thread), cpusetsize, cpuset);
#else
return pthread_getaffinity_np(thread, cpusetsize, cpuset);
#endif
}
void CNIOLinux_CPU_SET(int cpu, cpu_set_t *set) {
CPU_SET(cpu, set);
}
void CNIOLinux_CPU_ZERO(cpu_set_t *set) {
CPU_ZERO(set);
}
int CNIOLinux_CPU_ISSET(int cpu, cpu_set_t *set) {
return CPU_ISSET(cpu, set);
}
int CNIOLinux_CPU_SETSIZE() {
return CPU_SETSIZE;
}
struct cmsghdr *CNIOLinux_CMSG_FIRSTHDR(const struct msghdr *mhdr) {
assert(mhdr != NULL);
return CMSG_FIRSTHDR(mhdr);
}
struct cmsghdr *CNIOLinux_CMSG_NXTHDR(struct msghdr *mhdr, struct cmsghdr *cmsg) {
assert(mhdr != NULL);
assert(cmsg != NULL);
return CMSG_NXTHDR(mhdr, cmsg);
}
const void *CNIOLinux_CMSG_DATA(const struct cmsghdr *cmsg) {
assert(cmsg != NULL);
return CMSG_DATA(cmsg);
}
void *CNIOLinux_CMSG_DATA_MUTABLE(struct cmsghdr *cmsg) {
assert(cmsg != NULL);
return CMSG_DATA(cmsg);
}
size_t CNIOLinux_CMSG_LEN(size_t payloadSizeBytes) {
return CMSG_LEN(payloadSizeBytes);
}
size_t CNIOLinux_CMSG_SPACE(size_t payloadSizeBytes) {
return CMSG_SPACE(payloadSizeBytes);
}
const int CNIOLinux_SO_TIMESTAMP = SO_TIMESTAMP;
const int CNIOLinux_SO_RCVTIMEO = SO_RCVTIMEO;
bool supports_udp_sockopt(int opt, int value) {
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) {
return false;
}
int rc = setsockopt(fd, IPPROTO_UDP, opt, &value, sizeof(value));
close(fd);
return rc == 0;
}
bool CNIOLinux_supports_udp_segment() {
#ifndef UDP_SEGMENT
return false;
#else
return supports_udp_sockopt(UDP_SEGMENT, 512);
#endif
}
bool CNIOLinux_supports_udp_gro() {
#ifndef UDP_GRO
return false;
#else
return supports_udp_sockopt(UDP_GRO, 1);
#endif
}
int CNIOLinux_system_info(struct utsname* uname_data) {
return uname(uname_data);
}
const unsigned long CNIOLinux_IOCTL_VM_SOCKETS_GET_LOCAL_CID = IOCTL_VM_SOCKETS_GET_LOCAL_CID;
const char* CNIOLinux_dirent_dname(struct dirent* ent) {
return ent->d_name;
}
int CNIOLinux_renameat2(int oldfd, const char* old, int newfd, const char* newName, unsigned int flags) {
// Musl doesn't have renameat2, so we make the raw system call directly
return syscall(SYS_renameat2, oldfd, old, newfd, newName, flags);
}
// Musl also doesn't define the flags for renameat2, so we will do so.
#ifndef RENAME_NOREPLACE
#define RENAME_NOREPLACE 1
#endif
#ifndef RENAME_EXCHANGE
#define RENAME_EXCHANGE 2
#endif
const int CNIOLinux_O_TMPFILE = O_TMPFILE;
const unsigned int CNIOLinux_RENAME_NOREPLACE = RENAME_NOREPLACE;
const unsigned int CNIOLinux_RENAME_EXCHANGE = RENAME_EXCHANGE;
const int CNIOLinux_AT_EMPTY_PATH = AT_EMPTY_PATH;
#endif
|