1 /* 2 * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include <stdlib.h> 19 #include <stdio.h> 20 #include <stdint.h> 21 #include <string.h> 22 #include <unistd.h> 23 #include <inttypes.h> 24 #include <pthread.h> 25 26 int err; 27 28 #include "hex_test.h" 29 30 static inline int32_t atomic_inc32(int32_t *x) 31 { 32 int32_t old, dummy; 33 __asm__ __volatile__( 34 "1: %0 = memw_locked(%2)\n\t" 35 " %1 = add(%0, #1)\n\t" 36 " memw_locked(%2, p0) = %1\n\t" 37 " if (!p0) jump 1b\n\t" 38 : "=&r"(old), "=&r"(dummy) 39 : "r"(x) 40 : "p0", "memory"); 41 return old; 42 } 43 44 static inline int64_t atomic_inc64(int64_t *x) 45 { 46 int64_t old, dummy; 47 __asm__ __volatile__( 48 "1: %0 = memd_locked(%2)\n\t" 49 " %1 = #1\n\t" 50 " %1 = add(%0, %1)\n\t" 51 " memd_locked(%2, p0) = %1\n\t" 52 " if (!p0) jump 1b\n\t" 53 : "=&r"(old), "=&r"(dummy) 54 : "r"(x) 55 : "p0", "memory"); 56 return old; 57 } 58 59 static inline int32_t atomic_dec32(int32_t *x) 60 { 61 int32_t old, dummy; 62 __asm__ __volatile__( 63 "1: %0 = memw_locked(%2)\n\t" 64 " %1 = add(%0, #-1)\n\t" 65 " memw_locked(%2, p0) = %1\n\t" 66 " if (!p0) jump 1b\n\t" 67 : "=&r"(old), "=&r"(dummy) 68 : "r"(x) 69 : "p0", "memory"); 70 return old; 71 } 72 73 static inline int64_t atomic_dec64(int64_t *x) 74 { 75 int64_t old, dummy; 76 __asm__ __volatile__( 77 "1: %0 = memd_locked(%2)\n\t" 78 " %1 = #-1\n\t" 79 " %1 = add(%0, %1)\n\t" 80 " memd_locked(%2, p0) = %1\n\t" 81 " if (!p0) jump 1b\n\t" 82 : "=&r"(old), "=&r"(dummy) 83 : "r"(x) 84 : "p0", "memory"); 85 return old; 86 } 87 88 #define LOOP_CNT 1000 89 volatile int32_t tick32 = 1; /* Using volatile because we are testing atomics */ 90 volatile int64_t tick64 = 1; /* Using volatile because we are testing atomics */ 91 92 void *thread1_func(void *arg) 93 { 94 for (int i = 0; i < LOOP_CNT; i++) { 95 atomic_inc32(&tick32); 96 atomic_dec64(&tick64); 97 } 98 return NULL; 99 } 100 101 void *thread2_func(void *arg) 102 { 103 for (int i = 0; i < LOOP_CNT; i++) { 104 atomic_dec32(&tick32); 105 atomic_inc64(&tick64); 106 } 107 return NULL; 108 } 109 110 void test_pthread(void) 111 { 112 pthread_t tid1, tid2; 113 114 pthread_create(&tid1, NULL, thread1_func, "hello1"); 115 pthread_create(&tid2, NULL, thread2_func, "hello2"); 116 pthread_join(tid1, NULL); 117 pthread_join(tid2, NULL); 118 119 check32(tick32, 1); 120 check64(tick64, 1); 121 } 122 123 int main(int argc, char **argv) 124 { 125 test_pthread(); 126 puts(err ? "FAIL" : "PASS"); 127 return err; 128 } 129