source: tests/concurrent/readyQ/leader_spin.cfa @ 63db8fd7

ADTast-experimentalenumpthread-emulationqualifiedEnum
Last change on this file since 63db8fd7 was 63db8fd7, checked in by Thierry Delisle <tdelisle@…>, 2 years ago

Added test that checks fairness of the readyQ.

  • Property mode set to 100644
File size: 2.4 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 <bits/random.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
28__uint128_t lead_seed;
29volatile unsigned leader;
30volatile size_t lead_idx;
31
32const unsigned nthreads = 17;
33const unsigned 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                        Pause();
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 = lehmer64( lead_seed ) % 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        uint64_t lead_seed = prng();
101        for(10) lehmer64( lead_seed );
102
103        lead_idx = 0;
104        leader = lehmer64( lead_seed ) % nthreads;
105
106        the_main = active_thread();
107        processor procs[2];
108        {
109                threads = alloc(nthreads);
110                for(i; nthreads) {
111                        threads[i] = malloc();
112                        (*threads[i]){
113                                i
114                        };
115                }
116
117                for(i; nthreads) unpark(*threads[i]);
118
119                park();
120
121                for(i; nthreads) {
122                        MyThread * thrd = threads[i];
123                        join(*thrd);
124                        ^( *thrd ){};
125                        free(thrd);
126                }
127
128                free(threads);
129        }
130        sout | "done";
131}
Note: See TracBrowser for help on using the repository browser.