GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_utility_logical_sector_cache_entry_read.c Lines: 126 126 100.0 %
Date: 2026-03-06 18:49:02 Branches: 28 28 100.0 %

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
9703907
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
9703907
    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
2827822
        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
2827822
        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
2827822
        index =  index * FX_SECTOR_CACHE_DEPTH;
96
97
        /* Build a pointer to the cache entry.  */
98
2827822
        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

2827822
        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
2657553
            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
2657553
            media_ptr -> fx_media_logical_sector_cache_read_hits++;
113
#endif
114
            /* Success, return to caller immediately!  */
115
2657553
            return(FX_NULL);
116
        }
117

170269
        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
15169
            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
15169
            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
15169
            temp_storage.fx_cached_sector_memory_buffer =           (cache_entry) -> fx_cached_sector_memory_buffer;
133
15169
            temp_storage.fx_cached_sector =                         (cache_entry) -> fx_cached_sector;
134
15169
            temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry) -> fx_cached_sector_buffer_dirty;
135
15169
            temp_storage.fx_cached_sector_valid =                   (cache_entry) -> fx_cached_sector_valid;
136
15169
            temp_storage.fx_cached_sector_type =                    (cache_entry) -> fx_cached_sector_type;
137
138
15169
            (cache_entry) -> fx_cached_sector_memory_buffer =       (cache_entry + 1) -> fx_cached_sector_memory_buffer;
139
15169
            (cache_entry) -> fx_cached_sector =                     (cache_entry + 1) -> fx_cached_sector;
140
15169
            (cache_entry) -> fx_cached_sector_buffer_dirty =        (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
141
15169
            (cache_entry) -> fx_cached_sector_valid =               (cache_entry + 1) -> fx_cached_sector_valid;
142
15169
            (cache_entry) -> fx_cached_sector_type =                (cache_entry + 1) -> fx_cached_sector_type;
143
144
15169
            (cache_entry + 1) -> fx_cached_sector_memory_buffer =   temp_storage.fx_cached_sector_memory_buffer;
145
15169
            (cache_entry + 1) -> fx_cached_sector =                 temp_storage.fx_cached_sector;
146
15169
            (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    temp_storage.fx_cached_sector_buffer_dirty;
147
15169
            (cache_entry + 1) -> fx_cached_sector_valid =           temp_storage.fx_cached_sector_valid;
148
15169
            (cache_entry + 1) -> fx_cached_sector_type =            temp_storage.fx_cached_sector_type;
149
150
            /* Success, return to caller immediately!  */
151
15169
            return(FX_NULL);
152
        }
153

155100
        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
1493
            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
1493
            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
1493
            temp_storage.fx_cached_sector_memory_buffer =           (cache_entry) -> fx_cached_sector_memory_buffer;
168
1493
            temp_storage.fx_cached_sector =                         (cache_entry) -> fx_cached_sector;
169
1493
            temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry) -> fx_cached_sector_buffer_dirty;
170
1493
            temp_storage.fx_cached_sector_valid =                   (cache_entry) -> fx_cached_sector_valid;
171
1493
            temp_storage.fx_cached_sector_type =                    (cache_entry) -> fx_cached_sector_type;
172
173
1493
            (cache_entry) -> fx_cached_sector_memory_buffer =       (cache_entry + 2) -> fx_cached_sector_memory_buffer;
174
1493
            (cache_entry) -> fx_cached_sector =                     (cache_entry + 2) -> fx_cached_sector;
175
1493
            (cache_entry) -> fx_cached_sector_buffer_dirty =        (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
176
1493
            (cache_entry) -> fx_cached_sector_valid =               (cache_entry + 2) -> fx_cached_sector_valid;
177
1493
            (cache_entry) -> fx_cached_sector_type =                (cache_entry + 2) -> fx_cached_sector_type;
178
179
1493
            (cache_entry + 2) -> fx_cached_sector_memory_buffer =   (cache_entry + 1) -> fx_cached_sector_memory_buffer;
180
1493
            (cache_entry + 2) -> fx_cached_sector =                 (cache_entry + 1) -> fx_cached_sector;
181
1493
            (cache_entry + 2) -> fx_cached_sector_buffer_dirty =    (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
182
1493
            (cache_entry + 2) -> fx_cached_sector_valid =           (cache_entry + 1) -> fx_cached_sector_valid;
183
1493
            (cache_entry + 2) -> fx_cached_sector_type =            (cache_entry + 1) -> fx_cached_sector_type;
184
185
1493
            (cache_entry + 1) -> fx_cached_sector_memory_buffer =   temp_storage.fx_cached_sector_memory_buffer;
186
1493
            (cache_entry + 1) -> fx_cached_sector =                 temp_storage.fx_cached_sector;
187
1493
            (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    temp_storage.fx_cached_sector_buffer_dirty;
188
1493
            (cache_entry + 1) -> fx_cached_sector_valid =           temp_storage.fx_cached_sector_valid;
189
1493
            (cache_entry + 1) -> fx_cached_sector_type =            temp_storage.fx_cached_sector_type;
190
191
            /* Success, return to caller immediately!  */
192
1493
            return(FX_NULL);
193
        }
194

153607
        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
1299
            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
1299
            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
1299
            temp_storage.fx_cached_sector_memory_buffer =           (cache_entry) -> fx_cached_sector_memory_buffer;
209
1299
            temp_storage.fx_cached_sector =                         (cache_entry) -> fx_cached_sector;
210
1299
            temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry) -> fx_cached_sector_buffer_dirty;
211
1299
            temp_storage.fx_cached_sector_valid =                   (cache_entry) -> fx_cached_sector_valid;
212
1299
            temp_storage.fx_cached_sector_type =                    (cache_entry) -> fx_cached_sector_type;
213
214
1299
            (cache_entry) -> fx_cached_sector_memory_buffer =       (cache_entry + 3) -> fx_cached_sector_memory_buffer;
215
1299
            (cache_entry) -> fx_cached_sector =                     (cache_entry + 3) -> fx_cached_sector;
216
1299
            (cache_entry) -> fx_cached_sector_buffer_dirty =        (cache_entry + 3) -> fx_cached_sector_buffer_dirty;
217
1299
            (cache_entry) -> fx_cached_sector_valid =               (cache_entry + 3) -> fx_cached_sector_valid;
218
1299
            (cache_entry) -> fx_cached_sector_type =                (cache_entry + 3) -> fx_cached_sector_type;
219
220
1299
            (cache_entry + 3) -> fx_cached_sector_memory_buffer =   (cache_entry + 2) -> fx_cached_sector_memory_buffer;
221
1299
            (cache_entry + 3) -> fx_cached_sector =                 (cache_entry + 2) -> fx_cached_sector;
222
1299
            (cache_entry + 3) -> fx_cached_sector_buffer_dirty =    (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
223
1299
            (cache_entry + 3) -> fx_cached_sector_valid =           (cache_entry + 2) -> fx_cached_sector_valid;
224
1299
            (cache_entry + 3) -> fx_cached_sector_type =            (cache_entry + 2) -> fx_cached_sector_type;
225
226
1299
            (cache_entry + 2) -> fx_cached_sector_memory_buffer =   (cache_entry + 1) -> fx_cached_sector_memory_buffer;
227
1299
            (cache_entry + 2) -> fx_cached_sector =                 (cache_entry + 1) -> fx_cached_sector;
228
1299
            (cache_entry + 2) -> fx_cached_sector_buffer_dirty =    (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
229
1299
            (cache_entry + 2) -> fx_cached_sector_valid =           (cache_entry + 1) -> fx_cached_sector_valid;
230
1299
            (cache_entry + 2) -> fx_cached_sector_type =            (cache_entry + 1) -> fx_cached_sector_type;
231
232
1299
            (cache_entry + 1) -> fx_cached_sector_memory_buffer =   temp_storage.fx_cached_sector_memory_buffer;
233
1299
            (cache_entry + 1) -> fx_cached_sector =                 temp_storage.fx_cached_sector;
234
1299
            (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    temp_storage.fx_cached_sector_buffer_dirty;
235
1299
            (cache_entry + 1) -> fx_cached_sector_valid =           temp_storage.fx_cached_sector_valid;
236
1299
            (cache_entry + 1) -> fx_cached_sector_type =            temp_storage.fx_cached_sector_type;
237
238
            /* Success, return to caller immediately!  */
239
1299
            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
152308
        temp_storage.fx_cached_sector_memory_buffer =           (cache_entry + 3) -> fx_cached_sector_memory_buffer;
245
152308
        temp_storage.fx_cached_sector =                         (cache_entry + 3) -> fx_cached_sector;
246
152308
        temp_storage.fx_cached_sector_buffer_dirty =            (cache_entry + 3) -> fx_cached_sector_buffer_dirty;
247
152308
        temp_storage.fx_cached_sector_valid =                   (cache_entry + 3) -> fx_cached_sector_valid;
248
152308
        temp_storage.fx_cached_sector_type =                    (cache_entry + 3) -> fx_cached_sector_type;
249
250
152308
        (cache_entry + 3) -> fx_cached_sector_memory_buffer =   (cache_entry + 2) -> fx_cached_sector_memory_buffer;
251
152308
        (cache_entry + 3) -> fx_cached_sector =                 (cache_entry + 2) -> fx_cached_sector;
252
152308
        (cache_entry + 3) -> fx_cached_sector_buffer_dirty =    (cache_entry + 2) -> fx_cached_sector_buffer_dirty;
253
152308
        (cache_entry + 3) -> fx_cached_sector_valid =           (cache_entry + 2) -> fx_cached_sector_valid;
254
152308
        (cache_entry + 3) -> fx_cached_sector_type =            (cache_entry + 2) -> fx_cached_sector_type;
255
256
152308
        (cache_entry + 2) -> fx_cached_sector_memory_buffer =   (cache_entry + 1) -> fx_cached_sector_memory_buffer;
257
152308
        (cache_entry + 2) -> fx_cached_sector =                 (cache_entry + 1) -> fx_cached_sector;
258
152308
        (cache_entry + 2) -> fx_cached_sector_buffer_dirty =    (cache_entry + 1) -> fx_cached_sector_buffer_dirty;
259
152308
        (cache_entry + 2) -> fx_cached_sector_valid =           (cache_entry + 1) -> fx_cached_sector_valid;
260
152308
        (cache_entry + 2) -> fx_cached_sector_type =            (cache_entry + 1) -> fx_cached_sector_type;
261
262
152308
        (cache_entry + 1) -> fx_cached_sector_memory_buffer =   (cache_entry) -> fx_cached_sector_memory_buffer;
263
152308
        (cache_entry + 1) -> fx_cached_sector =                 (cache_entry) -> fx_cached_sector;
264
152308
        (cache_entry + 1) -> fx_cached_sector_buffer_dirty =    (cache_entry) -> fx_cached_sector_buffer_dirty;
265
152308
        (cache_entry + 1) -> fx_cached_sector_valid =           (cache_entry) -> fx_cached_sector_valid;
266
152308
        (cache_entry + 1) -> fx_cached_sector_type =            (cache_entry) -> fx_cached_sector_type;
267
268
152308
        (cache_entry) -> fx_cached_sector_memory_buffer =       temp_storage.fx_cached_sector_memory_buffer;
269
152308
        (cache_entry) -> fx_cached_sector =                     temp_storage.fx_cached_sector;
270
152308
        (cache_entry) -> fx_cached_sector_buffer_dirty =        temp_storage.fx_cached_sector_buffer_dirty;
271
152308
        (cache_entry) -> fx_cached_sector_valid =               temp_storage.fx_cached_sector_valid;
272
152308
        (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
152308
        *previous_cache_entry =  FX_NULL;
276
    }
277
    else
278
    {
279
280
        /* Search for an entry in the cache that matches this request.  */
281
6876085
        cache_size =            media_ptr -> fx_media_sector_cache_size;
282
6876085
        cache_entry =           media_ptr -> fx_media_sector_cache_list_ptr;
283
6876085
        *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
49382853
        while (cache_size--)
288
        {
289
290
            /* Determine if the requested sector has been found.  */
291

46856837
            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
4350069
                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
4350069
                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
2085927
                    (*previous_cache_entry) -> fx_cached_sector_next_used =
307
2085927
                        cache_entry -> fx_cached_sector_next_used;
308
309
                    /* Place this entry at the head of the list.  */
310
2085927
                    cache_entry -> fx_cached_sector_next_used =
311
2085927
                        media_ptr -> fx_media_sector_cache_list_ptr;
312
2085927
                    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
4350069
                media_ptr -> fx_media_logical_sector_cache_read_hits++;
319
#endif
320
321
                /* Success, return to caller immediately!  */
322
4350069
                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
42506768
            if (cache_entry -> fx_cached_sector_next_used)
329
            {
330
331
39980752
                *previous_cache_entry =  cache_entry;
332
39980752
                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
2678324
    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