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