source: CIVL/examples/cuda/exitBarrier.cvl@ 85d4675

1.23 2.0 main test-branch
Last change on this file since 85d4675 was 36b5ada, checked in by Manchun Zheng <zmanchun@…>, 12 years ago

Cleaned up examples.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@424 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 3.9 KB
Line 
1// Tyler Sorensen
2//
3// An attempt to create an "exit barrier"
4// as seen in NVIDIA PTX instructions
5// See "exit" and "bar.sync" instructions in PTX ISA
6//
7// The algorithm implemented uses the general CIVL barrier
8// module found in examples/concurrency/barrier2.cvl
9//
10// The exit semantics are a combination of barrier
11// resignation as seen in KRoC release of occam and
12// documented in the paper:
13// Higher Level of Process Synchronization by:
14// Peter H. Welch and David C. Wood.
15// and a return statement (to exit the thread)
16//
17// The resignation algorithm is given briefly in
18// the paper cited above which I attempted to
19// implement. However, this implementation assumes
20// that a resigned thread does not access the barrier
21// again! It is implemented with the exit barrier
22// semantics in mind, i.e. the thread will cease
23// execution right after resignation. No attempts
24// are made to guard against behavior deviating
25// from this.
26// Commandline execution:
27// civl verify exitBarrier.cvl
28
29// TODO: Right now, the thread termination is simply
30// a "return" statement. Anyway for that to actually
31// kill the thread?
32
33#include <civlc.h>
34
35struct _CIVL_Barrier {
36 int numProcs; //how many are enrolled to begin with, cannot change
37 int numWaiting; //New variable for exit barriers, how many you need to wait for, can change
38 int *in_barrier;
39 int num_in_barrier;
40 int lock;
41};
42
43typedef struct _CIVL_Barrier CIVL_Barrier;
44
45void CIVL_Barrier_init(int numProcs, CIVL_Barrier *barrier, int *array) {
46 barrier->numProcs = numProcs;
47 barrier->numWaiting = numProcs;
48 barrier->num_in_barrier = 0;
49 barrier->lock = 0;
50 barrier->in_barrier = array;
51 for (int i=0; i<numProcs; i++)
52 barrier->in_barrier[i] = 0;
53 return barrier;
54}
55
56void CIVL_barrier(CIVL_Barrier *barrier, int tid) {
57$atomic{
58 $when (barrier->lock==0) barrier->lock = 1;
59 barrier->in_barrier[tid] = 1;
60 barrier->num_in_barrier++;
61
62 //simply wait for how many need to be waited for, but
63 //free them all. No exceptions.
64 if (barrier->num_in_barrier == barrier->numWaiting) {
65 for (int i=0; i<barrier->numProcs; i++)
66 barrier->in_barrier[i] = 0;
67 barrier->num_in_barrier = 0;
68 }
69 barrier->lock = 0;
70 $when (barrier->in_barrier[tid] == 0);}
71}
72
73//The resign function: Basically the same, but
74//decrement the number waiting for. If
75//A barrier is waiting on the resigning thread, then free
76//the barrier before leaving. No need to wait also.
77void CIVL_barrier_resign(CIVL_Barrier *barrier, int tid) {
78$atomic{
79 $when (barrier->lock==0) barrier->lock = 1;
80 barrier->in_barrier[tid] = 1;
81 barrier->numWaiting--;
82 if (barrier->num_in_barrier == barrier->numWaiting) {
83 for (int i=0; i<barrier->numProcs; i++)
84 barrier->in_barrier[i] = 0;
85 barrier->num_in_barrier = 0;
86 }
87 barrier->lock = 0; }
88}
89
90#define CIVL_barrier_exit(barrier, tid) CIVL_barrier_resign(barrier, tid); return
91
92void main() {
93 int N=4;
94 $proc threads[N];
95 int counter = 0;
96 CIVL_Barrier b;
97 int barrier_array[N];
98
99 void run_proc0(int tid) {
100 $atomic{
101 $assert counter == 0;
102 CIVL_barrier_exit(&b, tid);}
103 }
104
105 void run_proc1(int tid) {
106 $atomic{
107 $assert counter == 0;
108 CIVL_barrier(&b, tid);
109 counter++;
110 CIVL_barrier_exit(&b, tid);}
111 }
112
113 void run_proc2(int tid) {
114 $atomic{
115 $assert counter == 0;
116 CIVL_barrier(&b, tid);
117 counter++;
118 CIVL_barrier(&b, tid);
119 $assert counter == 3;
120 CIVL_barrier_exit(&b, tid); }
121 }
122
123 void run_proc3(int tid) {
124 $atomic{
125 $assert counter == 0;
126 CIVL_barrier(&b, tid);
127 counter++;
128 CIVL_barrier(&b, tid);
129 $assert counter == 3;
130 CIVL_barrier(&b, tid);
131 counter--;
132 CIVL_barrier_exit(&b, tid);}
133 }
134
135 $atomic{
136 CIVL_Barrier_init(N, &b, barrier_array);}
137
138 //Spawn threads
139 $proc proc0 = $spawn run_proc0(0);
140 $proc proc1 = $spawn run_proc1(1);
141 $proc proc2 = $spawn run_proc2(2);
142 $proc proc3 = $spawn run_proc3(3);
143
144 //wait for threads
145 $wait proc0;
146 $wait proc1;
147 $wait proc2;
148 $wait proc3;
149
150 $assert counter == 2;
151}
Note: See TracBrowser for help on using the repository browser.