source: tests/io/comp_fair.cfa@ b230091

ADT ast-experimental enum pthread-emulation qualifiedEnum
Last change on this file since b230091 was 72ba508, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Updated test to be easier to debug

  • Property mode set to 100644
File size: 3.1 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// comp_fair.cfa -- Test that spinning doesn't cause completions to get stuck.
8// This test should work without io_uring but isn't very useful without
9//
10// Author : Thierry Delisle
11// Created On : Thu Mar 10 15:06:50 2022
12// Last Modified By :
13// Last Modified On :
14// Update Count :
15//
16
17
18#include <concurrency/locks.hfa>
19#include <fstream.hfa>
20#include <iofwd.hfa>
21#include <kernel.hfa>
22#include <thread.hfa>
23
24#include <errno.h>
25#include <string.h>
26#include <unistd.h>
27
28struct {
29 semaphore sem;
30 int pipe[2];
31
32} globals;
33
34Duration default_preemption() {
35 return 0;
36}
37
38enum { TIMES = 1000 };
39
40volatile unsigned counter = 0;
41
42
43// ----- Spinner -----
44// spins trying to prevent other threads from getting to this processor
45thread Spinner {};
46void main(Spinner &) {
47 unsigned last = 0;
48 for() {
49 unsigned curr = __atomic_load_n(&counter, __ATOMIC_SEQ_CST);
50
51 if(curr >= TIMES) break;
52
53 if(last == curr) {
54 Pause();
55 continue;
56 }
57
58 last = curr;
59 yield();
60 }
61
62 mutex(sout) sout | "Spinner done";
63}
64
65// ----- Reader -----
66// Reader from the pipe to test completion doesn't starve
67thread Reader {};
68void main(Reader & this) {
69 bool do_read = has_user_level_blocking( (fptr_t)async_read );
70
71 for(TIMES) {
72 yield( prng( this, 15 ) );
73
74 io_future_t f;
75 if ( do_read ) {
76 char thrash[1];
77 async_read(f, globals.pipe[0], thrash, 1, 0);
78 } else {
79 fulfil(f, 0); // If we don't have user-level blocking just play along
80 }
81
82 P( globals.sem );
83
84 unsigned i = __atomic_add_fetch( &counter, 1, __ATOMIC_SEQ_CST );
85 if(0 == (i % 100)) sout | i;
86
87 wait( f );
88
89 if(f.result < 0)
90 abort | "Read error" | -f.result | ":" | strerror(-f.result);
91 }
92
93 P( globals.sem );
94
95 mutex(sout) sout | "Reader done";
96}
97
98// ----- Writer -----
99// Writes to the pipe so the Reader can unblock
100// takes its sweet time so the Reader has to block
101thread Writer {};
102void main(Writer & this) {
103 for(TIMES) {
104 yield( prng( this, 15 ) );
105
106 V( globals.sem );
107
108 sleep( 1`us );
109
110 char buf[1] = { '+' };
111 int ret = write( globals.pipe[1], buf, 1 );
112 if(ret < 0)
113 abort | "Write error" | errno | ":" | strerror(errno);
114
115 }
116
117 mutex(sout) sout | "Writer done";
118}
119
120// ----- Yielder -----
121// Add some chaos into the mix
122thread Yielder {};
123void ^?{}(Yielder &mutex ) {}
124void main(Yielder&) {
125 while(TIMES > __atomic_load_n(&counter, __ATOMIC_SEQ_CST)) {
126 yield();
127 }
128
129 mutex(sout) sout | "Yielder done";
130}
131
132int main() {
133 int ret = pipe(globals.pipe);
134 if(ret != 0)
135 abort | "Pipe error" | errno | ":" | strerror(errno);
136
137 processor p;
138 sout | "starting";
139 {
140 Yielder y;
141 Spinner s;
142 Reader ior;
143 Writer iow;
144 }
145 sout | "done";
146}
Note: See TracBrowser for help on using the repository browser.