Advertisement
Guest User

Work Stealing Queue GCC Atomics

a guest
Mar 15th, 2022
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.04 KB | None | 0 0
  1.  
  2. #define WORK_QUEUE_SIZE 4096
  3. #define WORK_QUEUE_MASK (WORK_QUEUE_SIZE - 1)
  4.  
  5. struct work_entry {
  6.     void (*func) (void *user, void *data, void *sync);
  7.     //void (*func) (/*void *fiber, void *sched, */void *user, void *data, void *sync);
  8.     void *user;
  9.     void *data;
  10.     void *sync;
  11. };
  12.  
  13. struct work_queue {
  14.     atomic32_t top;
  15.     atomic32_t btm;
  16.     struct work_entry *entries;
  17. } __aligned(64);
  18.  
  19. int work_queue_enqueue (struct work_queue *queue, struct work_entry *entry);
  20. int work_queue_dequeue (struct work_queue *queue, struct work_entry *entry);
  21. int work_queue_steal (struct work_queue *queue, struct work_entry *entry);
  22.  
  23. #if 0
  24.     size_t b = load_explicit(&q->bottom, relaxed);
  25.     size_t t = load_explicit(&q->top, acquire);
  26.     Array *a = load_explicit(&q->array, relaxed);
  27.     if (b - t > a->size - 1) { /* Full queue. */
  28.         resize(q);
  29.         a = load_explicit(&q->array, relaxed);
  30.     }
  31.     store_explicit(&a->buffer[b % a->size], x, relaxed);
  32.     thread_fence(release);
  33.     store_explicit(&q->bottom, b + 1, relaxed);
  34. #endif
  35.  
  36. int work_queue_enqueue (struct work_queue *queue, struct work_entry *entry)
  37. {
  38.     int btm = __atomic_load_n (&queue->btm.counter, __ATOMIC_RELAXED);
  39.     int top = __atomic_load_n (&queue->top.counter, __ATOMIC_ACQUIRE);
  40.     struct work_entry *array = queue->entries;
  41.  
  42.     if (btm - top > (WORK_QUEUE_SIZE - 1)) {
  43.         return 1;
  44.     }
  45.  
  46.     __atomic_store_n (&array[btm & WORK_QUEUE_MASK].func, entry->func, __ATOMIC_RELAXED);
  47.     __atomic_store_n (&array[btm & WORK_QUEUE_MASK].data, entry->data, __ATOMIC_RELAXED);
  48.     __atomic_store_n (&array[btm & WORK_QUEUE_MASK].user, entry->user, __ATOMIC_RELAXED);
  49.     __atomic_store_n (&array[btm & WORK_QUEUE_MASK].sync, entry->sync, __ATOMIC_RELAXED);
  50.  
  51.     __atomic_thread_fence (__ATOMIC_RELEASE);
  52.     __atomic_store_n (&queue->btm.counter, btm + 1, __ATOMIC_RELAXED);
  53.     return 0;
  54. }
  55. #if 0
  56.     size_t b = load_explicit(&q->bottom, relaxed) - 1;
  57.     Array *a = load_explicit(&q->array, relaxed);
  58.     store_explicit(&q->bottom, b, relaxed);
  59.     thread_fence(seq_cst);
  60.     size_t t = load_explicit(&q->top, relaxed);
  61.     int x;
  62.  
  63.     if (t <= b) {
  64.         /* Non-empty queue. */
  65.         x = load_explicit(&a->buffer[b % a->size], relaxed);
  66.         if (t == b) {
  67.             /* Single last element in queue. */
  68.             if (!compare_exchange_strong_explicit(&q->top, &t, t + 1, seq_cst, relaxed))
  69.                 /* Failed race. */
  70.                 x = EMPTY;
  71.  
  72.             store_explicit(&q->bottom, b + 1, relaxed);
  73.         }
  74.  
  75.     } else { /* Empty queue. */
  76.         x = EMPTY;
  77.         store_explicit(&q->bottom, b + 1, relaxed);
  78.     }
  79. #endif
  80. int work_queue_dequeue (struct work_queue *queue, struct work_entry *entry)
  81. {
  82.     int btm = __atomic_load_n (&queue->btm.counter, __ATOMIC_RELAXED) - 1;
  83.     __atomic_store_n (&queue->btm.counter, btm, __ATOMIC_RELEASE); // update for steal()
  84.  
  85.     __atomic_thread_fence (__ATOMIC_SEQ_CST);
  86.     int top = __atomic_load_n (&queue->top.counter, __ATOMIC_RELAXED);
  87.  
  88.     entry->func = NULL;
  89.     entry->data = NULL;
  90.     entry->user = NULL;
  91.     entry->sync = NULL;
  92.  
  93.     int res = 0;
  94.     if (btm <= top) {
  95.         *entry = queue->entries[btm & WORK_QUEUE_MASK];
  96.         __atomic_thread_fence (__ATOMIC_ACQUIRE);
  97.  
  98.         if (top == btm) {
  99.             if (!__atomic_compare_exchange_n (&queue->top.counter, &top, top + 1, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
  100.                 res = 1;
  101.             }
  102.  
  103.             __atomic_store_n (&queue->btm.counter, btm + 1, __ATOMIC_RELAXED);
  104.             return res;
  105.         }
  106.     } else {
  107.         __atomic_store_n (&queue->btm.counter, btm + 1, __ATOMIC_RELAXED);
  108.         return 1;
  109.     }
  110. }
  111.  
  112. #if 0
  113. int steal(Deque *q) {
  114.     size_t t = load_explicit(&q->top, acquire);
  115.     thread_fence(seq_cst);
  116.     size_t b = load_explicit(&q->bottom, acquire);
  117.     int x = EMPTY;
  118.     if (t < b) {
  119.         /* Non-empty queue. */
  120.         Array *a = load_explicit(&q->array, consume);
  121.         x = load_explicit(&a->buffer[t % a->size], relaxed);
  122.         if (!compare_exchange_strong_explicit(&q->top, &t, t + 1, seq_cst, relaxed))
  123. /* Failed race. */
  124.         return ABORT;
  125.     }
  126. }
  127. #endif
  128.  
  129. int work_queue_steal (struct work_queue *queue, struct work_entry *entry)
  130. {
  131.     int top = __atomic_load_n (&queue->top, __ATOMIC_ACQUIRE);
  132.     __atomic_thread_fence (__ATOMIC_SEQ_CST);
  133.  
  134.     int btm = __atomic_load_n (&queue->btm, __ATOMIC_ACQUIRE);
  135.  
  136.     if (top < btm) {
  137.         entry->func = queue->entries[top & WORK_QUEUE_MASK].func;
  138.         entry->data = queue->entries[top & WORK_QUEUE_MASK].data;
  139.         entry->user = queue->entries[top & WORK_QUEUE_MASK].user;
  140.         entry->sync = queue->entries[top & WORK_QUEUE_MASK].sync;
  141.         // need fence?
  142.         if (!__atomic_compare_exchange_n (&queue->top, top, top + 1, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED)) {
  143.             entry->func = NULL;
  144.             entry->data = NULL;
  145.             entry->user = NULL;
  146.             entry->sync = NULL;
  147.             return 1;
  148.         }
  149.  
  150.         return 0;
  151.     }
  152.  
  153.     return 1;
  154. }
  155.  
  156.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement