xref: /openbmc/qemu/tests/tcg/hexagon/atomics.c (revision 9c9fff18c45b54fd9adf2282323aab1b6f0ec866)
1825d6ebaSTaylor Simpson /*
2*0d57cd61STaylor Simpson  *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
3825d6ebaSTaylor Simpson  *
4825d6ebaSTaylor Simpson  *  This program is free software; you can redistribute it and/or modify
5825d6ebaSTaylor Simpson  *  it under the terms of the GNU General Public License as published by
6825d6ebaSTaylor Simpson  *  the Free Software Foundation; either version 2 of the License, or
7825d6ebaSTaylor Simpson  *  (at your option) any later version.
8825d6ebaSTaylor Simpson  *
9825d6ebaSTaylor Simpson  *  This program is distributed in the hope that it will be useful,
10825d6ebaSTaylor Simpson  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11825d6ebaSTaylor Simpson  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12825d6ebaSTaylor Simpson  *  GNU General Public License for more details.
13825d6ebaSTaylor Simpson  *
14825d6ebaSTaylor Simpson  *  You should have received a copy of the GNU General Public License
15825d6ebaSTaylor Simpson  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16825d6ebaSTaylor Simpson  */
17825d6ebaSTaylor Simpson 
18825d6ebaSTaylor Simpson #include <stdlib.h>
19825d6ebaSTaylor Simpson #include <stdio.h>
20*0d57cd61STaylor Simpson #include <stdint.h>
21825d6ebaSTaylor Simpson #include <string.h>
22825d6ebaSTaylor Simpson #include <unistd.h>
23825d6ebaSTaylor Simpson #include <inttypes.h>
24825d6ebaSTaylor Simpson #include <pthread.h>
25825d6ebaSTaylor Simpson 
26*0d57cd61STaylor Simpson int err;
27*0d57cd61STaylor Simpson 
28*0d57cd61STaylor Simpson #include "hex_test.h"
29*0d57cd61STaylor Simpson 
atomic_inc32(int32_t * x)30*0d57cd61STaylor Simpson static inline int32_t atomic_inc32(int32_t *x)
31825d6ebaSTaylor Simpson {
32*0d57cd61STaylor Simpson     int32_t old, dummy;
33825d6ebaSTaylor Simpson     __asm__ __volatile__(
34825d6ebaSTaylor Simpson         "1: %0 = memw_locked(%2)\n\t"
35825d6ebaSTaylor Simpson         "   %1 = add(%0, #1)\n\t"
36825d6ebaSTaylor Simpson         "   memw_locked(%2, p0) = %1\n\t"
37825d6ebaSTaylor Simpson         "   if (!p0) jump 1b\n\t"
38825d6ebaSTaylor Simpson         : "=&r"(old), "=&r"(dummy)
39825d6ebaSTaylor Simpson         : "r"(x)
40825d6ebaSTaylor Simpson         : "p0", "memory");
41825d6ebaSTaylor Simpson     return old;
42825d6ebaSTaylor Simpson }
43825d6ebaSTaylor Simpson 
atomic_inc64(int64_t * x)44*0d57cd61STaylor Simpson static inline int64_t atomic_inc64(int64_t *x)
45825d6ebaSTaylor Simpson {
46*0d57cd61STaylor Simpson     int64_t old, dummy;
47825d6ebaSTaylor Simpson     __asm__ __volatile__(
48825d6ebaSTaylor Simpson         "1: %0 = memd_locked(%2)\n\t"
49825d6ebaSTaylor Simpson         "   %1 = #1\n\t"
50825d6ebaSTaylor Simpson         "   %1 = add(%0, %1)\n\t"
51825d6ebaSTaylor Simpson         "   memd_locked(%2, p0) = %1\n\t"
52825d6ebaSTaylor Simpson         "   if (!p0) jump 1b\n\t"
53825d6ebaSTaylor Simpson         : "=&r"(old), "=&r"(dummy)
54825d6ebaSTaylor Simpson         : "r"(x)
55825d6ebaSTaylor Simpson         : "p0", "memory");
56825d6ebaSTaylor Simpson     return old;
57825d6ebaSTaylor Simpson }
58825d6ebaSTaylor Simpson 
atomic_dec32(int32_t * x)59*0d57cd61STaylor Simpson static inline int32_t atomic_dec32(int32_t *x)
60825d6ebaSTaylor Simpson {
61*0d57cd61STaylor Simpson     int32_t old, dummy;
62825d6ebaSTaylor Simpson     __asm__ __volatile__(
63825d6ebaSTaylor Simpson         "1: %0 = memw_locked(%2)\n\t"
64825d6ebaSTaylor Simpson         "   %1 = add(%0, #-1)\n\t"
65825d6ebaSTaylor Simpson         "   memw_locked(%2, p0) = %1\n\t"
66825d6ebaSTaylor Simpson         "   if (!p0) jump 1b\n\t"
67825d6ebaSTaylor Simpson         : "=&r"(old), "=&r"(dummy)
68825d6ebaSTaylor Simpson         : "r"(x)
69825d6ebaSTaylor Simpson         : "p0", "memory");
70825d6ebaSTaylor Simpson     return old;
71825d6ebaSTaylor Simpson }
72825d6ebaSTaylor Simpson 
atomic_dec64(int64_t * x)73*0d57cd61STaylor Simpson static inline int64_t atomic_dec64(int64_t *x)
74825d6ebaSTaylor Simpson {
75*0d57cd61STaylor Simpson     int64_t old, dummy;
76825d6ebaSTaylor Simpson     __asm__ __volatile__(
77825d6ebaSTaylor Simpson         "1: %0 = memd_locked(%2)\n\t"
78825d6ebaSTaylor Simpson         "   %1 = #-1\n\t"
79825d6ebaSTaylor Simpson         "   %1 = add(%0, %1)\n\t"
80825d6ebaSTaylor Simpson         "   memd_locked(%2, p0) = %1\n\t"
81825d6ebaSTaylor Simpson         "   if (!p0) jump 1b\n\t"
82825d6ebaSTaylor Simpson         : "=&r"(old), "=&r"(dummy)
83825d6ebaSTaylor Simpson         : "r"(x)
84825d6ebaSTaylor Simpson         : "p0", "memory");
85825d6ebaSTaylor Simpson     return old;
86825d6ebaSTaylor Simpson }
87825d6ebaSTaylor Simpson 
88825d6ebaSTaylor Simpson #define LOOP_CNT 1000
89*0d57cd61STaylor Simpson volatile int32_t tick32 = 1; /* Using volatile because we are testing atomics */
90*0d57cd61STaylor Simpson volatile int64_t tick64 = 1; /* Using volatile because we are testing atomics */
91825d6ebaSTaylor Simpson 
thread1_func(void * arg)92825d6ebaSTaylor Simpson void *thread1_func(void *arg)
93825d6ebaSTaylor Simpson {
94*0d57cd61STaylor Simpson     for (int i = 0; i < LOOP_CNT; i++) {
95825d6ebaSTaylor Simpson         atomic_inc32(&tick32);
96825d6ebaSTaylor Simpson         atomic_dec64(&tick64);
97825d6ebaSTaylor Simpson     }
98825d6ebaSTaylor Simpson     return NULL;
99825d6ebaSTaylor Simpson }
100825d6ebaSTaylor Simpson 
thread2_func(void * arg)101825d6ebaSTaylor Simpson void *thread2_func(void *arg)
102825d6ebaSTaylor Simpson {
103*0d57cd61STaylor Simpson     for (int i = 0; i < LOOP_CNT; i++) {
104825d6ebaSTaylor Simpson         atomic_dec32(&tick32);
105825d6ebaSTaylor Simpson         atomic_inc64(&tick64);
106825d6ebaSTaylor Simpson     }
107825d6ebaSTaylor Simpson     return NULL;
108825d6ebaSTaylor Simpson }
109825d6ebaSTaylor Simpson 
test_pthread(void)110825d6ebaSTaylor Simpson void test_pthread(void)
111825d6ebaSTaylor Simpson {
112825d6ebaSTaylor Simpson     pthread_t tid1, tid2;
113825d6ebaSTaylor Simpson 
114825d6ebaSTaylor Simpson     pthread_create(&tid1, NULL, thread1_func, "hello1");
115825d6ebaSTaylor Simpson     pthread_create(&tid2, NULL, thread2_func, "hello2");
116825d6ebaSTaylor Simpson     pthread_join(tid1, NULL);
117825d6ebaSTaylor Simpson     pthread_join(tid2, NULL);
118825d6ebaSTaylor Simpson 
119*0d57cd61STaylor Simpson     check32(tick32, 1);
120*0d57cd61STaylor Simpson     check64(tick64, 1);
121825d6ebaSTaylor Simpson }
122825d6ebaSTaylor Simpson 
main(int argc,char ** argv)123825d6ebaSTaylor Simpson int main(int argc, char **argv)
124825d6ebaSTaylor Simpson {
125825d6ebaSTaylor Simpson     test_pthread();
126825d6ebaSTaylor Simpson     puts(err ? "FAIL" : "PASS");
127825d6ebaSTaylor Simpson     return err;
128825d6ebaSTaylor Simpson }
129