Created
September 4, 2022 16:46
-
-
Save Riebart/59a2372be16a1c6ebd18da70801d573c to your computer and use it in GitHub Desktop.
A simple test of ASK between two threads using a volatile incrementing global between them
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <thread> | |
#include <random> | |
#include <stdint.h> | |
#include <utime.h> | |
#include <unistd.h> | |
#include <atomic> | |
float READ_NOISE_RATIO = 0.0; | |
int32_t swap_write_count = 0; | |
int32_t swap_read_count = 0; | |
int32_t swap_read_attempts = 0; | |
// The issue with syscall sleep is that there was always | |
// about a 70us minimum extra sleep duration. | |
// usleep(10); | |
// std::this_thread::sleep_for(sleep_duration); | |
// Use the custom spin_sleep_for for precision sleeping at | |
// us down to 10ns accuracy. | |
#define SLEEP_FUNC spin_sleep_for //std::this_thread::sleep_for | |
struct args { | |
uint32_t sleep_us; | |
int32_t* channel; | |
}; | |
void spin_sleep_for(std::chrono::microseconds dura) | |
{ | |
auto start = std::chrono::high_resolution_clock::now(); | |
auto end = start; | |
auto elapsed = end - start; | |
while (elapsed < dura) | |
{ | |
end = std::chrono::high_resolution_clock::now(); | |
elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start); | |
} | |
} | |
void writer(void* args_v) | |
{ | |
struct args* args = (struct args*)args_v; | |
std::chrono::microseconds sleep_duration(args->sleep_us); | |
while (true) | |
{ | |
swap_write_count++; | |
(*args->channel)++; | |
SLEEP_FUNC(sleep_duration); | |
} | |
} | |
void reader(void* args_v) | |
{ | |
struct args* args = (struct args*)args_v; | |
std::chrono::microseconds sleep_duration(args->sleep_us / 4); | |
int32_t last_val = *(args->channel); | |
int32_t curr_val = *(args->channel); | |
while (true) | |
{ | |
swap_read_attempts++; | |
curr_val = *(args->channel); | |
// Check to see if this bit read is subject to noise | |
if (((1.0f + std::rand()) / RAND_MAX) < READ_NOISE_RATIO) | |
{ | |
curr_val = std::rand(); | |
} | |
if (curr_val == (last_val + 1)) | |
{ | |
swap_read_count++; | |
} | |
last_val = curr_val; | |
SLEEP_FUNC(sleep_duration); | |
} | |
} | |
int main(int argc, char** argv) | |
{ | |
int32_t channel = 0; | |
struct args t_args = { 12, &channel }; | |
std::thread read_thread = std::thread(reader, &t_args); | |
std::thread write_thread = std::thread(writer, &t_args); | |
std::chrono::milliseconds print_sleep(100); | |
int32_t test = 0; | |
while (true) | |
{ | |
printf("%d, %d, %d, %d, %f, %f, %f\n", | |
test, | |
swap_read_attempts, | |
swap_read_count, | |
swap_write_count, | |
1.0 - (1.0 * swap_read_count) / swap_write_count, | |
0.1 * test / swap_write_count, | |
0.1 * test / swap_read_attempts); | |
test++; | |
std::this_thread::sleep_for (print_sleep); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment