1 /*
2  * Copyright (c) 2021 - 2023, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include <helpers/nrfx_flag32_allocator.h>
34 
35 #if !defined(NRFX_ATOMIC_CAS)
nrfx_flag32_atomic_cas(nrfx_atomic_t * p_data,uint32_t old_value,uint32_t new_value)36 static bool nrfx_flag32_atomic_cas(nrfx_atomic_t * p_data, uint32_t old_value, uint32_t new_value)
37 {
38     bool status = false;
39     NRFX_CRITICAL_SECTION_ENTER();
40     if (*p_data == old_value)
41     {
42         *p_data = new_value;
43         status = true;
44     }
45     NRFX_CRITICAL_SECTION_EXIT();
46     return status;
47 }
48 
49 #define NRFX_ATOMIC_CAS(p_data, old_value, new_value) \
50     nrfx_flag32_atomic_cas(p_data, old_value, new_value)
51 #endif // !defined(NRFX_ATOMIC_CAS)
52 
nrfx_flag32_is_allocated(nrfx_atomic_t mask,uint8_t bitpos)53 bool nrfx_flag32_is_allocated(nrfx_atomic_t mask, uint8_t bitpos)
54 {
55     return (mask & NRFX_BIT(bitpos)) ? false : true;
56 }
57 
nrfx_flag32_alloc(nrfx_atomic_t * p_mask,uint8_t * p_flag)58 nrfx_err_t nrfx_flag32_alloc(nrfx_atomic_t * p_mask, uint8_t *p_flag)
59 {
60     uint8_t idx;
61     uint32_t new_mask, prev_mask;
62 
63     do {
64         prev_mask = *p_mask;
65         if (prev_mask == 0)
66         {
67             return NRFX_ERROR_NO_MEM;
68         }
69         else
70         {
71             idx = (uint8_t)(31UL - NRF_CLZ(prev_mask));
72         }
73 
74         new_mask = prev_mask & ~NRFX_BIT(idx);
75     } while (!NRFX_ATOMIC_CAS(p_mask, prev_mask, new_mask));
76 
77     *p_flag = idx;
78 
79     return NRFX_SUCCESS;
80 }
81 
nrfx_flag32_free(nrfx_atomic_t * p_mask,uint8_t flag)82 nrfx_err_t nrfx_flag32_free(nrfx_atomic_t * p_mask, uint8_t flag)
83 {
84     uint32_t new_mask, prev_mask;
85 
86     if ((NRFX_BIT(flag) & *p_mask))
87     {
88         return NRFX_ERROR_INVALID_PARAM;
89     }
90 
91     do {
92         prev_mask = *p_mask;
93         new_mask = prev_mask | NRFX_BIT(flag);
94     } while (!NRFX_ATOMIC_CAS(p_mask, prev_mask, new_mask));
95 
96     return NRFX_SUCCESS;
97 }
98