ud3tn/components/platform/posix/simple_queue.c
Maximilian Nitsch 4e125e3af7 fix: cppcheck warnings
Add command-line options for cppcheck to the CI job:

- `--suppress=constParameterCallback`

- `--check-level=exhaustive`

  information: Limiting analysis of branches.
  Use --check-level=exhaustive to analyze all branches.

- `--force`

  information: Too many #ifdef configurations - cppcheck only checks 12
  configurations. Use --force to check all configurations.

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2026-05-20 17:57:53 +02:00

189 lines
4.6 KiB
C

// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
/*
* simple_queue.c
*
* Description: simple and lightweight implementation of message-queues in C.
*
* Copyright (c) 2016, Robert Wiewel
*
* This file has been initially provided under the BSD 3-clause license and
* is now provided in agreement with the original author as part of uD3TN
* under the terms and conditions of either the Apache 2.0 or the BSD 3-clause
* license. See the LICENSE file in the project root for details.
*
*/
#include "platform/hal_semaphore.h"
#include "platform/posix/simple_queue.h"
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
static char *increment(char *current, char *abs_start, const char *abs_end,
const unsigned int item_size)
{
char *val = current + item_size;
if (val > abs_end)
val = abs_start;
return val;
}
// False positive: We cannot use const for the parameters here
// cppcheck-suppress [constParameterPointer, constParameter]
static char *decrement(char *current, const char *abs_start, char *abs_end,
const unsigned int item_size)
{
char *val = current - item_size;
if (val < abs_start)
val = abs_end - item_size;
return val;
}
Queue_t *queueCreate(unsigned int queue_length, unsigned int item_size)
{
if (queue_length == 0 || item_size == 0) {
// if one of the values is zero, creating a queue
// makes no sense
abort();
}
// allocate memory to store management data
Queue_t *queue = malloc(sizeof(Queue_t));
if (!queue)
return NULL;
// initialise the queue's semaphore
queue->semaphore = hal_semaphore_init_value(1);
queue->sem_pop = hal_semaphore_init_value(0);
queue->sem_push = hal_semaphore_init_value(queue_length);
queue->item_length = queue_length;
queue->item_size = item_size;
// allocate enough memory to store the actual items
queue->abs_start = malloc(queue->item_length * queue->item_size);
if (!queue->abs_start) {
free(queue);
return NULL;
}
queue->abs_end = queue->abs_start + (
queue->item_length * queue->item_size);
queue->current_start = queue->abs_start;
queue->current_end = queue->abs_start;
return queue;
}
void queueDelete(Queue_t *queue)
{
if (!queue)
return;
// get the semaphore
hal_semaphore_take_blocking(queue->semaphore);
// free the data memory
free(queue->abs_start);
hal_semaphore_delete(queue->sem_pop);
hal_semaphore_delete(queue->sem_push);
// destroy the semaphore
hal_semaphore_delete(queue->semaphore);
// free the memory resources for the management data
free(queue);
}
void queueReset(Queue_t *queue)
{
hal_semaphore_take_blocking(queue->semaphore);
// reset both current-pointers to the absolute start pointer
// old values will be simply overwritten when new items are stored
queue->current_start = queue->abs_start;
queue->current_end = queue->abs_start;
hal_semaphore_delete(queue->sem_pop);
hal_semaphore_delete(queue->sem_push);
queue->sem_pop = hal_semaphore_init_value(0);
queue->sem_push = hal_semaphore_init_value(queue->item_length);
hal_semaphore_release(queue->semaphore);
}
uint8_t queuePop(Queue_t *queue, void *targetBuffer, int64_t timeout)
{
if (hal_semaphore_try_take(queue->sem_pop, timeout) == UD3TN_FAIL)
return EXIT_FAILURE;
hal_semaphore_take_blocking(queue->semaphore);
if (queue->current_start >= queue->abs_end)
queue->current_start = queue->abs_start;
memcpy(targetBuffer, queue->current_start, queue->item_size);
queue->current_start = increment(
queue->current_start, queue->abs_start,
queue->abs_end, queue->item_size);
hal_semaphore_release(queue->sem_push);
hal_semaphore_release(queue->semaphore);
return EXIT_SUCCESS;
}
uint8_t queuePush(Queue_t *queue, const void *item, int64_t timeout, bool force)
{
// forcefully replace the last element of the queue
if (force) {
hal_semaphore_take_blocking(queue->semaphore);
if (hal_semaphore_is_blocked(queue->sem_push)) {
memcpy(
decrement(
queue->current_end, queue->abs_start,
queue->abs_end, queue->item_size
),
item, queue->item_size
);
}
hal_semaphore_release(queue->semaphore);
return EXIT_SUCCESS;
}
if (hal_semaphore_try_take(queue->sem_push, timeout) == UD3TN_FAIL)
return EXIT_FAILURE;
hal_semaphore_take_blocking(queue->semaphore);
if (queue->current_end >= queue->abs_end)
queue->current_end = queue->abs_start;
memcpy(queue->current_end, item, queue->item_size);
queue->current_end = increment(
queue->current_end, queue->abs_start,
queue->abs_end, queue->item_size);
hal_semaphore_release(queue->sem_pop);
hal_semaphore_release(queue->semaphore);
return EXIT_SUCCESS;
}