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