diff --git a/Makefile b/Makefile index 0800e659..0aad5964 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,15 @@ ifeq ($m, 64) ARCH = -m64 endif +UNAME_S := $(shell uname -s) + +ifeq ($(UNAME_S),FreeBSD) +CFLAGS = $(ARCH) -O3 -std=gnu11 -Wall -Wno-array-bounds -mpclmul -march=core2 -mfpmath=sse -mssse3 -fno-strict-aliasing -fwrapv -DAES=1 -DCOMMIT=\"${COMMIT}\" -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 -I/usr/local/include -I/usr/local/include/libepoll-shim +LDFLAGS = $(ARCH) -ggdb -L/usr/local/lib -lm -lcrypto -lz -lpthread -lepoll-shim -lexecinfo +else CFLAGS = $(ARCH) -O3 -std=gnu11 -Wall -Wno-array-bounds -mpclmul -march=core2 -mfpmath=sse -mssse3 -fno-strict-aliasing -fno-strict-overflow -fwrapv -DAES=1 -DCOMMIT=\"${COMMIT}\" -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 LDFLAGS = $(ARCH) -ggdb -rdynamic -lm -lrt -lcrypto -lz -lpthread -lcrypto +endif LIB = ${OBJ}/lib CINCLUDE = -iquote common -iquote . diff --git a/common/crc32.c b/common/crc32.c index a7a77fe5..69c4bd25 100644 --- a/common/crc32.c +++ b/common/crc32.c @@ -31,6 +31,19 @@ #include "common/cpuid.h" #include "common/kprintf.h" +/* Compatibility for GCC intrinsics when using clang */ +#ifdef __clang__ +#include +#include +#include + +#define __builtin_ia32_loaddqu(p) ((__m128i)_mm_loadu_si128((const __m128i *)(p))) +#define __builtin_ia32_pshufb128(a, b) ((__m128i)_mm_shuffle_epi8((__m128i)(a), (__m128i)(b))) +#define __builtin_ia32_pslldqi128(a, n) _mm_slli_si128((__m128i)(a), (n) / 8) +#define __builtin_ia32_psrldqi128(a, n) _mm_srli_si128((__m128i)(a), (n) / 8) +#define __builtin_ia32_punpckhqdq128(a, b) _mm_unpackhi_epi64((__m128i)(a), (__m128i)(b)) +#endif + #define FASTMOV_RMI32_TO_SSE(dst, src) \ asm volatile ("movd %1, %0\n\t" : "=x" (dst) : "g" (src)) diff --git a/common/mp-queue.c b/common/mp-queue.c index de69bd45..c6d32bb8 100644 --- a/common/mp-queue.c +++ b/common/mp-queue.c @@ -32,8 +32,14 @@ #include #include +#ifdef __linux__ #include #include +#endif +#ifdef __FreeBSD__ +#include +#include +#endif #include "server-functions.h" #include "kprintf.h" @@ -116,12 +122,16 @@ int get_this_thread_id (void) { return mpq_this_thread_id = i; } -/* custom semaphore implementation using futexes */ +/* custom semaphore implementation using futexes (Linux) or umtx (FreeBSD) */ int mp_sem_post (mp_sem_t *sem) { __sync_fetch_and_add (&sem->value, 1); if (sem->waiting > 0) { +#ifdef __linux__ syscall (__NR_futex, &sem->value, FUTEX_WAKE, 1, NULL, 0, 0); +#elif defined(__FreeBSD__) + _umtx_op (&sem->value, UMTX_OP_WAKE, 1, NULL, NULL); +#endif } return 0; } @@ -142,7 +152,11 @@ int mp_sem_wait (mp_sem_t *sem) { continue; } __sync_fetch_and_add (&sem->waiting, 1); +#ifdef __linux__ syscall (__NR_futex, &sem->value, FUTEX_WAIT, v, NULL, 0, 0); +#elif defined(__FreeBSD__) + _umtx_op (&sem->value, UMTX_OP_WAIT_UINT, v, NULL, NULL); +#endif __sync_fetch_and_add (&sem->waiting, -1); v = sem->value; q = 0; diff --git a/common/resolver.c b/common/resolver.c index b88f73ab..f0c4cb81 100644 --- a/common/resolver.c +++ b/common/resolver.c @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #include #include diff --git a/engine/engine.c b/engine/engine.c index 8489f038..f8be9ed0 100644 --- a/engine/engine.c +++ b/engine/engine.c @@ -310,7 +310,9 @@ void server_init (conn_type_t *listen_connection_type, void *listen_connection_e ksignal (SIGINT, sigint_handler); ksignal (SIGTERM, sigterm_handler); ksignal (SIGPIPE, empty_signal_handler); +#ifdef SIGPOLL ksignal (SIGPOLL, empty_signal_handler); +#endif if (daemonize) { ksignal (SIGHUP, default_signal_handler); @@ -534,11 +536,19 @@ static void check_server_functions (void) /* {{{ */ { check_signal_handler (F, SIGHUP, default_sighup); check_signal_handler (F, SIGUSR1, default_sigusr1); +#ifndef __FreeBSD__ check_signal_handler (F, SIGRTMAX-9, default_sigrtmax_9); check_signal_handler (F, SIGRTMAX-8, default_sigrtmax_8); check_signal_handler (F, SIGRTMAX-4, default_sigrtmax_4); check_signal_handler (F, SIGRTMAX-1, default_sigrtmax_1); check_signal_handler (F, SIGRTMAX, default_sigrtmax); +#else + check_signal_handler (F, OUR_SIGRTMAX-9, default_sigrtmax_9); + check_signal_handler (F, OUR_SIGRTMAX-8, default_sigrtmax_8); + check_signal_handler (F, OUR_SIGRTMAX-4, default_sigrtmax_4); + check_signal_handler (F, OUR_SIGRTMAX-1, default_sigrtmax_1); + check_signal_handler (F, OUR_SIGRTMAX, default_sigrtmax); +#endif if (!F->close_net_sockets) { F->close_net_sockets = default_close_network_sockets; } if (!F->cron) { F->cron = default_cron; } @@ -573,8 +583,10 @@ void engine_startup (engine_t *E, server_functions_t *F) /* {{{ */ { precise_now_diff = get_utime_monotonic () - get_double_time (); +#ifndef __FreeBSD__ assert (SIGRTMAX == OUR_SIGRTMAX); assert (SIGRTMAX - SIGRTMIN >= 20); +#endif E->sfd = 0; E->epoll_wait_timeout = DEFAULT_EPOLL_WAIT_TIMEOUT; diff --git a/engine/engine.h b/engine/engine.h index 776f56e3..d856d7a1 100644 --- a/engine/engine.h +++ b/engine/engine.h @@ -30,7 +30,12 @@ // GLIBC DEFINES RTMAX as function // engine_init () asserts, that OUT_SIGRTMAX == SIGRTMAX +// FreeBSD has SIGRTMAX=126 which doesn't fit in 64-bit signal mask, so use a lower value +#ifdef __FreeBSD__ +#define OUR_SIGRTMAX 63 +#else #define OUR_SIGRTMAX 64 +#endif #include "common/common-stats.h" #include "engine/engine-rpc.h" diff --git a/jobs/jobs.c b/jobs/jobs.c index 68b7d531..923bd5d1 100644 --- a/jobs/jobs.c +++ b/jobs/jobs.c @@ -20,7 +20,9 @@ */ #define _FILE_OFFSET_BITS 64 +#ifndef __FreeBSD__ #define _XOPEN_SOURCE 500 +#endif #define _GNU_SOURCE 1 #include @@ -33,10 +35,22 @@ #include #include #include +#include +#ifdef __linux__ #include #include -#include #include +#endif +#ifdef __FreeBSD__ +#include +#include +#include +#include +#include +#include +#include +static pthread_mutex_t drand48_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif #include "common/proc-stat.h" #include "crc32.h" @@ -369,6 +383,7 @@ __thread struct job_thread *this_job_thread; __thread job_t this_job; long int lrand48_j (void) { +#ifdef __linux__ if (this_job_thread) { long int t; lrand48_r (&this_job_thread->rand_data, &t); @@ -376,9 +391,17 @@ long int lrand48_j (void) { } else { return lrand48 (); } +#else + long int t; + pthread_mutex_lock (&drand48_mutex); + t = lrand48 (); + pthread_mutex_unlock (&drand48_mutex); + return t; +#endif } long int mrand48_j (void) { +#ifdef __linux__ if (this_job_thread) { long int t; mrand48_r (&this_job_thread->rand_data, &t); @@ -386,9 +409,17 @@ long int mrand48_j (void) { } else { return mrand48 (); } +#else + long int t; + pthread_mutex_lock (&drand48_mutex); + t = mrand48 (); + pthread_mutex_unlock (&drand48_mutex); + return t; +#endif } double drand48_j (void) { +#ifdef __linux__ if (this_job_thread) { double t; drand48_r (&this_job_thread->rand_data, &t); @@ -396,6 +427,13 @@ double drand48_j (void) { } else { return drand48 (); } +#else + double t; + pthread_mutex_lock (&drand48_mutex); + t = drand48 (); + pthread_mutex_unlock (&drand48_mutex); + return t; +#endif } struct mp_queue MainJobQueue __attribute__((aligned(128))); @@ -463,7 +501,13 @@ int create_job_thread_ex (int thread_class, void *(*thread_work)(void *)) { JT->id = i; assert (JT->job_queue); +#ifdef __linux__ srand48_r (rdtsc () ^ lrand48 (), &JT->rand_data); +#else + pthread_mutex_lock (&drand48_mutex); + srand48 (rdtsc () ^ lrand48 ()); + pthread_mutex_unlock (&drand48_mutex); +#endif if (thread_class != JC_MAIN) { @@ -889,7 +933,15 @@ void *job_thread_ex (void *arg, void (*work_one)(void *, int)) { assert (!(JT->thread_class & ~JC_MASK)); get_this_thread_id (); +#ifdef __linux__ JT->thread_system_id = syscall (SYS_gettid); +#elif defined(__FreeBSD__) + long tid; + thr_self (&tid); + JT->thread_system_id = (int) tid; +#else + JT->thread_system_id = (int) pthread_self (); +#endif set_job_interrupt_signal_handler (); diff --git a/jobs/jobs.h b/jobs/jobs.h index f249a0a4..35a90571 100644 --- a/jobs/jobs.h +++ b/jobs/jobs.h @@ -232,7 +232,9 @@ struct job_thread { long long jobs_created; long long jobs_active; int thread_system_id; +#ifdef __linux__ struct drand48_data rand_data; +#endif job_t timer_manager; double wakeup_time; struct job_class *job_class; diff --git a/mtproto/mtproto-proxy.c b/mtproto/mtproto-proxy.c index e28f36fc..18b55a99 100644 --- a/mtproto/mtproto-proxy.c +++ b/mtproto/mtproto-proxy.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -2098,9 +2099,11 @@ void mtfront_pre_loop (void) { listening_connection_job_t LC = Events[http_sfd[i]].data; assert (LC); CONN_INFO(LC)->window_clamp = window_clamp; +#ifdef TCP_WINDOW_CLAMP if (setsockopt (http_sfd[i], IPPROTO_TCP, TCP_WINDOW_CLAMP, &window_clamp, 4) < 0) { vkprintf (0, "error while setting window size for socket #%d to %d: %m\n", http_sfd[i], window_clamp); } +#endif } } // create_all_outbound_connections (); diff --git a/net/net-connections.c b/net/net-connections.c index d7a0cd7e..5a4cb28e 100644 --- a/net/net-connections.c +++ b/net/net-connections.c @@ -46,6 +46,11 @@ #include #include +/* libepoll-shim on FreeBSD defines close as a macro, which conflicts with struct members named 'close' */ +#ifdef close +#undef close +#endif + #include "crc32.h" #include "jobs/jobs.h" #include "net/net-events.h" @@ -321,8 +326,12 @@ void connection_write_close (connection_job_t C) /* {{{ */ { /* qack {{{ */ static inline void disable_qack (int fd) { +#ifdef TCP_QUICKACK vkprintf (2, "disable TCP_QUICKACK for %d\n", fd); assert (setsockopt (fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, sizeof (int)) >= 0); +#else + (void)fd; +#endif } static inline void cond_disable_qack (socket_connection_job_t C) { @@ -737,6 +746,7 @@ connection_job_t alloc_new_connection (int cfd, conn_target_job_t CTJ, listening } } } +#ifdef TCP_WINDOW_CLAMP if (c->window_clamp) { if (setsockopt (cfd, IPPROTO_TCP, TCP_WINDOW_CLAMP, &c->window_clamp, 4) < 0) { vkprintf (0, "error while setting window size for socket #%d to %d: %m\n", cfd, c->window_clamp); @@ -748,6 +758,7 @@ connection_job_t alloc_new_connection (int cfd, conn_target_job_t CTJ, listening vkprintf (2, "window clamp for socket #%d is %d, receive buffer is %d\n", cfd, t1, t2); } } +#endif } alloc_new_socket_connection (C); diff --git a/net/net-crypto-dh.c b/net/net-crypto-dh.c index b9aaa175..f16bb514 100644 --- a/net/net-crypto-dh.c +++ b/net/net-crypto-dh.c @@ -20,7 +20,9 @@ */ #define _FILE_OFFSET_BITS 64 +#ifndef __FreeBSD__ #define _XOPEN_SOURCE 500 +#endif #include diff --git a/net/net-events.c b/net/net-events.c index ba3e800c..4e6cfc3f 100644 --- a/net/net-events.c +++ b/net/net-events.c @@ -36,7 +36,9 @@ #include #include #include +#ifdef __linux__ #include +#endif #include #include #include @@ -568,7 +570,9 @@ int server_socket (int port, struct in_addr in_addr, int backlog, int mode) { if (mode & SM_UDP) { maximize_sndbuf (socket_fd, 0); maximize_rcvbuf (socket_fd, 0); +#ifdef IP_RECVERR setsockopt (socket_fd, SOL_IP, IP_RECVERR, &flags, sizeof (flags)); +#endif } else { setsockopt (socket_fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof (flags)); if (tcp_maximize_buffers) { @@ -644,7 +648,9 @@ int client_socket (in_addr_t in_addr, int port, int mode) { if (mode & SM_UDP) { maximize_sndbuf (socket_fd, 0); maximize_rcvbuf (socket_fd, 0); +#ifdef IP_RECVERR setsockopt (socket_fd, SOL_IP, IP_RECVERR, &flags, sizeof (flags)); +#endif } else { setsockopt (socket_fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof (flags)); if (tcp_maximize_buffers) { diff --git a/net/net-events.h b/net/net-events.h index 24e92c0f..2b1deb41 100644 --- a/net/net-events.h +++ b/net/net-events.h @@ -24,6 +24,7 @@ #pragma once +#include #include #ifndef EPOLLRDHUP