sysfutex_d.S revision 12771
113819Sgabeblack@google.com/*
213819Sgabeblack@google.com * Copyright (c) 2018, Cornell University
313819Sgabeblack@google.com * All rights reserved.
413819Sgabeblack@google.com *
513819Sgabeblack@google.com * Redistribution and use in source and binary forms, with or
613819Sgabeblack@google.com * without modification, are permitted provided that the following
713819Sgabeblack@google.com * conditions are met:
813819Sgabeblack@google.com *
913819Sgabeblack@google.com * Redistributions of source code must retain the above copyright
1013819Sgabeblack@google.com * notice, this list of conditions and the following disclaimer.
1113819Sgabeblack@google.com *
1213819Sgabeblack@google.com * Redistributions in binary form must reproduce the above
1313819Sgabeblack@google.com * copyright notice, this list of conditions and the following
1413819Sgabeblack@google.com * disclaimer in the documentation and/or other materials provided
1513819Sgabeblack@google.com * with the distribution.
1613819Sgabeblack@google.com *
1713819Sgabeblack@google.com * Neither the name of Cornell University nor the names of its
1813819Sgabeblack@google.com * contributors may be used to endorse or promote products derived
1913819Sgabeblack@google.com * from this software without specific prior written permission.
2013819Sgabeblack@google.com *
2113819Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
2213819Sgabeblack@google.com * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
2313819Sgabeblack@google.com * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2413819Sgabeblack@google.com * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2513819Sgabeblack@google.com * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
2613819Sgabeblack@google.com * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2713819Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2813819Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2913819Sgabeblack@google.com * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
3013819Sgabeblack@google.com * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3113819Sgabeblack@google.com * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3213819Sgabeblack@google.com * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3313819Sgabeblack@google.com * POSSIBILITY OF SUCH DAMAGE.
3413819Sgabeblack@google.com *
3513819Sgabeblack@google.com * Authors: Tuan Ta
3613819Sgabeblack@google.com */
3713819Sgabeblack@google.com
3813819Sgabeblack@google.com//------------------------------------------------------------------------
3913819Sgabeblack@google.com// sysfutex_d tests basic functionalities of futex system call:
4013819Sgabeblack@google.com//    - make a thread wait on a variable
4113819Sgabeblack@google.com//    - wake up a thread waiting on a variable
4213819Sgabeblack@google.com//------------------------------------------------------------------------
4313819Sgabeblack@google.com
4413819Sgabeblack@google.com#include "riscv_test.h"
4513819Sgabeblack@google.com#include "test_macros.h"
4613819Sgabeblack@google.com#include "test_macros_mt_ecall.h"
4713819Sgabeblack@google.com
4813819Sgabeblack@google.com  RVTEST_RV64U
4913819Sgabeblack@google.com  RVTEST_CODE_BEGIN
5013819Sgabeblack@google.com
5113819Sgabeblack@google.com#define NUM_THREADS 1
5213819Sgabeblack@google.com#define LOOP_COUNT  1000
5313819Sgabeblack@google.com
5413819Sgabeblack@google.com//------------------------------------------------------------------------
5513819Sgabeblack@google.com// Master thread creates new threads, call _master function, waits for all
5613819Sgabeblack@google.com// threads to complete, deallocates threads and checks result
5713819Sgabeblack@google.com//------------------------------------------------------------------------
5813819Sgabeblack@google.com  li      a0, NUM_THREADS
5913819Sgabeblack@google.com  call    _create_threads
6013819Sgabeblack@google.com
6113819Sgabeblack@google.com  la      t6, n_worker_threads
6213819Sgabeblack@google.com  ld      a0, (t6)
6313819Sgabeblack@google.com  beqz    a0, _fail        // exit if there's no worker thread
6413819Sgabeblack@google.com  call    _master_work
6513819Sgabeblack@google.com
6613819Sgabeblack@google.com  la      t6, n_worker_threads
6713819Sgabeblack@google.com  ld      a0, (t6)
6813819Sgabeblack@google.com  call    _join
6913819Sgabeblack@google.com
7013819Sgabeblack@google.com  la      t6, n_worker_threads
7113819Sgabeblack@google.com  ld      a0, (t6)
7213819Sgabeblack@google.com  call    _check
7313819Sgabeblack@google.com
7413819Sgabeblack@google.com  la      t6, n_worker_threads
7513819Sgabeblack@google.com  ld      a0, (t6)
7613819Sgabeblack@google.com  call    _delete_threads
7714189Sgabeblack@google.com
7813819Sgabeblack@google.com  li      a0, SUCCESS
7913819Sgabeblack@google.com
8013819Sgabeblack@google.com  RVTEST_CODE_END
8113819Sgabeblack@google.com
8213819Sgabeblack@google.com//------------------------------------------------------------------------
8313819Sgabeblack@google.com// master_work function executed by the parent/master thread
8413819Sgabeblack@google.com//
8513819Sgabeblack@google.com//    Wake up thread(s) waiting on futex_X and then wait on futex_Y in a
8613819Sgabeblack@google.com//    loop.
8713819Sgabeblack@google.com//------------------------------------------------------------------------
8813819Sgabeblack@google.com_master_work:
8913819Sgabeblack@google.com  mv    s0, ra                  // save return address
9013819Sgabeblack@google.com  li    t0, LOOP_COUNT
9113819Sgabeblack@google.com  la    t1, count_master
9213819Sgabeblack@google.com
9313819Sgabeblack@google.com1:
9413819Sgabeblack@google.com  // futex(futex_X, FUTEX_WAKE_PRIVATE, 1)
9513819Sgabeblack@google.com  la    a0, futex_X
9613819Sgabeblack@google.com  li    a1, FUTEX_WAKE_PRIVATE
9713819Sgabeblack@google.com  li    a2, 1                   // wake up at most 1 thread
9813819Sgabeblack@google.com  li    a7, SYSCALL_FUTEX
9913819Sgabeblack@google.com  ecall
10013819Sgabeblack@google.com
10113819Sgabeblack@google.com  // keep waking up until at least one thread is waken up
10213819Sgabeblack@google.com  beqz  a0, 1b
10313819Sgabeblack@google.com
10413819Sgabeblack@google.com  // increment count_master
10513819Sgabeblack@google.com  ld    t2, (t1)
10613819Sgabeblack@google.com  addi  t2, t2, 1
10713819Sgabeblack@google.com  sd    t2, (t1)
10813819Sgabeblack@google.com
10913819Sgabeblack@google.com  // futex(futex_Y, FUTEX_WAIT_PRIVATE, 0)
11013819Sgabeblack@google.com  la    a0, futex_Y
11114189Sgabeblack@google.com  li    a1, FUTEX_WAIT_PRIVATE
11213819Sgabeblack@google.com  li    a2, 0                   // expected val of futex_Y
11313819Sgabeblack@google.com  li    a7, SYSCALL_FUTEX
11413819Sgabeblack@google.com  ecall
11513819Sgabeblack@google.com
11613819Sgabeblack@google.com  // decrement t0
11713819Sgabeblack@google.com  addi  t0, t0, -1
11813819Sgabeblack@google.com  bnez  t0, 1b
11913819Sgabeblack@google.com
12013819Sgabeblack@google.com  // restore return address and return
12113819Sgabeblack@google.com  mv    ra, s0
12213819Sgabeblack@google.com  ret
12313819Sgabeblack@google.com
12413819Sgabeblack@google.com//------------------------------------------------------------------------
12513819Sgabeblack@google.com// mt_test function executed by child threads
12613819Sgabeblack@google.com//
127//    Wait on futex_X and then wake up threads waiting on futex_Y in a loop
128//------------------------------------------------------------------------
129_mt_test:
130  li    t0, LOOP_COUNT
131  la    t1, count_child
132
1331:
134  // futex(futex_X, FUTEX_WAIT_PRIVATE, 1)
135  la    a0, futex_X
136  li    a1, FUTEX_WAIT_PRIVATE
137  li    a2, 0                   // expected val of futex_X
138  li    a7, SYSCALL_FUTEX
139  ecall
140
141  // increment count_child
142  ld    t2, (t1)
143  addi  t2, t2, 1
144  sd    t2, (t1)
145
1462:
147  // futex(futex_Y, FUTEX_WAKE_PRIVATE, 0)
148  la    a0, futex_Y
149  li    a1, FUTEX_WAKE_PRIVATE
150  li    a2, 1                   // wake up at most 1 thread
151  li    a7, SYSCALL_FUTEX
152  ecall
153
154  // keep waking up until at least one thread is waken up
155  beqz  a0, 2b
156
157  // decrement t0
158  addi  t0, t0, -1
159  bnez  t0, 1b
160
161  RVTEST_CODE_END
162
163//------------------------------------------------------------------------
164// _check:
165//    Each thread should do LOOP_COUNT iterations
166//------------------------------------------------------------------------
167
168_check:
169  la    t0, count_master
170  la    t1, count_child
171  li    t2, LOOP_COUNT
172
173  ld    t0, (t0)
174  bne   t0, t2, _fail
175
176  ld    t1, (t1)
177  bne   t1, t2, _fail
178
179  ret
180
181_fail:
182  li        a0, FAILURE
183  RVTEST_CODE_END
184
185  .data
186
187futex_X:  .dword  0
188futex_Y:  .dword  0
189
190count_master:   .dword  0
191count_child:    .dword  0
192
193MT_DATA
194