diff --git a/spa/tests/meson.build b/spa/tests/meson.build index bed9485ce..3d86ea65a 100644 --- a/spa/tests/meson.build +++ b/spa/tests/meson.build @@ -8,6 +8,11 @@ executable('test-ringbuffer', 'test-ringbuffer.c', dependencies : [dl_lib, pthread_lib], link_with : spalib, install : false) +executable('stress-ringbuffer', 'stress-ringbuffer.c', + include_directories : [spa_inc, spa_libinc ], + dependencies : [dl_lib, pthread_lib], + link_with : spalib, + install : false) executable('test-v4l2', 'test-v4l2.c', include_directories : [spa_inc, spa_libinc ], dependencies : [dl_lib, sdl_dep, pthread_lib], diff --git a/spa/tests/stress-ringbuffer.c b/spa/tests/stress-ringbuffer.c new file mode 100644 index 000000000..f7e69f583 --- /dev/null +++ b/spa/tests/stress-ringbuffer.c @@ -0,0 +1,122 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +#include + +#define ARRAY_SIZE 64 +#define MAX_VALUE 0x10000 + +SpaRingbuffer rb; +uint8_t *data; + +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]; + unsigned long j = 0, nfailures = 0; + + printf("reader started on cpu: %d\n", sched_getcpu()); + + i = fill_int_array (a, i, ARRAY_SIZE); + + while (1) + { + uint32_t index; + + if (spa_ringbuffer_get_read_index (&rb, &index) >= ARRAY_SIZE * sizeof (int)) + { + spa_ringbuffer_read_data (&rb, data, index & rb.mask, b, ARRAY_SIZE * sizeof (int)); + + if (!cmp_array (a, b, ARRAY_SIZE)) + { + nfailures++; + printf("failure in chunk %lu - probability: %lu/%lu = %.3f per million\n", + j, nfailures, j, (float) nfailures / (j + 1) * 1000000); + i = (b[0] + ARRAY_SIZE) % MAX_VALUE; + } + i = fill_int_array (a, i, ARRAY_SIZE); + j++; + + spa_ringbuffer_read_update (&rb, index + ARRAY_SIZE * sizeof (int)); + } + } + + 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; + + if (spa_ringbuffer_get_write_index (&rb, &index) >= ARRAY_SIZE * sizeof (int)) + { + spa_ringbuffer_write_data (&rb, data, index & rb.mask, a, ARRAY_SIZE * sizeof (int)); + spa_ringbuffer_write_update (&rb, index + ARRAY_SIZE * sizeof (int)); + + i = fill_int_array (a, i, ARRAY_SIZE); + } + } + + return NULL; +} + +int main(int argc, char *argv[]) +{ + int size; + + printf("starting ringbuffer stress test\n"); + + sscanf(argv[1], "%d", &size); + + printf("buffer size (bytes): %d\n", size); + printf("array size (bytes): %ld\n", sizeof(int) * ARRAY_SIZE); + + spa_ringbuffer_init (&rb, size); + data = malloc (size); + + pthread_t reader_thread, writer_thread; + pthread_create (&reader_thread, NULL, reader_start, NULL); + pthread_create (&writer_thread, NULL, writer_start, NULL); + + while (1) + sleep(1); + + return 0; +}