summaryrefslogtreecommitdiff
path: root/firmware/include/bitarray.h
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2014-04-24 04:09:18 -0400
committerMichael Sevakis <jethead71@rockbox.org>2014-08-06 02:47:47 +0200
commit533d396761b630e372166f6f0522ba1c2d128d70 (patch)
tree823a5f800049f62d4ea9f573b4cdeb3e7ff9b3e1 /firmware/include/bitarray.h
parent6536f1db3eedf0a12d16c5504cba94725eb6500d (diff)
downloadrockbox-533d396761b630e372166f6f0522ba1c2d128d70.tar.gz
rockbox-533d396761b630e372166f6f0522ba1c2d128d70.zip
Add multi-reader, single-writer locks to kernel.
Any number of readers may be in the critical section at a time and writers are mutually exclusive to all other threads. They are a better choice when data is rarely modified but often read and multiple threads can safely access it for reading. Priority inheritance is fully implemented along with other changes to the kernel to fully support it on multiowner objects. This also cleans up priority code in the kernel and updates some associated structures in existing objects to the cleaner form. Currently doesn't add the mrsw_lock.[ch] files since they're not yet needed by anything but the supporting improvements are still useful. This includes a typed bitarray API (bitarray.h) which is pretty basic for now. Change-Id: Idbe43dcd9170358e06d48d00f1c69728ff45b0e3 Reviewed-on: http://gerrit.rockbox.org/801 Reviewed-by: Michael Sevakis <jethead71@rockbox.org> Tested: Michael Sevakis <jethead71@rockbox.org>
Diffstat (limited to 'firmware/include/bitarray.h')
-rw-r--r--firmware/include/bitarray.h231
1 files changed, 231 insertions, 0 deletions
diff --git a/firmware/include/bitarray.h b/firmware/include/bitarray.h
new file mode 100644
index 0000000000..4777ccb6a4
--- /dev/null
+++ b/firmware/include/bitarray.h
@@ -0,0 +1,231 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef BITARRAY_H
22#define BITARRAY_H
23
24/* Type-checked bit array definitions */
25
26/* All this stuff gets optimized into very simple object code */
27
28#define BITARRAY_WORD_BITS \
29 (sizeof (unsigned int) * 8)
30#define BITARRAY_NWORDS(bits) \
31 (((bits) + BITARRAY_WORD_BITS - 1) / BITARRAY_WORD_BITS)
32#define BITARRAY_BITWORD(bitnum) \
33 ((bitnum) / BITARRAY_WORD_BITS)
34#define BITARRAY_WORDBIT(bitnum) \
35 ((bitnum) % BITARRAY_WORD_BITS)
36#define BITARRAY_NBIT(word, bit) \
37 ((word)*BITARRAY_WORD_BITS + (bit))
38#define BITARRAY_BITS(bits) \
39 (BITARRAY_NWORDS(bits)*BITARRAY_WORD_BITS)
40#define BITARRAY_BITN(bitnum) \
41 (1u << BITARRAY_WORDBIT(bitnum))
42
43
44/** Iterators **/
45#include "config.h"
46#include <stdint.h>
47
48#if (defined(CPU_ARM) && ARM_ARCH >= 5) || UINT32_MAX < UINT_MAX
49#define __BITARRAY_CTZ(wval) __builtin_ctz(wval)
50#else
51#include "system.h"
52#define __BITARRAY_CTZ(wval) find_first_set_bit(wval)
53#endif
54#define __BITARRAY_POPCNT(wval) __builtin_popcount(wval)
55
56#ifndef BIT_N
57#define BIT_N(n) (1u << (n))
58#endif
59
60/* Enumerate each word index */
61#define FOR_EACH_BITARRAY_WORD_INDEX(nwords, index) \
62 for (unsigned int index = 0, _nwords = (nwords); \
63 index < _nwords; index++)
64
65/* Enumerate each word value */
66#define FOR_EACH_BITARRAY_WORD(a, wval) \
67 FOR_EACH_BITARRAY_WORD_INDEX(ARRAYLEN((a)->words), _w) \
68 for (unsigned int wval = (a)->words[_w], _ = 1; _; _--)
69
70/* Enumerate the bit number of each set bit of a word in sequence */
71#define FOR_EACH_BITARRAY_SET_WORD_BIT(wval, bit) \
72 for (unsigned int _wval = (wval), bit; \
73 _wval ? (((bit) = __BITARRAY_CTZ(_wval)), 1) : 0; \
74 _wval &= ~BIT_N(bit))
75
76/* Enumerate the bit number of each set bit in the bit array in sequence */
77#define FOR_EACH_BITARRAY_SET_BIT_ARR(nwords, words, nbit) \
78 FOR_EACH_BITARRAY_WORD_INDEX(nwords, _w) \
79 FOR_EACH_BITARRAY_SET_WORD_BIT(words[_w], _bit) \
80 for (unsigned int nbit = BITARRAY_NBIT(_w, _bit), _ = 1; _; _--)
81
82/* As above but takes an array type for an argument */
83#define FOR_EACH_BITARRAY_SET_BIT(a, nbit) \
84 FOR_EACH_BITARRAY_SET_BIT_ARR(ARRAYLEN((a)->words), (a)->words, nbit)
85
86
87/** Base functions (called by typed functions) **/
88
89/* Return the word associated with the bit */
90static inline unsigned int
91__bitarray_get_word(unsigned int words[], unsigned int bitnum)
92{
93 return words[BITARRAY_BITWORD(bitnum)];
94}
95
96/* Set the word associated with the bit */
97static inline void
98__bitarray_set_word(unsigned int words[], unsigned int bitnum,
99 unsigned int wordval)
100{
101 words[BITARRAY_BITWORD(bitnum)] = wordval;
102}
103
104/* Set the bit at index 'bitnum' to '1' */
105static inline void
106__bitarray_set_bit(unsigned int words[], unsigned int bitnum)
107{
108 unsigned int word = BITARRAY_BITWORD(bitnum);
109 unsigned int bit = BITARRAY_BITN(bitnum);
110 words[word] |= bit;
111}
112
113/* Set the bit at index 'bitnum' to '0' */
114static inline void
115__bitarray_clear_bit(unsigned int words[], unsigned int bitnum)
116{
117 unsigned int word = BITARRAY_BITWORD(bitnum);
118 unsigned int bit = BITARRAY_BITN(bitnum);
119 words[word] &= ~bit;
120}
121
122/* Return the value of the specified bit ('0' or '1') */
123static inline unsigned int
124__bitarray_test_bit(const unsigned int words[], unsigned int bitnum)
125{
126 unsigned int word = BITARRAY_BITWORD(bitnum);
127 unsigned int nbit = BITARRAY_WORDBIT(bitnum);
128 return (words[word] >> nbit) & 1u;
129}
130
131/* Check if all bits in the bit array are '0' */
132static inline bool
133__bitarray_is_clear(const unsigned int words[], unsigned int nbits)
134{
135 FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
136 {
137 if (words[word] != 0)
138 return false;
139 }
140
141 return true;
142}
143
144/* Set every bit in the array to '0' */
145static inline void
146__bitarray_clear(unsigned int words[], unsigned int nbits)
147{
148 FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
149 words[word] = 0;
150}
151
152/* Set every bit in the array to '1' */
153static inline void
154__bitarray_set(unsigned int words[], unsigned int nbits)
155{
156 FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
157 words[word] = ~0u;
158}
159
160/* Find the lowest-indexed '1' bit in the bit array, returning the size of
161 the array if none are set */
162static inline unsigned int
163__bitarray_ffs(const unsigned int words[], unsigned int nbits)
164{
165 FOR_EACH_BITARRAY_SET_BIT_ARR(BITARRAY_NWORDS(nbits), words, nbit)
166 return nbit;
167
168 return BITARRAY_BITS(nbits);
169}
170
171/* Return the number of bits currently set to '1' in the bit array */
172static inline unsigned int
173__bitarray_popcount(const unsigned int words[], unsigned int nbits)
174{
175 unsigned int count = 0;
176
177 FOR_EACH_BITARRAY_WORD_INDEX(BITARRAY_NWORDS(nbits), word)
178 count += __BITARRAY_POPCNT(words[word]);
179
180 return count;
181}
182
183/**
184 * Giant macro to define all the typed functions
185 * typename: The name of the type (e.g. myarr_t myarr;)
186 * fnprefix: The prefix all functions get (e.g. myarr_set_bit)
187 * nbits : The minimum number of bits the array is meant to hold
188 * (the implementation rounds this up to the word size
189 * and all words may be fully utilized)
190 *
191 * uses 'typedef' to freely change from, e.g., struct to union without
192 * changing source code
193 */
194#define BITARRAY_TYPE_DECLARE(typename, fnprefix, nbits) \
195typedef struct \
196{ \
197 unsigned int words[BITARRAY_NWORDS(nbits)]; \
198} typename; \
199static inline unsigned int \
200fnprefix##_get_word(typename *array, unsigned int bitnum) \
201 { return __bitarray_get_word(array->words, bitnum); } \
202static inline void \
203fnprefix##_set_word(typename *array, unsigned int bitnum, \
204 unsigned int wordval) \
205 { __bitarray_set_word(array->words, bitnum, wordval); } \
206static inline void \
207fnprefix##_set_bit(typename *array, unsigned int bitnum) \
208 { __bitarray_set_bit(array->words, bitnum); } \
209static inline void \
210fnprefix##_clear_bit(typename *array, unsigned int bitnum) \
211 { __bitarray_clear_bit(array->words, bitnum); } \
212static inline unsigned int \
213fnprefix##_test_bit(const typename *array, unsigned int bitnum) \
214 { return __bitarray_test_bit(array->words, bitnum); } \
215static inline bool \
216fnprefix##_is_clear(const typename *array) \
217 { return __bitarray_is_clear(array->words, nbits); } \
218static inline void \
219fnprefix##_clear(typename *array) \
220 { __bitarray_clear(array->words, nbits); } \
221static inline void \
222fnprefix##_set(typename *array) \
223 { __bitarray_set(array->words, nbits); } \
224static inline unsigned int \
225fnprefix##_ffs(const typename *array) \
226 { return __bitarray_ffs(array->words, nbits); } \
227static inline unsigned int \
228fnprefix##_popcount(const typename *array) \
229 { return __bitarray_popcount(array->words, nbits); }
230
231#endif /* BITARRAY_H */