Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/tilt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/*/build*/*
24 changes: 20 additions & 4 deletions examples/tilt/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# Tutorial: Tilt
# Tilt

## Clone libvsync and tilt repositories

```bash
cd examples/tilt/
mkdir deps/
cd deps/
git clone https://github.com/open-s4c/libvsync.git
git clone https://github.com/open-s4c/tilt.git
Expand All @@ -18,8 +17,25 @@ cd ../
. ./venv/bin/activate
```

## Run simple test campaign
## Campaigns

### Simple Mutex test

Runs a simple campaign to run Tilt locks.

```bash
./campaign_tilt.py
./campaign_test.py
```

### Reciprocating lock benchmarks

Runs a campaign that runs the benchmarks described in the Reciprocating Locks paper, using the Tilt.

```bash
./campaign_reciprocating_locks.py
```

## Todo

- [ ] Fix implemenation of CLH lock
- [ ] Fix implementation of the atomic benchmark
25 changes: 22 additions & 3 deletions examples/tilt/bench/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
# Copyright (C) 2025 Vrije Universiteit Brussel. All rights reserved.
# SPDX-License-Identifier: MIT

cmake_minimum_required(VERSION 3.10)
project(PthreadMutexExample)
project(PthreadMutex)
# project(PthreadMutex LANGUAGES C CXX)

# Build options
set(NB_THREADS 4 CACHE STRING "Number of threads increasing the counter")
set(RUN_DURATION_SECONDS 10 CACHE STRING "Time during which the threads will increase the counter")

set(CMAKE_C_STANDARD 99)
# set(CMAKE_CXX_STANDARD 11)

configure_file(${CMAKE_SOURCE_DIR}/include/config.h.in ${CMAKE_BINARY_DIR}/include/config.h)

include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)

add_executable(mutex mutex.c)
add_executable(test_mutex test_mutex.c)
add_executable(bench_mutex bench_mutex.cpp)
add_executable(bench_mutex_moderate bench_mutex_moderate.cpp)
# add_executable(bench_atomic bench_atomic.cpp)

find_package(Threads REQUIRED)
target_link_libraries(mutex Threads::Threads)
target_link_libraries(test_mutex Threads::Threads)
target_link_libraries(bench_mutex Threads::Threads)
target_link_libraries(bench_mutex_moderate Threads::Threads)
# target_link_libraries(bench_atomic Threads::Threads)
85 changes: 85 additions & 0 deletions examples/tilt/bench/bench_atomic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (C) 2025 Vrije Universiteit Brussel. All rights reserved.
// SPDX-License-Identifier: MIT

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <atomic>
#include <random>
#include <chrono>
#include <iostream>
#include <vector>
#include <thread>
#include <config.h> /* defines NB_THREADS, RUN_DURATION_SECONDS */

#define IMPLICIT_INIT

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

struct S {
uint32_t a, b, c, d, e;
};
std::atomic<S> shared;
std::atomic<bool> done{false};
std::atomic<uint64_t> iterations_total{0};

void* worker(void* arg) {
S local = {1, 2, 3, 4, 5};
uint64_t iterations_local = 0;
while (!atomic_load_explicit(&done, std::memory_order_relaxed)) { // TODO: fix
pthread_mutex_lock(&lock);
// Critical section
atomic_exchange_explicit(&shared, local, std::memory_order_seq_cst); // exchange with global

pthread_mutex_unlock(&lock);

// Non-critical section
// (sleep or dummy ops to simulate delay)
++iterations_local;
}
atomic_fetch_add_explicit(&iterations_total, iterations_local, std::memory_order_relaxed);
return NULL;
}

int main() {
#if !defined(IMPLICIT_INIT)
if (pthread_mutex_init(&lock, NULL) != 0) {
printf("Mutex initialization failed\n");
return 1;
}
#endif /* EXPLICIT_INIT */

// Initialize shared atomic with zeros
S zeroes = {0, 0, 0, 0, 0};
shared.store(zeroes, std::memory_order_relaxed); // TODO: fix
//atomic_store_explicit(&shared, {0, 0, 0, 0, 0}, std::memory_order_relaxed);

pthread_t threads[NB_THREADS];
unsigned long thread_iterations[NB_THREADS];
for (int i = 0; i < NB_THREADS; ++i)
pthread_create(&threads[i], NULL, worker, NULL);

// Run for a fixed duration
std::this_thread::sleep_for(std::chrono::seconds(RUN_DURATION_SECONDS));
atomic_store_explicit(&done, 1, std::memory_order_relaxed);

for (int i = 0; i < NB_THREADS; ++i) {
void* return_value;
pthread_join(threads[i], &return_value);
thread_iterations[i] = (unsigned long) return_value;
}

std::cout << "total_iterations=" << iterations_total.load();
std::cout << ";duration=" << RUN_DURATION_SECONDS;
std::cout << ";nb_threads=" << NB_THREADS;

// print per thread iterations
for (size_t k = 0u; k < NB_THREADS; ++k) {
std::cout << ";thread_" << k << "=" << thread_iterations[k];
}

std::cout << "\n";
pthread_mutex_destroy(&lock);

return 0;
}
79 changes: 79 additions & 0 deletions examples/tilt/bench/bench_mutex.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (C) 2025 Vrije Universiteit Brussel. All rights reserved.
// SPDX-License-Identifier: MIT

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <atomic>
#include <random>
#include <chrono>
#include <iostream>
#include <vector>
#include <thread>

#include <config.h> /* defines NB_THREADS, RUN_DURATION_SECONDS and lock_* operations and types. */

#define IMPLICIT_INIT

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

std::mt19937 prng{42}; // shared global PRNG
std::atomic<bool> done{false};
std::atomic<uint64_t> iterations_total{0};

void* worker(void* arg) {
uint64_t iterations_local = 0;
while (!atomic_load_explicit(&done, std::memory_order_relaxed)) {
pthread_mutex_lock(&lock);
// Critical section
prng(); // one step of PRNG in critical section

pthread_mutex_unlock(&lock);

// Non-critical section
// (sleep or dummy ops to simulate delay)
++iterations_local;
}
atomic_fetch_add_explicit(&iterations_total, iterations_local, std::memory_order_relaxed);
void *result = (void*) iterations_local;
return result;
}

int main() {
#if !defined(IMPLICIT_INIT)
if (pthread_mutex_init(&lock, NULL) != 0) {
printf("Mutex initialization failed\n");
return 1;
}
#endif /* EXPLICIT_INIT */

pthread_t threads[NB_THREADS];
unsigned long thread_iterations[NB_THREADS];
for (int i = 0; i < NB_THREADS; ++i)
pthread_create(&threads[i], NULL, worker, NULL);

//sleep(RUN_DURATION_SECONDS);
std::this_thread::sleep_for(std::chrono::seconds(RUN_DURATION_SECONDS));
atomic_store_explicit(&done, 1, std::memory_order_relaxed);


for (int i = 0; i < NB_THREADS; ++i) {
void* return_value;
pthread_join(threads[i], &return_value);
thread_iterations[i] = (unsigned long) return_value;
}

std::cout << "total_iterations=" << iterations_total.load();
std::cout << ";duration=" << RUN_DURATION_SECONDS;
std::cout << ";nb_threads=" << NB_THREADS;

// print per thread iterations
for (size_t k = 0u; k < NB_THREADS; ++k) {
std::cout << ";thread_" << k << "=" << thread_iterations[k];
}

std::cout << "\n";
pthread_mutex_destroy(&lock);

return 0;
}
93 changes: 93 additions & 0 deletions examples/tilt/bench/bench_mutex_moderate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright (C) 2025 Vrije Universiteit Brussel. All rights reserved.
// SPDX-License-Identifier: MIT

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <atomic>
#include <random>
#include <chrono>
#include <iostream>
#include <vector>
#include <thread>
#include <config.h> /* defines NB_THREADS, RUN_DURATION_SECONDS */

#define IMPLICIT_INIT

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

std::mt19937 prng_global{42}; // shared global PRNG
std::atomic<bool> done{false};
std::atomic<uint64_t> iterations_total{0};

volatile uint32_t prng_sink_global = 0; // Necessary to prevent optimization of the non-critical section

void* worker(void* arg) {
uint64_t iterations_local = 0;

// Setup local PRNG for non-critical section
std::mt19937 prng_local{42}; // local PRNG
std::uniform_int_distribution<int> dist(0, 249);
uint32_t prng_sink = 0; // value to prevent optimization

while (!atomic_load_explicit(&done, std::memory_order_relaxed)) {

// Critical section
pthread_mutex_lock(&lock);
prng_global(); // one step of PRNG in critical section
pthread_mutex_unlock(&lock);

// Non-critical section
int steps = dist(prng_local);
for (int i = 0; i < steps; ++i)
prng_sink += prng_local();

++iterations_local;
}

// Consume final value so optimizer can't skip
prng_sink_global += prng_sink;

atomic_fetch_add_explicit(&iterations_total, iterations_local, std::memory_order_relaxed);

void *result = (void*) iterations_local;
return result;
}

int main() {
#if !defined(IMPLICIT_INIT)
if (pthread_mutex_init(&lock, NULL) != 0) {
printf("Mutex initialization failed\n");
return 1;
}
#endif /* EXPLICIT_INIT */

pthread_t threads[NB_THREADS];
unsigned long thread_iterations[NB_THREADS];
for (int i = 0; i < NB_THREADS; ++i)
pthread_create(&threads[i], NULL, worker, NULL);

// Run for a fixed duration
std::this_thread::sleep_for(std::chrono::seconds(RUN_DURATION_SECONDS));
atomic_store_explicit(&done, 1, std::memory_order_relaxed);

for (int i = 0; i < NB_THREADS; ++i) {
void* return_value;
pthread_join(threads[i], &return_value);
thread_iterations[i] = (unsigned long) return_value;
}

std::cout << "total_iterations=" << iterations_total.load();
std::cout << ";duration=" << RUN_DURATION_SECONDS;
std::cout << ";nb_threads=" << NB_THREADS;

// print per thread iterations
for (size_t k = 0u; k < NB_THREADS; ++k) {
std::cout << ";thread_" << k << "=" << thread_iterations[k];
}

std::cout << "\n";
pthread_mutex_destroy(&lock);

return 0;
}
13 changes: 13 additions & 0 deletions examples/tilt/bench/include/config.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright (C) 2025 Vrije Universiteit Brussel. All rights reserved.
* SPDX-License-Identifier: MIT
*/

#ifndef CONFIG_H
#define CONFIG_H

#define NB_THREADS @NB_THREADS@

#define RUN_DURATION_SECONDS @RUN_DURATION_SECONDS@

#endif /* CONFIG_H */
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (C) 2025 Vrije Universiteit Brussel. All rights reserved.
// SPDX-License-Identifier: MIT

#include <stdio.h>
#include <pthread.h>
#include <string.h>
Expand Down
Loading