GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 99.2% 126 / 0 / 127
Functions: 100.0% 1 / 0 / 1
Branches: 100.0% 28 / 0 / 28

fx_utility_logical_sector_cache_entry_read.c
Line Branch Exec Source
1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 * Copyright (c) 2026-present Eclipse ThreadX contributors
4 *
5 * This program and the accompanying materials are made available under the
6 * terms of the MIT License which is available at
7 * https://opensource.org/licenses/MIT.
8 *
9 * SPDX-License-Identifier: MIT
10 **************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** FileX Component */
17 /** */
18 /** Utility */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define FX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "fx_api.h"
29 #include "fx_system.h"
30 #include "fx_utility.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _fx_utility_logical_sector_cache_entry_read PORTABLE C */
38 /* 6.1.10 */
39 /* AUTHOR */
40 /* */
41 /* William E. Lamie, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function handles logical sector cache read requests for the */
46 /* logical sector read function. If the function finds the requested */
47 /* sector in the cache, it setup the appropriate pointers and */
48 /* returns a FX_NULL. */
49 /* */
50 /* INPUT */
51 /* */
52 /* media_ptr Media control block pointer */
53 /* logical_sector Logical sector number */
54 /* previous_cache_entry Pointer to previous entry in */
55 /* non-hashed cache */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* FX_CACHED_SECTOR * Cache entry to setup */
60 /* */
61 /* CALLS */
62 /* */
63 /* None */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* _fx_utility_logical_sector_read Logical sector read function */
68 /* */
69 /**************************************************************************/
70 494341687 FX_CACHED_SECTOR *_fx_utility_logical_sector_cache_entry_read(FX_MEDIA *media_ptr, ULONG64 logical_sector,
71 FX_CACHED_SECTOR **previous_cache_entry)
72 {
73
74 #ifndef FX_DISABLE_CACHE
75 FX_CACHED_SECTOR *cache_entry;
76 FX_CACHED_SECTOR temp_storage;
77 ULONG cache_size;
78 ULONG index;
79
80
81 /* Determine if the logical sector cache access should use the hash function. */
82
2/2
✓ Branch 2 → 3 taken 29716223 times.
✓ Branch 2 → 16 taken 464625464 times.
494341687 if (media_ptr -> fx_media_sector_cache_hashed)
83 {
84
85 /* Calculate the area of the cache for this logical sector. */
86
87 /* First compute the hashed value of this index by simply using the lower bits of
88 the sector number. */
89 29716223 index = (ULONG)(logical_sector & media_ptr -> fx_media_sector_cache_hash_mask);
90
91 /* Set the bit indicating there is one or more valid sectors at this cache index. */
92 29716223 media_ptr -> fx_media_sector_cache_hashed_sector_valid |= ((ULONG)1) << (index % 32);
93
94 /* Compute the actual array index by multiplying by the cache depth. */
95 29716223 index = index * FX_SECTOR_CACHE_DEPTH;
96
97 /* Build a pointer to the cache entry. */
98 29716223 cache_entry = &(media_ptr -> fx_media_sector_cache[index]);
99
100 /* Determine if the logical sector is in the cache - assuming the depth of the
101 sector cache is 4 entries. */
102
4/4
✓ Branch 3 → 4 taken 21701389 times.
✓ Branch 3 → 6 taken 8014834 times.
✓ Branch 4 → 5 taken 19529172 times.
✓ Branch 4 → 6 taken 2172217 times.
29716223 if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
103 {
104
105 /* Yes, we found a match. Simply setup the pointer to this
106 buffer and return. */
107 19529172 media_ptr -> fx_media_memory_buffer = cache_entry -> fx_cached_sector_memory_buffer;
108
109 #ifndef FX_MEDIA_STATISTICS_DISABLE
110
111 /* Increment the number of logical sectors cache read hits. */
112 19529172 media_ptr -> fx_media_logical_sector_cache_read_hits++;
113 #endif
114 /* Success, return to caller immediately! */
115 19529172 return(FX_NULL);
116 }
117
4/4
✓ Branch 6 → 7 taken 2137497 times.
✓ Branch 6 → 9 taken 8049554 times.
✓ Branch 7 → 8 taken 1027191 times.
✓ Branch 7 → 9 taken 1110306 times.
10187051 else if (((cache_entry + 1) -> fx_cached_sector_valid) && ((cache_entry + 1) -> fx_cached_sector == logical_sector))
118 {
119
120 /* Yes, we found a match. Simply setup the pointer to this
121 buffer and return. */
122 1027191 media_ptr -> fx_media_memory_buffer = (cache_entry + 1) -> fx_cached_sector_memory_buffer;
123
124 #ifndef FX_MEDIA_STATISTICS_DISABLE
125
126 /* Increment the number of logical sectors cache read hits. */
127 1027191 media_ptr -> fx_media_logical_sector_cache_read_hits++;
128 #endif
129
130 /* Swap the first and second cache entries to keep the most recently used
131 at the top. */
132 1027191 temp_storage.fx_cached_sector_memory_buffer = (cache_entry) -> fx_cached_sector_memory_buffer;
133 1027191 temp_storage.fx_cached_sector = (cache_entry) -> fx_cached_sector;
134 1027191 temp_storage.fx_cached_sector_buffer_dirty = (cache_entry) -> fx_cached_sector_buffer_dirty;
135 1027191 temp_storage.fx_cached_sector_valid = (cache_entry) -> fx_cached_sector_valid;
136 1027191 temp_storage.fx_cached_sector_type = (cache_entry) -> fx_cached_sector_type;
137
138 1027191 (cache_entry) -> fx_cached_sector_memory_buffer = (cache_entry + 1) -> fx_cached_sector_memory_buffer;
139 1027191 (cache_entry) -> fx_cached_sector = (cache_entry + 1) -> fx_cached_sector;
140 1027191 (cache_entry) -> fx_cached_sector_buffer_dirty = (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
141 1027191 (cache_entry) -> fx_cached_sector_valid = (cache_entry + 1) -> fx_cached_sector_valid;
142 1027191 (cache_entry) -> fx_cached_sector_type = (cache_entry + 1) -> fx_cached_sector_type;
143
144 1027191 (cache_entry + 1) -> fx_cached_sector_memory_buffer = temp_storage.fx_cached_sector_memory_buffer;
145 1027191 (cache_entry + 1) -> fx_cached_sector = temp_storage.fx_cached_sector;
146 1027191 (cache_entry + 1) -> fx_cached_sector_buffer_dirty = temp_storage.fx_cached_sector_buffer_dirty;
147 1027191 (cache_entry + 1) -> fx_cached_sector_valid = temp_storage.fx_cached_sector_valid;
148 1027191 (cache_entry + 1) -> fx_cached_sector_type = temp_storage.fx_cached_sector_type;
149
150 /* Success, return to caller immediately! */
151 1027191 return(FX_NULL);
152 }
153
4/4
✓ Branch 9 → 10 taken 1101836 times.
✓ Branch 9 → 12 taken 8058024 times.
✓ Branch 10 → 11 taken 352708 times.
✓ Branch 10 → 12 taken 749128 times.
9159860 else if (((cache_entry + 2) -> fx_cached_sector_valid) && ((cache_entry + 2) -> fx_cached_sector == logical_sector))
154 {
155
156 /* Yes, we found a match. Simply setup the pointer to this
157 buffer and return. */
158 352708 media_ptr -> fx_media_memory_buffer = (cache_entry + 2) -> fx_cached_sector_memory_buffer;
159
160 #ifndef FX_MEDIA_STATISTICS_DISABLE
161
162 /* Increment the number of logical sectors cache read hits. */
163 352708 media_ptr -> fx_media_logical_sector_cache_read_hits++;
164 #endif
165
166 /* Move the third entry to the top and the first two entries down. */
167 352708 temp_storage.fx_cached_sector_memory_buffer = (cache_entry) -> fx_cached_sector_memory_buffer;
168 352708 temp_storage.fx_cached_sector = (cache_entry) -> fx_cached_sector;
169 352708 temp_storage.fx_cached_sector_buffer_dirty = (cache_entry) -> fx_cached_sector_buffer_dirty;
170 352708 temp_storage.fx_cached_sector_valid = (cache_entry) -> fx_cached_sector_valid;
171 352708 temp_storage.fx_cached_sector_type = (cache_entry) -> fx_cached_sector_type;
172
173 352708 (cache_entry) -> fx_cached_sector_memory_buffer = (cache_entry + 2) -> fx_cached_sector_memory_buffer;
174 352708 (cache_entry) -> fx_cached_sector = (cache_entry + 2) -> fx_cached_sector;
175 352708 (cache_entry) -> fx_cached_sector_buffer_dirty = (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
176 352708 (cache_entry) -> fx_cached_sector_valid = (cache_entry + 2) -> fx_cached_sector_valid;
177 352708 (cache_entry) -> fx_cached_sector_type = (cache_entry + 2) -> fx_cached_sector_type;
178
179 352708 (cache_entry + 2) -> fx_cached_sector_memory_buffer = (cache_entry + 1) -> fx_cached_sector_memory_buffer;
180 352708 (cache_entry + 2) -> fx_cached_sector = (cache_entry + 1) -> fx_cached_sector;
181 352708 (cache_entry + 2) -> fx_cached_sector_buffer_dirty = (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
182 352708 (cache_entry + 2) -> fx_cached_sector_valid = (cache_entry + 1) -> fx_cached_sector_valid;
183 352708 (cache_entry + 2) -> fx_cached_sector_type = (cache_entry + 1) -> fx_cached_sector_type;
184
185 352708 (cache_entry + 1) -> fx_cached_sector_memory_buffer = temp_storage.fx_cached_sector_memory_buffer;
186 352708 (cache_entry + 1) -> fx_cached_sector = temp_storage.fx_cached_sector;
187 352708 (cache_entry + 1) -> fx_cached_sector_buffer_dirty = temp_storage.fx_cached_sector_buffer_dirty;
188 352708 (cache_entry + 1) -> fx_cached_sector_valid = temp_storage.fx_cached_sector_valid;
189 352708 (cache_entry + 1) -> fx_cached_sector_type = temp_storage.fx_cached_sector_type;
190
191 /* Success, return to caller immediately! */
192 352708 return(FX_NULL);
193 }
194
4/4
✓ Branch 12 → 13 taken 743148 times.
✓ Branch 12 → 15 taken 8064004 times.
✓ Branch 13 → 14 taken 154752 times.
✓ Branch 13 → 15 taken 588396 times.
8807152 else if (((cache_entry + 3) -> fx_cached_sector_valid) && ((cache_entry + 3) -> fx_cached_sector == logical_sector))
195 {
196
197 /* Yes, we found a match. Simply setup the pointer to this
198 buffer and return. */
199 154752 media_ptr -> fx_media_memory_buffer = (cache_entry + 3) -> fx_cached_sector_memory_buffer;
200
201 #ifndef FX_MEDIA_STATISTICS_DISABLE
202
203 /* Increment the number of logical sectors cache read hits. */
204 154752 media_ptr -> fx_media_logical_sector_cache_read_hits++;
205 #endif
206
207 /* Move the last entry to the top and the first three entries down. */
208 154752 temp_storage.fx_cached_sector_memory_buffer = (cache_entry) -> fx_cached_sector_memory_buffer;
209 154752 temp_storage.fx_cached_sector = (cache_entry) -> fx_cached_sector;
210 154752 temp_storage.fx_cached_sector_buffer_dirty = (cache_entry) -> fx_cached_sector_buffer_dirty;
211 154752 temp_storage.fx_cached_sector_valid = (cache_entry) -> fx_cached_sector_valid;
212 154752 temp_storage.fx_cached_sector_type = (cache_entry) -> fx_cached_sector_type;
213
214 154752 (cache_entry) -> fx_cached_sector_memory_buffer = (cache_entry + 3) -> fx_cached_sector_memory_buffer;
215 154752 (cache_entry) -> fx_cached_sector = (cache_entry + 3) -> fx_cached_sector;
216 154752 (cache_entry) -> fx_cached_sector_buffer_dirty = (cache_entry + 3) -> fx_cached_sector_buffer_dirty;
217 154752 (cache_entry) -> fx_cached_sector_valid = (cache_entry + 3) -> fx_cached_sector_valid;
218 154752 (cache_entry) -> fx_cached_sector_type = (cache_entry + 3) -> fx_cached_sector_type;
219
220 154752 (cache_entry + 3) -> fx_cached_sector_memory_buffer = (cache_entry + 2) -> fx_cached_sector_memory_buffer;
221 154752 (cache_entry + 3) -> fx_cached_sector = (cache_entry + 2) -> fx_cached_sector;
222 154752 (cache_entry + 3) -> fx_cached_sector_buffer_dirty = (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
223 154752 (cache_entry + 3) -> fx_cached_sector_valid = (cache_entry + 2) -> fx_cached_sector_valid;
224 154752 (cache_entry + 3) -> fx_cached_sector_type = (cache_entry + 2) -> fx_cached_sector_type;
225
226 154752 (cache_entry + 2) -> fx_cached_sector_memory_buffer = (cache_entry + 1) -> fx_cached_sector_memory_buffer;
227 154752 (cache_entry + 2) -> fx_cached_sector = (cache_entry + 1) -> fx_cached_sector;
228 154752 (cache_entry + 2) -> fx_cached_sector_buffer_dirty = (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
229 154752 (cache_entry + 2) -> fx_cached_sector_valid = (cache_entry + 1) -> fx_cached_sector_valid;
230 154752 (cache_entry + 2) -> fx_cached_sector_type = (cache_entry + 1) -> fx_cached_sector_type;
231
232 154752 (cache_entry + 1) -> fx_cached_sector_memory_buffer = temp_storage.fx_cached_sector_memory_buffer;
233 154752 (cache_entry + 1) -> fx_cached_sector = temp_storage.fx_cached_sector;
234 154752 (cache_entry + 1) -> fx_cached_sector_buffer_dirty = temp_storage.fx_cached_sector_buffer_dirty;
235 154752 (cache_entry + 1) -> fx_cached_sector_valid = temp_storage.fx_cached_sector_valid;
236 154752 (cache_entry + 1) -> fx_cached_sector_type = temp_storage.fx_cached_sector_type;
237
238 /* Success, return to caller immediately! */
239 154752 return(FX_NULL);
240 }
241
242 /* At this point we have a cache miss. We need to move all of the sectors down one slot, swapping
243 the 4th entry with the first. */
244 8652400 temp_storage.fx_cached_sector_memory_buffer = (cache_entry + 3) -> fx_cached_sector_memory_buffer;
245 8652400 temp_storage.fx_cached_sector = (cache_entry + 3) -> fx_cached_sector;
246 8652400 temp_storage.fx_cached_sector_buffer_dirty = (cache_entry + 3) -> fx_cached_sector_buffer_dirty;
247 8652400 temp_storage.fx_cached_sector_valid = (cache_entry + 3) -> fx_cached_sector_valid;
248 8652400 temp_storage.fx_cached_sector_type = (cache_entry + 3) -> fx_cached_sector_type;
249
250 8652400 (cache_entry + 3) -> fx_cached_sector_memory_buffer = (cache_entry + 2) -> fx_cached_sector_memory_buffer;
251 8652400 (cache_entry + 3) -> fx_cached_sector = (cache_entry + 2) -> fx_cached_sector;
252 8652400 (cache_entry + 3) -> fx_cached_sector_buffer_dirty = (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
253 8652400 (cache_entry + 3) -> fx_cached_sector_valid = (cache_entry + 2) -> fx_cached_sector_valid;
254 8652400 (cache_entry + 3) -> fx_cached_sector_type = (cache_entry + 2) -> fx_cached_sector_type;
255
256 8652400 (cache_entry + 2) -> fx_cached_sector_memory_buffer = (cache_entry + 1) -> fx_cached_sector_memory_buffer;
257 8652400 (cache_entry + 2) -> fx_cached_sector = (cache_entry + 1) -> fx_cached_sector;
258 8652400 (cache_entry + 2) -> fx_cached_sector_buffer_dirty = (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
259 8652400 (cache_entry + 2) -> fx_cached_sector_valid = (cache_entry + 1) -> fx_cached_sector_valid;
260 8652400 (cache_entry + 2) -> fx_cached_sector_type = (cache_entry + 1) -> fx_cached_sector_type;
261
262 8652400 (cache_entry + 1) -> fx_cached_sector_memory_buffer = (cache_entry) -> fx_cached_sector_memory_buffer;
263 8652400 (cache_entry + 1) -> fx_cached_sector = (cache_entry) -> fx_cached_sector;
264 8652400 (cache_entry + 1) -> fx_cached_sector_buffer_dirty = (cache_entry) -> fx_cached_sector_buffer_dirty;
265 8652400 (cache_entry + 1) -> fx_cached_sector_valid = (cache_entry) -> fx_cached_sector_valid;
266 8652400 (cache_entry + 1) -> fx_cached_sector_type = (cache_entry) -> fx_cached_sector_type;
267
268 8652400 (cache_entry) -> fx_cached_sector_memory_buffer = temp_storage.fx_cached_sector_memory_buffer;
269 8652400 (cache_entry) -> fx_cached_sector = temp_storage.fx_cached_sector;
270 8652400 (cache_entry) -> fx_cached_sector_buffer_dirty = temp_storage.fx_cached_sector_buffer_dirty;
271 8652400 (cache_entry) -> fx_cached_sector_valid = temp_storage.fx_cached_sector_valid;
272 8652400 (cache_entry) -> fx_cached_sector_type = temp_storage.fx_cached_sector_type;
273
274 /* Set the previous pointer to NULL to avoid the linked list update below. */
275 8652400 *previous_cache_entry = FX_NULL;
276 }
277 else
278 {
279
280 /* Search for an entry in the cache that matches this request. */
281 464625464 cache_size = media_ptr -> fx_media_sector_cache_size;
282 464625464 cache_entry = media_ptr -> fx_media_sector_cache_list_ptr;
283 464625464 *previous_cache_entry = FX_NULL;
284
285 /* Look at the cache entries until a match is found or the end of
286 the cache is reached. */
287
2/2
✓ Branch 25 → 17 taken 943906170 times.
✓ Branch 25 → 26 taken 29332853 times.
973239023 while (cache_size--)
288 {
289
290 /* Determine if the requested sector has been found. */
291
4/4
✓ Branch 17 → 18 taken 925316695 times.
✓ Branch 17 → 22 taken 18589475 times.
✓ Branch 18 → 19 taken 435292611 times.
✓ Branch 18 → 22 taken 490024084 times.
943906170 if ((cache_entry -> fx_cached_sector_valid) && (cache_entry -> fx_cached_sector == logical_sector))
292 {
293
294 /* Yes, we found a match. Simply setup the pointer to this
295 buffer and return. */
296 435292611 media_ptr -> fx_media_memory_buffer = cache_entry -> fx_cached_sector_memory_buffer;
297
298 /* Determine if we need to update the last used list. */
299
2/2
✓ Branch 19 → 20 taken 172990517 times.
✓ Branch 19 → 21 taken 262302094 times.
435292611 if (*previous_cache_entry)
300 {
301
302 /* Yes, the current entry is not at the front of the list
303 so we need to change the order. */
304
305 /* Link the previous entry to this entry's next pointer. */
306 172990517 (*previous_cache_entry) -> fx_cached_sector_next_used =
307 172990517 cache_entry -> fx_cached_sector_next_used;
308
309 /* Place this entry at the head of the list. */
310 172990517 cache_entry -> fx_cached_sector_next_used =
311 172990517 media_ptr -> fx_media_sector_cache_list_ptr;
312 172990517 media_ptr -> fx_media_sector_cache_list_ptr = cache_entry;
313 }
314
315 #ifndef FX_MEDIA_STATISTICS_DISABLE
316
317 /* Increment the number of logical sectors cache read hits. */
318 435292611 media_ptr -> fx_media_logical_sector_cache_read_hits++;
319 #endif
320
321 /* Success, return to caller immediately! */
322 435292611 return(FX_NULL);
323 }
324
325 /* Otherwise, we have not found the cached entry yet. */
326
327 /* If there are more entries, move to the next one. */
328
2/2
✓ Branch 22 → 23 taken 479280706 times.
✓ Branch 22 → 24 taken 29332853 times.
508613559 if (cache_entry -> fx_cached_sector_next_used)
329 {
330
331 479280706 *previous_cache_entry = cache_entry;
332 479280706 cache_entry = cache_entry -> fx_cached_sector_next_used;
333 }
334 }
335 }
336
337 /* The requested sector is not in cache, return the last cache entry. */
338 37985253 return(cache_entry);
339 #else
340 FX_PARAMETER_NOT_USED(media_ptr);
341 FX_PARAMETER_NOT_USED(logical_sector);
342 FX_PARAMETER_NOT_USED(previous_cache_entry);
343 ✗ return(FX_NULL);
344 #endif /* FX_DISABLE_CACHE */
345 }
346
347