Release candidate
This commit is contained in:
parent
c8cae5055a
commit
d6e467c7c4
52
Makefile
Normal file
52
Makefile
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
# ******************************************************************************
|
||||||
|
#
|
||||||
|
# @file Makefile
|
||||||
|
#
|
||||||
|
# @brief Makefile for Duplex Queue library
|
||||||
|
#
|
||||||
|
# @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
|
||||||
|
#
|
||||||
|
# @date Mar 2024
|
||||||
|
# @author Barrett Edwards <code@jrlabs.io>
|
||||||
|
#
|
||||||
|
# ******************************************************************************
|
||||||
|
|
||||||
|
CC=gcc
|
||||||
|
CFLAGS= -g3 -O0 -Wall -Wextra
|
||||||
|
MACROS=
|
||||||
|
INCLUDE_DIR=/usr/local/include
|
||||||
|
LIB_DIR=/usr/local/lib
|
||||||
|
INCLUDE_PATH=-I $(INCLUDE_DIR)
|
||||||
|
LIB_PATH=-L $(LIB_DIR)
|
||||||
|
LIBS=-l ptrqueue
|
||||||
|
TARGET=duplexqueue
|
||||||
|
|
||||||
|
all: testbench lib$(TARGET).a
|
||||||
|
|
||||||
|
testbench: testbench.c main.o
|
||||||
|
$(CC) $^ $(CFLAGS) $(MACROS) $(INCLUDE_PATH) $(LIB_PATH) $(LIBS) -o $@
|
||||||
|
|
||||||
|
lib$(TARGET).a: main.o
|
||||||
|
ar rcs $@ $^
|
||||||
|
|
||||||
|
main.o: main.c main.h
|
||||||
|
$(CC) -c $< $(CFLAGS) $(MACROS) $(INCLUDE_PATH) -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf ./*.o ./*.a testbench
|
||||||
|
|
||||||
|
doc:
|
||||||
|
doxygen
|
||||||
|
|
||||||
|
install: lib$(TARGET).a
|
||||||
|
sudo cp lib$(TARGET).a $(LIB_DIR)/
|
||||||
|
sudo cp main.h $(INCLUDE_DIR)/$(TARGET).h
|
||||||
|
|
||||||
|
.PHONY: all clean doc install
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
# $^ Will expand to be all the sensitivity list
|
||||||
|
# $< Will expand to be the frist file in sensitivity list
|
||||||
|
# $@ Will expand to be the target name (the left side of the ":" )
|
||||||
|
# -c gcc will compile but not try and link
|
||||||
142
main.c
Normal file
142
main.c
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0 */
|
||||||
|
/**
|
||||||
|
* @file duplexqueue.c
|
||||||
|
*
|
||||||
|
* @brief Code file for Duplex Queue library
|
||||||
|
*
|
||||||
|
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* @date Feb 2024
|
||||||
|
* @author Barrett Edwards <code@jrlabs.io>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ==================================================================*/
|
||||||
|
|
||||||
|
/* free()
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* printf()
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* errno
|
||||||
|
*/
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* memset()
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* __u32
|
||||||
|
* __s32
|
||||||
|
*/
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include <ptrqueue.h>
|
||||||
|
|
||||||
|
#include "duplexqueue.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* MACROS ====================================================================*/
|
||||||
|
|
||||||
|
/* ENUMERATIONS ==============================================================*/
|
||||||
|
|
||||||
|
/* STRUCTS ===================================================================*/
|
||||||
|
|
||||||
|
/* GLOBAL VARIABLES ==========================================================*/
|
||||||
|
|
||||||
|
/* PROTOTYPES ================================================================*/
|
||||||
|
|
||||||
|
/* FUNCTIONS =================================================================*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Relese allocated memory
|
||||||
|
*
|
||||||
|
* Return 0 upon success, 1 otherwise and set errno
|
||||||
|
*/
|
||||||
|
int dq_free(struct duplex_queue *dq)
|
||||||
|
{
|
||||||
|
/* STEPS
|
||||||
|
* 1: Validate inputs
|
||||||
|
* 2: Free data buffer
|
||||||
|
* 3: Free ring buffer pointer
|
||||||
|
*/
|
||||||
|
if (dq == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
pq_free(dq->tx);
|
||||||
|
pq_free(dq->rx);
|
||||||
|
free(dq->data);
|
||||||
|
free(dq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
end:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create and initialize a duplex queue
|
||||||
|
* Param:
|
||||||
|
* count : This is the number of buffer entries in each direction of the queue pair
|
||||||
|
*
|
||||||
|
* Returns a pointer to a struct duplex_queue upon success. Upon error, returns NULL and sets errno
|
||||||
|
*/
|
||||||
|
struct duplex_queue *dq_init(size_t count, size_t obj_size)
|
||||||
|
{
|
||||||
|
struct duplex_queue *dq;
|
||||||
|
|
||||||
|
/* STEPS
|
||||||
|
* 1. Validate inputs
|
||||||
|
* 2. Allocate memory for duplex_queue struct
|
||||||
|
* 3. Init the rx and tx ptr_queues
|
||||||
|
* 4. Allocate memory for data buffers
|
||||||
|
* 5: Add pointers into rx queue
|
||||||
|
*/
|
||||||
|
|
||||||
|
// STEP 1. Validate inputs
|
||||||
|
if ( (count == 0) || (obj_size == 0) ) {
|
||||||
|
errno = EINVAL;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 2. Allocate memory for duplex_queue struct
|
||||||
|
dq = (struct duplex_queue*) malloc (sizeof(struct duplex_queue));
|
||||||
|
if (dq == 0) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
memset(dq, 0, sizeof(struct duplex_queue));
|
||||||
|
|
||||||
|
dq->count = count;
|
||||||
|
dq->obj_size = obj_size;
|
||||||
|
|
||||||
|
// STEP 3. Init the rx and tx ptr_queues
|
||||||
|
dq->rx = pq_init(count, 0);
|
||||||
|
dq->tx = pq_init(count, 0);
|
||||||
|
|
||||||
|
// STEP 4. Allocate memory for data buffer
|
||||||
|
dq->data = (__u8*) malloc (count * obj_size);
|
||||||
|
if (dq->data == 0) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
goto end_free;;
|
||||||
|
}
|
||||||
|
memset(dq->data, 0, count * obj_size);
|
||||||
|
|
||||||
|
// STEP 5: Add pointers into rx queue
|
||||||
|
for ( size_t i = 0 ; i < count ; i++ )
|
||||||
|
pq_push(dq->rx, &dq->data[i*obj_size]);
|
||||||
|
|
||||||
|
return dq;
|
||||||
|
|
||||||
|
end_free:
|
||||||
|
dq_free(dq);
|
||||||
|
|
||||||
|
end:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
47
main.h
Normal file
47
main.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0 */
|
||||||
|
/**
|
||||||
|
* @file duplexqueue.h
|
||||||
|
*
|
||||||
|
* @brief Header file for Duplex Queue library
|
||||||
|
*
|
||||||
|
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* @date Feb 2024
|
||||||
|
* @author Barrett Edwards <code@jrlabs.io>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DUPLEXQUEUE_H
|
||||||
|
#define _DUPLEXQUEUE_H
|
||||||
|
|
||||||
|
/* INCLUDES ==================================================================*/
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include <ptrqueue.h>
|
||||||
|
|
||||||
|
/* MACROS ====================================================================*/
|
||||||
|
|
||||||
|
/* ENUMERATIONS ==============================================================*/
|
||||||
|
|
||||||
|
/* STRUCTS ===================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opaque data structure
|
||||||
|
*/
|
||||||
|
struct duplex_queue {
|
||||||
|
struct ptr_queue *tx;
|
||||||
|
struct ptr_queue *rx;
|
||||||
|
__u8 *data;
|
||||||
|
size_t count;
|
||||||
|
size_t obj_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* GLOBAL VARIABLES ==========================================================*/
|
||||||
|
|
||||||
|
/* PROTOTYPES ================================================================*/
|
||||||
|
|
||||||
|
int dq_free(struct duplex_queue *pq);
|
||||||
|
struct duplex_queue *dq_init(size_t count, size_t obj_size);
|
||||||
|
|
||||||
|
#endif /* ifndef _DUPLEXQUEUE_H */
|
||||||
119
testbench.c
Normal file
119
testbench.c
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0 */
|
||||||
|
/**
|
||||||
|
* @file textbench.c
|
||||||
|
*
|
||||||
|
* @brief Testbench code file for Duplex Queue library
|
||||||
|
*
|
||||||
|
* @copyright Copyright (C) 2024 Jackrabbit Founders LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* @date Feb 2024
|
||||||
|
* @author Barrett Edwards <code@jrlabs.io>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ==================================================================*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include <ptrqueue.h>
|
||||||
|
|
||||||
|
#include "duplexqueue.h"
|
||||||
|
|
||||||
|
/* MACROS ====================================================================*/
|
||||||
|
|
||||||
|
#define QUEUE_CAPACITY 10
|
||||||
|
#define ITERATIONS 10000
|
||||||
|
|
||||||
|
/* ENUMERATIONS ==============================================================*/
|
||||||
|
|
||||||
|
/* STRUCTS ===================================================================*/
|
||||||
|
|
||||||
|
/* GLOBAL VARIABLES ==========================================================*/
|
||||||
|
|
||||||
|
/* PROTOTYPES ================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
void *consumer(void *arg)
|
||||||
|
{
|
||||||
|
struct duplex_queue *dq;
|
||||||
|
void *ptr;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
dq = (struct duplex_queue*) arg;
|
||||||
|
|
||||||
|
printf("%s started \n", __FUNCTION__);
|
||||||
|
|
||||||
|
for ( __u64 i = 0 ; i < ITERATIONS ; i++ ) {
|
||||||
|
ptr = pq_pop(dq->tx, 1);
|
||||||
|
rv = pq_push(dq->rx, ptr);
|
||||||
|
printf("%s pushed on to rx queue val:%p rv:%d\n", __FUNCTION__, ptr, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *producer(void *arg)
|
||||||
|
{
|
||||||
|
struct duplex_queue *dq;
|
||||||
|
int rv;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
dq = (struct duplex_queue*) arg;
|
||||||
|
|
||||||
|
printf("%s started \n", __FUNCTION__);
|
||||||
|
|
||||||
|
for ( __u64 i = 0 ; i < ITERATIONS ; i++ ) {
|
||||||
|
ptr = pq_pop(dq->rx, 1);
|
||||||
|
rv = pq_push(dq->tx, ptr);
|
||||||
|
printf("%s pushed on to tx queue val:%p rv:%d\n", __FUNCTION__, ptr, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void threads(struct duplex_queue *dq)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
pthread_t producer_thread;
|
||||||
|
pthread_t consumer_thread;
|
||||||
|
|
||||||
|
rv = pthread_create( &consumer_thread, NULL, consumer, (void*) dq );
|
||||||
|
if (rv != 0) {
|
||||||
|
printf("Error creating producer thread\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
rv = pthread_create( &producer_thread, NULL, producer, (void*) dq );
|
||||||
|
if (rv != 0) {
|
||||||
|
printf("Error creating producer thread\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
printf("%s Waiting for threads to exit\n", __FUNCTION__);
|
||||||
|
pthread_join( producer_thread, NULL);
|
||||||
|
printf("%s joined with producer thread\n", __FUNCTION__);
|
||||||
|
pthread_join( consumer_thread, NULL);
|
||||||
|
printf("%s joined with consumer thread\n", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct duplex_queue *dq;
|
||||||
|
|
||||||
|
dq = dq_init(QUEUE_CAPACITY, 4);
|
||||||
|
|
||||||
|
threads(dq);
|
||||||
|
|
||||||
|
dq_free(dq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user