Correctly implemented lock-free bit array?

There are bitmap and multiple streams, in this case two. Each thread gets its numbers from the operations that it must perform. All threads receive different numbers of operations. Each of the operations - an array of type int containing -1 and ending bit numbers that need to be set in the bit array, if the bit is set, it was neustanovena, the stream should output the number of this bit. Question: correctly implemented lock-free bit pattern in this code?

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdatomic.h>
#include <threads.h>

#define BITS 2109 // the Number of bits in the bit array
#define MAX_OPS 1000 // the Maximum number of operations
#define MAX_OP_SIZE 100 // Maximum size of operation
atomic_uchar static bitset[(BITS>>3) + ((BITS&7) != 0)];

static int* ops[MAX_OPS];
static int num_ops;

// A structure to pass the flow of transaction numbers, which he should accomplish
struct range { int from, to; };

// Function initialize the array of operations with random values
static inline void gen_ops() {
 num_ops = 300 + rand()%(MAX_OPS-300);
 for(int i = 0; i < num_ops; i++) {
 int op_size = 20 + rand()%(MAX_OP_SIZE-20);
 int *op = malloc(sizeof(int)*(op_size+1));
 if(!op) {
perror("malloc");
exit(EXIT_FAILURE);
}
 for(int j = 0; j < op_size; j++)
 op[j] = rand()%BITS;
 op[op_size] = -1;
 ops[i] = op;
}
}

static inline void free_ops() {
 for(int i = 0; i < num_ops; i++)
free(ops[i]);
}

// Function that is running in streams
static int worker(void *arg) {
 struct range *r = (struct range*)arg;
 for(int i = r->from; i < r->to; i++) {
 int *op = ops[i];
 for(;;) {
 int val = *op; // Get the bit number that you want to install
 if(val < 0) // If the end of the operation, exit the loop
break;

 int or = 1 << (val&7);
 // Atomically set a bit and get the previous value
 unsigned char byte = atomic_fetch_or(&bitset[val >> 3], or);
 if((byte & or) == 0) {
 // If the bit was not set before, get him out of the room
 printf("%d\n", val);
}
op++;
}
}
 return 0;
}

int main() {
srand(time(NULL));
 for(int i = 0; i < sizeof(bitset); i++)
 atomic_init(&bitset[i], 0);

gen_ops();

 thrd_t thr1, thr2;
 struct range r1 = {0, num_ops/2};
 struct range r2 = {r1.to, num_ops};
 thrd_create(&thr1, worker, &r1);
 thrd_create(&thr2, worker, &r2);
 thrd_join(thr1, NULL);
 thrd_join(thr2, NULL);

free_ops();
}
April 7th 20 at 15:18
1 answer
April 7th 20 at 15:20
What specific lock-free algorithm you have in your code there.
Enough for ctest/write to use atomic operation and it will work fine without data races.

Find more questions by tags CParallel computing