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