1 /* 2 * Copyright (c) 2021 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include <stdint.h> 8 #include <stdbool.h> 9 10 #include <soc.h> 11 12 #include "hal/cpu.h" 13 14 #include "util/util.h" 15 #include "dbuf.h" 16 dbuf_alloc(struct dbuf_hdr * hdr,uint8_t * idx)17void *dbuf_alloc(struct dbuf_hdr *hdr, uint8_t *idx) 18 { 19 uint8_t first, last; 20 21 first = hdr->first; 22 last = hdr->last; 23 if (first == last) { 24 /* Return the index of next free PDU in the double buffer */ 25 last++; 26 if (last == DOUBLE_BUFFER_SIZE) { 27 last = 0U; 28 } 29 } else { 30 uint8_t first_latest; 31 32 /* LLL has not consumed the first PDU. Revert back the `last` so 33 * that LLL still consumes the first PDU while the caller of 34 * this function updates/modifies the latest PDU. 35 * 36 * Under race condition: 37 * 1. LLL runs before `pdu->last` is reverted, then `pdu->first` 38 * has changed, hence restore `pdu->last` and return index of 39 * next free PDU in the double buffer. 40 * 2. LLL runs after `pdu->last` is reverted, then `pdu->first` 41 * will not change, return the saved `last` as the index of 42 * the next free PDU in the double buffer. 43 */ 44 hdr->last = first; 45 cpu_dmb(); 46 first_latest = hdr->first; 47 if (first_latest != first) { 48 hdr->last = last; 49 last++; 50 if (last == DOUBLE_BUFFER_SIZE) { 51 last = 0U; 52 } 53 } 54 } 55 56 *idx = last; 57 58 return &hdr->data[last * hdr->elem_size]; 59 } 60 dbuf_latest_get(struct dbuf_hdr * hdr,uint8_t * is_modified)61void *dbuf_latest_get(struct dbuf_hdr *hdr, uint8_t *is_modified) 62 { 63 uint8_t first; 64 65 first = hdr->first; 66 if (first != hdr->last) { 67 uint8_t cfg_idx; 68 69 cfg_idx = first; 70 71 first += 1U; 72 if (first == DOUBLE_BUFFER_SIZE) { 73 first = 0U; 74 } 75 hdr->first = first; 76 77 if (is_modified) { 78 *is_modified = 1U; 79 } 80 } 81 82 return &hdr->data[first * hdr->elem_size]; 83 } 84