xref: /haiku/src/system/kernel/arch/arm/arch_atomic32.cpp (revision 73254051b196497dfee9ab89eb0c2f60cc305819)
1 /*
2  * Copyright 2013 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ithamar R. Adema, ithamar@upgrade-android.com
7  */
8 
9 #include <KernelExport.h>
10 
11 #include <kernel.h>
12 #include <user_atomic.h>
13 
14 #include <util/AutoLock.h>
15 
16 #ifdef ATOMIC_FUNCS_ARE_SYSCALLS
17 
18 /*
19  * NOTE: These functions are _intentionally_ not using spinlocks, unlike
20  * the 64 bit versions. The reason for this is that they are used by the
21  * spinlock code itself, and therefore would deadlock.
22  *
23  * Since these are only really needed for ARMv5, which is not SMP anyway,
24  * this is an acceptable compromise.
25  */
26 
27 int32
28 atomic_set(vint32 *value, int32 newValue)
29 {
30 	InterruptsLocker locker;
31 
32 	int32 oldValue = *value;
33 	*value = newValue;
34 	return oldValue;
35 }
36 
37 int32
38 atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst)
39 {
40 	InterruptsLocker locker;
41 
42 	int32 oldValue = *value;
43 	if (oldValue == testAgainst)
44 		*value = newValue;
45 	return oldValue;
46 }
47 
48 int32
49 atomic_add(vint32 *value, int32 addValue)
50 {
51 	InterruptsLocker locker;
52 
53 	int32 oldValue = *value;
54 	*value += addValue;
55 	return oldValue;
56 }
57 
58 int32
59 atomic_and(vint32 *value, int32 andValue)
60 {
61 	InterruptsLocker locker;
62 
63 	int32 oldValue = *value;
64 	*value &= andValue;
65 	return oldValue;
66 }
67 
68 int32
69 atomic_or(vint32 *value, int32 orValue)
70 {
71 	InterruptsLocker locker;
72 
73 	int32 oldValue = *value;
74 	*value |= orValue;
75 	return oldValue;
76 }
77 
78 int32
79 atomic_get(vint32 *value)
80 {
81 	InterruptsLocker locker;
82 
83 	int32 oldValue = *value;
84 	return oldValue;
85 }
86 
87 int32
88 _user_atomic_set(vint32 *value, int32 newValue)
89 {
90 	if (IS_USER_ADDRESS(value)
91 		&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
92 		int32 oldValue = atomic_set(value, newValue);
93 		unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
94 		return oldValue;
95 	}
96 
97 access_violation:
98 	// XXX kill application
99 	return -1;
100 }
101 
102 int32
103 _user_atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst)
104 {
105 	if (IS_USER_ADDRESS(value)
106 		&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
107 		int32 oldValue = atomic_test_and_set(value, newValue, testAgainst);
108 		unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
109 		return oldValue;
110 	}
111 
112 access_violation:
113 	// XXX kill application
114 	return -1;
115 }
116 
117 int32
118 _user_atomic_add(vint32 *value, int32 addValue)
119 {
120 	if (IS_USER_ADDRESS(value)
121 		&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
122 		int32 oldValue = atomic_add(value, addValue);
123 		unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
124 		return oldValue;
125 	}
126 
127 access_violation:
128 	// XXX kill application
129 	return -1;
130 }
131 
132 int32
133 _user_atomic_and(vint32 *value, int32 andValue)
134 {
135 	if (IS_USER_ADDRESS(value)
136 		&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
137 		int32 oldValue = atomic_and(value, andValue);
138 		unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
139 		return oldValue;
140 	}
141 
142 access_violation:
143 	// XXX kill application
144 	return -1;
145 }
146 
147 int32
148 _user_atomic_or(vint32 *value, int32 orValue)
149 {
150 	if (IS_USER_ADDRESS(value)
151 		&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
152 		int32 oldValue = atomic_or(value, orValue);
153 		unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
154 		return oldValue;
155 	}
156 
157 access_violation:
158 	// XXX kill application
159 	return -1;
160 }
161 
162 int32
163 _user_atomic_get(vint32 *value)
164 {
165 	if (IS_USER_ADDRESS(value)
166 		&& lock_memory((void *)value, sizeof(int32), B_READ_DEVICE) == B_OK) {
167 		int32 oldValue = atomic_get(value);
168 		unlock_memory((void *)value, sizeof(int32), B_READ_DEVICE);
169 		return oldValue;
170 	}
171 
172 access_violation:
173 	// XXX kill application
174 	return -1;
175 }
176 
177 #endif /* ATOMIC_FUNCS_ARE_SYSCALLS */
178