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// sysfutex1_d tests basic functionalities of futex system call:
40//    - make some threads wait on a variable
41//    - wake up all threads 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 MAX_NUM_THREADS 20
52
53//------------------------------------------------------------------------
54// Master thread creates new threads, call _master function, waits for all
55// threads to complete, deallocates threads and checks result
56//------------------------------------------------------------------------
57  li      a0, MAX_NUM_THREADS
58  call    _create_threads
59
60  la      t6, n_worker_threads
61  ld      a0, (t6)
62  beqz    a0, _fail                   // exit if there's no worker thread
63
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 all threads waiting on futex_X
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_WAKE_PRIVATE, n_worker_threads)
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  add   t0, t0, a0              // track the number of waken threads so far
102
103  // keep waking up until all threads are waken up
104  blt   t0, t1, 1b
105
106  // restore return address and return
107  mv    ra, s0
108  ret
109
110//------------------------------------------------------------------------
111// mt_test function executed by child threads
112//
113//    Wait on futex_X
114//------------------------------------------------------------------------
115_mt_test:
116  // futex(futex_X, FUTEX_WAIT_PRIVATE, 1)
117  la    a0, futex_X
118  li    a1, FUTEX_WAIT_PRIVATE
119  li    a2, 0                   // expected val of futex_X
120  li    a7, SYSCALL_FUTEX
121  ecall
122
123  RVTEST_CODE_END
124
125//------------------------------------------------------------------------
126// _check:
127//    Each thread should do LOOP_COUNT iterations
128//------------------------------------------------------------------------
129
130_check:
131  ret
132
133_fail:
134  li        a0, FAILURE
135  RVTEST_CODE_END
136
137  .data
138
139futex_X:  .dword  0
140futex_Y:  .dword  0
141
142count_master:   .dword  0
143count_child:    .dword  0
144
145MT_DATA
146