1/*
2 * Copyright (c) 2018, Cornell University
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or
6 * without modification, are permitted provided that the following
7 * conditions are met:
8 *
9 * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 *
17 * Neither the name of Cornell University nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
22 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
29 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * Authors: Tuan Ta, Moyang
36 */
37
38//------------------------------------------------------------------------
39// sysfutex_d tests FUTEX_WAKE_OP functionalities of futex system call:
40//    - make a thread wait on a variable
41//    - atomically wake up a thread waiting on a variable and perform
42//      a operation on a value
43//------------------------------------------------------------------------
44
45#include "riscv_test.h"
46#include "test_macros.h"
47#include "test_macros_mt_ecall.h"
48
49  RVTEST_RV64U
50  RVTEST_CODE_BEGIN
51
52#define NUM_THREADS 1
53#define LOOP_COUNT  1000
54
55//------------------------------------------------------------------------
56// Master thread creates new threads, call _master function, waits for all
57// threads to complete, deallocates threads and checks result
58//------------------------------------------------------------------------
59  li      a0, NUM_THREADS
60  call    _create_threads
61
62  la      t6, n_worker_threads
63  ld      a0, (t6)
64  beqz    a0, _fail        // exit if there's no worker thread
65
66  call    _master_work
67
68  la      t6, n_worker_threads
69  ld      a0, (t6)
70  call    _join
71
72  la      t6, n_worker_threads
73  ld      a0, (t6)
74  call    _check
75
76  la      t6, n_worker_threads
77  ld      a0, (t6)
78  call    _delete_threads
79
80  li      a0, SUCCESS
81
82  RVTEST_CODE_END
83
84//------------------------------------------------------------------------
85// master_work function executed by the parent/master thread
86//
87//    Wake up thread(s) waiting on futex_X and then wait on futex_Y in a
88//    loop. Also atomically modify futex_Z during the wake-up.
89//------------------------------------------------------------------------
90_master_work:
91  mv    s0, ra                  // save return address
92  li    t0, LOOP_COUNT
93  la    t1, count_master
94  la    t3, count_Z
95
961:
97  // futex(futex_X, FUTEX_WAKE_OP, 1, val2, futex_Z, val3 )
98  la    a0, futex_X
99  li    a1, FUTEX_WAKE_OP
100  li    a2, 1                   // wake up at most 1 thread
101  li    a3, 0                   // should not perform the second wake up
102  la    a4, futex_Z             // add 1 to futex_Z each time
103  li    a5, FUTEX_OP(FUTEX_OP_ADD, 1, FUTEX_OP_CMP_LT, 0)
104  li    a7, SYSCALL_FUTEX
105  ecall
106
107  // increment count_Z (should equals to futex_Z)
108  ld    t4, (t3)
109  addi  t4, t4, 1
110  sd    t4, (t3)
111
112  // keep waking up until at least one thread is waken up
113  beqz  a0, 1b
114
115  // increment count_master
116  ld    t2, (t1)
117  addi  t2, t2, 1
118  sd    t2, (t1)
119
120  // futex(futex_Y, FUTEX_WAIT_PRIVATE, 0)
121  la    a0, futex_Y
122  li    a1, FUTEX_WAIT_PRIVATE
123  li    a2, 0                   // expected val of futex_Y
124  li    a7, SYSCALL_FUTEX
125  ecall
126
127  // decrement t0
128  addi  t0, t0, -1
129  bnez  t0, 1b
130
131  // restore return address and return
132  mv    ra, s0
133  ret
134
135//------------------------------------------------------------------------
136// mt_test function executed by child threads
137//
138//    Wait on futex_X and then wake up threads waiting on futex_Y in a loop
139//------------------------------------------------------------------------
140_mt_test:
141  li    t0, LOOP_COUNT
142  la    t1, count_child
143
1441:
145  // futex(futex_X, FUTEX_WAIT_PRIVATE, 1)
146  la    a0, futex_X
147  li    a1, FUTEX_WAIT_PRIVATE
148  li    a2, 0                   // expected val of futex_X
149  li    a7, SYSCALL_FUTEX
150  ecall
151
152  // increment count_child
153  ld    t2, (t1)
154  addi  t2, t2, 1
155  sd    t2, (t1)
156
1572:
158  // futex(futex_Y, FUTEX_WAKE_PRIVATE, 0)
159  la    a0, futex_Y
160  li    a1, FUTEX_WAKE_PRIVATE
161  li    a2, 1                   // wake up at most 1 thread
162  li    a7, SYSCALL_FUTEX
163  ecall
164
165  // keep waking up until at least one thread is waken up
166  beqz  a0, 2b
167
168  // decrement t0
169  addi  t0, t0, -1
170  bnez  t0, 1b
171
172  RVTEST_CODE_END
173
174//------------------------------------------------------------------------
175// _check:
176//    Each thread should do LOOP_COUNT iterations
177//------------------------------------------------------------------------
178
179_check:
180  la    t0, count_master
181  la    t1, count_child
182  li    t2, LOOP_COUNT
183  la    t3, count_Z
184  la    t4, futex_Z
185
186  ld    t0, (t0)
187  bne   t0, t2, _fail
188
189  ld    t1, (t1)
190  bne   t1, t2, _fail
191
192  ld    t3, (t3)
193  ld    t4, (t4)
194  bne   t3, t4, _fail
195
196  ret
197
198_fail:
199  li        a0, FAILURE
200  RVTEST_CODE_END
201
202  .data
203
204futex_X:  .dword  0
205futex_Y:  .dword  0
206futex_Z:  .dword  0
207
208count_master:   .dword  0
209count_child:    .dword  0
210count_Z:        .dword  0
211
212MT_DATA
213