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