1 /**
2  * @brief Atomically set a bit.
3  *
4  * Atomically set bit number @a bit of @a target.
5  * The target may be a single atomic variable or an array of them.
6  *
7  * @param target Address of atomic variable or array.
8  * @param bit Bit number (starting from 0).
9  *
10  * @return N/A
11  */
12 
13 /*
14  * Copyright (c) 2016 Intel Corporation
15  * Copyright (c) 2011-2014 Wind River Systems, Inc.
16  * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  */
20 
21 #include "mesh_atomic.h"
22 #include "mesh_mutex.h"
23 
24 #ifndef CONFIG_ATOMIC_OPERATIONS_BUILTIN
25 
26 /**
27 *
28 * @brief Atomic get primitive
29 *
30 * @param target memory location to read from
31 *
32 * This routine provides the atomic get primitive to atomically read
33 * a value from <target>. It simply does an ordinary load.  Note that <target>
34 * is expected to be aligned to a 4-byte boundary.
35 *
36 * @return The value read from <target>
37 */
bt_mesh_atomic_get(const bt_mesh_atomic_t * target)38 bt_mesh_atomic_val_t bt_mesh_atomic_get(const bt_mesh_atomic_t *target)
39 {
40     return *target;
41 }
42 
43 /**
44  *
45  * @brief Atomic get-and-set primitive
46  *
47  * This routine provides the atomic set operator. The <value> is atomically
48  * written at <target> and the previous value at <target> is returned.
49  *
50  * @param target the memory location to write to
51  * @param value the value to write
52  *
53  * @return The previous value from <target>
54  */
bt_mesh_atomic_set(bt_mesh_atomic_t * target,bt_mesh_atomic_val_t value)55 bt_mesh_atomic_val_t bt_mesh_atomic_set(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value)
56 {
57     bt_mesh_atomic_val_t ret = 0;
58 
59     bt_mesh_atomic_lock();
60 
61     ret = *target;
62     *target = value;
63 
64     bt_mesh_atomic_unlock();
65 
66     return ret;
67 }
68 
69 /**
70  *
71  * @brief Atomic bitwise inclusive OR primitive
72  *
73  * This routine provides the atomic bitwise inclusive OR operator. The <value>
74  * is atomically bitwise OR'ed with the value at <target>, placing the result
75  * at <target>, and the previous value at <target> is returned.
76  *
77  * @param target the memory location to be modified
78  * @param value the value to OR
79  *
80  * @return The previous value from <target>
81  */
bt_mesh_atomic_or(bt_mesh_atomic_t * target,bt_mesh_atomic_val_t value)82 bt_mesh_atomic_val_t bt_mesh_atomic_or(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value)
83 {
84     bt_mesh_atomic_val_t ret = 0;
85 
86     bt_mesh_atomic_lock();
87 
88     ret = *target;
89     *target |= value;
90 
91     bt_mesh_atomic_unlock();
92 
93     return ret;
94 }
95 
96 /**
97  *
98  * @brief Atomic bitwise AND primitive
99  *
100  * This routine provides the atomic bitwise AND operator. The <value> is
101  * atomically bitwise AND'ed with the value at <target>, placing the result
102  * at <target>, and the previous value at <target> is returned.
103  *
104  * @param target the memory location to be modified
105  * @param value the value to AND
106  *
107  * @return The previous value from <target>
108  */
bt_mesh_atomic_and(bt_mesh_atomic_t * target,bt_mesh_atomic_val_t value)109 bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value)
110 {
111     bt_mesh_atomic_val_t ret = 0;
112 
113     bt_mesh_atomic_lock();
114 
115     ret = *target;
116     *target &= value;
117 
118     bt_mesh_atomic_unlock();
119 
120     return ret;
121 }
122 
123 /**
124  *
125  * @brief Atomic decrement primitive
126  *
127  * @param target memory location to decrement
128  *
129  * This routine provides the atomic decrement operator. The value at <target>
130  * is atomically decremented by 1, and the old value from <target> is returned.
131  *
132  * @return The value from <target> prior to the decrement
133  */
bt_mesh_atomic_dec(bt_mesh_atomic_t * target)134 bt_mesh_atomic_val_t bt_mesh_atomic_dec(bt_mesh_atomic_t *target)
135 {
136     bt_mesh_atomic_val_t ret = 0;
137 
138     bt_mesh_atomic_lock();
139 
140     ret = *target;
141     (*target)--;
142 
143     bt_mesh_atomic_unlock();
144 
145     return ret;
146 }
147 
148 /**
149  *
150  * @brief Atomic increment primitive
151  *
152  * @param target memory location to increment
153  *
154  * This routine provides the atomic increment operator. The value at <target>
155  * is atomically incremented by 1, and the old value from <target> is returned.
156  *
157  * @return The value from <target> before the increment
158  */
bt_mesh_atomic_inc(bt_mesh_atomic_t * target)159 bt_mesh_atomic_val_t bt_mesh_atomic_inc(bt_mesh_atomic_t *target)
160 {
161     bt_mesh_atomic_val_t ret = 0;
162 
163     bt_mesh_atomic_lock();
164 
165     ret = *target;
166     (*target)++;
167 
168     bt_mesh_atomic_unlock();
169 
170     return ret;
171 }
172 
173 #endif /* #ifndef CONFIG_ATOMIC_OPERATIONS_BUILTIN */
174