Browse Source

Updating bottleneck with a semaphore

master
Ludovic 'Archivist' Lagouardette 2 years ago
parent
commit
66ba3d98e4
4 changed files with 61 additions and 7 deletions
  1. +5
    -5
      extra_tests/001_test/Makefile
  2. +1
    -1
      extra_tests/001_test/main.cpp
  3. +1
    -1
      extra_tests/001_test/syscall.hpp
  4. +54
    -0
      include/gp/ipc/bottleneck.hpp

+ 5
- 5
extra_tests/001_test/Makefile View File

@ -1,17 +1,17 @@
CXX= clang++
CXXFLAGS= --std=c++20 -target x86_64-none-linux-elf -Os -ffreestanding -nostdlib -pedantic \
-Wno-unknown-attributes -fno-omit-frame-pointer -MD -fno-use-cxa-atexit -fno-rtti -I../../include -I.
CXXFLAGS= --std=c++20 -target x86_64-none-linux-elf -O2 -ffreestanding -nostdlib -pedantic \
-Wno-unknown-attributes -fno-omit-frame-pointer -MD -fno-use-cxa-atexit -fno-rtti -I. -I../../include
# -fsanitize=address -fsanitize-blacklist=blacklist.txt
all: tests
tests: bin/tests
./bin/tests
./bin/tests potato
bin/tests: main.cpp
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) main.cpp -o $@
$(CXX) $(CXXFLAGS) main.cpp -nostartfiles -s -static -o $@
clean: ./bin
@rm -rf $<
@rm -rf $<

+ 1
- 1
extra_tests/001_test/main.cpp View File

@ -1,4 +1,4 @@
#include <gp/containers/array.hpp>
#include <gp/containers/buffer.hpp>
#include "syscall.hpp"
gp::buffer<char> hello = "Hello world\n";

+ 1
- 1
extra_tests/001_test/syscall.hpp View File

@ -133,7 +133,7 @@ inline int write(int fd, char* buffer, size_t sz) {
return _write((int64_t)fd, (int64_t)buffer, (int64_t)sz);
}
inline void* mmap(void *addr, size_t length, int prot, int flags, int fd, n">off_t offset) {
inline void* mmap(void *addr, size_t length, int prot, int flags, int fd, kt">int64_t offset) {
return (void*)_mmap((int64_t)addr, (int64_t)length, (int64_t)prot, (int64_t)flags, (int64_t)fd, (int64_t)offset);
}

+ 54
- 0
include/gp/ipc/bottleneck.hpp View File

@ -1,6 +1,7 @@
#pragma once
#include <atomic>
#include <concepts>
#include "gp_config.hpp"
@ -55,4 +56,57 @@ namespace gp {
return flag.compare_exchange_strong(t,f,std::memory_order::release);
}
};
/**
* @brief A fast semaphore exclusion handler WITHOUT deadlock detection
*/
template<std::integral T, T default_increment, T maximum_increment>
class fast_semaphore {
std::atomic<T> flag;
public:
fast_semaphore() = default;
fast_semaphore(fast_semaphore&) = delete;
fast_semaphore(fast_semaphore&&) = delete;
enum class tristate {
success,
timing,
error
};
void lock_super() {
auto value = flag.fetch_add(maximum_increment, std::memory_order::relaxed);
while(value > maximum_increment) { value = flag.load(std::memory_order::release); }
}
template<T increment = default_increment>
void lock() {
while(not try_lock<increment>());
}
template<T increment = default_increment>
[[nodiscard]] bool try_lock() {
T expect = flag.load(std::memory_order::relaxed);
T target = expect + increment;
if(target > maximum_increment) return false;
return flag.compare_exchange_strong(expect,target,std::memory_order::acquire);
}
template<T increment = default_increment>
void unlock() {
tristate v;
do{ v = try_unlock<increment>(); }
while(v == tristate::timing);
gp_config::assertion(v == tristate::success, "Over unlocking may have happened");
}
template<T increment = default_increment>
[[nodiscard]] tristate try_unlock() {
T expect = flag.load(std::memory_order::relaxed);
T target = expect - increment;
if(target < 0) return tristate::error;
return flag.compare_exchange_strong(expect,target,std::memory_order::release) ? tristate::success : tristate::timing;
}
};
}

Loading…
Cancel
Save