From 65323efaf1e90967f9ffc80770bae15fe7b0f6d9 Mon Sep 17 00:00:00 2001 From: Fan Jiang Date: Wed, 18 Jul 2018 15:37:42 +0800 Subject: [PATCH] Add macOS support --- Disruptor/BuildConfig.h | 5 + Disruptor/CMakeLists.txt | 4 +- Disruptor/ThreadHelper_Linux.cpp | 2 +- Disruptor/ThreadHelper_macOS.cpp | 151 +++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 Disruptor/ThreadHelper_macOS.cpp diff --git a/Disruptor/BuildConfig.h b/Disruptor/BuildConfig.h index e33d5a7..624967a 100644 --- a/Disruptor/BuildConfig.h +++ b/Disruptor/BuildConfig.h @@ -62,6 +62,11 @@ # define DISRUPTOR_OS_FAMILY_WINDOWS #else # define DISRUPTOR_OS_FAMILY_UNIX +# ifdef __APPLE__ +# define DISRUPTOR_OS_FAMILY_MACOS +# else +# define DISRUPTOR_OS_FAMILY_LINUX +# endif #endif #ifdef _DEBUG diff --git a/Disruptor/CMakeLists.txt b/Disruptor/CMakeLists.txt index 4780158..6f9bc4f 100644 --- a/Disruptor/CMakeLists.txt +++ b/Disruptor/CMakeLists.txt @@ -1,7 +1,7 @@ project(Disruptor) cmake_minimum_required(VERSION 2.6) -find_package(Boost COMPONENTS system) +find_package(Boost COMPONENTS system thread chrono) if(Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) @@ -27,6 +27,7 @@ set(Disruptor_sources stdafx.cpp ThreadPerTaskScheduler.cpp ThreadHelper_Linux.cpp + ThreadHelper_macOS.cpp ThreadHelper_Windows.cpp TimeoutBlockingWaitStrategy.cpp TypeInfo.cpp @@ -114,6 +115,7 @@ set(Disruptor_headers ) add_library(DisruptorShared SHARED ${Disruptor_sources}) +target_link_libraries(DisruptorShared ${Boost_LIBRARIES}) set_target_properties(DisruptorShared PROPERTIES OUTPUT_NAME Disruptor) set_target_properties(DisruptorShared PROPERTIES VERSION ${DISRUPTOR_VERSION}) set_target_properties(DisruptorShared PROPERTIES SOVERSION ${DISRUPTOR_VERSION_MAJOR}) diff --git a/Disruptor/ThreadHelper_Linux.cpp b/Disruptor/ThreadHelper_Linux.cpp index 96c56b0..58f3ecb 100644 --- a/Disruptor/ThreadHelper_Linux.cpp +++ b/Disruptor/ThreadHelper_Linux.cpp @@ -3,7 +3,7 @@ #include "BuildConfig.h" -#ifdef DISRUPTOR_OS_FAMILY_UNIX +#ifdef DISRUPTOR_OS_FAMILY_LINUX #include diff --git a/Disruptor/ThreadHelper_macOS.cpp b/Disruptor/ThreadHelper_macOS.cpp new file mode 100644 index 0000000..6ae77aa --- /dev/null +++ b/Disruptor/ThreadHelper_macOS.cpp @@ -0,0 +1,151 @@ +#include "stdafx.h" +#include "ThreadHelper.h" + +#include "BuildConfig.h" + +#ifdef DISRUPTOR_OS_FAMILY_MACOS + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SYSCTL_CORE_COUNT "machdep.cpu.core_count" + +#define CPUID(INFO, LEAF, SUBLEAF) __cpuid_count(LEAF, SUBLEAF, INFO[0], INFO[1], INFO[2], INFO[3]) + +#define GETCPU(CPU) { \ + uint32_t CPUInfo[4]; \ + CPUID(CPUInfo, 1, 0); \ + /* CPUInfo[1] is EBX, bits 24-31 are APIC ID */ \ + if ( (CPUInfo[3] & (1 << 9)) == 0) { \ + (CPU) = -1; /* no APIC on chip */ \ + } \ + else { \ + (CPU) = (unsigned)CPUInfo[1] >> 24; \ + } \ + if ((CPU) < 0) (CPU) = 0; \ + } + +namespace Disruptor +{ +namespace ThreadHelper +{ + typedef struct cpu_set { + uint32_t count; + } cpu_set_t; + + static inline void CPU_ZERO(cpu_set_t *cs) { cs->count = 0; } + + static inline void CPU_SET(int num, cpu_set_t *cs) { cs->count |= (1 << num); } + + static inline int CPU_ISSET(int num, cpu_set_t *cs) { return (cs->count & (1 << num)); } + + int sched_getaffinity(pid_t pid, size_t cpu_size, cpu_set_t *cpu_set) + { + (void) pid; + (void) cpu_size; + + int32_t core_count = 0; + size_t len = sizeof(core_count); + int ret = sysctlbyname(SYSCTL_CORE_COUNT, &core_count, &len, 0, 0); + if (ret) { + return -1; + } + cpu_set->count = 0; + for (int i = 0; i < core_count; i++) { + cpu_set->count |= (1 << i); + } + + return 0; + } + + int pthread_setaffinity_np(pthread_t thread, size_t cpu_size, + cpu_set_t *cpu_set) + { + thread_port_t mach_thread; + int core = 0; + + for (core = 0; core < 8 * (int)cpu_size; core++) { + if (CPU_ISSET(core, cpu_set)) break; + } + + thread_affinity_policy_data_t policy = { core }; + mach_thread = pthread_mach_thread_np(thread); + thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, + (thread_policy_t)&policy, 1); + return 0; + } + + + size_t getProcessorCount() + { + return static_cast(sysconf(_SC_NPROCESSORS_CONF)); + } + + uint32_t getCurrentProcessor() + { + uint32_t cpu_id; + + GETCPU(cpu_id); + + return cpu_id; + } + + bool setThreadAffinity(const AffinityMask& mask) + { + cpu_set_t cpuSet; + CPU_ZERO(&cpuSet); + + for (size_t i = 0; i < mask.size(); ++i) + { + if (mask.test(i)) + CPU_SET(i, &cpuSet); + } + + return pthread_setaffinity_np(pthread_self(), sizeof(cpuSet), &cpuSet) == 0; + } + + AffinityMask getThreadAffinity() + { + AffinityMask mask; + + cpu_set_t cpuSet; + CPU_ZERO(&cpuSet); + if (sched_getaffinity(0, sizeof(cpuSet), &cpuSet) == 0) + { + int processorCount = getProcessorCount(); + int maskSize = (int) mask.size(); + for (int i = 0; i < processorCount && i < maskSize; ++i) + { + if (CPU_ISSET(i, &cpuSet)) + mask.set(i); + } + } + + return mask; + } + + uint32_t getCurrentThreadId() + { + uint64_t result; + pthread_threadid_np(NULL, &result); + return (uint32_t) result; + } + + void setThreadName(const std::string& name) + { + pthread_setname_np(name.c_str()); + } + +} // namespace ThreadHelper +} // namespace Disruptor + +#endif // DISRUPTOR_OS_FAMILY_UNIX