source: tests/concurrency/readyQ/leader_spin.cfa @ ce0b8b8

Last change on this file since ce0b8b8 was b2fa3c2, checked in by Peter A. Buhr <pabuhr@…>, 17 months ago

fix comments referring to concurrency directory

  • 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// 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.