sysclone_d.S revision 12771
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// sysclone_d tests basic functionalities of clone system call: 4012771Sqtt2@cornell.edu// - create a new thread 4112771Sqtt2@cornell.edu// - assign a new per-thread stack frame to the child thread 4212771Sqtt2@cornell.edu// - assign a new per-thread TLS to the child thread 4312771Sqtt2@cornell.edu// 4412771Sqtt2@cornell.edu// In addition to testing clone(), sysclone_d partially checks 4512771Sqtt2@cornell.edu// functionalities of futex and exit system calls that are used to 4612771Sqtt2@cornell.edu// facilitate thread exit and synchronization. 4712771Sqtt2@cornell.edu//------------------------------------------------------------------------ 4812771Sqtt2@cornell.edu 4912771Sqtt2@cornell.edu#include "riscv_test.h" 5012771Sqtt2@cornell.edu#include "test_macros.h" 5112771Sqtt2@cornell.edu#include "test_macros_mt_ecall.h" 5212771Sqtt2@cornell.edu 5312771Sqtt2@cornell.edu RVTEST_RV64U 5412771Sqtt2@cornell.edu RVTEST_CODE_BEGIN 5512771Sqtt2@cornell.edu 5612771Sqtt2@cornell.edu#define MAX_NUM_THREADS 20 5712771Sqtt2@cornell.edu 5812771Sqtt2@cornell.edu//------------------------------------------------------------------------ 5912771Sqtt2@cornell.edu// Master thread creates new threads, waits for all threads to complete, 6012771Sqtt2@cornell.edu// deallocates threads and checks result 6112771Sqtt2@cornell.edu//------------------------------------------------------------------------ 6212771Sqtt2@cornell.edu li a0, MAX_NUM_THREADS 6312771Sqtt2@cornell.edu call _create_threads 6412771Sqtt2@cornell.edu 6512771Sqtt2@cornell.edu la t6, n_worker_threads 6612771Sqtt2@cornell.edu ld a0, (t6) 6712771Sqtt2@cornell.edu beqz a0, _fail // exit if there's no worker thread 6812771Sqtt2@cornell.edu call _join 6912771Sqtt2@cornell.edu 7012771Sqtt2@cornell.edu la t6, n_worker_threads 7112771Sqtt2@cornell.edu ld a0, (t6) 7212771Sqtt2@cornell.edu call _check 7312771Sqtt2@cornell.edu 7412771Sqtt2@cornell.edu la t6, n_worker_threads 7512771Sqtt2@cornell.edu ld a0, (t6) 7612771Sqtt2@cornell.edu call _delete_threads 7712771Sqtt2@cornell.edu 7812771Sqtt2@cornell.edu li a0, SUCCESS 7912771Sqtt2@cornell.edu 8012771Sqtt2@cornell.edu RVTEST_CODE_END 8112771Sqtt2@cornell.edu 8212771Sqtt2@cornell.edu//------------------------------------------------------------------------ 8312771Sqtt2@cornell.edu// mt_test function executed by child threads 8412771Sqtt2@cornell.edu//------------------------------------------------------------------------ 8512771Sqtt2@cornell.edu_mt_test: 8612771Sqtt2@cornell.edu // get this thread's TID 8712771Sqtt2@cornell.edu li a7, SYSCALL_GETTID 8812771Sqtt2@cornell.edu ecall 8912771Sqtt2@cornell.edu 9012771Sqtt2@cornell.edu // store the TID to both stack and TLS of this thread 9112771Sqtt2@cornell.edu addi sp, sp, -8 9212771Sqtt2@cornell.edu sd a0, (sp) 9312771Sqtt2@cornell.edu sd a0, (tp) 9412771Sqtt2@cornell.edu 9512771Sqtt2@cornell.edu RVTEST_CODE_END 9612771Sqtt2@cornell.edu 9712771Sqtt2@cornell.edu//------------------------------------------------------------------------ 9812771Sqtt2@cornell.edu// _check: 9912771Sqtt2@cornell.edu// The master thread looks into the stack and TLS of each child thread 10012771Sqtt2@cornell.edu// and check if the child thread's TID was written in both places. 10112771Sqtt2@cornell.edu// 10212771Sqtt2@cornell.edu// This function assumes the following structure in the calling thread's 10312771Sqtt2@cornell.edu// stack frame 10412771Sqtt2@cornell.edu// 10512771Sqtt2@cornell.edu// | child_stack_ptr_0 | << fp: frame pointer 10612771Sqtt2@cornell.edu// | child_tls_ptr_0 | 10712771Sqtt2@cornell.edu// | child_thread_id_0 | 10812771Sqtt2@cornell.edu// | saved_child_thread_id_0 | 10912771Sqtt2@cornell.edu// | child_stack_ptr_1 | 11012771Sqtt2@cornell.edu// | child_tls_ptr_1 | 11112771Sqtt2@cornell.edu// | child_thread_id_1 | 11212771Sqtt2@cornell.edu// | saved_child_thread_id_1 | 11312771Sqtt2@cornell.edu// | ... | << sp: stack pointer 11412771Sqtt2@cornell.edu// 11512771Sqtt2@cornell.edu// This function takes a number of threads to check in a0 11612771Sqtt2@cornell.edu//------------------------------------------------------------------------ 11712771Sqtt2@cornell.edu 11812771Sqtt2@cornell.edu_check: 11912771Sqtt2@cornell.edu mv t0, a0 // get the number of threads 12012771Sqtt2@cornell.edu mv s0, ra // save return register 12112771Sqtt2@cornell.edu mv s1, sp // save stack pointer 12212771Sqtt2@cornell.edu1: 12312771Sqtt2@cornell.edu ld t1, (sp) // get child_thread_saved_id 12412771Sqtt2@cornell.edu 12512771Sqtt2@cornell.edu addi sp, sp, 8 12612771Sqtt2@cornell.edu ld t2, (sp) // get child_thread_id 12712771Sqtt2@cornell.edu bnez t2, _fail // this child_thread_id should have been cleared 12812771Sqtt2@cornell.edu 12912771Sqtt2@cornell.edu addi sp, sp, 8 13012771Sqtt2@cornell.edu ld t3, (sp) // get child_tls_ptr 13112771Sqtt2@cornell.edu ld t3, (t3) // get the first value stored in child's TLS 13212771Sqtt2@cornell.edu bne t1, t3, _fail // child_tid should have been saved in the TLS 13312771Sqtt2@cornell.edu 13412771Sqtt2@cornell.edu addi sp, sp, 8 13512771Sqtt2@cornell.edu ld t4, (sp) // get child_stack_ptr 13612771Sqtt2@cornell.edu li t5, MEM_SIZE 13712771Sqtt2@cornell.edu add t4, t4, t5 // get the high address of child's stack 13812771Sqtt2@cornell.edu ld t4, -8(t4) // get the first value stored in child's stack 13912771Sqtt2@cornell.edu bne t1, t4, _fail // child_tid should have been saved in the stack 14012771Sqtt2@cornell.edu 14112771Sqtt2@cornell.edu addi sp, sp, 8 14212771Sqtt2@cornell.edu 14312771Sqtt2@cornell.edu // decrement the number of threads to wait for 14412771Sqtt2@cornell.edu addi t0, t0, -1 14512771Sqtt2@cornell.edu bnez t0, 1b 14612771Sqtt2@cornell.edu 14712771Sqtt2@cornell.edu // finish checking all threads 14812771Sqtt2@cornell.edu mv ra, s0 // restore return register 14912771Sqtt2@cornell.edu mv sp, s1 // restore stack pointer 15012771Sqtt2@cornell.edu ret 15112771Sqtt2@cornell.edu 15212771Sqtt2@cornell.edu_fail: 15312771Sqtt2@cornell.edu li a0, FAILURE 15412771Sqtt2@cornell.edu RVTEST_CODE_END 15512771Sqtt2@cornell.edu 15612771Sqtt2@cornell.edu .data 15712771Sqtt2@cornell.edu 15812771Sqtt2@cornell.eduMT_DATA 159