112771Sqtt2@cornell.edu/*
212771Sqtt2@cornell.edu * Copyright (c) 2018, Cornell University
312771Sqtt2@cornell.edu * All rights reserved.
412771Sqtt2@cornell.edu *
512771Sqtt2@cornell.edu * Redistribution and use in source and binary forms, with or
612771Sqtt2@cornell.edu * without modification, are permitted provided that the following
712771Sqtt2@cornell.edu * conditions are met:
812771Sqtt2@cornell.edu *
912771Sqtt2@cornell.edu * Redistributions of source code must retain the above copyright
1012771Sqtt2@cornell.edu * notice, this list of conditions and the following disclaimer.
1112771Sqtt2@cornell.edu *
1212771Sqtt2@cornell.edu * Redistributions in binary form must reproduce the above
1312771Sqtt2@cornell.edu * copyright notice, this list of conditions and the following
1412771Sqtt2@cornell.edu * disclaimer in the documentation and/or other materials provided
1512771Sqtt2@cornell.edu * with the distribution.
1612771Sqtt2@cornell.edu *
1712771Sqtt2@cornell.edu * Neither the name of Cornell University nor the names of its
1812771Sqtt2@cornell.edu * contributors may be used to endorse or promote products derived
1912771Sqtt2@cornell.edu * from this software without specific prior written permission.
2012771Sqtt2@cornell.edu *
2112771Sqtt2@cornell.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
2212771Sqtt2@cornell.edu * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
2312771Sqtt2@cornell.edu * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2412771Sqtt2@cornell.edu * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2512771Sqtt2@cornell.edu * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
2612771Sqtt2@cornell.edu * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2712771Sqtt2@cornell.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2812771Sqtt2@cornell.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2912771Sqtt2@cornell.edu * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
3012771Sqtt2@cornell.edu * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3112771Sqtt2@cornell.edu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3212771Sqtt2@cornell.edu * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3312771Sqtt2@cornell.edu * POSSIBILITY OF SUCH DAMAGE.
3412771Sqtt2@cornell.edu *
3512771Sqtt2@cornell.edu * Authors: Tuan Ta
3612771Sqtt2@cornell.edu */
3712771Sqtt2@cornell.edu
3812771Sqtt2@cornell.edu//------------------------------------------------------------------------
3912771Sqtt2@cornell.edu// This code tests lr.d and sc.d instructions in multi-threading system.
4012771Sqtt2@cornell.edu// All threads execute a critical section LOOP_COUNT times. A thread
4112771Sqtt2@cornell.edu// gets into a critical section by acquiring a lock variable (i.e.,
4212771Sqtt2@cornell.edu// shared_var) and checking return value.
4312771Sqtt2@cornell.edu// 0 means the lock is not being locked. Each thread increments
4412771Sqtt2@cornell.edu// a variable (i.e., var) inside the critical section and releases the
4512771Sqtt2@cornell.edu// lock by swapping back 0 to the lock variable.
4612771Sqtt2@cornell.edu// The master thread (i.e., thread 0) waits for all threads to complete
4712771Sqtt2@cornell.edu// and compare the var's value to the expected result.
4812771Sqtt2@cornell.edu//------------------------------------------------------------------------
4912771Sqtt2@cornell.edu
5012771Sqtt2@cornell.edu#include "riscv_test.h"
5112771Sqtt2@cornell.edu#include "test_macros.h"
5212771Sqtt2@cornell.edu#include "test_macros_mt.h"
5312771Sqtt2@cornell.edu
5412771Sqtt2@cornell.edu  RVTEST_RV64U
5512771Sqtt2@cornell.edu  RVTEST_CODE_BEGIN
5612771Sqtt2@cornell.edu
5712771Sqtt2@cornell.edu#define LOOP_COUNT  1000
5812771Sqtt2@cornell.edu#define RESULT      NUM_THREADS * LOOP_COUNT
5912771Sqtt2@cornell.edu
6012771Sqtt2@cornell.edu//------------------------------------------------------------------------
6112771Sqtt2@cornell.edu// Master thread creates new threads, waits for all threads to complete,
6212771Sqtt2@cornell.edu// deallocates threads and checks result
6312771Sqtt2@cornell.edu//------------------------------------------------------------------------
6412771Sqtt2@cornell.edu  call _create_threads
6512771Sqtt2@cornell.edu  call _join
6612771Sqtt2@cornell.edu  call _delete_threads
6712771Sqtt2@cornell.edu  call _check
6812771Sqtt2@cornell.edu
6912771Sqtt2@cornell.edu  RVTEST_CODE_END
7012771Sqtt2@cornell.edu
7112771Sqtt2@cornell.edu//------------------------------------------------------------------------
7212771Sqtt2@cornell.edu// mt_test function executed in child threads
7312771Sqtt2@cornell.edu// A child thread signals its completion by atomicaly adding 1 to barrier
7412771Sqtt2@cornell.edu//------------------------------------------------------------------------
7512771Sqtt2@cornell.edu_mt_test:
7612771Sqtt2@cornell.edu  li        t0, 1               // initialize the swap value (1-locked)
7712771Sqtt2@cornell.edu  li        t1, LOOP_COUNT
7812771Sqtt2@cornell.edu  la        t2, var             // load the var's address
7912771Sqtt2@cornell.edu  la        a0, shared_var
8012771Sqtt2@cornell.edu
8112771Sqtt2@cornell.edu1:
8212771Sqtt2@cornell.edu  lr.d.aq       s2, (a0)        // load and reserve a0
8312771Sqtt2@cornell.edu  bnez          s2, 1b          // retry lr if the lock is being held
8412771Sqtt2@cornell.edu  sc.d.rl       s2, t0, (a0)    // try to lock a0
8512771Sqtt2@cornell.edu  bnez          s2, 1b          // retry if sc failed
8612771Sqtt2@cornell.edu
8712771Sqtt2@cornell.edu  lw            t3, (t2)        // load the var's value
8812771Sqtt2@cornell.edu  addi          t3, t3, 1       // add 1 to the value
8912771Sqtt2@cornell.edu  sw            t3, (t2)        // store the new value to var
9012771Sqtt2@cornell.edu
9112771Sqtt2@cornell.edu  sd            zero, (a0)      // release the lock by storing 0 to a0
9212771Sqtt2@cornell.edu
9312771Sqtt2@cornell.edu  addi          t1, t1, -1      // decrement the loop_count
9412771Sqtt2@cornell.edu  bnez          t1, 1b          // repeat if not done yet
9512771Sqtt2@cornell.edu
9612771Sqtt2@cornell.edu  la            a0, barrier
9712771Sqtt2@cornell.edu  amoadd.d      zero, t0, (a0)  // signal this thread's completion
9812771Sqtt2@cornell.edu
9912771Sqtt2@cornell.edu  RVTEST_CODE_END
10012771Sqtt2@cornell.edu
10112771Sqtt2@cornell.edu//------------------------------------------------------------------------
10212771Sqtt2@cornell.edu// Master thread checks result
10312771Sqtt2@cornell.edu//------------------------------------------------------------------------
10412771Sqtt2@cornell.edu_check:
10512771Sqtt2@cornell.edu  la        a0, var
10612771Sqtt2@cornell.edu  li        a1, RESULT
10712771Sqtt2@cornell.edu  ld        a0, (a0)
10812771Sqtt2@cornell.edu  bne       a0, a1, _fail
10912771Sqtt2@cornell.edu  li        a0, SUCCESS
11012771Sqtt2@cornell.edu  ret
11112771Sqtt2@cornell.edu
11212771Sqtt2@cornell.edu_fail:
11312771Sqtt2@cornell.edu  li        a0, FAILURE
11412771Sqtt2@cornell.edu  ret
11512771Sqtt2@cornell.edu
11612771Sqtt2@cornell.edu  .data
11712771Sqtt2@cornell.edu
11812771Sqtt2@cornell.eduMT_DATA
11912771Sqtt2@cornell.eduvar: .dword   0
120