Skip to content

Instantly share code, notes, and snippets.

@Riebart
Created September 4, 2022 16:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Riebart/59a2372be16a1c6ebd18da70801d573c to your computer and use it in GitHub Desktop.
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
#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