#include <pthread.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct Item {
_Atomic(struct Item*) next;
int64_t value;
} item_t;
typedef struct {
int thread_index;
int k;
} thread_arg;
_Atomic(item_t*) last;
atomic_int allocs = 0;
atomic_int frees = 0;
atomic_int length = 0;
void build_new_element(int number, int thread_number)
{
// printf("number: %d, thread: %d\n", number, thread_number);
item_t* new_elem = malloc(sizeof(item_t));
++allocs;
new_elem->next = NULL;
new_elem->value = number;
if (atomic_load(&last->next) != NULL) {
printf("ooops: %ld\n", last->next->value);
abort();
}
item_t* prev = atomic_load(&last);
atomic_store(&last, new_elem);
prev->next = new_elem;
// atomic_store(&last->next, new_elem);
//++length;
// atomic_store(&last, new_elem);
//sched_yield();
}
void* routine(void* arg)
{
thread_arg* argument = (thread_arg*)arg;
int index = argument->thread_index;
int k = argument->k;
for (int number = index * k; number < (index + 1) * k; ++number) {
build_new_element(number, index);
}
return arg;
}
void delete_list(_Atomic(item_t*) ptr)
{
item_t* to_delete = atomic_load(&ptr);
if (atomic_load(&to_delete->next) == NULL) {
free(to_delete);
return;
}
delete_list(to_delete->next);
++frees;
free(to_delete);
}
int main(int argc, char* argv[])
{
int N = atoi(argv[1]);
int k = atoi(argv[2]);
if (k == 0)
return 0;
item_t* begin = malloc(sizeof(item_t));
atomic_store(&last, begin);
pthread_t threads[N];
for (int i = 0; i < N; ++i) {
thread_arg* arg = malloc(sizeof(thread_arg));
arg->k = k;
arg->thread_index = i;
if (pthread_create(threads + i, NULL, &routine, arg))
return 1;
}
for (int i = 0; i < N; ++i) {
void* p;
if (pthread_join(threads[i], &p))
return 2;
free(p);
}
item_t* ptr = atomic_load(&begin->next);
while (ptr != NULL) {
printf("%ld\n", ptr->value);
ptr = atomic_load(&ptr->next);
}
delete_list(begin->next);
free(begin);
++frees;
// printf("Total: %d allocs, %d frees\n", allocs, frees);
}