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 36 */ 37 38//------------------------------------------------------------------------ 39// sysfutex_d tests basic functionalities of futex system call: 40// - make a thread wait on a variable 41// - wake up a thread waiting on a variable 42//------------------------------------------------------------------------ 43 44#include "riscv_test.h" 45#include "test_macros.h" 46#include "test_macros_mt_ecall.h" 47 48 RVTEST_RV64U 49 RVTEST_CODE_BEGIN 50 51#define NUM_THREADS 1 52#define LOOP_COUNT 1000 53 54//------------------------------------------------------------------------ 55// Master thread creates new threads, call _master function, waits for all 56// threads to complete, deallocates threads and checks result 57//------------------------------------------------------------------------ 58 li a0, NUM_THREADS 59 call _create_threads 60 61 la t6, n_worker_threads 62 ld a0, (t6) 63 beqz a0, _fail // exit if there's no worker thread 64 call _master_work 65 66 la t6, n_worker_threads 67 ld a0, (t6) 68 call _join 69 70 la t6, n_worker_threads 71 ld a0, (t6) 72 call _check 73 74 la t6, n_worker_threads 75 ld a0, (t6) 76 call _delete_threads 77 78 li a0, SUCCESS 79 80 RVTEST_CODE_END 81 82//------------------------------------------------------------------------ 83// master_work function executed by the parent/master thread 84// 85// Wake up thread(s) waiting on futex_X and then wait on futex_Y in a 86// loop. 87//------------------------------------------------------------------------ 88_master_work: 89 mv s0, ra // save return address 90 li t0, LOOP_COUNT 91 la t1, count_master 92 931: 94 // futex(futex_X, FUTEX_WAKE_PRIVATE, 1) 95 la a0, futex_X 96 li a1, FUTEX_WAKE_PRIVATE 97 li a2, 1 // wake up at most 1 thread 98 li a7, SYSCALL_FUTEX 99 ecall 100 101 // keep waking up until at least one thread is waken up 102 beqz a0, 1b 103 104 // increment count_master 105 ld t2, (t1) 106 addi t2, t2, 1 107 sd t2, (t1) 108 109 // futex(futex_Y, FUTEX_WAIT_PRIVATE, 0) 110 la a0, futex_Y 111 li a1, FUTEX_WAIT_PRIVATE 112 li a2, 0 // expected val of futex_Y 113 li a7, SYSCALL_FUTEX 114 ecall 115 116 // decrement t0 117 addi t0, t0, -1 118 bnez t0, 1b 119 120 // restore return address and return 121 mv ra, s0 122 ret 123 124//------------------------------------------------------------------------ 125// mt_test function executed by child threads 126// 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