aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
l---------COPYING1
-rw-r--r--INSTALL25
-rw-r--r--LICENSE31
-rw-r--r--Makefile45
-rw-r--r--rb.c462
-rw-r--r--rb.h174
-rw-r--r--readme.md120
-rw-r--r--version.h6
9 files changed, 865 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..e8d3abd
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Michał Łyszczek <michal.lyszczek@bofc.pl>
diff --git a/COPYING b/COPYING
new file mode 120000
index 0000000..7a694c9
--- /dev/null
+++ b/COPYING
@@ -0,0 +1 @@
+LICENSE \ No newline at end of file
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..aba2bfa
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,25 @@
+Requirements:
+
+ * libc (glibc, uclibc)
+ * pthread
+
+Install locally:
+
+make && make install
+
+Cross Compile:
+
+To compile for different architecture 3 env variables should be set
+
+CC - cross compiler
+INC - staging include directory
+LINC - staging library directory
+
+Example make might look like this
+
+$ CC=arm-none-eabi \
+ INC=-I/usr/arm-none-eabi/usr/include \
+ LINC=-L/usr/arm-none-eabi/usr/lib \
+ make
+
+$ INSTALL_DIR=/usr/arm-none-eabi/usr make install
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d638e18
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+/*****************************************************************************
+ * Copyright (C) 2016 Michał Łyszczek. All rights reserved.
+ * Author: Michał Łyszczek <michal.lyszczek@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NAME nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ ****************************************************************************/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..cbdfb57
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,45 @@
+LIBS = -lpthread
+SRCS = rb.c
+MAIN = librb
+
+STD = -std=c89
+WARN = -Wall -Wextra -pedantic -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wwrite-strings -Winit-self -Wcast-align -Wstrict-aliasing -Wformat=2 -Wmissing-include-dirs -Wno-unused-parameter -Wuninitialized -Wstrict-overflow=5 -pedantic-errors
+CFLAGS = $(STD) $(WARN) -fPIC
+LDFLAGS = -shared
+
+VERSION = `grep "define VERSION" version.h | cut -d \" -f2`
+VERSION_MAJOR = `grep "define VERSION" version.h | cut -d \" -f2 | cut -d. -f1`
+CC ?= x86_64-pc-linux-gnu-gcc
+INSTALL_DIR ?= /usr/local
+INC ?=
+LINC ?=
+
+OBJS = $(SRCS:.c=.o)
+
+.PHONY: depend clean debug release
+
+all: release
+
+release: WARN += -Werror
+release: CFLAGS += -O2
+release: $(MAIN)
+
+debug: CFLAGS += -O0 -ggdb -g3
+debug: $(MAIN)
+
+install:
+ mkdir -p $(INSTALL_DIR)/include
+ mkdir -p $(INSTALL_DIR)/lib
+ cp rb.h $(INSTALL_DIR)/include
+ cp $(MAIN).so.$(VERSION) $(INSTALL_DIR)/lib
+ ln -sf $(MAIN).so.$(VERSION) $(INSTALL_DIR)/lib/$(MAIN).so.$(VERSION_MAJOR)
+ ln -sf $(MAIN).so.$(VERSION) $(INSTALL_DIR)/lib/$(MAIN).so
+
+clean:
+ $(RM) *.o *~ $(MAIN).so.$(VERSION)
+
+$(MAIN): $(OBJS)
+ $(CC) $(CFLAGS) $(LIBS) $(LINC) $(LDFLAGS) -o $(MAIN).so.$(VERSION) $(OBJS)
+
+.c.o:
+ $(CC) $(CFLAGS) $(INC) -c $< -o $@
diff --git a/rb.c b/rb.c
new file mode 100644
index 0000000..831e547
--- /dev/null
+++ b/rb.c
@@ -0,0 +1,462 @@
+/*****************************************************************************
+ * Licensed under BSD 3-clause license. See LICENSE file for more information.
+ * Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "rb.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "version.h"
+
+/*****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Name: rb_count
+ *
+ * Description:
+ * Calculates number of elements in ring buffer
+ ****************************************************************************/
+
+static size_t rb_count(const struct rb *rb)
+{
+ return (rb->head - rb->tail) & (rb->count - 1);
+}
+
+/*****************************************************************************
+ * Name: rb_space
+ *
+ * Description:
+ * Calculates how many elements can be pushed into ring buffer
+ ****************************************************************************/
+
+static size_t rb_space(const struct rb *rb)
+{
+ return (rb->tail - (rb->head + 1)) & (rb->count -1 );
+}
+
+/*****************************************************************************
+ * Name: rb_count_end
+ *
+ * Description:
+ * Calculates number of elements in ring buffer until the end of buffer
+ * memory. If elements don't overlap memory, function acts like rb_count
+ ****************************************************************************/
+
+static size_t rb_count_end(const struct rb *rb)
+{
+ size_t end = rb->count - rb->tail;
+ size_t n = (rb->head + end) & (rb->count - 1);
+ return n < end ? n : end;
+}
+
+/*****************************************************************************
+ * Name: rb_space_end
+ *
+ * Description:
+ * Calculates how many elements can be pushed into ring buffer without
+ * overlapping memory
+ ****************************************************************************/
+
+static size_t rb_space_end(const struct rb *rb)
+{
+ size_t end = rb->count - 1 - rb->head;
+ size_t n = (end + rb->tail) & (rb->count - 1);
+ return n <= end ? n : end + 1;
+}
+
+/*****************************************************************************
+ * Name: rb_is_power_of_two
+ *
+ * Description:
+ * Checks if number x is exactly power of two number (ie. 1, 2, 4, 8, 16)
+ *
+ * Input Parameters:
+ * x: number to check
+ *
+ * Return Values:
+ * 0: x is NOT a power of two number
+ * 1: x is a power of two number
+ ****************************************************************************/
+
+static int rb_is_power_of_two(size_t x)
+{
+ return ((x != 0) && ((x & (~x + 1)) == x));
+}
+
+/*****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Name: rb_new
+ *
+ * Description:
+ * Initializes ring buffer and alocates necessary resources
+ *
+ * Input Parameters:
+ * rb: ring buffer structure where data will be stored
+ * count: number of elements (not bytes!) that buffer can hold. It MUST be a
+ * value that is a power of two (ie 16, 32 or 4096)
+ * object_size: size, in bytes, of the objects that will be put into buffer
+ * Once declared cannot be changed, and data must always be of this size,
+ * or undefinied behaviours will occur.
+ * non_blocking: if set to 1, function will not block when resources are not
+ * available. Otherwise thread will go to sleep until resoures are
+ * available again (just like any blocking socket)
+ *
+ * Return Values:
+ * 0: success
+ * -1: failure
+ *
+ * errno:
+ * EINVAL: rb is null or count is not a power of two number
+ *
+ * Function can also return errno values from:
+ * * malloc
+ * * pthread_mutex_init
+ * * pthread_cond_init
+ * Check proper man pages for details *
+ ****************************************************************************/
+
+int rb_new(struct rb *rb, size_t count, size_t object_size, int non_blocking)
+{
+ int errnos;
+
+ if (rb == NULL || rb_is_power_of_two(count) == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((rb->buffer = malloc(count * object_size)) == NULL)
+ {
+ errnos = errno;
+ goto error;
+ }
+
+ rb->head = 0;
+ rb->tail = 0;
+ rb->count = count;
+ rb->object_size = object_size;
+ rb->force_exit = 0;
+ rb->non_blocking = non_blocking;
+
+ if (pthread_mutex_init(&rb->lock, NULL))
+ {
+ errnos = errno;
+ goto error;
+ }
+
+ if (pthread_cond_init(&rb->wait_data, NULL))
+ {
+ errnos = errno;
+ goto error;
+ }
+
+ if (pthread_cond_init(&rb->wait_room, NULL))
+ {
+ errnos = errno;
+ goto error;
+ }
+
+ return 0;
+
+error:
+ pthread_mutex_destroy(&rb->lock);
+ pthread_cond_destroy(&rb->wait_data);
+ pthread_cond_destroy(&rb->wait_room);
+
+ free(rb->buffer);
+ rb->buffer = NULL;
+
+ errno = errnos;
+ return -1;
+}
+
+/*****************************************************************************
+ * Name: rb_read
+ *
+ * Description:
+ * Reads count data from rb into buffer. Function will block until count
+ * elements are stored into buffer, unless blocking flag is set to 1. When
+ * rb is exhausted and there is still data to read, caller thread will be
+ * put to sleep and will be waked up as soon as there is data in rb. count
+ * can be any size, it can be much bigger than rb size, just keep in mind if
+ * count is too big, time waiting for data might be significant.
+ *
+ * When blocking flag is set to 1, and there is less data in rb than count
+ * expects, function will copy as many elements as it can (actually it
+ * will copy all of data that is in rb) and will return with number of
+ * elements stored in buffer.
+ *
+ * Input Parameters:
+ * rb: ring buffer object to work on
+ * buffer: place where you want data to be copied to
+ * count: number fo elements (not bytes) you want to be copied
+ *
+ * Return Values:
+ * count: all requested data were read into buffer
+ * <count: only part of requested count elements were copied into buffer
+ * -1: this value is returned when buffer object is being destroyed
+ *
+ * errno:
+ * EAGAIN: in case of return value <count
+ ****************************************************************************/
+
+ssize_t rb_read(struct rb *rb, void *buffer, size_t count)
+{
+ size_t read;
+ uint8_t *buf;
+
+ if (rb == NULL || buffer == NULL || rb->buffer == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ read = 0;
+ buf = (uint8_t *)buffer;
+
+ while (count)
+ {
+ size_t count_to_end;
+ size_t count_to_read;
+ size_t bytes_to_read;
+
+ pthread_mutex_lock(&rb->lock);
+
+ while (rb_count(rb) == 0 && rb->force_exit == 0)
+ {
+ if (rb->non_blocking == 1)
+ {
+ pthread_mutex_unlock(&rb->lock);
+ errno = EAGAIN;
+ return read;
+ }
+
+ /* Buffer is empty, wait for data */
+
+ pthread_cond_wait(&rb->wait_data, &rb->lock);
+ }
+
+ if (rb->force_exit == 1)
+ {
+ /* ring buffer is going down operations on buffer are not allowed */
+
+ pthread_mutex_unlock(&rb->lock);
+ return -1;
+ }
+
+ /* Elements in memory can overlap, so we need to calculate how much
+ * elements we can safely read */
+
+ count_to_end = rb_count_end(rb);
+ count_to_read = count > count_to_end ? count_to_end : count;
+ bytes_to_read = count_to_read * rb->object_size;
+
+ memcpy(buf, rb->buffer + rb->tail * rb->object_size, bytes_to_read);
+
+ /* Adjust pointers and counts for the next read */
+
+ buf += bytes_to_read;
+ rb->tail += count_to_read;
+ rb->tail &= rb->count - 1;
+ read += count_to_read;
+ count -= count_to_read;
+
+ /* Signal any threads that waits for space to put data in buffer */
+
+ pthread_cond_signal(&rb->wait_room);
+ pthread_mutex_unlock(&rb->lock);
+ }
+
+ return read;
+}
+
+/*****************************************************************************
+ * Name: rb_write
+ *
+ * Description:
+ * Writes count data pointed by buffer in to rb. Function will block until
+ * count elements are stored into rb, unless blocking flag is set to 1. When
+ * rb is full and there is still data to write, caller thread will be put to
+ * sleep and will be waked up as soon as there is space in rb. count can be
+ * any size, it can be much bigger than rb size, just keep in mind if count
+ * is too big, time waiting for space might be significant.
+ *
+ * When blocking flag is set to 1, and there is less space in rb than count
+ * expects, function will copy as many elements as it can and will return
+ * with number of elements written to rb.
+ *
+ * Input Parameters:
+ * rb: ring buffer object to work on
+ * buffer: location from where data are stored into rb
+ * count: number of elements caller desires to store into rb
+ *
+ * Return Values:
+ * count: all requested data were written into rb
+ * <count: only part of requested count elements were copied into rb
+ * -1: this value is returned when buffer object is being destroyed
+ *
+ * errno:
+ * EAGAIN: in case of return value <count
+ ****************************************************************************/
+
+ssize_t rb_write(struct rb *rb, const void *buffer, size_t count)
+{
+ size_t written;
+ const uint8_t *buf;
+
+ if (rb == NULL || buffer == NULL || rb->buffer == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ written = 0;
+ buf = (const uint8_t *)buffer;
+
+ while (count)
+ {
+ size_t count_to_end;
+ size_t count_to_write;
+ size_t bytes_to_write;
+
+ pthread_mutex_lock(&rb->lock);
+
+ while (rb_space(rb) == 0 && rb->force_exit == 0)
+ {
+ if (rb->non_blocking == 1)
+ {
+ pthread_mutex_unlock(&rb->lock);
+ errno = EAGAIN;
+ return written;
+ }
+
+ /* Buffer is full, wait for someone to read data and free space */
+
+ pthread_cond_wait(&rb->wait_room, &rb->lock);
+ }
+
+ if (rb->force_exit == 1)
+ {
+ /* ring buffer is going down operations on buffer are not allowed */
+
+ pthread_mutex_unlock(&rb->lock);
+ return -1;
+ }
+
+ /* Count might be too large to store it in one burst, we calculate how
+ * many elements can we store before needing to overlap memory */
+
+ count_to_end = rb_space_end(rb);
+ count_to_write = count > count_to_end ? count_to_end : count;
+ bytes_to_write = count_to_write * rb->object_size;
+
+ memcpy(rb->buffer + rb->head * rb->object_size, buf, bytes_to_write);
+
+ /* Adjust pointers and counts for next write */
+
+ buf += bytes_to_write;
+ rb->head += count_to_write;
+ rb->head &= rb->count - 1;
+ written += count_to_write;
+ count -= count_to_write;
+
+ /* Signal any threads that waits for data to read */
+
+ pthread_cond_signal(&rb->wait_data);
+ pthread_mutex_unlock(&rb->lock);
+ }
+
+ return written;
+}
+
+/*****************************************************************************
+ * Name: rb_destroy
+ *
+ * Description:
+ * Frees resources allocated by rb_new. Also it stops any blocked rb_read or
+ * rb_write functions so they can return. When rb_read and rb_write work in
+ * another threads and you want to join them after stopping rb, you should
+ * call this function before joining threads. If you do it otherwise,
+ * threads calling rb_write or rb_read can be in locked state, waiting for
+ * resources, and threads might never return to call this function. You have
+ * been warned
+ *
+ * Input Parameters:
+ * rb: ring buffer object to destroy
+ ****************************************************************************/
+
+void rb_destroy(struct rb *rb)
+{
+ if (rb == NULL)
+ {
+ errno = EINVAL;
+ return;
+ }
+
+ rb->force_exit = 1;
+
+ /* Signal locked threads in conditional variables to return, so callers can
+ * exit */
+
+ pthread_cond_signal(&rb->wait_data);
+ pthread_cond_signal(&rb->wait_room);
+
+ /* To prevent any pending operations on buffer, we lock before freeing
+ * memory, so there is no crash on buffer destroy */
+
+ pthread_mutex_lock(&rb->lock);
+ free(rb->buffer);
+ rb->buffer = NULL;
+ pthread_mutex_unlock(&rb->lock);
+
+ pthread_mutex_destroy(&rb->lock);
+ pthread_cond_destroy(&rb->wait_data);
+ pthread_cond_destroy(&rb->wait_room);
+}
+
+/*****************************************************************************
+ * Name: rb_version
+ *
+ * Description:
+ * Returns version of the library
+ *
+ * Output Parameters:
+ * major: Major version (API/ABI changes)
+ * minor: Minor version (Added functions)
+ * patch: Patch version (bug fixes)
+ *
+ * Function also returns pointer to static allocated pointer to char where
+ * full version string is stored
+ ****************************************************************************/
+
+const char *rb_version(char *major, char *minor, char *patch)
+{
+ if (major && minor && patch)
+ {
+ /* strtok modified input string, so we need copy of version */
+
+ char version[11 + 1];
+ strcpy(version, VERSION);
+
+ strcpy(major, strtok(version, "."));
+ strcpy(minor, strtok(NULL, "."));
+ strcpy(patch, strtok(NULL, "."));
+ }
+
+ return VERSION;
+}
diff --git a/rb.h b/rb.h
new file mode 100644
index 0000000..515d826
--- /dev/null
+++ b/rb.h
@@ -0,0 +1,174 @@
+/*****************************************************************************
+ * Licensed under BSD 3-clause license. See LICENSE file for more information.
+ * Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ****************************************************************************/
+
+#ifndef LIBRB_H
+#define LIBRB_H 1
+
+/*****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <pthread.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+/*****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct rb
+{
+ size_t head;
+ size_t tail;
+ size_t count;
+ size_t object_size;
+
+ uint8_t *buffer;
+
+ pthread_mutex_t lock;
+ pthread_cond_t wait_data;
+ pthread_cond_t wait_room;
+
+ uint8_t force_exit;
+ uint8_t non_blocking;
+};
+
+/*****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Name: rb_new
+ *
+ * Description:
+ * Initializes ring buffer and alocates necessary resources
+ *
+ * Input Parameters:
+ * rb: ring buffer structure where data will be stored
+ * count: number of elements (not bytes!) that buffer can hold. It MUST be a
+ * value that is a power of two (ie 16, 32 or 4096)
+ * object_size: size, in bytes, of the objects that will be put into buffer
+ * Once declared cannot be changed, and data must always be of this size,
+ * or undefinied behaviours will occur.
+ * non_blocking: if set to 1, function will not block when resources are not
+ * available. Otherwise thread will go to sleep until resoures are
+ * available again (just like any blocking socket)
+ *
+ * Return Values:
+ * 0: success
+ * -1: failure
+ *
+ * errno:
+ * EINVAL: rb is null or count is not a power of two number
+ *
+ * Function can also return errno values from:
+ * * malloc
+ * * pthread_mutex_init
+ * * pthread_cond_init
+ * Check proper man pages for details *
+ ****************************************************************************/
+
+int rb_new(struct rb *rb, size_t count, size_t object_size, int non_blocking);
+
+/*****************************************************************************
+ * Name: rb_read
+ *
+ * Description:
+ * Reads count data from rb into buffer. Function will block until count
+ * elements are stored into buffer, unless blocking flag is set to 1. When
+ * rb is exhausted and there is still data to read, caller thread will be
+ * put to sleep and will be waked up as soon as there is data in rb. count
+ * can be any size, it can be much bigger than rb size, just keep in mind if
+ * count is too big, time waiting for data might be significant.
+ *
+ * When blocking flag is set to 1, and there is less data in rb than count
+ * expects, function will copy as many elements as it can (actually it
+ * will copy all of data that is in rb) and will return with number of
+ * elements stored in buffer.
+ *
+ * Input Parameters:
+ * rb: ring buffer object to work on
+ * buffer: place where you want data to be copied to
+ * count: number fo elements (not bytes) you want to be copied
+ *
+ * Return Values:
+ * count: all requested data were read into buffer
+ * <count: only part of requested count elements were copied into buffer
+ * -1: this value is returned when buffer object is being destroyed
+ *
+ * errno:
+ * EAGAIN: in case of return value <count
+ ****************************************************************************/
+
+ssize_t rb_read(struct rb *rb, void *buffer, size_t count);
+
+/*****************************************************************************
+ * Name: rb_write
+ *
+ * Description:
+ * Writes count data pointed by buffer in to rb. Function will block until
+ * count elements are stored into rb, unless blocking flag is set to 1. When
+ * rb is full and there is still data to write, caller thread will be put to
+ * sleep and will be waked up as soon as there is space in rb. count can be
+ * any size, it can be much bigger than rb size, just keep in mind if count
+ * is too big, time waiting for space might be significant.
+ *
+ * When blocking flag is set to 1, and there is less space in rb than count
+ * expects, function will copy as many elements as it can and will return
+ * with number of elements written to rb.
+ *
+ * Input Parameters:
+ * rb: ring buffer object to work on
+ * buffer: location from where data are stored into rb
+ * count: number of elements caller desires to store into rb
+ *
+ * Return Values:
+ * count: all requested data were written into rb
+ * <count: only part of requested count elements were copied into rb
+ * -1: this value is returned when buffer object is being destroyed
+ *
+ * errno:
+ * EAGAIN: in case of return value <count
+ ****************************************************************************/
+
+ssize_t rb_write(struct rb *rb, const void *buffer, size_t count);
+
+/*****************************************************************************
+ * Name: rb_destroy
+ *
+ * Description:
+ * Frees resources allocated by rb_new. Also it stops any blocked rb_read or
+ * rb_write functions so they can return. When rb_read and rb_write work in
+ * another threads and you want to join them after stopping rb, you should
+ * call this function before joining threads. If you do it otherwise,
+ * threads calling rb_write or rb_read can be in locked state, waiting for
+ * resources, and threads might never return to call this function. You have
+ * been warned
+ *
+ * Input Parameters:
+ * rb: ring buffer object to destroy
+ ****************************************************************************/
+
+void rb_destroy(struct rb *rb);
+
+/*****************************************************************************
+ * Name: rb_version
+ *
+ * Description:
+ * Returns version of the library
+ *
+ * Output Parameters:
+ * major: Major version (API/ABI changes)
+ * minor: Minor version (Added functions)
+ * patch: Patch version (bug fixes)
+ *
+ * Function also returns pointer to static allocated pointer to char where
+ * full version string is stored
+ ****************************************************************************/
+
+const char *rb_version(char *major, char *minor, char *patch);
+
+#endif /* LIBRB_H */
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..b61dcaf
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,120 @@
+About
+=====
+
+This is library that provides fast, easy to use ring buffer. It's interface is
+very similar to read/write interface from POSIX. Library has only 4 functions:
+
+ * rb_new - creates new ring buffer
+ * rb_read - reads from the ring buffer
+ * rb_write - writes to the ring buffer
+ * rb_destroy - destroys ring buffer
+
+Library is thread safe and thread aware. If there are not resources available
+while reading or writting, caller thread gets locked and doesn't use any
+resources until data is available. Ring buffer can also be configured to work
+in non-blocking mode, so calls from read and write will return immediately
+when there are not enough resources. There is only one malloc and free in new
+and destory functions.
+
+As this library is focused on speed, user can create buffer with only power of
+two count (n^2). Thanks to this solution there is much less conditional jumps.
+Altough user is limited to number of elements, single element can be any size.
+Thanks to that, ring buffer can also be easily used with structs as an item.
+
+Library is C89 complaint and will work under any POSIX environment that
+implements pthreads and libc.
+
+License
+=======
+
+Library is licensed under BSD 3-clause license. See LICENSE file for details
+
+Compiling and installing
+========================
+
+Standard **make** and **make install** should be enough. If you want to
+install to different directory, just use **INSTALL_DIR=/custom/path make
+install**.
+
+To compile for different architecture 3 env variables should be set
+
+ * CC - cross compiler
+ * INC - staging include directory
+ * LINC - staging library directory
+
+Example make might look like this
+
+~~~.sh
+$ CC=arm-none-eabi \
+ INC=-I/usr/arm-none-eabi/usr/include \
+ LINC=-L/usr/arm-none-eabi/usr/lib \
+ make
+$ INSTALL_DIR=/usr/arm-none-eabi/usr make install
+~~~
+
+Function descriptions
+=====================
+
+rb_new
+------
+
+~~~.c
+int rb_new(struct rb *rb, size_t count, size_t object_size, int non_blocking);
+~~~
+
+This function is used to create and initialize new ring buffer. Information
+about created ring buffer is stored into memory pointed by rb. User is
+responsible to create this structure in his application. This object will be
+later used to identify ring buffer.
+
+count and object_size describes buffer sizes. Library will allocate on callers
+heap (count * object_size) bytes. Count must be a power of two number, as
+library tries to avoid unecessary conditional jump to improve performance.
+Object size determines how big is a single element. This value is constant for
+lifetime of a ring buffer. Object size might be for example
+**sizeof(uint8_t)** or **sizeof(uint32_t)** or even **sizeof(struct my_msg)**.
+In short, object size should be a size of an object ring buffer will hold. You
+should not write nor read objects of different size than created one, as this
+will lead to undefinied behaviour or even crashes.
+
+non_blocking defines whether **rb_read** and **rb_write** function should
+block or not when there is not enough resources available.
+
+rb_write and rb_read
+--------------------
+
+~~~.c
+ssize_t rb_write(struct rb *rb, const void *buffer, size_t count);
+ssize_t rb_read(struct rb *rb, void *buffer, size_t count);
+~~~
+
+Functions used read and write elements to the ring buffer. Function will
+commit (count * rb->object_size) bytes. Functions can and will try to commit
+as many bytes as possible in a single burst, so it is better to call these
+function once with big count number than call it in a loop with count == 1.
+
+When non_blocking flag is not set, every read and write will block until it
+commits every element passed to the function. When read or write function
+blocks, caller thread is put to sleep to it doesn't use any processor time,
+until it is waked by opossite write or read call. Ie. when ring buffer is
+full, and user calls **rb_write**, thread will sleep until another thread
+calls **rb_read** and makes space for writing operation. When non_blocking
+flag is set, and resources are not available, read or write will return
+immediately with number of elements commited and EAGAIN errno. Just like with
+sockets.
+
+rb_destroy
+----------
+
+~~~.c
+void rb_destroy(struct rb *rb);
+~~~
+
+Function frees resources allocated by **rb_new**. Also it forces **rb_write**
+and **rb_read** return even in blocking mode, so users thread using them can
+be joined.
+
+Contact
+=======
+
+Michał Łyszczek <michal.lyszczek@bofc.pl>
diff --git a/version.h b/version.h
new file mode 100644
index 0000000..7d35986
--- /dev/null
+++ b/version.h
@@ -0,0 +1,6 @@
+#ifndef LIBRB_VERSION_H
+#define LIBRB_VERSION_H 1
+
+#define VERSION "1.0.0"
+
+#endif /* LIBRB_VERSION_H */