Compare commits
6 Commits
7b31bd5efe
...
cf-integri
Author | SHA1 | Date | |
---|---|---|---|
c46f633dbf | |||
400350946c | |||
607a4ef6e2 | |||
b0750772ec | |||
86abc02188 | |||
a90e353fcd |
@@ -31,11 +31,19 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|||||||
"MinSizeRel" "RelWithDebInfo")
|
"MinSizeRel" "RelWithDebInfo")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_compile_options(-fdata-sections -ffunction-sections -Wswitch-enum
|
add_compile_options(
|
||||||
-Werror=switch-enum -fPIC)
|
-Werror=switch-enum -Wswitch-enum -fPIC -fdata-sections -ffunction-sections
|
||||||
|
-fno-jump-tables # https://github.com/llvm/llvm-project/issues/54247
|
||||||
|
)
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
add_link_options("-Wno-unused-command-line-argument")
|
add_link_options("-Wno-unused-command-line-argument")
|
||||||
|
find_program(LLVM_OBJCOPY llvm-objcopy)
|
||||||
|
if(LLVM_OBJCOPY)
|
||||||
|
set(CMAKE_OBJCOPY
|
||||||
|
${LLVM_OBJCOPY}
|
||||||
|
CACHE FILEPATH "path to objcopy binary" FORCE)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
@@ -56,6 +64,21 @@ if(HAS_FULL_RELRO)
|
|||||||
endif()
|
endif()
|
||||||
cmake_pop_check_state()
|
cmake_pop_check_state()
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
|
||||||
|
add_compile_options(-mbranch-protection=standard)
|
||||||
|
else()
|
||||||
|
add_compile_options(-fcf-protection)
|
||||||
|
set(rewrite_endbr_flags "-fuse-ld=mold;LINKER:-z,rewrite-endbr")
|
||||||
|
cmake_push_check_state()
|
||||||
|
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${rewrite_endbr_flags})
|
||||||
|
check_cxx_source_compiles("int main(){}" HAS_REWRITE_ENDBR FAIL_REGEX
|
||||||
|
"warning:")
|
||||||
|
if(HAS_REWRITE_ENDBR)
|
||||||
|
add_link_options(${rewrite_endbr_flags})
|
||||||
|
endif()
|
||||||
|
cmake_pop_check_state()
|
||||||
|
endif()
|
||||||
|
|
||||||
set(version_script_flags
|
set(version_script_flags
|
||||||
LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.map)
|
LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.map)
|
||||||
cmake_push_check_state()
|
cmake_push_check_state()
|
||||||
@@ -323,7 +346,8 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND BUILD_TESTING)
|
|||||||
# c++98
|
# c++98
|
||||||
add_executable(conflict_set_cxx_api_test conflict_set_cxx_api_test.cpp)
|
add_executable(conflict_set_cxx_api_test conflict_set_cxx_api_test.cpp)
|
||||||
target_compile_options(conflict_set_cxx_api_test PRIVATE ${TEST_FLAGS})
|
target_compile_options(conflict_set_cxx_api_test PRIVATE ${TEST_FLAGS})
|
||||||
target_link_libraries(conflict_set_cxx_api_test PRIVATE ${PROJECT_NAME})
|
target_link_libraries(conflict_set_cxx_api_test
|
||||||
|
PRIVATE ${PROJECT_NAME}-static)
|
||||||
set_target_properties(conflict_set_cxx_api_test PROPERTIES CXX_STANDARD 98)
|
set_target_properties(conflict_set_cxx_api_test PROPERTIES CXX_STANDARD 98)
|
||||||
set_target_properties(conflict_set_cxx_api_test
|
set_target_properties(conflict_set_cxx_api_test
|
||||||
PROPERTIES CXX_STANDARD_REQUIRED ON)
|
PROPERTIES CXX_STANDARD_REQUIRED ON)
|
||||||
@@ -356,6 +380,15 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND BUILD_TESTING)
|
|||||||
${symbol_imports})
|
${symbol_imports})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_CROSSCOMPILING)
|
||||||
|
find_program(HARDENING_CHECK hardening-check)
|
||||||
|
if(HARDENING_CHECK)
|
||||||
|
add_test(NAME hardening_check
|
||||||
|
COMMAND ${HARDENING_CHECK} $<TARGET_FILE:${PROJECT_NAME}>
|
||||||
|
--nofortify --nostackprotector)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# bench
|
# bench
|
||||||
add_executable(conflict_set_bench Bench.cpp)
|
add_executable(conflict_set_bench Bench.cpp)
|
||||||
target_link_libraries(conflict_set_bench PRIVATE ${PROJECT_NAME} nanobench)
|
target_link_libraries(conflict_set_bench PRIVATE ${PROJECT_NAME} nanobench)
|
||||||
|
@@ -3183,6 +3183,12 @@ Node *firstGeqPhysical(Node *n, const TrivialSpan key) {
|
|||||||
#define PRESERVE_NONE
|
#define PRESERVE_NONE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __has_attribute(musttail) && __has_attribute(preserve_none)
|
||||||
|
constexpr bool kEnableInterleaved = true;
|
||||||
|
#else
|
||||||
|
constexpr bool kEnableInterleaved = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace check {
|
namespace check {
|
||||||
|
|
||||||
typedef PRESERVE_NONE void (*Continuation)(struct Job *, struct Context *);
|
typedef PRESERVE_NONE void (*Continuation)(struct Job *, struct Context *);
|
||||||
@@ -4969,51 +4975,50 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
check::Context context;
|
check::Context context;
|
||||||
context.readContext.impl = this;
|
context.readContext.impl = this;
|
||||||
|
|
||||||
#if __has_attribute(musttail)
|
if constexpr (kEnableInterleaved) {
|
||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
useSequential(reads, result, count, context);
|
useSequential(reads, result, count, context);
|
||||||
} else {
|
} else {
|
||||||
constexpr int kConcurrent = 16;
|
constexpr int kConcurrent = 16;
|
||||||
check::Job inProgress[kConcurrent];
|
check::Job inProgress[kConcurrent];
|
||||||
context.count = count;
|
context.count = count;
|
||||||
context.oldestVersionFullPrecision = oldestVersionFullPrecision;
|
context.oldestVersionFullPrecision = oldestVersionFullPrecision;
|
||||||
context.root = root;
|
context.root = root;
|
||||||
context.queries = reads;
|
context.queries = reads;
|
||||||
context.results = result;
|
context.results = result;
|
||||||
int64_t started = std::min(kConcurrent, count);
|
int64_t started = std::min(kConcurrent, count);
|
||||||
context.started = started;
|
context.started = started;
|
||||||
for (int i = 0; i < started; i++) {
|
for (int i = 0; i < started; i++) {
|
||||||
inProgress[i].init(reads + i, result + i, root,
|
inProgress[i].init(reads + i, result + i, root,
|
||||||
oldestVersionFullPrecision);
|
oldestVersionFullPrecision);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < started - 1; i++) {
|
for (int i = 0; i < started - 1; i++) {
|
||||||
inProgress[i].next = inProgress + i + 1;
|
inProgress[i].next = inProgress + i + 1;
|
||||||
}
|
}
|
||||||
for (int i = 1; i < started; i++) {
|
for (int i = 1; i < started; i++) {
|
||||||
inProgress[i].prev = inProgress + i - 1;
|
inProgress[i].prev = inProgress + i - 1;
|
||||||
}
|
}
|
||||||
inProgress[0].prev = inProgress + started - 1;
|
inProgress[0].prev = inProgress + started - 1;
|
||||||
inProgress[started - 1].next = inProgress;
|
inProgress[started - 1].next = inProgress;
|
||||||
|
|
||||||
// Kick off the sequence of tail calls that finally returns once all jobs
|
// Kick off the sequence of tail calls that finally returns once all
|
||||||
// are done
|
// jobs are done
|
||||||
inProgress->continuation(inProgress, &context);
|
inProgress->continuation(inProgress, &context);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
Arena arena;
|
Arena arena;
|
||||||
auto *results2 = new (arena) Result[count];
|
auto *results2 = new (arena) Result[count];
|
||||||
check::Context context2;
|
check::Context context2;
|
||||||
context2.readContext.impl = this;
|
context2.readContext.impl = this;
|
||||||
useSequential(reads, results2, count, context2);
|
useSequential(reads, results2, count, context2);
|
||||||
assert(memcmp(result, results2, count) == 0);
|
assert(memcmp(result, results2, count) == 0);
|
||||||
assert(context.readContext == context2.readContext);
|
assert(context.readContext == context2.readContext);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
useSequential(reads, result, count, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
useSequential(reads, result, count, context);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
assert(reads[i].readVersion >= 0);
|
assert(reads[i].readVersion >= 0);
|
||||||
assert(reads[i].readVersion <= newestVersionFullPrecision);
|
assert(reads[i].readVersion <= newestVersionFullPrecision);
|
||||||
@@ -5186,11 +5191,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
assert(allPointWrites || sorted);
|
assert(allPointWrites || sorted);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __has_attribute(musttail)
|
|
||||||
constexpr bool kEnableInterleaved = true;
|
|
||||||
#else
|
|
||||||
constexpr bool kEnableInterleaved = false;
|
|
||||||
#endif
|
|
||||||
if (kEnableInterleaved && count > 1) {
|
if (kEnableInterleaved && count > 1) {
|
||||||
interleavedWrites(writes, count, InternalVersionT(writeVersion));
|
interleavedWrites(writes, count, InternalVersionT(writeVersion));
|
||||||
} else {
|
} else {
|
||||||
|
@@ -13,12 +13,14 @@ RUN TZ=America/Los_Angeles DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
|||||||
ccache \
|
ccache \
|
||||||
cmake \
|
cmake \
|
||||||
curl \
|
curl \
|
||||||
|
devscripts \
|
||||||
g++-aarch64-linux-gnu \
|
g++-aarch64-linux-gnu \
|
||||||
gcovr \
|
gcovr \
|
||||||
git \
|
git \
|
||||||
gnupg \
|
gnupg \
|
||||||
libc6-dbg \
|
libc6-dbg \
|
||||||
lsb-release \
|
lsb-release \
|
||||||
|
mold \
|
||||||
ninja-build \
|
ninja-build \
|
||||||
pre-commit \
|
pre-commit \
|
||||||
python3-requests \
|
python3-requests \
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <span>
|
#include <string_view>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -64,7 +64,7 @@ int main(int argc, const char **argv) {
|
|||||||
auto *const mapOriginal = begin;
|
auto *const mapOriginal = begin;
|
||||||
const auto sizeOriginal = size;
|
const auto sizeOriginal = size;
|
||||||
|
|
||||||
using StringView = std::span<const uint8_t>;
|
using StringView = std::basic_string_view<uint8_t>;
|
||||||
|
|
||||||
StringView write;
|
StringView write;
|
||||||
std::vector<StringView> reads;
|
std::vector<StringView> reads;
|
||||||
@@ -78,9 +78,9 @@ int main(int argc, const char **argv) {
|
|||||||
end = (uint8_t *)memchr(begin, '\n', size);
|
end = (uint8_t *)memchr(begin, '\n', size);
|
||||||
|
|
||||||
if (line.size() > 0 && line[0] == 'P') {
|
if (line.size() > 0 && line[0] == 'P') {
|
||||||
write = line.subspan(2, line.size());
|
write = line.substr(2, line.size());
|
||||||
} else if (line.size() > 0 && line[0] == 'L') {
|
} else if (line.size() > 0 && line[0] == 'L') {
|
||||||
reads.push_back(line.subspan(2, line.size()));
|
reads.push_back(line.substr(2, line.size()));
|
||||||
} else if (line.empty()) {
|
} else if (line.empty()) {
|
||||||
{
|
{
|
||||||
readRanges.resize(reads.size());
|
readRanges.resize(reads.size());
|
||||||
|
@@ -64,31 +64,47 @@ template <class... Ts> std::string tupleKey(const Ts &...ts) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int kWindowSize = 300000;
|
constexpr int kTotalKeyRange = 1'000'000'000;
|
||||||
|
constexpr int kWindowSize = 1'000'000;
|
||||||
|
constexpr int kNumKeys = 10;
|
||||||
|
|
||||||
void workload(weaselab::ConflictSet *cs) {
|
void workload(weaselab::ConflictSet *cs) {
|
||||||
int64_t version = kWindowSize;
|
int64_t version = kWindowSize;
|
||||||
constexpr int kNumWrites = 16;
|
|
||||||
for (;; transactions.fetch_add(1, std::memory_order_relaxed)) {
|
for (;; transactions.fetch_add(1, std::memory_order_relaxed)) {
|
||||||
std::vector<int64_t> keyIndices;
|
std::vector<int64_t> keyIndices;
|
||||||
for (int i = 0; i < kNumWrites; ++i) {
|
for (int i = 0; i < kNumKeys; ++i) {
|
||||||
keyIndices.push_back(rand() % 100'000'000);
|
keyIndices.push_back(rand() % kTotalKeyRange);
|
||||||
}
|
}
|
||||||
std::sort(keyIndices.begin(), keyIndices.end());
|
std::sort(keyIndices.begin(), keyIndices.end());
|
||||||
std::vector<std::string> keys;
|
std::vector<std::string> keys;
|
||||||
std::vector<weaselab::ConflictSet::WriteRange> writes;
|
constexpr std::string_view fullString =
|
||||||
constexpr std::string_view suffix = "this is a suffix";
|
"this is a string, where a prefix of it is used as an element of the "
|
||||||
for (int i = 0; i < kNumWrites; ++i) {
|
"tuple forming the key";
|
||||||
keys.push_back(tupleKey(0x100, i, keyIndices[i],
|
for (int i = 0; i < kNumKeys; ++i) {
|
||||||
suffix.substr(0, rand() % suffix.size()),
|
keys.push_back(
|
||||||
rand()));
|
tupleKey(0x100, keyIndices[i] / fullString.size(),
|
||||||
|
fullString.substr(0, keyIndices[i] % fullString.size())));
|
||||||
// printf("%s\n", printable(keys.back()).c_str());
|
// printf("%s\n", printable(keys.back()).c_str());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < kNumWrites; ++i) {
|
|
||||||
|
std::vector<weaselab::ConflictSet::ReadRange> reads;
|
||||||
|
std::vector<weaselab::ConflictSet::WriteRange> writes;
|
||||||
|
std::vector<weaselab::ConflictSet::Result> results;
|
||||||
|
for (int i = 0; i < kNumKeys; ++i) {
|
||||||
writes.push_back({{(const uint8_t *)keys[i].data(), int(keys[i].size())},
|
writes.push_back({{(const uint8_t *)keys[i].data(), int(keys[i].size())},
|
||||||
{nullptr, 0}});
|
{nullptr, 0}});
|
||||||
|
reads.push_back({{(const uint8_t *)keys[i].data(), int(keys[i].size())},
|
||||||
|
{nullptr, 0},
|
||||||
|
version - kWindowSize});
|
||||||
}
|
}
|
||||||
cs->addWrites(writes.data(), writes.size(), version);
|
results.resize(reads.size());
|
||||||
|
|
||||||
|
cs->check(reads.data(), results.data(), reads.size());
|
||||||
|
bool ok = true;
|
||||||
|
for (auto result : results) {
|
||||||
|
ok &= result == weaselab::ConflictSet::Commit;
|
||||||
|
}
|
||||||
|
cs->addWrites(writes.data(), ok ? writes.size() : 0, version);
|
||||||
cs->setOldestVersion(version - kWindowSize);
|
cs->setOldestVersion(version - kWindowSize);
|
||||||
++version;
|
++version;
|
||||||
}
|
}
|
||||||
|
@@ -767,7 +767,9 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
false, true);
|
false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
sortPoints(points);
|
if (!std::is_sorted(points.begin(), points.end())) {
|
||||||
|
sortPoints(points);
|
||||||
|
}
|
||||||
|
|
||||||
int activeWriteCount = 0;
|
int activeWriteCount = 0;
|
||||||
std::vector<std::pair<StringRef, StringRef>> combinedWriteConflictRanges;
|
std::vector<std::pair<StringRef, StringRef>> combinedWriteConflictRanges;
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
___chkstk_darwin
|
|
||||||
___stack_chk_fail
|
___stack_chk_fail
|
||||||
___stack_chk_guard
|
___stack_chk_guard
|
||||||
__tlv_bootstrap
|
__tlv_bootstrap
|
||||||
@@ -6,7 +5,6 @@ _abort
|
|||||||
_bzero
|
_bzero
|
||||||
_free
|
_free
|
||||||
_malloc
|
_malloc
|
||||||
_memcmp
|
|
||||||
_memcpy
|
_memcpy
|
||||||
_memmove
|
_memmove
|
||||||
dyld_stub_binder
|
dyld_stub_binder
|
@@ -8,7 +8,7 @@ SRC_DIR="${0%/*}"
|
|||||||
BUILD_ARM="$(mktemp -d -t conflict-set-arm)"
|
BUILD_ARM="$(mktemp -d -t conflict-set-arm)"
|
||||||
BUILD_X86="$(mktemp -d -t conflict-set-x86)"
|
BUILD_X86="$(mktemp -d -t conflict-set-x86)"
|
||||||
|
|
||||||
cmake_args=(-DCMAKE_CXX_FLAGS=-DNVALGRIND -DCPACK_PACKAGING_INSTALL_PREFIX=/usr/local -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++)
|
cmake_args=(-DCMAKE_CXX_FLAGS=-DNVALGRIND -DCPACK_PACKAGING_INSTALL_PREFIX=/usr/local)
|
||||||
|
|
||||||
cmake -S"$SRC_DIR" -B"$BUILD_ARM" -DCMAKE_OSX_ARCHITECTURES=arm64 "${cmake_args[@]}"
|
cmake -S"$SRC_DIR" -B"$BUILD_ARM" -DCMAKE_OSX_ARCHITECTURES=arm64 "${cmake_args[@]}"
|
||||||
cmake --build "$BUILD_ARM" --target conflict-set --target conflict-set-static
|
cmake --build "$BUILD_ARM" --target conflict-set --target conflict-set-static
|
||||||
|
Reference in New Issue
Block a user