pipewire/spa/tests/stress-ringbuffer.c
Wim Taymans 351fb9ce29 pod: improve parser and builder
Remove the spa_pod_iter helpers
Remove builder/parser vararg recurse option, you have to
manually recurse into structures when needed. This simplifies
things a lot.
Pass spa_pod_frames to builder and parser explicitly, we don't
have to keep an internal stack anymore.
The parser is now almost a mirror image of the builder.
Make the parser safer when iterating over objects, add functions
to check and get pod contents in a safe way.
Make the builder return errno style results on errors
Improve performance of object properties when they are stored and
retrieved in the same order.
Add many more tests for the builder and parser
Add some benchmarks
2019-01-22 17:38:23 +01:00

140 lines
2.8 KiB
C

#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <sched.h>
#include <errno.h>
#include <semaphore.h>
#include <spa/utils/ringbuffer.h>
#define DEFAULT_SIZE 0x2000
#define ARRAY_SIZE 63
#define MAX_VALUE 0x10000
static struct spa_ringbuffer rb;
static uint32_t size;
static void *data;
static sem_t sem;
static int fill_int_array(int *array, int start, int count)
{
int i, j = start;
for (i = 0; i < count; i++) {
array[i] = j;
j = (j + 1) % MAX_VALUE;
}
return j;
}
static int cmp_array(int *array1, int *array2, int count)
{
int i;
for (i = 0; i < count; i++)
if (array1[i] != array2[i]) {
printf("%d != %d at offset %d\n", array1[i], array2[i], i);
return 0;
}
return 1;
}
static void *reader_start(void *arg)
{
int i = 0, a[ARRAY_SIZE], b[ARRAY_SIZE];
printf("reader started on cpu: %d\n", sched_getcpu());
i = fill_int_array(a, i, ARRAY_SIZE);
while (1) {
uint32_t index;
int32_t avail;
avail = spa_ringbuffer_get_read_index(&rb, &index);
if (avail >= (int32_t)(sizeof(b))) {
spa_ringbuffer_read_data(&rb, data, size, index % size, b, sizeof(b));
spa_ringbuffer_read_update(&rb, index + sizeof(b));
if (index >= INT32_MAX - sizeof(a))
break;
spa_assert(cmp_array(a, b, ARRAY_SIZE));
i = fill_int_array(a, i, ARRAY_SIZE);
}
}
sem_post(&sem);
return NULL;
}
static void *writer_start(void *arg)
{
int i = 0, a[ARRAY_SIZE];
printf("writer started on cpu: %d\n", sched_getcpu());
i = fill_int_array(a, i, ARRAY_SIZE);
while (1) {
uint32_t index;
int32_t avail;
avail = size - spa_ringbuffer_get_write_index(&rb, &index);
if (avail >= (int32_t)(sizeof(a))) {
spa_ringbuffer_write_data(&rb, data, size, index % size, a, sizeof(a));
spa_ringbuffer_write_update(&rb, index + sizeof(a));
if (index >= INT32_MAX - sizeof(a))
break;
i = fill_int_array(a, i, ARRAY_SIZE);
}
}
sem_post(&sem);
return NULL;
}
#define exit_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
pthread_t reader_thread, writer_thread;
struct timespec ts;
int s;
printf("starting ringbuffer stress test\n");
if (argc > 1)
sscanf(argv[1], "%d", &size);
else
size = DEFAULT_SIZE;
printf("buffer size (bytes): %d\n", size);
printf("array size (bytes): %ld\n", sizeof(int) * ARRAY_SIZE);
spa_ringbuffer_init(&rb);
data = malloc(size);
if (sem_init(&sem, 0, 0) != 0)
exit_error("init_sem");
pthread_create(&reader_thread, NULL, reader_start, NULL);
pthread_create(&writer_thread, NULL, writer_start, NULL);
if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
exit_error("clock_gettime");
ts.tv_sec += 2;
while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
continue;
while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
continue;
printf("read %u, written %u\n", rb.readindex, rb.writeindex);
return 0;
}