Coverage Report

Created: 2025-07-09 06:41

/src/libavc/common/ih264_list.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Copyright (C) 2015 The Android Open Source Project
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 *****************************************************************************
18
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19
*/
20
21
/**
22
*******************************************************************************
23
* @file
24
*  ih264_list.c
25
*
26
* @brief
27
*  Contains functions for buf queue
28
*
29
* @author
30
*  ittiam
31
*
32
* @par List of Functions:
33
*  - ih264_list_size
34
*  - ih264_list_lock
35
*  - ih264_list_unlock
36
*  - ih264_list_yield
37
*  - ih264_list_free
38
*  - ih264_list_init
39
*  - ih264_list_reset
40
*  - ih264_list_deinit
41
*  - ih264_list_terminate
42
*  - ih264_list_queue
43
*  - ih264_list_dequeue
44
*
45
* @remarks
46
*  none
47
*
48
*******************************************************************************
49
*/
50
51
/*****************************************************************************/
52
/* File Includes                                                             */
53
/*****************************************************************************/
54
55
/* System Include Files */
56
#include <stdio.h>
57
#include <stddef.h>
58
#include <stdlib.h>
59
#include <string.h>
60
#include <assert.h>
61
62
/* User Include Files */
63
#include "ih264_typedefs.h"
64
#include "ithread.h"
65
#include "ih264_debug.h"
66
#include "ih264_macros.h"
67
#include "ih264_error.h"
68
#include "ih264_list.h"
69
#include "ih264_platform_macros.h"
70
71
/*****************************************************************************/
72
/* Function Definitions                                                      */
73
/*****************************************************************************/
74
75
/**
76
*******************************************************************************
77
*
78
* @brief Returns size for job queue context.
79
*
80
* @par Description
81
*  Returns size for job queue context.
82
*
83
* @param[in] num_entries
84
*  max number of jobs that can be queued
85
*
86
* @param[in] entry_size
87
*  memory needed for a single job
88
*
89
* @returns Size of the job queue context
90
*
91
* @remarks
92
*
93
*******************************************************************************
94
*/
95
WORD32 ih264_list_size(WORD32 num_entries, WORD32 entry_size)
96
38.9k
{
97
38.9k
    WORD32 size;
98
38.9k
    WORD32 clz;
99
100
38.9k
    size = sizeof(list_t);
101
38.9k
    size += ithread_get_mutex_lock_size();
102
103
    /* Use next power of two number of entries*/
104
38.9k
    clz = CLZ(num_entries);
105
38.9k
    num_entries = 1 << (32 - clz);
106
107
38.9k
    size += num_entries * entry_size;
108
38.9k
    return size;
109
38.9k
}
110
111
/**
112
*******************************************************************************
113
*
114
* @brief Locks the list context
115
*
116
* @par Description
117
*  Locks the list context by calling ithread_mutex_lock()
118
*
119
* @param[in] ps_list
120
*  Pointer to job queue context
121
*
122
* @returns IH264_FAIL if mutex lock fails else IH264_SUCCESS
123
*
124
* @remarks
125
*
126
*******************************************************************************
127
*/
128
IH264_ERROR_T ih264_list_lock(list_t *ps_list)
129
83.7M
{
130
83.7M
    WORD32 retval;
131
132
83.7M
    retval = ithread_mutex_lock(ps_list->pv_mutex);
133
83.7M
    if(retval)
134
0
        return IH264_FAIL;
135
83.7M
    return IH264_SUCCESS;
136
83.7M
}
137
138
/**
139
*******************************************************************************
140
*
141
* @brief Unlocks the list context
142
*
143
* @par Description
144
*  Unlocks the list context by calling ithread_mutex_unlock()
145
*
146
* @param[in] ps_list
147
*  Pointer to job queue context
148
*
149
* @returns IH264_FAIL if mutex unlock fails else IH264_SUCCESS
150
*
151
* @remarks
152
*
153
*******************************************************************************
154
*/
155
IH264_ERROR_T ih264_list_unlock(list_t *ps_list)
156
83.7M
{
157
83.7M
    WORD32 retval;
158
159
83.7M
    retval = ithread_mutex_unlock(ps_list->pv_mutex);
160
83.7M
    if(retval)
161
0
        return IH264_FAIL;
162
83.7M
    return IH264_SUCCESS;
163
83.7M
}
164
165
/**
166
*******************************************************************************
167
*
168
* @brief Yields the thread
169
*
170
* @par Description
171
*  Unlocks the list context by calling  ih264_list_unlock(), ithread_yield()
172
*  and then ih264_list_lock(). List is unlocked before to ensure its
173
*  access by other threads. If unlock is not done before calling yield then
174
*  no other thread can access the list functions and update list.
175
*
176
* @param[in] ps_list
177
*  pointer to Job Queue context
178
*
179
* @returns IH264_FAIL if mutex lock unlock or yield fails else IH264_SUCCESS
180
*
181
* @remarks
182
*
183
*******************************************************************************
184
*/
185
IH264_ERROR_T ih264_list_yield(list_t *ps_list)
186
134k
{
187
134k
    IH264_ERROR_T ret;
188
189
134k
    ret = ih264_list_unlock(ps_list);
190
134k
    RETURN_IF((ret != IH264_SUCCESS), ret);
191
192
134k
    ithread_yield();
193
194
134k
    if(ps_list->i4_yield_interval_us > 0)
195
134k
        ithread_usleep(ps_list->i4_yield_interval_us);
196
197
134k
    ret = ih264_list_lock(ps_list);
198
134k
    RETURN_IF((ret != IH264_SUCCESS), ret);
199
134k
    return IH264_SUCCESS;
200
134k
}
201
202
/**
203
*******************************************************************************
204
*
205
* @brief free the list context
206
*
207
* @par Description
208
*  Frees the list context
209
*
210
* @param[in] ps_list
211
*  pointer to Job Queue context
212
*
213
* @returns IH264_FAIL if mutex desttroy fails else IH264_SUCCESS
214
*
215
* @remarks
216
*  Since it will be called only once by master thread this is not thread safe.
217
*
218
*******************************************************************************
219
*/
220
IH264_ERROR_T ih264_list_free(list_t *ps_list)
221
9.56k
{
222
9.56k
    WORD32 ret;
223
224
9.56k
    ret = ithread_mutex_destroy(ps_list->pv_mutex);
225
9.56k
    if(0 == ret)
226
9.56k
        return IH264_SUCCESS;
227
0
    return IH264_FAIL;
228
9.56k
}
229
230
/**
231
*******************************************************************************
232
*
233
* @brief Initialize the buf queue
234
*
235
* @par Description
236
*  Initializes the list context and sets write and read pointers to start of
237
*  buf queue buffer
238
*
239
* @param[in] pv_buf
240
*  Memory for job queue context
241
*
242
* @param[in] buf_size
243
*  Size of the total memory allocated
244
*
245
* @param[in] num_entries
246
*  max number of jobs that can be queued
247
*
248
* @param[in] entry_size
249
*  memory needed for a single job
250
*
251
* @param[in] yield_interval_us
252
*  Thread sleep duration
253
*
254
* @returns Pointer to job queue context
255
*
256
* @remarks
257
*  Since it will be called only once by master thread this is not thread safe.
258
*
259
*******************************************************************************
260
*/
261
void* ih264_list_init(void *pv_buf,
262
                      WORD32 buf_size,
263
                      WORD32 num_entries,
264
                      WORD32 entry_size,
265
                      WORD32 yield_interval_us)
266
19.4k
{
267
19.4k
    list_t *ps_list = (list_t *)pv_buf;
268
19.4k
    UWORD8 *pu1_buf = (UWORD8 *)pv_buf;
269
270
19.4k
    pu1_buf += sizeof(list_t);
271
19.4k
    buf_size -= sizeof(list_t);
272
273
19.4k
    ps_list->pv_mutex = pu1_buf;
274
19.4k
    pu1_buf += ithread_get_mutex_lock_size();
275
19.4k
    buf_size -= ithread_get_mutex_lock_size();
276
277
19.4k
    if (buf_size <= 0)
278
0
      return NULL;
279
280
19.4k
    ithread_mutex_init(ps_list->pv_mutex);
281
282
    /* Ensure num_entries is power of two */
283
19.4k
    ASSERT(0 == (num_entries & (num_entries - 1)));
284
285
    /* Ensure remaining buffer is large enough to hold given number of entries */
286
19.4k
    ASSERT((num_entries * entry_size) <= buf_size);
287
288
19.4k
    ps_list->pv_buf_base = pu1_buf;
289
19.4k
    ps_list->i4_terminate = 0;
290
19.4k
    ps_list->i4_entry_size = entry_size;
291
19.4k
    ps_list->i4_buf_rd_idx = 0;
292
19.4k
    ps_list->i4_buf_wr_idx = 0;
293
19.4k
    ps_list->i4_log2_buf_max_idx = 32 - CLZ(num_entries);
294
19.4k
    ps_list->i4_buf_max_idx = num_entries;
295
19.4k
    ps_list->i4_yield_interval_us = yield_interval_us;
296
297
19.4k
    return ps_list;
298
19.4k
}
299
300
/**
301
*******************************************************************************
302
*
303
* @brief Resets the list context
304
*
305
* @par Description
306
*  Resets the list context by initializing buf queue context elements
307
*
308
* @param[in] ps_list
309
*  Pointer to job queue context
310
*
311
* @returns IH264_FAIL if lock unlock fails else IH264_SUCCESS
312
*
313
* @remarks
314
*
315
*******************************************************************************
316
*/
317
IH264_ERROR_T ih264_list_reset(list_t *ps_list)
318
227k
{
319
227k
    IH264_ERROR_T ret = IH264_SUCCESS;
320
321
227k
    ret = ih264_list_lock(ps_list);
322
227k
    RETURN_IF((ret != IH264_SUCCESS), ret);
323
324
227k
    ps_list->i4_terminate  = 0;
325
227k
    ps_list->i4_buf_rd_idx = 0;
326
227k
    ps_list->i4_buf_wr_idx = 0;
327
328
227k
    ret = ih264_list_unlock(ps_list);
329
227k
    RETURN_IF((ret != IH264_SUCCESS), ret);
330
331
227k
    return ret;
332
227k
}
333
334
/**
335
*******************************************************************************
336
*
337
* @brief De-initializes the list context
338
*
339
* @par Description
340
*  De-initializes the list context by calling ih264_list_reset() and then
341
*  destroying the mutex created
342
*
343
* @param[in] ps_list
344
*  Pointer to job queue context
345
*
346
* @returns IH264_FAIL if lock unlock fails else IH264_SUCCESS
347
*
348
* @remarks
349
*
350
*******************************************************************************
351
*/
352
IH264_ERROR_T ih264_list_deinit(list_t *ps_list)
353
0
{
354
0
    WORD32 retval;
355
0
    IH264_ERROR_T ret = IH264_SUCCESS;
356
357
0
    ret = ih264_list_reset(ps_list);
358
0
    RETURN_IF((ret != IH264_SUCCESS), ret);
359
360
0
    retval = ithread_mutex_destroy(ps_list->pv_mutex);
361
0
    if(retval)
362
0
        return IH264_FAIL;
363
0
    return IH264_SUCCESS;
364
0
}
365
366
/**
367
*******************************************************************************
368
*
369
* @brief Terminates the list
370
*
371
* @par Description
372
*  Terminates the list by setting a flag in context.
373
*
374
* @param[in] ps_list
375
*  Pointer to job queue context
376
*
377
* @returns IH264_FAIL if lock unlock fails else IH264_SUCCESS
378
*
379
* @remarks
380
*
381
*******************************************************************************
382
*/
383
IH264_ERROR_T ih264_list_terminate(list_t *ps_list)
384
204k
{
385
204k
    IH264_ERROR_T ret = IH264_SUCCESS;
386
387
204k
    ret = ih264_list_lock(ps_list);
388
204k
    RETURN_IF((ret != IH264_SUCCESS), ret);
389
390
204k
    ps_list->i4_terminate = 1;
391
392
204k
    ret = ih264_list_unlock(ps_list);
393
204k
    RETURN_IF((ret != IH264_SUCCESS), ret);
394
204k
    return ret;
395
204k
}
396
397
/**
398
*******************************************************************************
399
*
400
* @brief Adds a job to the queue
401
*
402
* @par Description
403
*  Adds a buffer to the queue and updates write address to next location.
404
*
405
* @param[in] ps_list
406
*  Pointer to job queue context
407
*
408
* @param[in] pv_buf
409
*  Pointer to the location that contains details of the job to be added
410
*
411
* @param[in] blocking
412
*  To signal if the write is blocking or non-blocking.
413
*
414
* @returns IH264_SUCCESS on success and IH264_FAIL on fail
415
*
416
* @remarks
417
*  Job Queue buffer is assumed to be allocated to handle worst case number of
418
*  buffers. Wrap around is not supported
419
*
420
*******************************************************************************
421
*/
422
IH264_ERROR_T ih264_list_queue(list_t *ps_list, void *pv_buf, WORD32 blocking)
423
930k
{
424
930k
    IH264_ERROR_T ret = IH264_SUCCESS;
425
930k
    IH264_ERROR_T rettmp;
426
930k
    WORD32 diff;
427
930k
    void *pv_buf_wr;
428
930k
    volatile WORD32 *pi4_wr_idx, *pi4_rd_idx;
429
930k
    WORD32 buf_size = ps_list->i4_entry_size;
430
431
432
930k
    rettmp = ih264_list_lock(ps_list);
433
930k
    RETURN_IF((rettmp != IH264_SUCCESS), rettmp);
434
435
930k
    while(1)
436
930k
    {
437
        /* Ensure wr idx does not go beyond rd idx by more than number of entries
438
         */
439
930k
        pi4_wr_idx = &ps_list->i4_buf_wr_idx;
440
930k
        pi4_rd_idx = &ps_list->i4_buf_rd_idx;
441
930k
        diff = *pi4_wr_idx - *pi4_rd_idx;
442
443
930k
        if(diff < ps_list->i4_buf_max_idx)
444
930k
        {
445
930k
            WORD32 wr_idx;
446
930k
            wr_idx = ps_list->i4_buf_wr_idx & (ps_list->i4_buf_max_idx - 1);
447
930k
            pv_buf_wr = (UWORD8 *)ps_list->pv_buf_base + wr_idx * buf_size;
448
449
930k
            memcpy(pv_buf_wr, pv_buf, buf_size);
450
930k
            ps_list->i4_buf_wr_idx++;
451
930k
            break;
452
930k
        }
453
0
        else
454
0
        {
455
            /* wr is ahead, so wait for rd to consume */
456
0
            if(blocking)
457
0
            {
458
0
                ih264_list_yield(ps_list);
459
0
            }
460
0
            else
461
0
            {
462
0
                ret = IH264_FAIL;
463
0
                break;
464
0
            }
465
0
        }
466
930k
    }
467
930k
    ps_list->i4_terminate = 0;
468
469
930k
    rettmp = ih264_list_unlock(ps_list);
470
930k
    RETURN_IF((rettmp != IH264_SUCCESS), rettmp);
471
472
930k
    return ret;
473
930k
}
474
475
/**
476
*******************************************************************************
477
*
478
* @brief Gets next job from the job queue
479
*
480
* @par   Description
481
*  Gets next job from the job queue and updates rd address to next location.
482
*  If it is a blocking call and if there is no new buf then this functions
483
*  unlocks the mutex and calls yield and then locks it back and continues
484
*  till a buf is available or terminate is set
485
*
486
* @param[in] ps_list
487
*  Pointer to Job Queue context
488
*
489
* @param[out] pv_buf
490
*  Pointer to the location that contains details of the buf to be written
491
*
492
* @param[in] blocking
493
*  To signal if the read is blocking or non-blocking.
494
*
495
* @returns
496
*
497
* @remarks
498
*  Job Queue buffer is assumed to be allocated to handle worst case number of
499
*  buffers. Wrap around is not supported
500
*
501
*******************************************************************************
502
*/
503
IH264_ERROR_T ih264_list_dequeue(list_t *ps_list, void *pv_buf, WORD32 blocking)
504
76.8M
{
505
76.8M
    IH264_ERROR_T ret = IH264_SUCCESS;
506
76.8M
    IH264_ERROR_T rettmp;
507
76.8M
    WORD32 buf_size = ps_list->i4_entry_size;
508
76.8M
    WORD32 diff;
509
76.8M
    void *pv_buf_rd;
510
76.8M
    volatile WORD32 *pi4_wr_idx, *pi4_rd_idx;
511
512
76.8M
    rettmp = ih264_list_lock(ps_list);
513
76.8M
    RETURN_IF((rettmp != IH264_SUCCESS), rettmp);
514
515
76.9M
    while(1)
516
77.0M
    {
517
        /* Ensure wr idx is ahead of rd idx and
518
         * wr idx does not go beyond rd idx by more than number of entries
519
         */
520
77.0M
        pi4_wr_idx = &ps_list->i4_buf_wr_idx;
521
77.0M
        pi4_rd_idx = &ps_list->i4_buf_rd_idx;
522
77.0M
        diff = *pi4_wr_idx - *pi4_rd_idx;
523
524
77.0M
        if(diff > 0)
525
922k
        {
526
922k
            WORD32 rd_idx;
527
922k
            rd_idx = ps_list->i4_buf_rd_idx & (ps_list->i4_buf_max_idx - 1);
528
922k
            pv_buf_rd = (UWORD8 *)ps_list->pv_buf_base + rd_idx * buf_size;
529
530
922k
            memcpy(pv_buf, pv_buf_rd, buf_size);
531
922k
            ps_list->i4_buf_rd_idx++;
532
922k
            break;
533
922k
        }
534
76.0M
        else
535
76.0M
        {
536
            /* If terminate is signaled then break */
537
76.0M
            if(ps_list->i4_terminate)
538
52.4M
            {
539
52.4M
                ret = IH264_FAIL;
540
52.4M
                break;
541
52.4M
            }
542
            /* wr is ahead, so wait for rd to consume */
543
23.6M
            if(blocking)
544
134k
            {
545
134k
                ih264_list_yield(ps_list);
546
134k
            }
547
23.5M
            else
548
23.5M
            {
549
23.5M
                ret = IH264_FAIL;
550
23.5M
                break;
551
23.5M
            }
552
23.6M
        }
553
77.0M
    }
554
555
76.8M
    rettmp = ih264_list_unlock(ps_list);
556
76.8M
    RETURN_IF((rettmp != IH264_SUCCESS), rettmp);
557
558
76.8M
    return ret;
559
76.8M
}
560
561
/**
562
*******************************************************************************
563
*
564
* @brief
565
*   Gets the number of jobs
566
*
567
* @par   Description
568
*   Gets the number of jobs to be processed in job queue context.
569
*
570
* @param[in] ps_list
571
*   Job Queue context
572
*
573
* @returns 0 if lock unlock fails else number of jobs to be processed
574
*
575
* @remarks
576
*
577
*******************************************************************************
578
*/
579
WORD32 ih264_get_job_count_in_list(list_t *ps_list)
580
5.39M
{
581
5.39M
    WORD32 jobs = 0;
582
5.39M
    RETURN_IF((ih264_list_lock(ps_list) != IH264_SUCCESS), 0);
583
5.39M
    jobs = ps_list->i4_buf_wr_idx - ps_list->i4_buf_rd_idx;
584
5.39M
    RETURN_IF((ih264_list_unlock(ps_list) != IH264_SUCCESS), 0);
585
5.39M
    return jobs;
586
5.39M
}