diff options
-rw-r--r-- | src/patree.c | 3 | ||||
-rw-r--r-- | src/ring.c | 15 | ||||
-rw-r--r-- | test/ring_test.c | 96 | ||||
-rwxr-xr-x | waf | bin | 86496 -> 91079 bytes | |||
-rw-r--r-- | wscript | 38 | ||||
-rw-r--r-- | zix/ring.h | 2 |
6 files changed, 126 insertions, 28 deletions
diff --git a/src/patree.c b/src/patree.c index b8fd183..0cb74d3 100644 --- a/src/patree.c +++ b/src/patree.c @@ -289,7 +289,6 @@ change_index_c(const char* a, const char* b, size_t len) static inline int change_index_sse(const char* a, const char* b, const size_t len) { - int ret; for (size_t i = 0; i < len; i += sizeof(__m128i)) { const __m128i r = _mm_loadu_si128((const __m128i*)(a + i)); const __m128i* s = (const __m128i*)(b + i); @@ -297,7 +296,7 @@ change_index_sse(const char* a, const char* b, const size_t len) r, *s, _SIDD_SBYTE_OPS|_SIDD_CMP_EQUAL_EACH|_SIDD_NEGATIVE_POLARITY); if (index != sizeof(__m128i)) { - int ret = i + index; + size_t ret = i + index; if (ret > len) { ret = len; } @@ -14,7 +14,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <assert.h> #include <stdint.h> #include <stdlib.h> #include <string.h> @@ -70,8 +69,6 @@ zix_ring_new(uint32_t size) ring->size = next_power_of_two(size); ring->size_mask = ring->size - 1; ring->buf = malloc(ring->size); - assert(zix_ring_read_space(ring) == 0); - assert(zix_ring_write_space(ring) == ring->size - 1); return ring; } @@ -103,7 +100,7 @@ zix_ring_reset(ZixRing* ring) static inline uint32_t read_space_internal(const ZixRing* ring, uint32_t r, uint32_t w) { - if (w > r) { + if (r < w) { return w - r; } else { return (w - r + ring->size) & ring->size_mask; @@ -119,12 +116,12 @@ zix_ring_read_space(const ZixRing* ring) static inline uint32_t write_space_internal(const ZixRing* ring, uint32_t r, uint32_t w) { - if (w > r) { + if (r == w) { + return ring->size - 1; + } else if (r < w) { return ((r - w + ring->size) & ring->size_mask) - 1; - } else if (w < r) { - return (r - w) - 1; } else { - return ring->size - 1; + return (r - w) - 1; } } @@ -212,8 +209,6 @@ zix_ring_write(ZixRing* ring, const void* src, uint32_t size) ring->write_head = (w + size) & ring->size_mask; } else { const uint32_t this_size = ring->size - w; - assert(this_size < size); - assert(w + this_size <= ring->size); memcpy(&ring->buf[w], src, this_size); memcpy(&ring->buf[0], (char*)src + this_size, size - this_size); ZIX_WRITE_BARRIER(); diff --git a/test/ring_test.c b/test/ring_test.c index 7cde650..658f6af 100644 --- a/test/ring_test.c +++ b/test/ring_test.c @@ -16,6 +16,7 @@ #include <limits.h> #include <pthread.h> +#include <stdarg.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -30,6 +31,17 @@ size_t n_writes = 0; bool read_error = false; static int +failure(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + fprintf(stderr, "error: "); + vfprintf(stderr, fmt, args); + va_end(args); + return 1; +} + +static int gen_msg(int* msg, int start) { for (int i = 0; i < MSG_SIZE; ++i) { @@ -120,26 +132,100 @@ main(int argc, char** argv) n_writes, MSG_SIZE, size); ring = zix_ring_new(size); + if (zix_ring_read_space(ring) != 0) { + return failure("New ring is not empty\n"); + } + if (zix_ring_write_space(ring) != zix_ring_capacity(ring)) { + return failure("New ring write space != capacity\n"); + } + + zix_ring_mlock(ring); pthread_t reader_thread; if (pthread_create(&reader_thread, NULL, reader, NULL)) { - fprintf(stderr, "Failed to create reader thread\n"); - return 1; + return failure("Failed to create reader thread\n"); } pthread_t writer_thread; if (pthread_create(&writer_thread, NULL, writer, NULL)) { - fprintf(stderr, "Failed to create writer thread\n"); - return 1; + return failure("Failed to create writer thread\n"); } pthread_join(reader_thread, NULL); pthread_join(writer_thread, NULL); if (read_error) { - fprintf(stderr, "FAIL: Read error\n"); + return failure("Read error\n"); + } + + zix_ring_reset(ring); + if (zix_ring_read_space(ring) > 0) { + fprintf(stderr, "Reset did not empty ring.\n"); return 1; } + if (zix_ring_write_space(ring) != zix_ring_capacity(ring)) { + fprintf(stderr, "Empty write space != capacity\n"); + return 1; + } + + zix_ring_write(ring, "a", 1); + zix_ring_write(ring, "b", 1); + + char buf; + uint32_t n = zix_ring_peek(ring, &buf, 1); + if (n != 1) { + return failure("Peek n (%d) != 1\n", n); + } + if (buf != 'a') { + return failure("Peek error: '%c' != 'a'\n", buf); + } + + n = zix_ring_skip(ring, 1); + if (n != 1) { + return failure("Skip n (%d) != 1\n", n); + } + + if (zix_ring_read_space(ring) != 1) { + return failure("Read space %d != 1\n", zix_ring_read_space(ring)); + } + + n = zix_ring_read(ring, &buf, 1); + if (n != 1) { + return failure("Peek n (%d) != 1\n", n); + } + if (buf != 'b') { + return failure("Peek error: '%c' != 'b'\n", buf); + } + + if (zix_ring_read_space(ring) != 0) { + return failure("Read space %d != 0\n", zix_ring_read_space(ring)); + } + + n = zix_ring_peek(ring, &buf, 1); + if (n > 0) { + return failure("Successful underrun peak\n"); + } + + n = zix_ring_read(ring, &buf, 1); + if (n > 0) { + return failure("Successful underrun read\n"); + } + + n = zix_ring_skip(ring, 1); + if (n > 0) { + return failure("Successful underrun read\n"); + } + + char* big_buf = calloc(size, 1); + n = zix_ring_write(ring, big_buf, size - 1); + if (n != (uint32_t)size - 1) { + return failure("Maximum size write failed (wrote %u)\n", n); + } + + n = zix_ring_write(ring, big_buf, size); + if (n != 0) { + return failure("Successful overrun write (size %u)\n", n); + } zix_ring_free(ring); return 0; Binary files differ@@ -9,7 +9,8 @@ from waflib.extras import autowaf as autowaf import waflib.Logs as Logs, waflib.Options as Options # Version of this package (even if built as a child) -ZIX_VERSION = '0.0.2' +ZIX_VERSION = '0.0.2' +ZIX_MAJOR_VERSION = '0' # Library version (UNIX style major, minor, micro) # major increment <=> incompatible changes @@ -41,14 +42,21 @@ def configure(conf): conf.load('compiler_c') conf.env.append_value('CFLAGS', '-std=c99') + conf.env['BUILD_BENCH'] = Options.options.build_bench + conf.env['BUILD_TESTS'] = Options.options.build_tests + # Check for mlock conf.check(function_name='mlock', header_name='sys/mman.h', define_name='HAVE_MLOCK', mandatory=False) - conf.env['BUILD_BENCH'] = Options.options.build_bench - conf.env['BUILD_TESTS'] = Options.options.build_tests + # Check for gcov library (for test coverage) + if conf.env['BUILD_TESTS']: + conf.check_cc(lib='gcov', + define_name='HAVE_GCOV', + mandatory=False) + if Options.options.build_bench: autowaf.check_pkg(conf, 'glib-2.0', uselib_store='GLIB', atleast_version='2.0.0', mandatory=False) @@ -77,7 +85,8 @@ def build(bld): bld.install_files('${INCLUDEDIR}/zix', bld.path.ant_glob('zix/*.h')) # Pkgconfig file - autowaf.build_pc(bld, 'ZIX', ZIX_VERSION, []) + autowaf.build_pc(bld, 'ZIX', ZIX_VERSION, ZIX_MAJOR_VERSION, [], + {'ZIX_MAJOR_VERSION' : ZIX_MAJOR_VERSION}) framework = '' if Options.platform == 'darwin': @@ -108,27 +117,34 @@ def build(bld): '-DZIX_INTERNAL' ]) if bld.env['BUILD_TESTS']: + test_libs = ['pthread'] + test_cflags = [] + if bld.is_defined('HAVE_GCOV'): + test_libs += ['gcov'] + test_cflags += ['-fprofile-arcs', '-ftest-coverage'] + # Static library (for unit test code coverage) obj = bld(features = 'c cstlib', source = lib_source, includes = ['.', './src'], - name = 'libzix_static', - target = 'zix_static', + lib = test_libs, + name = 'libzix_profiled', + target = 'zix_profiled', install_path = '', framework = framework, - cflags = ['-fprofile-arcs', '-ftest-coverage']) + cflags = test_cflags + ['-DZIX_INTERNAL']) # Unit test programs for i in tests: obj = bld(features = 'c cprogram', source = 'test/%s.c' % i, includes = ['.'], - use = 'libzix_static', - linkflags = ['-lgcov', '-lpthread'], + use = 'libzix_profiled', + lib = test_libs, target = 'test/%s' % i, install_path = '', framework = framework, - cflags = ['-fprofile-arcs', '-ftest-coverage' ]) + cflags = test_cflags) if bld.env['BUILD_BENCH']: # Benchmark programs @@ -138,7 +154,7 @@ def build(bld): includes = ['.'], use = 'libzix', uselib = 'GLIB', - linkflags = '-lrt', + lib = ['rt'], target = 'test/%s' % i, framework = framework, install_path = '') @@ -32,6 +32,8 @@ typedef struct ZixRingImpl ZixRing; /** Create a new ring. @param size Size in bytes (note this may be rounded up). + + At most @c size - 1 bytes may be stored in the ring at once. */ ZixRing* zix_ring_new(uint32_t size); |