1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <atomic.h>
8 #include <kernel/refcount.h>
9 
refcount_inc(struct refcount * r)10 bool refcount_inc(struct refcount *r)
11 {
12 	unsigned int nval;
13 	unsigned int oval = atomic_load_uint(&r->val);
14 
15 	while (true) {
16 		nval = oval + 1;
17 
18 		/* r->val is 0, we can't do anything more. */
19 		if (!oval)
20 			return false;
21 
22 		if (atomic_cas_uint(&r->val, &oval, nval))
23 			return true;
24 		/*
25 		 * At this point atomic_cas_uint() has updated oval to the
26 		 * current r->val.
27 		 */
28 	}
29 }
30 
refcount_dec(struct refcount * r)31 bool refcount_dec(struct refcount *r)
32 {
33 	unsigned int nval;
34 	unsigned int oval = atomic_load_uint(&r->val);
35 
36 	while (true) {
37 		assert(oval);
38 		nval = oval - 1;
39 
40 		if (atomic_cas_uint(&r->val, &oval, nval)) {
41 			/*
42 			 * Value has been updated, if value was set to 0
43 			 * return true to indicate that.
44 			 */
45 			return !nval;
46 		}
47 		/*
48 		 * At this point atomic_cas_uint() has updated oval to the
49 		 * current r->val.
50 		 */
51 	}
52 }
53