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 Wang 36 */ 37 38//------------------------------------------------------------------------ 39// sysfutex3_d tests FUTEX_CMP_REQUEUE functionalities of futex system 40// call: 41// - make worker threads waiting on futex 1 42// - wake up 1 thread, requeue the rest of the threads to futex 2 43// - wake all threads waiting on futex 1 and futex 2 44//------------------------------------------------------------------------ 45 46#include "riscv_test.h" 47#include "test_macros.h" 48#include "test_macros_mt_ecall.h" 49 50 RVTEST_RV64U 51 RVTEST_CODE_BEGIN 52 53#define NUM_THREADS 20 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_master_work: 88 mv s0, ra // save return address 89 li t0, 0 // number of threads that have been waken 90 la t1, n_worker_threads 91 ld t1, (t1) 92 931: 94 // futex(futex_X, FUTEX_CMP_REQUEUE, 1, INT_MAX, futex_Y, *futex_X) 95 la a0, futex_X 96 li a1, FUTEX_CMP_REQUEUE 97 li a2, 1 // wake up at most 1 thread 98 li a3, 1000 // practically is INT_MAX 99 la a4, futex_Y // move all other waiter to futex_Y 100 li a5, 0 101 li a7, SYSCALL_FUTEX 102 ecall 103 104 // loop until wake up one thread, all other waiter are requeued to 105 // futex_Y 106 beqz a0, 1b 107 108 addi t0, t0, 1 109 1102: 111 // alternating between futex_X and futex_Y 112 // because there could be new threads added to futex_X's queue 113 // after our futex_requeue 114 115 // futex(futex_Y, FUTEX_WAKE_PRIVATE, 0) 116 la a0, futex_Y 117 li a1, FUTEX_WAKE 118 li a2, 1 // wake up at most 1 thread 119 li a7, SYSCALL_FUTEX 120 ecall 121 122 add t0, t0, a0 // track the number of waken threads so far 123 124 // futex(futex_X, FUTEX_WAKE_PRIVATE, 0) 125 la a0, futex_X 126 li a1, FUTEX_WAKE 127 li a2, 1 // wake up at most 1 thread 128 li a7, SYSCALL_FUTEX 129 ecall 130 131 add t0, t0, a0 // track the number of waken threads so far 132 133 // keep waking up until all threads are waken up 134 blt t0, t1, 2b 135 136 // restore return address and return 137 mv ra, s0 138 ret 139 140//------------------------------------------------------------------------ 141// mt_test function executed by child threads 142// 143// Wait on futex_X 144//------------------------------------------------------------------------ 145_mt_test: 146 // futex(futex_X, FUTEX_WAIT_PRIVATE, 1) 147 la a0, futex_X 148 li a1, FUTEX_WAIT 149 li a2, 0 // expected val of futex_X 150 li a7, SYSCALL_FUTEX 151 ecall 152 153 RVTEST_CODE_END 154 155//------------------------------------------------------------------------ 156// _check: 157// counter should equals to number of child threads 158//------------------------------------------------------------------------ 159 160_check: 161 ret 162 163_fail: 164 li a0, FAILURE 165 RVTEST_CODE_END 166 167 .data 168 169futex_X: .dword 0 170futex_Y: .dword 0 171 172MT_DATA 173