1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 2#include <assert.h> 3#include <limits.h> 4#include <stddef.h> 5#include <stdint.h> 6 7#include "lsquic_int_types.h" 8#include "lsquic_trechist.h" 9 10 11static unsigned 12find_free_slot (uint32_t slots) 13{ 14#if __GNUC__ 15 return __builtin_ctz(~slots); 16#else 17 unsigned n; 18 19 slots =~ slots; 20 n = 0; 21 22 if (0 == (slots & ((1ULL << 16) - 1))) { n += 16; slots >>= 16; } 23 if (0 == (slots & ((1ULL << 8) - 1))) { n += 8; slots >>= 8; } 24 if (0 == (slots & ((1ULL << 4) - 1))) { n += 4; slots >>= 4; } 25 if (0 == (slots & ((1ULL << 2) - 1))) { n += 2; slots >>= 2; } 26 if (0 == (slots & ((1ULL << 1) - 1))) { n += 1; slots >>= 1; } 27 return n; 28#endif 29} 30 31 32/* When capacity is reached, smallest element is removed. When the number 33 * of elements in a single range cannot be represented by te_count, an 34 * error is returned. This is the only error this function returns. 35 */ 36int 37lsquic_trechist_insert (trechist_mask_t *mask, struct trechist_elem *elems, 38 uint32_t packno) 39{ 40 struct trechist_elem *el, *prev, *cur, *next; 41 unsigned idx; 42 43 if (*mask == 0) 44 { 45 elems[0].te_low = packno; 46 elems[0].te_count = 1; 47 elems[0].te_next = 0; 48 *mask |= 1; 49 return 0; 50 } 51 52 el = elems; 53 prev = NULL; 54 while (1) 55 { 56 if (packno > TE_HIGH(el) + 1) 57 goto insert_before; 58 if (packno == el->te_low - 1) 59 { 60 if (el->te_next && el->te_low == TE_HIGH(&elems[el->te_next]) + 2) 61 { 62 if (el->te_count + elems[el->te_next].te_count - 1 > UCHAR_MAX) 63 return -1; 64 *mask &= ~(1u << el->te_next); 65 el->te_count += elems[el->te_next].te_count + 1; 66 el->te_low = elems[el->te_next].te_low; 67 el->te_next = elems[el->te_next].te_next; 68 } 69 else 70 { 71 if (el->te_count == UCHAR_MAX) 72 return -1; 73 --el->te_low; 74 ++el->te_count; 75 } 76 return 0; 77 } 78 if (packno == TE_HIGH(el) + 1) 79 { 80 if (el->te_count == UCHAR_MAX) 81 return -1; 82 ++el->te_count; 83 return 0; 84 } 85 if (packno >= el->te_low && packno <= TE_HIGH(el)) 86 return 0; /* Dup */ 87 if (!el->te_next) 88 break; /* insert tail */ 89 prev = el; 90 el = &elems[el->te_next]; 91 } 92 93 if (*mask == TRECHIST_MAX_RANGES_MASK) 94 /* No need to insert element smaller than the smallest element 95 * already in our list. The new element "overflows". 96 */ 97 return 0; 98 99 idx = find_free_slot(*mask); 100 elems[idx].te_low = packno; 101 elems[idx].te_count = 1; 102 elems[idx].te_next = 0; 103 *mask |= 1u << idx;; 104 el->te_next = idx; 105 return 0; 106 107 insert_before: 108 109 if (*mask != TRECHIST_MAX_RANGES_MASK) 110 idx = find_free_slot(*mask); 111 else 112 { /* Drop last element and reuse its slot */ 113 for (next = &elems[el->te_next], cur = el; next->te_next; 114 cur = next, next = &elems[cur->te_next]) 115 ; 116 idx = cur->te_next; 117 cur->te_next = 0; 118 } 119 120 *mask |= 1u << idx;; 121 if (el == elems) 122 { 123 elems[idx] = *el; 124 elems[0].te_low = packno; 125 elems[0].te_count = 1; 126 elems[0].te_next = idx; 127 } 128 else 129 { 130 assert(prev); 131 elems[idx].te_low = packno; 132 elems[idx].te_count = 1; 133 elems[idx].te_next = prev->te_next; 134 prev->te_next = idx; 135 } 136 137 return 0; 138} 139 140 141void 142lsquic_trechist_iter (struct trechist_iter *iter, trechist_mask_t mask, 143 const struct trechist_elem *elems) 144{ 145 iter->mask = mask; 146 iter->elems = elems; 147} 148 149 150const struct lsquic_packno_range * 151lsquic_trechist_first (void *iter_p) 152{ 153 struct trechist_iter *const iter = iter_p; 154 155 if (iter->mask == 0) 156 return NULL; 157 158 iter->next = iter->elems[0].te_next; 159 iter->range.low = iter->elems[0].te_low; 160 iter->range.high = TE_HIGH(&iter->elems[0]); 161 return &iter->range; 162} 163 164 165const struct lsquic_packno_range * 166lsquic_trechist_next (void *iter_p) 167{ 168 struct trechist_iter *const iter = iter_p; 169 170 if (iter->next == 0) 171 return NULL; 172 173 iter->range.low = iter->elems[iter->next].te_low; 174 iter->range.high = TE_HIGH(&iter->elems[iter->next]); 175 iter->next = iter->elems[iter->next].te_next; 176 return &iter->range; 177} 178 179 180/* First TRECHIST_MAX_RANGES ranges are copied */ 181void 182lsquic_trechist_copy_ranges (trechist_mask_t *mask, 183 struct trechist_elem *elems, void *src_rechist, 184 const struct lsquic_packno_range * (*first) (void *), 185 const struct lsquic_packno_range * (*next) (void *)) 186{ 187 const struct lsquic_packno_range *range; 188 struct trechist_elem *el; 189 unsigned i; 190 191 for (el = NULL, i = 0, range = first(src_rechist); 192 i < TRECHIST_MAX_RANGES && range; 193 range = next(src_rechist), ++i) 194 { 195 /* This should never happen: */ 196 assert(range->high - range->low + 1 <= UINT_MAX); 197 198 el = &elems[i]; 199 el->te_low = range->low; 200 el->te_count = range->high - range->low + 1; 201 el->te_next = i + 1; 202 } 203 204 if (el) 205 el->te_next = 0; 206 207 if (i < 32) 208 *mask = (1u << i) - 1; 209 else 210 *mask = UINT32_MAX; 211} 212 213 214int 215lsquic_trechist_contains (trechist_mask_t mask, 216 const struct trechist_elem *elems, uint32_t packno) 217{ 218 const struct trechist_elem *el; 219 if (mask == 0) 220 return 0; 221 222 el = &elems[0]; 223 while (1) 224 { 225 if (packno > TE_HIGH(el)) 226 return 0; 227 if (packno >= el->te_low) 228 return 1; 229 if (el->te_next) 230 el = &elems[el->te_next]; 231 else 232 break; 233 } 234 235 return 0; 236} 237 238 239uint32_t 240lsquic_trechist_max (trechist_mask_t mask, const struct trechist_elem *elems) 241{ 242 if (mask) 243 { 244 assert(mask & 1); 245 return TE_HIGH(&elems[0]); 246 } 247 else 248 return 0; 249} 250