Merge pull request #2634 from skunkwerks/feature/add-freebsd

support FreeBSD
This commit is contained in:
Alex Miller 2020-04-30 22:00:45 -07:00 committed by GitHub
commit 9f2c07a97c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 633 additions and 56 deletions

View File

@ -146,6 +146,10 @@ set(SEED "0x${SEED_}" CACHE STRING "Random seed for testing")
# components
################################################################################
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
include_directories(/usr/local/include)
endif()
include(CompileBoost)
add_subdirectory(flow)
add_subdirectory(fdbrpc)
@ -173,6 +177,10 @@ else()
include(CPack)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
add_link_options(-lexecinfo)
endif()
################################################################################
# process compile commands for IDE
################################################################################

View File

@ -123,6 +123,37 @@ cmake -G Xcode -DOPEN_FOR_IDE=ON <FDB_SOURCE_DIRECTORY>
You should create a second build-directory which you will use for building
(probably with make or ninja) and debugging.
#### FreeBSD
1. Check out this repo on your server.
1. Install compile-time dependencies from ports.
1. (Optional) Use tmpfs & ccache for significantly faster repeat builds
1. (Optional) Install a [JDK](https://www.freshports.org/java/openjdk8/)
for Java Bindings. FoundationDB currently builds with Java 8.
1. Navigate to the directory where you checked out the foundationdb
repo.
1. Build from source.
```shell
sudo pkg install -r FreeBSD \
shells/bash devel/cmake devel/ninja devel/ccache \
lang/mono lang/python3 \
devel/boost-libs devel/libeio \
security/openssl
mkdir .build && cd .build
cmake -G Ninja \
-DUSE_CCACHE=on \
-DDISABLE_TLS=off \
-DUSE_DTRACE=off \
..
ninja -j 10
# run fast tests
ctest -L fast
# run all tests
ctest --output-on-failure -v
```
### Linux
There are no special requirements for Linux. A docker image can be pulled from

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
######################################################
#
# FoundationDB Binding Test Script

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
LOGGING_LEVEL=WARNING

View File

@ -61,7 +61,7 @@ def write_windows_asm(asmfile, functions):
def write_unix_asm(asmfile, functions, prefix):
asmfile.write(".intel_syntax noprefix\n")
if platform == "linux":
if platform == "linux" or platform == "freebsd":
asmfile.write("\n.data\n")
for f in functions:
asmfile.write("\t.extern fdb_api_ptr_%s\n" % f)

View File

@ -12,6 +12,9 @@
#if defined(__linux__)
#include <linux/limits.h>
#elif defined(__FreeBSD__)
#include <sys/stat.h>
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST
#elif defined(__APPLE__)
#include <sys/syslimits.h>
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC

View File

@ -25,6 +25,9 @@ platform=$(uname)
if [[ "${platform}" == "Darwin" ]] ; then
FDBLIBDIR="${FDBLIBDIR:-/usr/local/lib}"
libfdbc="libfdb_c.dylib"
elif [[ "${platform}" == "FreeBSD" ]] ; then
FDBLIBDIR="${FDBLIBDIR:-/lib}"
libfdbc="libfdb_c.so"
elif [[ "${platform}" == "Linux" ]] ; then
libfdbc="libfdb_c.so"
custom_libdir="${FDBLIBDIR:-}"
@ -248,8 +251,11 @@ else
:
elif [[ "${status}" -eq 0 ]] ; then
echo "Building generated files."
if [[ "${platform}" == "FreeBSD" ]] ; then
cmd=( 'gmake' '-C' "${fdbdir}" 'bindings/c/foundationdb/fdb_c_options.g.h' )
else
cmd=( 'make' '-C' "${fdbdir}" 'bindings/c/foundationdb/fdb_c_options.g.h' )
fi
echo "${cmd[*]}"
if ! "${cmd[@]}" ; then
let status="${status} + 1"

View File

@ -1231,6 +1231,8 @@ if platform.system() == 'Windows':
capi_name = 'fdb_c.dll'
elif platform.system() == 'Linux':
capi_name = 'libfdb_c.so'
elif platform.system() == 'FreeBSD':
capi_name = 'libfdb_c.so'
elif platform.system() == 'Darwin':
capi_name = 'libfdb_c.dylib'
elif sys.platform == 'win32':

View File

@ -1,6 +1,7 @@
include(CompilerChecks)
env_set(USE_GPERFTOOLS OFF BOOL "Use gperfools for profiling")
env_set(USE_DTRACE ON BOOL "Enable dtrace probes on supported platforms")
env_set(USE_VALGRIND OFF BOOL "Compile for valgrind usage")
env_set(USE_VALGRIND_FOR_CTEST ${USE_VALGRIND} BOOL "Use valgrind for ctest")
env_set(ALLOC_INSTRUMENTATION OFF BOOL "Instrument alloc")
@ -255,7 +256,7 @@ else()
check_symbol_exists(DTRACE_PROBE sys/sdt.h SUPPORT_DTRACE)
check_symbol_exists(aligned_alloc stdlib.h HAS_ALIGNED_ALLOC)
message(STATUS "Has aligned_alloc: ${HAS_ALIGNED_ALLOC}")
if(SUPPORT_DTRACE)
if((SUPPORT_DTRACE) AND (USE_DTRACE))
add_compile_definitions(DTRACE_PROBES)
endif()
if(HAS_ALIGNED_ALLOC)

View File

@ -47,7 +47,8 @@ endif()
set(WITH_JAVA OFF)
find_package(JNI 1.8)
find_package(Java 1.8 COMPONENTS Development)
if(JNI_FOUND AND Java_FOUND AND Java_Development_FOUND)
# leave FreeBSD JVM compat for later
if(JNI_FOUND AND Java_FOUND AND Java_Development_FOUND AND NOT (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD"))
set(WITH_JAVA ON)
include(UseJava)
enable_language(Java)

View File

@ -37,6 +37,11 @@
#include <linux/limits.h>
#endif
#ifdef __FreeBSD__
#include <sys/event.h>
#define O_EVTONLY O_RDONLY
#endif
#ifdef __APPLE__
#include <sys/event.h>
#include <mach/mach.h>
@ -78,7 +83,7 @@
#ifdef __linux__
typedef fd_set* fdb_fd_set;
#elif defined __APPLE__
#elif defined(__APPLE__) || defined(__FreeBSD__)
typedef int fdb_fd_set;
#endif
@ -89,7 +94,7 @@ void monitor_fd( fdb_fd_set list, int fd, int* maxfd, void* cmd ) {
FD_SET( fd, list );
if ( fd > *maxfd )
*maxfd = fd;
#elif defined __APPLE__
#elif defined(__APPLE__) || defined(__FreeBSD__)
/* ignore maxfd */
struct kevent ev;
EV_SET( &ev, fd, EVFILT_READ, EV_ADD, 0, 0, cmd );
@ -100,7 +105,7 @@ void monitor_fd( fdb_fd_set list, int fd, int* maxfd, void* cmd ) {
void unmonitor_fd( fdb_fd_set list, int fd ) {
#ifdef __linux__
FD_CLR( fd, list );
#elif defined __APPLE__
#elif defined(__APPLE__) || defined(__FreeBSD__)
struct kevent ev;
EV_SET( &ev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL );
kevent( list, &ev, 1, NULL, 0, NULL ); // FIXME: check?
@ -194,7 +199,7 @@ const char* get_value_multi(const CSimpleIni& ini, const char* key, ...) {
}
double timer() {
#if defined(__linux__)
#if defined(__linux__) || defined(__FreeBSD__)
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return double(ts.tv_sec) + (ts.tv_nsec * 1e-9);
@ -913,7 +918,7 @@ void read_child_output( Command* cmd, int pipe_idx, fdb_fd_set fds ) {
}
}
#ifdef __APPLE__
#if defined(__APPLE__) || defined(__FreeBSD__)
void watch_conf_dir( int kq, int* confd_fd, std::string confdir ) {
struct kevent ev;
std::string original = confdir;
@ -1171,7 +1176,11 @@ int main(int argc, char** argv) {
// testPathOps(); return -1;
std::string lockfile = "/var/run/fdbmonitor.pid";
#ifdef __FreeBSD__
std::string _confpath = "/usr/local/etc/foundationdb/foundationdb.conf";
#else
std::string _confpath = "/etc/foundationdb/foundationdb.conf";
#endif
std::vector<const char *> additional_watch_paths;
@ -1266,12 +1275,12 @@ int main(int argc, char** argv) {
#endif
if (daemonize) {
#ifdef __APPLE__
#if defined(__APPLE__) || defined(__FreeBSD__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
if (daemon(0, 0)) {
#ifdef __APPLE__
#if defined(__APPLE__) || defined(__FreeBSD__)
#pragma GCC diagnostic pop
#endif
log_err("daemon", errno, "Unable to daemonize");
@ -1330,7 +1339,7 @@ int main(int argc, char** argv) {
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
#elif defined(__APPLE__)
#elif defined(__APPLE__) || defined(__FreeBSD__)
int kq = kqueue();
if ( kq < 0 ) {
log_err( "kqueue", errno, "Unable to create kqueue" );
@ -1375,11 +1384,11 @@ int main(int argc, char** argv) {
/* normal will be restored in our main loop in the call to
pselect, but none blocks all signals while processing events */
sigprocmask(SIG_SETMASK, &full_mask, &normal_mask);
#elif defined(__APPLE__)
#elif defined(__APPLE__) || defined(__FreeBSD__)
sigprocmask(0, NULL, &normal_mask);
#endif
#ifdef __APPLE__
#if defined(__APPLE__) || defined(__FreeBSD__)
struct stat st_buf;
struct timespec mtimespec;
@ -1438,7 +1447,7 @@ int main(int argc, char** argv) {
load_conf(confpath.c_str(), uid, gid, &normal_mask, &rfds, &maxfd);
reload_additional_watches = false;
#elif defined(__APPLE__)
#elif defined(__APPLE__) || defined(__FreeBSD__)
load_conf( confpath.c_str(), uid, gid, &normal_mask, watched_fds, &maxfd );
watch_conf_file( kq, &conff_fd, confpath.c_str() );
watch_conf_dir( kq, &confd_fd, confdir );
@ -1476,7 +1485,7 @@ int main(int argc, char** argv) {
if(nfds == 0) {
reload = true;
}
#elif defined(__APPLE__)
#elif defined(__APPLE__) || defined(__FreeBSD__)
int nev = 0;
if(timeout < 0) {
nev = kevent( kq, NULL, 0, &ev, 1, NULL );

View File

@ -49,7 +49,16 @@ if(APPLE)
list(APPEND FDBRPC_THIRD_PARTY_SRCS libcoroutine/asm.S)
endif()
if(NOT WIN32)
list(APPEND FDBRPC_THIRD_PARTY_SRCS libcoroutine/context.c libeio/eio.c)
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
find_library(EIO eio)
if(EIO)
list(APPEND FDBRPC_THIRD_PARTY_SRCS libcoroutine/context.c)
else()
list(APPEND FDBRPC_THIRD_PARTY_SRCS libcoroutine/context.c libeio/eio.c)
endif()
else()
list(APPEND FDBRPC_THIRD_PARTY_SRCS libcoroutine/context.c libeio/eio.c)
endif()
endif()
add_library(thirdparty STATIC ${FDBRPC_THIRD_PARTY_SRCS})

142
fdbrpc/libeio/config.h.FreeBSD Executable file
View File

@ -0,0 +1,142 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* fdatasync(2) is available */
#define HAVE_FDATASYNC 1
/* futimes(2) is available */
#define HAVE_FUTIMES 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* fallocate(2) is available */
/* #undef HAVE_LINUX_FALLOCATE */
/* Define to 1 if you have the <linux/fiemap.h> header file. */
/* #undef HAVE_LINUX_FIEMAP_H */
/* Define to 1 if you have the <linux/fs.h> header file. */
/* #undef HAVE_LINUX_FS_H */
/* splice/vmsplice/tee(2) are available */
/* #undef HAVE_LINUX_SPLICE */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* posix_fadvise(2) is available */
#define HAVE_POSIX_FADVISE 1
/* posix_madvise(2) is available */
#define HAVE_POSIX_MADVISE 1
/* prctl(PR_SET_NAME) is available */
/* #undef HAVE_PRCTL_SET_NAME */
/* readahead(2) is available (linux) */
/* #undef HAVE_READAHEAD */
/* sendfile(2) is available and supported */
#define HAVE_SENDFILE 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* sync_file_range(2) is available */
/* #undef HAVE_SYNC_FILE_RANGE */
/* Define to 1 if you have the <sys/prctl.h> header file. */
/* #undef HAVE_SYS_PRCTL_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* syscall(__NR_syncfs) is available */
/* #undef HAVE_SYS_SYNCFS */
/* Define to 1 if you have the <sys/syscall.h> header file. */
#define HAVE_SYS_SYSCALL_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* utimes(2) is available */
#define HAVE_UTIMES 1
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libeio"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME ""
/* Define to the full name and version of this package. */
#define PACKAGE_STRING ""
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# define _TANDEM_SOURCE 1
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
#endif
/* Version number of package */
#define VERSION "1.0"
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
/* #undef _POSIX_1_SOURCE */
/* Define to 1 if you need to in order for `stat' and other things to work. */
/* #undef _POSIX_SOURCE */

View File

@ -39,6 +39,8 @@
#ifdef __linux__
#include "config.h.linux"
#elif defined(__FreeBSD__)
#include "config.h.FreeBSD"
#elif defined(__APPLE__)
#include "config.h.osx"
#endif

View File

@ -60,7 +60,7 @@
#include "fdbmonitor/SimpleIni.h"
#ifdef __linux__
#if defined(__linux__) || defined(__FreeBSD__)
#include <execinfo.h>
#include <signal.h>
#ifdef ALLOC_INSTRUMENTATION
@ -75,6 +75,7 @@
#endif
#include "flow/SimpleOpt.h"
#include <fstream>
#include "flow/actorcompiler.h" // This must be the last #include.
// clang-format off
@ -291,7 +292,7 @@ public:
throw platform_error();
}
permission.set_permissions( &sa );
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
// There is nothing to do here, since the default permissions are fine
#else
#error Port me!
@ -301,7 +302,7 @@ public:
virtual ~WorldReadablePermissions() {
#ifdef _WIN32
LocalFree( sa.lpSecurityDescriptor );
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
// There is nothing to do here, since the default permissions are fine
#else
#error Port me!

View File

@ -48,6 +48,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#if defined(__linux__) || defined(__FreeBSD__)
#ifdef USE_GPERFTOOLS
#include "gperftools/profiler.h"
#include "gperftools/heap-profiler.h"
@ -526,7 +528,7 @@ ACTOR Future<Void> registrationClient(
}
}
#if defined(__linux__) && defined(USE_GPERFTOOLS)
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS)
//A set of threads that should be profiled
std::set<std::thread::id> profiledThreads;
@ -538,7 +540,7 @@ int filter_in_thread(void *arg) {
//Enables the calling thread to be profiled
void registerThreadForProfiling() {
#if defined(__linux__) && defined(USE_GPERFTOOLS)
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS)
//Not sure if this is actually needed, but a call to backtrace was advised here:
//http://groups.google.com/group/google-perftools/browse_thread/thread/0dfd74532e038eb8/2686d9f24ac4365f?pli=1
profiledThreads.insert(std::this_thread::get_id());
@ -552,7 +554,7 @@ void registerThreadForProfiling() {
void updateCpuProfiler(ProfilerRequest req) {
switch (req.type) {
case ProfilerRequest::Type::GPROF:
#if defined(__linux__) && defined(USE_GPERFTOOLS) && !defined(VALGRIND)
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS) && !defined(VALGRIND)
switch (req.action) {
case ProfilerRequest::Action::ENABLE: {
const char *path = (const char*)req.outputFile.begin();

View File

@ -94,6 +94,13 @@ elseif(WIN32)
target_link_libraries(flow PUBLIC winmm.lib)
target_link_libraries(flow PUBLIC psapi.lib)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set (FLOW_LIBS ${FLOW_LIBS} execinfo devstat)
find_library(EIO eio)
if(EIO)
target_link_libraries(flow PUBLIC ${EIO})
endif()
endif()
target_link_libraries(flow PRIVATE ${FLOW_LIBS})
if(USE_VALGRIND)
target_link_libraries(flow PUBLIC Valgrind)

View File

@ -41,6 +41,10 @@
#include <linux/mman.h>
#endif
#ifdef __FreeBSD__
#include <sys/mman.h>
#endif
#define FAST_ALLOCATOR_DEBUG 0
#ifdef _MSC_VER
@ -54,6 +58,8 @@
#elif defined(__GNUG__)
#ifdef __linux__
#define INIT_SEG __attribute__ ((init_priority (1000)))
#elif defined(__FreeBSD__)
#define INIT_SEG __attribute__ ((init_priority (1000)))
#elif defined(__APPLE__)
#pragma message "init_priority is not supported on this platform; will this be a problem?"
#define INIT_SEG

View File

@ -55,7 +55,7 @@ intptr_t g_stackYieldLimit = 0;
using namespace boost::asio::ip;
#if defined(__linux__)
#if defined(__linux__) || defined(__FreeBSD__)
#include <execinfo.h>
std::atomic<int64_t> net2RunLoopIterations(0);

View File

@ -104,6 +104,39 @@
#include <sys/sysmacros.h>
#endif
#ifdef __FreeBSD__
/* Needed for processor affinity */
#include <sys/sched.h>
/* Needed for getProcessorTime and setpriority */
#include <sys/syscall.h>
/* Needed for setpriority */
#include <sys/resource.h>
/* Needed for crash handler */
#include <sys/signal.h>
/* Needed for proc info */
#include <sys/user.h>
/* Needed for vm info */
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <sys/cpuset.h>
#include <sys/resource.h>
/* Needed for sysctl info */
#include <sys/sysctl.h>
#include <sys/fcntl.h>
/* Needed for network info */
#include <net/if.h>
#include <net/if_mib.h>
#include <net/if_var.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/tcp_var.h>
/* Needed for device info */
#include <devstat.h>
#include <kvm.h>
#include <libutil.h>
#endif
#ifdef __APPLE__
#include <sys/uio.h>
#include <sys/syslimits.h>
@ -203,7 +236,7 @@ double getProcessorTimeThread() {
throw platform_error();
}
return FiletimeAsInt64(ftKernel) / double(1e7) + FiletimeAsInt64(ftUser) / double(1e7);
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
return getProcessorTimeGeneric(RUSAGE_THREAD);
#elif defined(__APPLE__)
/* No RUSAGE_THREAD so we use the lower level interface */
@ -255,6 +288,29 @@ uint64_t getResidentMemoryUsage() {
rssize *= sysconf(_SC_PAGESIZE);
return rssize;
#elif defined(__FreeBSD__)
uint64_t rssize = 0;
int status;
pid_t ppid = getpid();
int pidinfo[4];
pidinfo[0] = CTL_KERN;
pidinfo[1] = KERN_PROC;
pidinfo[2] = KERN_PROC_PID;
pidinfo[3] = (int)ppid;
struct kinfo_proc procstk;
size_t len = sizeof(procstk);
status = sysctl(pidinfo, nitems(pidinfo), &procstk, &len, NULL, 0);
if (status < 0){
TraceEvent(SevError, "GetResidentMemoryUsage").GetLastError();
throw platform_error();
}
rssize = (uint64_t)procstk.ki_rssize;
return rssize;
#elif defined(_WIN32)
PROCESS_MEMORY_COUNTERS_EX pmc;
@ -292,6 +348,29 @@ uint64_t getMemoryUsage() {
vmsize *= sysconf(_SC_PAGESIZE);
return vmsize;
#elif defined(__FreeBSD__)
uint64_t vmsize = 0;
int status;
pid_t ppid = getpid();
int pidinfo[4];
pidinfo[0] = CTL_KERN;
pidinfo[1] = KERN_PROC;
pidinfo[2] = KERN_PROC_PID;
pidinfo[3] = (int)ppid;
struct kinfo_proc procstk;
size_t len = sizeof(procstk);
status = sysctl(pidinfo, nitems(pidinfo), &procstk, &len, NULL, 0);
if (status < 0){
TraceEvent(SevError, "GetMemoryUsage").GetLastError();
throw platform_error();
}
vmsize = (uint64_t)procstk.ki_size >> PAGE_SHIFT;
return vmsize;
#elif defined(_WIN32)
PROCESS_MEMORY_COUNTERS_EX pmc;
@ -401,6 +480,52 @@ void getMachineRAMInfo(MachineRAMInfo& memInfo) {
memInfo.available = 1024 * (std::max<int64_t>(0, (memFree-lowWatermark) + std::max(pageCache-lowWatermark, pageCache/2) + std::max(slabReclaimable-lowWatermark, slabReclaimable/2)) - usedSwap);
}
memInfo.committed = memInfo.total - memInfo.available;
#elif defined(__FreeBSD__)
int status;
u_int page_size;
u_int free_count;
u_int active_count;
u_int inactive_count;
u_int wire_count;
size_t uint_size;
uint_size = sizeof(page_size);
status = sysctlbyname("vm.stats.vm.v_page_size", &page_size, &uint_size, NULL, 0);
if (status < 0){
TraceEvent(SevError, "GetMachineMemInfo").GetLastError();
throw platform_error();
}
status = sysctlbyname("vm.stats.vm.v_free_count", &free_count, &uint_size, NULL, 0);
if (status < 0){
TraceEvent(SevError, "GetMachineMemInfo").GetLastError();
throw platform_error();
}
status = sysctlbyname("vm.stats.vm.v_active_count", &active_count, &uint_size, NULL, 0);
if (status < 0){
TraceEvent(SevError, "GetMachineMemInfo").GetLastError();
throw platform_error();
}
status = sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count, &uint_size, NULL, 0);
if (status < 0){
TraceEvent(SevError, "GetMachineMemInfo").GetLastError();
throw platform_error();
}
status = sysctlbyname("vm.stats.vm.v_wire_count", &wire_count, &uint_size, NULL, 0);
if (status < 0){
TraceEvent(SevError, "GetMachineMemInfo").GetLastError();
throw platform_error();
}
memInfo.total = (int64_t)((free_count + active_count + inactive_count + wire_count) * (u_int64_t)(page_size));
memInfo.available = (int64_t)(free_count * (u_int64_t)(page_size));
memInfo.committed = memInfo.total - memInfo.available;
#elif defined(_WIN32)
MEMORYSTATUSEX mem_status;
@ -456,7 +581,7 @@ Error systemErrorCodeToError() {
void getDiskBytes(std::string const& directory, int64_t& free, int64_t& total) {
INJECT_FAULT( platform_error, "getDiskBytes" );
#if defined(__unixish__)
#ifdef __linux__
#if defined (__linux__) || defined (__FreeBSD__)
struct statvfs buf;
if (statvfs(directory.c_str(), &buf)) {
Error e = systemErrorCodeToError();
@ -755,6 +880,196 @@ dev_t getDeviceId(std::string path) {
#endif
#if defined(__FreeBSD__)
void getNetworkTraffic(const IPAddress ip, uint64_t& bytesSent, uint64_t& bytesReceived,
uint64_t& outSegs, uint64_t& retransSegs) {
INJECT_FAULT( platform_error, "getNetworkTraffic" );
const char* ifa_name = nullptr;
try {
ifa_name = getInterfaceName(ip);
}
catch(Error &e) {
if(e.code() != error_code_platform_error) {
throw;
}
}
if (!ifa_name)
return;
struct ifaddrs *interfaces = NULL;
if (getifaddrs(&interfaces))
{
TraceEvent(SevError, "GetNetworkTrafficError").GetLastError();
throw platform_error();
}
int if_count, i;
int mib[6];
size_t ifmiblen;
struct ifmibdata ifmd;
mib[0] = CTL_NET;
mib[1] = PF_LINK;
mib[2] = NETLINK_GENERIC;
mib[3] = IFMIB_IFDATA;
mib[4] = IFMIB_IFCOUNT;
mib[5] = IFDATA_GENERAL;
ifmiblen = sizeof(ifmd);
for (i = 1; i <= if_count; i++)
{
mib[4] = i;
sysctl(mib, 6, &ifmd, &ifmiblen, (void *)0, 0);
if (!strcmp(ifmd.ifmd_name, ifa_name))
{
bytesSent = ifmd.ifmd_data.ifi_obytes;
bytesReceived = ifmd.ifmd_data.ifi_ibytes;
break;
}
}
freeifaddrs(interfaces);
struct tcpstat tcpstat;
size_t stat_len;
stat_len = sizeof(tcpstat);
int tcpstatus = sysctlbyname("net.inet.tcp.stats", &tcpstat, &stat_len, NULL, 0);
if (tcpstatus < 0) {
TraceEvent(SevError, "GetNetworkTrafficError").GetLastError();
throw platform_error();
}
outSegs = tcpstat.tcps_sndtotal;
retransSegs = tcpstat.tcps_sndrexmitpack;
}
void getMachineLoad(uint64_t& idleTime, uint64_t& totalTime, bool logDetails) {
INJECT_FAULT( platform_error, "getMachineLoad" );
long cur[CPUSTATES], last[CPUSTATES];
size_t cur_sz = sizeof cur;
int cpustate;
long sum;
memset(last, 0, sizeof last);
if (sysctlbyname("kern.cp_time", &cur, &cur_sz, NULL, 0) < 0)
{
TraceEvent(SevError, "GetMachineLoad").GetLastError();
throw platform_error();
}
sum = 0;
for (cpustate = 0; cpustate < CPUSTATES; cpustate++)
{
long tmp = cur[cpustate];
cur[cpustate] -= last[cpustate];
last[cpustate] = tmp;
sum += cur[cpustate];
}
totalTime = (uint64_t)(cur[CP_USER] + cur[CP_NICE] + cur[CP_SYS] + cur[CP_IDLE]);
idleTime = (uint64_t)(cur[CP_IDLE]);
//need to add logging here to TraceEvent
}
void getDiskStatistics(std::string const& directory, uint64_t& currentIOs, uint64_t& busyTicks, uint64_t& reads, uint64_t& writes, uint64_t& writeSectors, uint64_t& readSectors) {
INJECT_FAULT( platform_error, "getDiskStatistics" );
currentIOs = 0;
busyTicks = 0;
reads = 0;
writes = 0;
writeSectors = 0;
readSectors = 0;
struct stat buf;
if (stat(directory.c_str(), &buf)) {
TraceEvent(SevError, "GetDiskStatisticsStatError").detail("Directory", directory).GetLastError();
throw platform_error();
}
static struct statinfo dscur;
double etime;
struct timespec ts;
static int num_devices;
kvm_t *kd = NULL;
etime = ts.tv_nsec * 1e-6;;
int dn;
u_int64_t total_transfers_read, total_transfers_write;
u_int64_t total_blocks_read, total_blocks_write;
u_int64_t queue_len;
long double ms_per_transaction;
dscur.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo));
if (dscur.dinfo == NULL) {
TraceEvent(SevError, "GetDiskStatisticsStatError").GetLastError();
throw platform_error();
}
if (devstat_getdevs(kd, &dscur) == -1) {
TraceEvent(SevError, "GetDiskStatisticsStatError").GetLastError();
throw platform_error();
}
num_devices = dscur.dinfo->numdevs;
for (dn = 0; dn < num_devices; dn++)
{
if (devstat_compute_statistics(&dscur.dinfo->devices[dn], NULL, etime,
DSM_MS_PER_TRANSACTION, &ms_per_transaction,
DSM_TOTAL_TRANSFERS_READ, &total_transfers_read,
DSM_TOTAL_TRANSFERS_WRITE, &total_transfers_write,
DSM_TOTAL_BLOCKS_READ, &total_blocks_read,
DSM_TOTAL_BLOCKS_WRITE, &total_blocks_write,
DSM_QUEUE_LENGTH, &queue_len,
DSM_NONE) != 0) {
TraceEvent(SevError, "GetDiskStatisticsStatError").GetLastError();
throw platform_error();
}
currentIOs = queue_len;
busyTicks = (u_int64_t)ms_per_transaction;
reads = total_transfers_read;
writes = total_transfers_write;
writeSectors = total_blocks_read;
readSectors = total_blocks_write;
}
}
dev_t getDeviceId(std::string path) {
struct stat statInfo;
while (true) {
int returnValue = stat(path.c_str(), &statInfo);
if (!returnValue) break;
if (errno == ENOENT) {
path = parentDirectory(path);
} else {
TraceEvent(SevError, "GetDeviceIdError").detail("Path", path).GetLastError();
throw platform_error();
}
}
return statInfo.st_dev;
}
#endif
#ifdef __APPLE__
void getNetworkTraffic(const IPAddress& ip, uint64_t& bytesSent, uint64_t& bytesReceived, uint64_t& outSegs,
uint64_t& retransSegs) {
@ -1277,7 +1592,7 @@ struct OffsetTimer {
return offset + count * secondsPerCount;
}
};
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
#define DOUBLETIME(ts) (double(ts.tv_sec) + (ts.tv_nsec * 1e-9))
#ifndef CLOCK_MONOTONIC_RAW
#define CLOCK_MONOTONIC_RAW 4 // Confirmed safe to do with glibc >= 2.11 and kernel >= 2.6.28. No promises with older glibc. Older kernel definitely breaks it.
@ -1342,7 +1657,7 @@ double timer() {
GetSystemTimeAsFileTime(&fileTime);
static_assert( sizeof(fileTime) == sizeof(uint64_t), "FILETIME size wrong" );
return (*(uint64_t*)&fileTime - FILETIME_C_EPOCH) * 100e-9;
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return double(ts.tv_sec) + (ts.tv_nsec * 1e-9);
@ -1362,7 +1677,7 @@ uint64_t timer_int() {
GetSystemTimeAsFileTime(&fileTime);
static_assert( sizeof(fileTime) == sizeof(uint64_t), "FILETIME size wrong" );
return (*(uint64_t*)&fileTime - FILETIME_C_EPOCH);
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return uint64_t(ts.tv_sec) * 1e9 + ts.tv_nsec;
@ -1412,7 +1727,7 @@ void setMemoryQuota( size_t limit ) {
}
if (!AssignProcessToJobObject( job, GetCurrentProcess() ))
TraceEvent(SevWarn, "FailedToSetMemoryLimit").GetLastError();
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
struct rlimit rlim;
if (getrlimit(RLIMIT_AS, &rlim)) {
TraceEvent(SevError, "GetMemoryLimit").GetLastError();
@ -1514,7 +1829,7 @@ static void *allocateInternal(size_t length, bool largePages) {
flags |= MAP_HUGETLB;
return mmap(NULL, length, PROT_READ|PROT_WRITE, flags, -1, 0);
#elif defined(__APPLE__)
#elif defined(__APPLE__) || defined(__FreeBSD__)
int flags = MAP_PRIVATE|MAP_ANON;
return mmap(NULL, length, PROT_READ|PROT_WRITE, flags, -1, 0);
@ -1588,6 +1903,11 @@ void setAffinity(int proc) {
CPU_ZERO(&set);
CPU_SET(proc, &set);
sched_setaffinity(0, sizeof(cpu_set_t), &set);
#elif defined(__FreeBSD__)
cpuset_t set;
CPU_ZERO(&set);
CPU_SET(proc, &set);
cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,sizeof(set), &set);
#endif
}
@ -1648,7 +1968,7 @@ void renameFile( std::string const& fromPath, std::string const& toPath ) {
//renamedFile();
return;
}
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
if (!rename( fromPath.c_str(), toPath.c_str() )) {
//FIXME: We cannot inject faults after renaming the file, because we could end up with two asyncFileNonDurable open for the same file
//renamedFile();
@ -1814,7 +2134,7 @@ bool createDirectory( std::string const& directory ) {
Error e = systemErrorCodeToError();
TraceEvent(SevError, "CreateDirectory").detail("Directory", directory).GetLastError().error(e);
throw e;
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
size_t sep = 0;
do {
sep = directory.find_first_of('/', sep + 1);
@ -1967,8 +2287,7 @@ std::string abspath( std::string const& path, bool resolveLinks, bool mustExist
if (*x == '/')
*x = CANONICAL_PATH_SEPARATOR;
return nameBuffer;
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
char result[PATH_MAX];
// Must resolve links, so first try realpath on the whole thing
const char *r = realpath( path.c_str(), result );
@ -2031,7 +2350,7 @@ std::string getUserHomeDirectory() {
#ifdef _WIN32
#define FILE_ATTRIBUTE_DATA DWORD
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
#define FILE_ATTRIBUTE_DATA mode_t
#else
#error Port me!
@ -2040,7 +2359,7 @@ std::string getUserHomeDirectory() {
bool acceptFile( FILE_ATTRIBUTE_DATA fileAttributes, std::string name, std::string extension ) {
#ifdef _WIN32
return !(fileAttributes & FILE_ATTRIBUTE_DIRECTORY) && StringRef(name).endsWith(extension);
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
return S_ISREG(fileAttributes) && StringRef(name).endsWith(extension);
#else
#error Port me!
@ -2050,7 +2369,7 @@ bool acceptFile( FILE_ATTRIBUTE_DATA fileAttributes, std::string name, std::stri
bool acceptDirectory( FILE_ATTRIBUTE_DATA fileAttributes, std::string name, std::string extension ) {
#ifdef _WIN32
return (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
return S_ISDIR(fileAttributes);
#else
#error Port me!
@ -2086,7 +2405,7 @@ std::vector<std::string> findFiles( std::string const& directory, std::string co
}
FindClose(h);
}
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
DIR *dip;
if ((dip = opendir(directory.c_str())) != NULL) {
@ -2150,7 +2469,7 @@ void findFilesRecursively(std::string path, std::vector<std::string> &out) {
void threadSleep( double seconds ) {
#ifdef _WIN32
Sleep( (DWORD)(seconds * 1e3) );
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
struct timespec req, rem;
req.tv_sec = seconds;
@ -2201,7 +2520,7 @@ void setCloseOnExec( int fd ) {
THREAD_HANDLE startThread(void (*func) (void *), void *arg) {
return (void *)_beginthread(func, 0, arg);
}
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
THREAD_HANDLE startThread(void *(*func) (void *), void *arg) {
pthread_t t;
pthread_create(&t, NULL, func, arg);
@ -2214,7 +2533,7 @@ THREAD_HANDLE startThread(void *(*func) (void *), void *arg) {
void waitThread(THREAD_HANDLE thread) {
#ifdef _WIN32
WaitForSingleObject(thread, INFINITE);
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
pthread_join(thread, NULL);
#else
#error Port me!
@ -2256,7 +2575,7 @@ int64_t fileSize(std::string const& filename) {
return 0;
else
return file_status.st_size;
#elif (defined(__linux__) || defined(__APPLE__))
#elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
struct stat file_status;
if(stat(filename.c_str(), &file_status) != 0)
return 0;
@ -2395,7 +2714,7 @@ std::string getDefaultConfigPath() {
return _filepath + "\\foundationdb";
#elif defined(__linux__)
return "/etc/foundationdb";
#elif defined(__APPLE__)
#elif defined(__APPLE__) || defined(__FreeBSD__)
return "/usr/local/etc/foundationdb";
#else
#error Port me!
@ -2524,7 +2843,7 @@ int eraseDirectoryRecursive(std::string const& dir) {
__eraseDirectoryRecurseiveCount = 0;
#ifdef _WIN32
system( ("rd /s /q \"" + dir + "\"").c_str() );
#elif defined(__linux__) || defined(__APPLE__)
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
int error =
nftw(dir.c_str(),
[](const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) -> int {
@ -2701,7 +3020,7 @@ void* getImageOffset() { return NULL; }
#endif
bool isLibraryLoaded(const char* lib_path) {
#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32)
#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__FreeBSD__)
#error Port me!
#endif
@ -2717,7 +3036,7 @@ bool isLibraryLoaded(const char* lib_path) {
}
void* loadLibrary(const char* lib_path) {
#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32)
#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__FreeBSD__)
#error Port me!
#endif
@ -2774,6 +3093,20 @@ std::string exePath() {
} else {
throw platform_error();
}
#elif defined(__FreeBSD__)
char binPath[2048];
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
size_t len = sizeof(binPath);
if (sysctl(mib, 4, binPath, &len, NULL, 0) != 0) {
binPath[0] = '\0';
return std::string(binPath);
} else {
throw platform_error();
}
#elif defined(__APPLE__)
uint32_t bufSize = 1024;
std::unique_ptr<char[]> buf(new char[bufSize]);

View File

@ -22,7 +22,7 @@
#define FLOW_PLATFORM_H
#pragma once
#if (defined(__linux__) || defined(__APPLE__))
#if (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__))
#define __unixish__ 1
#endif
@ -172,6 +172,8 @@ THREAD_HANDLE startThread(void *(func) (void *), void *arg);
#define DYNAMIC_LIB_EXT ".dll"
#elif defined(__linux)
#define DYNAMIC_LIB_EXT ".so"
#elif defined(__FreeBSD__)
#define DYNAMIC_LIB_EXT ".so"
#elif defined(__APPLE__)
#define DYNAMIC_LIB_EXT ".dylib"
#else
@ -422,6 +424,16 @@ inline static uint64_t __rdtsc() {
#endif
#endif
#ifdef __FreeBSD__
#if !(__has_builtin(__rdtsc))
inline static uint64_t __rdtsc() {
uint64_t lo, hi;
asm( "rdtsc" : "=a" (lo), "=d" (hi) );
return( lo | (hi << 32) );
}
#endif
#endif
#ifdef _WIN32
#include <intrin.h>
inline static int32_t interlockedIncrement(volatile int32_t *a) { return _InterlockedIncrement((long*)a); }
@ -531,6 +543,8 @@ inline static void aligned_free(void* ptr) { free(ptr); }
#if (!defined(_ISOC11_SOURCE)) // old libc versions
inline static void* aligned_alloc(size_t alignment, size_t size) { return memalign(alignment, size); }
#endif
#elif defined(__FreeBSD__)
inline static void aligned_free(void* ptr) { free(ptr); }
#elif defined(__APPLE__)
#if !defined(HAS_ALIGNED_ALLOC)
#include <cstdlib>

View File

@ -37,7 +37,7 @@ extern std::string format( const char *form, ... );
Event::Event() {
#ifdef _WIN32
ev = CreateEvent(NULL, FALSE, FALSE, NULL);
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
int result = sem_init(&sem, 0, 0);
if (result)
criticalError(FDB_EXIT_INIT_SEMAPHORE, "UnableToInitializeSemaphore", format("Could not initialize semaphore - %s", strerror(errno)).c_str());
@ -54,7 +54,7 @@ Event::Event() {
Event::~Event() {
#ifdef _WIN32
CloseHandle(ev);
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
sem_destroy(&sem);
#elif defined(__APPLE__)
semaphore_destroy(self, sem);
@ -66,7 +66,7 @@ Event::~Event() {
void Event::set() {
#ifdef _WIN32
SetEvent(ev);
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
sem_post(&sem);
#elif defined(__APPLE__)
semaphore_signal(sem);
@ -78,7 +78,7 @@ void Event::set() {
void Event::block() {
#ifdef _WIN32
WaitForSingleObject(ev, INFINITE);
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
int ret;
do {
ret = sem_wait(&sem);

View File

@ -25,7 +25,7 @@
#include "flow/Error.h"
#include "flow/Trace.h"
#ifdef __linux__
#if defined(__linux__) || defined(__FreeBSD__)
#include <semaphore.h>
#endif
@ -115,7 +115,7 @@ public:
private:
#ifdef _WIN32
void* ev;
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
sem_t sem;
#elif defined(__APPLE__)
mach_port_t self;