Skip to content

Commit b58bf9e

Browse files
committed
soc: nordic: common: dmm: Fix allocation algorithm
There were some corner cases and stress test could fail. Reworking tail bits handling to make the stress test pass. Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent ca68c77 commit b58bf9e

File tree

1 file changed

+32
-40
lines changed

1 file changed

+32
-40
lines changed

soc/nordic/common/dmm.c

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -137,30 +137,19 @@ static void tail_mask_set(atomic_t *tail_mask, size_t num_bits, size_t off)
137137

138138
/* If bit mask exceeds a single word then tail may spill to the adjacent word. */
139139
size_t idx = tail_off / 32;
140+
atomic_t *t_mask = &tail_mask[idx];
140141

141142
tail_off = tail_off - 32 * idx;
142-
if ((tail_off + tail_bits) <= 32) {
143-
/* Tail mask fits in a single word. */
144-
atomic_or(&tail_mask[idx], BIT_MASK(tail_bits) << tail_off);
145-
return;
146-
}
147-
148-
/* Tail spilled. Remainder is set in the next word. Since number of tail_masks
149-
* match number of words in bitarray we don't need to check if we are exceeding
150-
* the array boundary.
151-
*/
152-
atomic_or(&tail_mask[idx], BIT_MASK(32 - tail_off) << tail_off);
153-
143+
while (tail_bits > 0) {
144+
uint32_t rem_bits = MIN(32 - tail_off, tail_bits);
145+
uint32_t bits = MIN(tail_bits, rem_bits);
146+
uint32_t mask = (bits == 32) ? UINT32_MAX : (BIT_MASK(bits) << tail_off);
154147

155-
size_t rem_tail = tail_bits - (32 - tail_off);
156-
atomic_t *mask = &tail_mask[idx + 1];
157-
158-
while (rem_tail >= 32) {
159-
atomic_or(mask, UINT32_MAX);
160-
mask++;
161-
rem_tail -= 32;
148+
atomic_or(t_mask, mask);
149+
t_mask++;
150+
tail_off = 0;
151+
tail_bits -= bits;
162152
}
163-
atomic_or(mask, BIT_MASK(rem_tail));
164153
}
165154

166155
/* Function determines how many chunks were used for the allocated buffer. It is
@@ -189,33 +178,36 @@ static uint32_t num_bits_get(atomic_t *tail_mask, size_t off)
189178
return num_bits;
190179
}
191180

192-
/* In multiword bit array we need to check if tail is spilling over to the next word. */
193-
size_t idx = off / 32;
194-
size_t w_off = off - 32 * idx;
181+
size_t tail_off = off + 1;
182+
size_t idx = tail_off / 32;
195183
atomic_t *t_mask = &tail_mask[idx];
196184

197-
mask = (*t_mask | BIT(w_off)) >> w_off;
198-
num_bits = (~mask == 0) ? 32 : __builtin_ctz(~mask);
199-
if (num_bits == 1) {
185+
tail_off = tail_off % 32;
186+
num_bits = 1;
187+
if ((*t_mask & BIT(tail_off)) == 0) {
200188
return num_bits;
201189
}
202190

203-
mask = BIT_MASK(num_bits - 1) << (w_off + 1);
204-
atomic_and(t_mask, ~mask);
205-
if (((w_off + num_bits) == 32) && (idx < (HEAP_NUM_WORDS - 1))) {
206-
size_t tmp_bits;
191+
do {
192+
uint32_t mask = (uint32_t)*t_mask >> tail_off;
193+
uint32_t bits = (mask == UINT32_MAX) ? 32 : __builtin_ctz(~mask);
207194

208-
/* If we are at the end of the one mask we need to check the beginning of the
209-
* next one as there might be remaining part of the tail.
210-
*/
211-
do {
212-
t_mask++;
213-
tmp_bits = (*t_mask == UINT32_MAX) ? 32 : __builtin_ctz(~(*t_mask));
214-
mask = (tmp_bits == 32) ? UINT32_MAX : BIT_MASK(tmp_bits);
195+
num_bits += bits;
196+
if (mask == UINT32_MAX) {
197+
198+
atomic_set(t_mask, 0);
199+
} else {
200+
mask = BIT_MASK(bits) << tail_off;
215201
atomic_and(t_mask, ~mask);
216-
num_bits += tmp_bits;
217-
} while ((tmp_bits == 32) && (t_mask != &tail_mask[HEAP_NUM_WORDS - 1]));
218-
}
202+
}
203+
204+
if ((bits + tail_off) < 32) {
205+
return num_bits;
206+
}
207+
208+
tail_off = 0;
209+
t_mask++;
210+
} while (t_mask != &tail_mask[HEAP_NUM_WORDS]);
219211

220212
return num_bits;
221213
}

0 commit comments

Comments
 (0)