source: tests/concurrent/readyQ/leader_spin.cfa@ 441a6a7

ADT ast-experimental
Last change on this file since 441a6a7 was be1d00c, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

Changed fairness tests to use sched_yield in case exhausting the time slice is what causing test failures

  • Property mode set to 100644
File size: 2.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2022 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// concurrent/readyQ/leader_spin.cfa -- validates ready queue fairness
8//
9// Author : Thierry Delisle
10// Created On : Fri Apr 01 11:39:09 2022
11// Last Modified By :
12// Last Modified On :
13// Update Count :
14//
15
16#include <stdlib.hfa>
17#include <fstream.hfa>
18#include <thread.hfa>
19
20// Test validates that all cores being constantly active doesn't prevent starvation.
21// This test is very similar to the transfer benchmark, without all the benchmark bells and whistle.
22
23// Deactivate preemption because it could fix starvation issues.
24Duration default_preemption() {
25 return 0;
26}
27
28PRNG64 lead_rng;
29volatile unsigned leader;
30volatile size_t lead_idx;
31
32const uint64_t nthreads = 17;
33const uint64_t stop_count = 327;
34
35thread$ * the_main;
36
37thread __attribute__((aligned(128))) MyThread {
38 unsigned id;
39 volatile size_t idx;
40};
41
42void ?{}( MyThread & this, unsigned id ) {
43 this.id = id;
44 this.idx = 0;
45}
46
47MyThread ** threads;
48
49static void waitgroup() {
50 for(i; nthreads) {
51 while( threads[i]->idx != lead_idx ) {
52 sched_yield();
53 }
54 }
55}
56
57static void lead(MyThread & this) {
58 this.idx = ++lead_idx;
59 if(lead_idx > stop_count) {
60 sout | "Leader done";
61 unpark( the_main );
62 return;
63 }
64
65 waitgroup();
66
67 unsigned nleader = prng( lead_rng, nthreads );
68 __atomic_store_n( &leader, nleader, __ATOMIC_SEQ_CST );
69}
70
71static void wait(MyThread & this) {
72 yield();
73 if(lead_idx == this.idx) {
74 return;
75 }
76
77 assert( (lead_idx - 1) == this.idx );
78 __atomic_add_fetch( &this.idx, 1, __ATOMIC_SEQ_CST );
79 yield();
80}
81
82void main(MyThread & this) {
83 park();
84
85 unsigned me = this.id;
86
87 for() {
88 if(leader == me) {
89 lead( this );
90 }
91 else {
92 wait( this );
93 }
94 if(lead_idx > stop_count) break;
95 }
96}
97
98// ==================================================
99int main(int argc, char * argv[]) {
100 lead_idx = 0;
101 leader = prng( lead_rng, nthreads );
102
103 the_main = active_thread();
104 processor procs[2];
105 {
106 threads = alloc(nthreads);
107 for(i; nthreads) {
108 threads[i] = malloc();
109 (*threads[i]){
110 i
111 };
112 }
113
114 for(i; nthreads) unpark(*threads[i]);
115
116 park();
117
118 for(i; nthreads) {
119 MyThread * thrd = threads[i];
120 join(*thrd);
121 ^( *thrd ){};
122 free(thrd);
123 }
124
125 free(threads);
126 }
127 sout | "done";
128}
Note: See TracBrowser for help on using the repository browser.