[FIX] Ksyms: Fix warnings
[kernel/swap-modules.git] / buffer / buffer_queue.c
index 7869f10..8744b21 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  SWAP Buffer Module
- *  modules/buffer/swap_buffer_module.c
+ *  modules/buffer/buffer_queue.c
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,7 +18,7 @@
  *
  * Copyright (C) Samsung Electronics, 2013
  *
- * 2013         Alexander Aksenov <a.aksenov@samsung.com>: SWAP Buffer implement
+ * 2013         Alexander Aksenov <a.aksenov@samsung.com>: SWAP Buffer implement
  *
  */
 
@@ -27,7 +27,7 @@
 /* For all memory allocation/deallocation operations, except buffer memory
  * allocation/deallocation should be used 
  *  memory_allocation(size_t memory_size)
- *  memory_free(voidptr)
+ *  memory_free(void *ptr)
  * defines.
  * For subbuffer allocation/deallocation operations should be used
  *  buffer_allocation(size_t subbuffer_size)
 
 
 #include "buffer_queue.h"
-#include "buffer_description.h"
 #include "swap_buffer_to_buffer_queue.h"
-#include "space_dep_operations.h"
-
-typedef struct swap_buffer* write_start_ptr_type;
-typedef struct swap_buffer* write_end_ptr_type;
-typedef struct swap_buffer* read_start_ptr_type;
-typedef struct swap_buffer* read_end_ptr_type;
-
-static write_start_ptr_type queue_write_start_ptr = NULL;   //Points to the
-                                                            //write queue first
-                                                            //element
-static write_end_ptr_type queue_write_end_ptr = NULL;       //Points to the
-                                                            //write queue last
-                                                            //element
-static read_start_ptr_type queue_read_start_ptr = NULL;     //Points to the read
-                                                            //queue first 
-                                                            //element
-static read_end_ptr_type queue_read_end_ptr = NULL;         //Points to the read
-                                                            //queue last element
-static struct swap_buffer** queue_busy = NULL;          //Pointers array. Points
-                                                        //to occupied buffers
-static unsigned int queue_busy_last_element;            //Store last occupied
-                                                        //element in queue_busy
-static unsigned int queue_subbuffer_count = 0;          //Subbuffers count
-static size_t queue_subbuffer_size = 0;                 //Subbuffers size
-static buffer_access_sync_type buffer_read_sync;        //add_to_read_list and
-                                                        //get_from_read_list 
-                                                        //sync
-static buffer_access_sync_type buffer_write_sync;       //add_to_write_list and
-                                                        //get_from_write_list
-                                                        //sync
-static buffer_access_sync_type buffer_busy_sync;        //add_to_busy_list and
-                                                        //remove_from_busy_list
-                                                        //sync
-static int pages_order_in_subbuffer = 0;                //Page count in one
-                                                        //subbuffer
-
-
-int buffer_queue_allocation(const size_t subbuffer_size,
-                            const unsigned int subbuffers_count)
+#include "swap_buffer_errors.h"
+#include "kernel_operations.h"
+
+/* Queue structure. Consist of pointers to the first and the last elements of
+ * queue. */
+struct queue_t {
+       struct swap_subbuffer *start_ptr;
+       struct swap_subbuffer *end_ptr;
+       unsigned int subbuffers_count;
+       struct sync_t queue_sync;
+};
+
+/* Write queue */
+struct queue_t write_queue = {
+       .start_ptr = NULL,
+       .end_ptr = NULL,
+       .subbuffers_count = 0,
+       .queue_sync = {
+               .flags = 0x0
+       }
+};
+
+/* Read queue */
+struct queue_t read_queue = {
+       .start_ptr = NULL,
+       .end_ptr = NULL,
+       .subbuffers_count = 0,
+       .queue_sync = {
+               .flags = 0x0
+       }
+};
+
+/* Pointers array. Points to busy buffers */
+static struct swap_subbuffer **queue_busy = NULL;
+
+/* Store last busy element */
+static unsigned int queue_busy_last_element;
+
+/* Subbuffers count */
+static unsigned int queue_subbuffer_count = 0;
+
+/* One subbuffer size */
+static size_t queue_subbuffer_size = 0;
+
+/* Busy list sync */
+static struct sync_t buffer_busy_sync = {
+       .flags = 0x0
+};
+
+/* Memory pages count in one subbuffer */
+static int pages_order_in_subbuffer = 0;
+
+
+int buffer_queue_allocation(size_t subbuffer_size,
+                           unsigned int subbuffers_count)
 {
-    int result = 0;
-    int i;
-
-    /*  0 - ok
-     * -1 - memory for queue_busy wasn't allocated
-     * -2 - memory for swap_buffer structure wasn't allocated
-     * -3 - memory for buffer wasn't allocated
-     * -4 - semaphore cannot be inited
-     * -5 - sync primitives cannot be inited
-     */
-
-    /* Static varibles initialization */
-    queue_subbuffer_size = subbuffer_size;
-    queue_subbuffer_count = subbuffers_count;
-    queue_busy_last_element = 0;
-
-    /* Set variable pages_in_subbuffer. It is used for allocation and
-     * deallocation memory pages and its value is returned from
-     * swap_buffer_get() and contains page count in one subbuffer.
-     * All this useful only in kernel space. In userspace it is dummy.*/
-    set_pages_order_in_subbuffer(queue_subbuffer_size);
-
-    /* Sync primitives initialization */
-    if (buffer_access_init(&buffer_read_sync)) {
-        result = -5;
-        return result;
-    }
-    if (buffer_access_init(&buffer_write_sync)) {
-        result = -5;
-        return result;
-    }
-    if (buffer_access_init(&buffer_busy_sync)) {
-        result = -5;
-        return result;
-    }
-
-    /* Memory allocation for queue_busy */
-    queue_busy = memory_allocation(sizeof(struct swap_buffer*) *
-                                   queue_subbuffer_count);
-
-    if (!queue_busy) {
-        result = -1;
-        return result;
-    }
-
-    /* Memory allocation for swap_buffer structures */
-    /* Allocation for first structure. */
-
-    queue_write_start_ptr = memory_allocation(sizeof(struct swap_buffer));
-
-    if (!queue_write_start_ptr) {
-        result = -2;
-        memory_free(queue_busy);
-        queue_busy = NULL;
-        return result;
-    }
-    queue_write_end_ptr = queue_write_start_ptr;
-
-    queue_write_end_ptr->next_in_queue = NULL;
-    queue_write_end_ptr->full_buffer_part = 0;
-    queue_write_end_ptr->buffer = buffer_allocation(queue_subbuffer_size);
-    if (!queue_write_end_ptr->buffer) {
-        print_err("Cannot allocate memory for buffer 1\n");
-        result = -3;
-        memory_free(queue_busy);
-        memory_free(queue_write_start_ptr);
-        queue_write_start_ptr = NULL;
-        queue_busy = NULL;
-
-        return result;
-    }
-
-    print_msg(" Buffer allocated = 0x%x\n", (unsigned long)queue_write_end_ptr->buffer);
-
-    if (buffer_rw_init(&queue_write_end_ptr->buffer_sync) != 0) {
-        result = -4;
-        memory_free(queue_busy);
-        queue_busy = NULL;
-        memory_free(queue_write_start_ptr);
-        queue_write_start_ptr = NULL;
-        return result;
-    }
-
-    /* Buffer initialization */
-    memset(buffer_address(queue_write_end_ptr->buffer), 0, queue_subbuffer_size);
-
-    /* Allocation for other structures. */
-    for (i = 1; i < queue_subbuffer_count; i++) {
-        queue_write_end_ptr->next_in_queue = memory_allocation(sizeof(struct swap_buffer));
-        if (!queue_write_end_ptr->next_in_queue) {
-        /* Free all previously allocated memory */
-            int j;
-            struct swap_buffer *clean_tmp_struct = queue_write_start_ptr;
-
-            result = -2;
-            for (j = 0; j < i; j++) {
-                clean_tmp_struct = queue_write_start_ptr;
-                if (queue_write_start_ptr != queue_write_end_ptr) {
-                    queue_write_start_ptr = queue_write_start_ptr->next_in_queue;
-                }
-                buffer_free(clean_tmp_struct->buffer,queue_subbuffer_size);
-                memory_free(clean_tmp_struct);
-            }
-            queue_write_end_ptr = NULL;
-            queue_write_start_ptr = NULL;
-            memory_free(queue_busy);
-            queue_busy = NULL;
-            return result;
-        }
-
-        /* Now next queue_write_end_ptr is next */
-        queue_write_end_ptr = queue_write_end_ptr->next_in_queue;
-
-        queue_write_end_ptr->next_in_queue = NULL;
-        queue_write_end_ptr->full_buffer_part = 0;
-        queue_write_end_ptr->buffer = buffer_allocation(queue_subbuffer_size);
-        if (!queue_write_end_ptr->buffer) {
-        /* Free all previously allocated memory */
-            int j;
-            struct swap_buffer *clean_tmp_struct = queue_write_start_ptr;
-
-            result = -3;
-            print_err("Cannot allocate memory for buffer %d\n", i+1);
-
-            for (j = 0; j < i; j++) {
-                clean_tmp_struct = queue_write_start_ptr;
-                if (queue_write_start_ptr != queue_write_end_ptr) {
-                    queue_write_start_ptr = queue_write_start_ptr->next_in_queue;
-                    buffer_free(clean_tmp_struct->buffer, queue_subbuffer_size);
-                }
-                memory_free(clean_tmp_struct);
-            }
-            queue_write_end_ptr = NULL;
-            queue_write_start_ptr = NULL;
-            memory_free(queue_busy);
-            queue_busy = NULL;
-            return result;
-        }
-
-        print_msg(" Buffer allocated = 0x%x, pages_order = %d\n", (unsigned long)queue_write_end_ptr->buffer, pages_order_in_subbuffer);
-
-        if (buffer_rw_init(&queue_write_end_ptr->buffer_sync) != 0) {
-        /* Free all previously allocated memory */
-            int j;
-            struct swap_buffer *clean_tmp_struct = queue_write_start_ptr;
-
-            result = -4;
-            for (j = 0; j < i; j++) {
-                clean_tmp_struct = queue_write_start_ptr;
-                if (queue_write_start_ptr != queue_write_end_ptr) {
-                    queue_write_start_ptr = queue_write_start_ptr->next_in_queue;
-                }
-                buffer_free(clean_tmp_struct->buffer, queue_subbuffer_size);
-                memory_free(clean_tmp_struct);
-            }
-            queue_write_end_ptr = NULL;
-            queue_write_start_ptr = NULL;
-            memory_free(queue_busy);
-            queue_busy = NULL;
-            return result;
-        }
-
-        /* Buffer initialization */
-        memset(buffer_address(queue_write_end_ptr->buffer), 0,
-               queue_subbuffer_size);
-    }
-
-    return result;
+       unsigned int i = 0;
+       unsigned int j = 0;
+       unsigned int allocated_buffers = 0;
+       unsigned int allocated_structs = 0;
+       struct swap_subbuffer *clean_tmp_struct;
+       int result;
+
+       /* Static varibles initialization */
+       queue_subbuffer_size = subbuffer_size;
+       queue_subbuffer_count = subbuffers_count;
+       queue_busy_last_element = 0;
+
+       /* Set variable pages_in_subbuffer. It is used for allocation and
+        * deallocation memory pages and its value is returned from
+        * swap_buffer_get() and contains page count in one subbuffer.
+        * All this useful only in kernel space. In userspace it is dummy.*/
+       set_pages_order_in_subbuffer(queue_subbuffer_size);
+       /* Sync primitives initialization */
+       sync_init(&read_queue.queue_sync);
+       sync_init(&write_queue.queue_sync);
+       sync_init(&buffer_busy_sync);
+
+       /* Memory allocation for queue_busy */
+       queue_busy = memory_allocation(sizeof(*queue_busy) * queue_subbuffer_count);
+
+       if (!queue_busy) {
+               result = -E_SB_NO_MEM_QUEUE_BUSY;
+               goto buffer_allocation_error_ret;
+       }
+
+       /* Memory allocation for swap_subbuffer structures */
+
+       /* Allocation for first structure. */
+       write_queue.start_ptr = memory_allocation(sizeof(*write_queue.start_ptr));
+
+       if (!write_queue.start_ptr) {
+               result = -E_SB_NO_MEM_BUFFER_STRUCT;
+               goto buffer_allocation_queue_busy_free;
+       }
+       allocated_structs++;
+
+
+       write_queue.end_ptr = write_queue.start_ptr;
+
+       write_queue.end_ptr->next_in_queue = NULL;
+       write_queue.end_ptr->full_buffer_part = 0;
+       write_queue.end_ptr->data_buffer = buffer_allocation(queue_subbuffer_size);
+       if (!write_queue.end_ptr->data_buffer) {
+               print_err("Cannot allocate memory for buffer 1\n");
+               result = -E_SB_NO_MEM_DATA_BUFFER;
+               goto buffer_allocation_error_free;
+       }
+       allocated_buffers++;
+
+       sync_init(&write_queue.end_ptr->buffer_sync);
+
+       /* Buffer initialization */
+       memset(buffer_address(write_queue.end_ptr->data_buffer), 0, queue_subbuffer_size);
+
+       /* Allocation for other structures. */
+       for (i = 1; i < queue_subbuffer_count; i++) {
+               write_queue.end_ptr->next_in_queue =
+                   memory_allocation(sizeof(*write_queue.end_ptr->next_in_queue));
+               if (!write_queue.end_ptr->next_in_queue) {
+                       result = -E_SB_NO_MEM_BUFFER_STRUCT;
+                       goto buffer_allocation_error_free;
+               }
+               allocated_structs++;
+
+               /* Now next write_queue.end_ptr is next */
+               write_queue.end_ptr = write_queue.end_ptr->next_in_queue;
+
+               write_queue.end_ptr->next_in_queue = NULL;
+               write_queue.end_ptr->full_buffer_part = 0;
+               write_queue.end_ptr->data_buffer = 
+                       buffer_allocation(queue_subbuffer_size);
+               if (!write_queue.end_ptr->data_buffer) {
+                       result = -E_SB_NO_MEM_DATA_BUFFER;
+                       goto buffer_allocation_error_free;
+               }
+               allocated_buffers++;
+
+               sync_init(&write_queue.end_ptr->buffer_sync);
+
+               /* Buffer initialization */
+               memset(buffer_address(write_queue.end_ptr->data_buffer), 0,
+                      queue_subbuffer_size);
+       }
+
+       /* All subbuffers are in write list */
+       write_queue.subbuffers_count = subbuffers_count;
+
+       return E_SB_SUCCESS;
+
+       /* In case of errors, this code is called */
+       /* Free all previously allocated memory */
+buffer_allocation_error_free:
+       clean_tmp_struct = write_queue.start_ptr;
+
+       for (j = 0; j < allocated_structs; j++) {
+               clean_tmp_struct = write_queue.start_ptr;
+               if (allocated_buffers) {
+                       buffer_free(clean_tmp_struct->data_buffer, queue_subbuffer_size);
+                       allocated_buffers--;
+               }
+               if (write_queue.start_ptr != write_queue.end_ptr)
+                       write_queue.start_ptr = write_queue.start_ptr->next_in_queue;
+               memory_free(clean_tmp_struct);
+       }
+       write_queue.end_ptr = NULL;
+       write_queue.start_ptr = NULL;
+
+buffer_allocation_queue_busy_free:
+       memory_free(queue_busy);
+       queue_busy = NULL;
+
+buffer_allocation_error_ret:
+       return result;
 }
 
-int buffer_queue_free(void)
+int buffer_queue_reset(void)
 {
-    int result = 0;
-    struct swap_buffer* tmp = NULL;
-
-    /*  0 - ok
-     * <0 - set_all_to_read_list() error
-     */
-
-    //TODO Lock read list semaphore to prevent getting subbuffer from read list 
-    /* Set all write buffers to read list */
-    result = set_all_to_read_list();
-
-    if (result < 0) {
-        return result;
-    }
-
-    /* Free buffers and structures memory that are in read list */
-    while (queue_read_start_ptr) {
-        tmp = queue_read_start_ptr;
-        queue_read_start_ptr = queue_read_start_ptr->next_in_queue;
-        buffer_free(tmp->buffer, queue_subbuffer_size);
-        memory_free(tmp);
-    }
-
-    /* Free busy_list */
-    memory_free(queue_busy);
-    queue_busy = NULL;
-
-    queue_subbuffer_size = 0;
-    queue_subbuffer_count = 0;
-    queue_read_start_ptr = NULL;
-    queue_read_end_ptr = NULL;
-    queue_write_start_ptr = NULL;
-    queue_write_end_ptr = NULL;
-
-    return result;
+       struct swap_subbuffer *buffer = read_queue.start_ptr;
+
+       /* Check if there are some subbuffers in busy list. If so - return error */
+       if (get_busy_buffers_count())
+               return -E_SB_UNRELEASED_BUFFERS;
+
+       /* Lock read sync primitive */
+       sync_lock(&read_queue.queue_sync);
+
+       /* Set all subbuffers in read list to write list and reinitialize them */
+       while (read_queue.start_ptr) {
+
+               /* Lock buffer sync primitive to prevent writing to buffer if it had
+                * been selected for writing, but still wasn't wrote. */
+               sync_lock(&buffer->buffer_sync);
+
+               buffer = read_queue.start_ptr;
+
+               /* If we reached end of the list */
+               if (read_queue.start_ptr == read_queue.end_ptr) {
+                       read_queue.end_ptr = NULL;
+               }
+               read_queue.start_ptr = read_queue.start_ptr->next_in_queue;
+
+               /* Reinit full buffer part */
+               buffer->full_buffer_part = 0;
+
+               add_to_write_list(buffer);
+
+               /* Unlock buffer sync primitive */
+               sync_unlock(&buffer->buffer_sync);
+       }
+
+       /* Unlock read primitive */
+       sync_unlock(&read_queue.queue_sync);
+
+       return E_SB_SUCCESS;
 }
 
-static unsigned int is_buffer_enough(struct swap_buffer* subbuffer, size_t size)
+void buffer_queue_free(void)
 {
-    return ((queue_subbuffer_size-subbuffer->full_buffer_part) >= size) ? 1 : 0;
+       struct swap_subbuffer *tmp = NULL;
+
+       /* Lock all sync primitives to prevet accessing free memory */
+       sync_lock(&write_queue.queue_sync);
+       sync_lock(&read_queue.queue_sync);
+       sync_lock(&buffer_busy_sync);
+
+       /* Free buffers and structures memory that are in read list */
+       while (read_queue.start_ptr) {
+               tmp = read_queue.start_ptr;
+               read_queue.start_ptr = read_queue.start_ptr->next_in_queue;
+               buffer_free(tmp->data_buffer, queue_subbuffer_size);
+               memory_free(tmp);
+       }
+
+       /* Free buffers and structures memory that are in read list */
+       while (write_queue.start_ptr) {
+               tmp = write_queue.start_ptr;
+               write_queue.start_ptr = write_queue.start_ptr->next_in_queue;
+               buffer_free(tmp->data_buffer, queue_subbuffer_size);
+               memory_free(tmp);
+       }
+
+       /* Free busy_list */
+       memory_free(queue_busy);
+       queue_busy = NULL;
+
+       queue_subbuffer_size = 0;
+       queue_subbuffer_count = 0;
+       read_queue.start_ptr = NULL;
+       read_queue.end_ptr = NULL;
+       write_queue.start_ptr = NULL;
+       write_queue.end_ptr = NULL;
+
+       /* Unlock all sync primitives */
+       sync_unlock(&buffer_busy_sync);
+       sync_unlock(&read_queue.queue_sync);
+       sync_unlock(&write_queue.queue_sync);
+}
+
+static unsigned int is_buffer_enough(struct swap_subbuffer *subbuffer,
+                                    size_t size)
+{
+       /* XXX Think about checking full_buffer_part for correctness 
+        * (<queue_subbuffer_size). It should be true, but if isn't (due to sources
+        * chaning, etc.) this function should be true! */
+       return ((queue_subbuffer_size-subbuffer->full_buffer_part) >= size) ? 1 : 0;
+}
+
+static void next_queue_element(struct queue_t *queue)
+{
+       /* If we reached the last elemenet, end pointer should point to NULL */
+       if (queue->start_ptr == queue->end_ptr)
+               queue->end_ptr = NULL;
+
+       queue->start_ptr = queue->start_ptr->next_in_queue;
+       --queue->subbuffers_count;
 }
 
 /* Get first subbuffer from read list */
-struct swap_buffer* get_from_read_list(void)
+struct swap_subbuffer *get_from_read_list(void)
 {
-    struct swap_buffer* result = NULL;
+       struct swap_subbuffer *result = NULL;
 
-    /* Lock read sync primitive */
-    if (buffer_access_lock(&buffer_read_sync)) {
-        return NULL;
-    }
+       /* Lock read sync primitive */
+       sync_lock(&read_queue.queue_sync);
 
-    if (queue_read_start_ptr == NULL) {
-        result = NULL;
-        goto get_from_read_list_unlock;
-    }
+       if (read_queue.start_ptr == NULL) {
+               result = NULL;
+               goto get_from_read_list_unlock;
+       }
 
-    result = queue_read_start_ptr;
+       result = read_queue.start_ptr;
 
-    /* If this is the last readable buffer, queue_read_start_ptr next time will 
-     * points to NULL and that case is handled in the beginning of function
-     */
-    if (queue_read_start_ptr == queue_read_end_ptr) {
-        queue_read_end_ptr = NULL;
-    }
-    queue_read_start_ptr = queue_read_start_ptr->next_in_queue;
+       next_queue_element(&read_queue);
 
 get_from_read_list_unlock:
-    /* Unlock read sync primitive */
-    if (buffer_access_unlock(&buffer_read_sync)) {
-        return NULL;
-    }
+       /* Unlock read sync primitive */
+       sync_unlock(&read_queue.queue_sync);
 
-    return result;
+       return result;
 }
 
 /* Add subbuffer to read list */
-int add_to_read_list(struct swap_buffer* subbuffer)
+void add_to_read_list(struct swap_subbuffer *subbuffer)
 {
-    int result = 0;
-
-    /* 0 - ok
-     * 1 - cannot lock
-     * 2 - cannot unlock */
-
-    /* Lock read sync primitive */
-    if (buffer_access_lock(&buffer_read_sync)) {
-        result = 1;
-        return result;
-    }
-
-    // TODO Sanitization?
-    if (!queue_read_start_ptr) {
-        queue_read_start_ptr = subbuffer;
-    }
-
-    if (queue_read_end_ptr) {
-        queue_read_end_ptr->next_in_queue = subbuffer;
-
-        queue_read_end_ptr = queue_read_end_ptr->next_in_queue;
-    } else {
-        queue_read_end_ptr = subbuffer;
-    }
-    queue_read_end_ptr->next_in_queue = NULL;
-
-    /* Unlock read sync primitive */
-    if (buffer_access_unlock(&buffer_read_sync)) {
-        result = 2;
-        return result;
-    }
-
-    return result;
+       /* Lock read sync primitive */
+       sync_lock(&read_queue.queue_sync);
+
+       if (!read_queue.start_ptr)
+               read_queue.start_ptr = subbuffer;
+
+       if (read_queue.end_ptr) {
+               read_queue.end_ptr->next_in_queue = subbuffer;
+
+               read_queue.end_ptr = read_queue.end_ptr->next_in_queue;
+       } else {
+               read_queue.end_ptr = subbuffer;
+       }
+       read_queue.end_ptr->next_in_queue = NULL;
+       ++read_queue.subbuffers_count;
+
+       /* Unlock read sync primitive */
+       sync_unlock(&read_queue.queue_sync);
 }
 
 /* Call add to read list and callback function from driver module */
-int add_to_read_list_with_callback(struct swap_buffer* subbuffer)
+int add_to_read_list_with_callback(struct swap_subbuffer *subbuffer)
 {
-    int result = 0;
+       int result = 0;
 
-    result = add_to_read_list(subbuffer);
-    // TODO Handle ret value
-    swap_buffer_callback(subbuffer);
+       add_to_read_list(subbuffer);
+       // TODO Handle ret value
+       result = swap_buffer_callback(subbuffer);
 
-    return result;
+       return result;
 }
 
-/* Get first writable subbuffer from write list */
-struct swap_buffer* get_from_write_list(size_t size)
+/* Returns subbuffers to read count */
+unsigned int get_readable_buf_cnt(void)
 {
-    struct swap_buffer *result = NULL;
-
-    /* Callbacks are called at the end of the function to prevent deadlocks */
-    struct swap_buffer *queue_callback_start_ptr = NULL;
-    struct swap_buffer *queue_callback_end_ptr = NULL;
-    struct swap_buffer *tmp_buffer = NULL;
-
-    /* Lock write list sync primitive */
-    if (buffer_access_lock(&buffer_write_sync)) {
-        return NULL;
-    }
-
-    while (queue_write_start_ptr) {
-        /* If start points to NULL => list is empty => exit */
-        if (!queue_write_start_ptr) {
-            result = NULL;
-            goto get_from_write_list_unlock;
-        }
-
-        /* Get semaphore value. Useful only if we want buffer to write to
-         * several buffers the same time
-         *
-         * We're trying to lock semaphore, and if it is successful, unlocking 
-         * it. Otherwise, going to the next step. */
-        if (buffer_rw_lock(&queue_write_start_ptr->buffer_sync) != 0) {
-            // TODO HOW? HOW is it possible to get there?!
-            result = queue_write_start_ptr;
-            /* If we reached end of the list */
-            if (queue_write_start_ptr == queue_write_end_ptr) {
-                queue_write_end_ptr = NULL;
-            }
-            /* Move start write pointer */
-            queue_write_start_ptr = queue_write_start_ptr->next_in_queue;
-
-            /* Add to callback list */
-            if (!queue_callback_start_ptr) {
-                queue_callback_start_ptr = result;
-            }
-            if (queue_callback_end_ptr) {
-                queue_callback_end_ptr->next_in_queue = result;
-            }
-            queue_callback_end_ptr = result;
-            queue_callback_end_ptr->next_in_queue = NULL;
-
-            result = NULL;
-            continue;
-        }
-        buffer_rw_unlock(&queue_write_start_ptr->buffer_sync);
-
-// TODO Do something
-
-        if (is_buffer_enough(queue_write_start_ptr, size)) {
-            result = queue_write_start_ptr;
-            break;
-        } else {
-            /* If size is not enough, subbuffers goes to read list */
-            result = queue_write_start_ptr;
-            /* If we reached end of the list */
-            if (queue_write_start_ptr == queue_write_end_ptr) {
-                queue_write_end_ptr = NULL;
-            }
-            /* Move start write pointer */
-            queue_write_start_ptr = queue_write_start_ptr->next_in_queue;
-
-            /* Add to callback list */
-            if (!queue_callback_start_ptr) {
-                queue_callback_start_ptr = result;
-            }
-            if (queue_callback_end_ptr) {
-                queue_callback_end_ptr->next_in_queue = result;
-            }
-            queue_callback_end_ptr = result;
-            queue_callback_end_ptr->next_in_queue = NULL;
-
-            result = NULL;
-        }
-    }
-
-    /* Lock writing semaphore */
-    if (result) {
-        if (buffer_rw_lock(&result->buffer_sync)) {
-            result = NULL;
-            goto get_from_write_list_unlock;
-        }
-    }
-
-get_from_write_list_unlock:
-    /* Unlock write list sync primitive */
-    if (buffer_access_unlock(&buffer_write_sync)) {
-        if (result) {
-            buffer_rw_unlock(&result->buffer_sync);
-        }
-        return NULL;
-    }
-
-    /* Adding buffers to read list and calling callbacks */
-    for (tmp_buffer = NULL; queue_callback_start_ptr; ) {
-
-        if (queue_callback_start_ptr == queue_callback_end_ptr) {
-            queue_callback_end_ptr = NULL;
-        }
-        tmp_buffer = queue_callback_start_ptr;
-        queue_callback_start_ptr = queue_callback_start_ptr->next_in_queue;
-
-        add_to_read_list_with_callback(tmp_buffer);
-    }
-
-    return result;
+       return read_queue.subbuffers_count;
 }
 
-/* Add subbuffer to write list */
-int add_to_write_list(struct swap_buffer* subbuffer)
+
+/* Get first writable subbuffer from write list */
+struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write)
 {
-    /*  0 - ok
-     * -1 - cannot lock
-     * -2 - cannot unlock */
-
-    if (buffer_access_lock(&buffer_write_sync)) {
-        return -1;
-    }
-
-    /* Reinitialize */
-    memset(buffer_address(subbuffer->buffer), 0, queue_subbuffer_size);
-    subbuffer->full_buffer_part = 0;
-
-    if (!queue_write_start_ptr) {
-        queue_write_start_ptr = subbuffer;
-    }
-
-    if (queue_write_end_ptr) {
-        queue_write_end_ptr->next_in_queue = subbuffer;
-        queue_write_end_ptr = queue_write_end_ptr->next_in_queue;
-    } else {
-        queue_write_end_ptr = subbuffer;
-    }
-    queue_write_end_ptr->next_in_queue = NULL;
-
-    if (buffer_access_unlock(&buffer_write_sync)) {
-        return -2;
-    }
-
-    return 0;
+       struct swap_subbuffer *result = NULL;
+
+       /* Callbacks are called at the end of the function to prevent deadlocks */
+       struct queue_t callback_queue = {
+               .start_ptr = NULL,
+               .end_ptr = NULL,
+               .queue_sync = {
+                       .flags = 0x0
+               }
+       };
+       struct swap_subbuffer *tmp_buffer = NULL;
+
+       /* Init pointer */
+       *ptr_to_write = NULL;
+
+       /* Lock write list sync primitive */
+       sync_lock(&write_queue.queue_sync);
+
+       while (write_queue.start_ptr) {
+
+               /* We're found subbuffer */
+               if (is_buffer_enough(write_queue.start_ptr, size)) {
+
+                       result = write_queue.start_ptr;
+                       *ptr_to_write = (void *)((unsigned long)
+                                                (buffer_address(result->data_buffer)) +
+                                                result->full_buffer_part);
+
+                       /* Add data size to full_buffer_part. Very important to do it in
+                        * write_queue.queue_sync spinlock */
+                       write_queue.start_ptr->full_buffer_part += size;
+
+                       /* Lock rw sync. Should be unlocked in swap_buffer_write() */
+                       sync_lock(&result->buffer_sync);
+                       break;
+               /* This subbuffer is not enough => it goes to read list */
+               } else {
+                       result = write_queue.start_ptr;
+
+                       next_queue_element(&write_queue);
+
+                       /* Add to callback list */
+                       if (!callback_queue.start_ptr)
+                               callback_queue.start_ptr = result;
+
+                       if (callback_queue.end_ptr)
+                               callback_queue.end_ptr->next_in_queue = result;
+                       callback_queue.end_ptr = result;
+                       callback_queue.end_ptr->next_in_queue = NULL;
+                       result = NULL;
+               }
+       }
+
+       /* Unlock write list sync primitive */
+       sync_unlock(&write_queue.queue_sync);
+
+       /* Adding buffers to read list and calling callbacks */
+       for (tmp_buffer = NULL; callback_queue.start_ptr; ) {
+               if (callback_queue.start_ptr == callback_queue.end_ptr)
+                       callback_queue.end_ptr = NULL;
+
+               tmp_buffer = callback_queue.start_ptr;
+               callback_queue.start_ptr = callback_queue.start_ptr->next_in_queue;
+
+               add_to_read_list_with_callback(tmp_buffer);
+       }
+
+       return result;
 }
 
-/* Add subbuffer to busy list when it is read from out of the buffer */
-int add_to_busy_list(struct swap_buffer* subbuffer)
+/* Add subbuffer to write list */
+void add_to_write_list(struct swap_subbuffer *subbuffer)
 {
-    /*  0 - ok
-     * -1 - cannot lock
-     * -2 - cannot unlock */
+       sync_lock(&write_queue.queue_sync);
 
-    /* Lock busy sync primitive */
-    if (buffer_access_lock(&buffer_busy_sync)) {
-        return -1;
-    }
+       /* Reinitialize */
+       subbuffer->full_buffer_part = 0;
 
-    subbuffer->next_in_queue = NULL;
-    queue_busy[queue_busy_last_element] = subbuffer;
-    queue_busy_last_element += 1;
+       if (!write_queue.start_ptr)
+               write_queue.start_ptr = subbuffer;
 
-    /* Unlock busy sync primitive */
-    if (buffer_access_unlock(&buffer_busy_sync)) {
-        return -2;
-    }
+       if (write_queue.end_ptr) {
+               write_queue.end_ptr->next_in_queue = subbuffer;
+               write_queue.end_ptr = write_queue.end_ptr->next_in_queue;
+       } else {
+               write_queue.end_ptr = subbuffer;
+       }
+       write_queue.end_ptr->next_in_queue = NULL;
+       ++write_queue.subbuffers_count;
 
-    return 0;
+       sync_unlock(&write_queue.queue_sync);
 }
 
-/* Remove subbuffer from busy list when it is released */
-int remove_from_busy_list(struct swap_buffer* subbuffer)
+/* Returns subbuffers to write count */
+unsigned int get_writable_buf_cnt(void)
 {
-    int result = -1; // For sanitization
-    int i;
-
-    /*  0 - ok
-     * -1 - no such buffer in queue_busy list
-     * -2 - cannot lock
-     * -3 - cannot unlock
-     */
-
-    /* Lock busy list sync primitive */
-    if (buffer_access_lock(&buffer_busy_sync)) {
-        result = -2;
-        return result;
-    }
-
-    /* Sanitization and removing */
-    for (i = 0; i < queue_busy_last_element; i++) {
-        if (queue_busy[i] == subbuffer) {
-            /* Last element goes here and length is down 1 */
-            queue_busy[i] = queue_busy[queue_busy_last_element - 1];
-            queue_busy_last_element -= 1;
-            result = 0;
-            break;
-        }
-    }
-
-    /* Unlock busy list sync primitive */
-    if (buffer_access_unlock(&buffer_busy_sync)) {
-        result = -3;
-        return result;
-    }
-
-    return result;
+       return write_queue.subbuffers_count;
 }
 
-/* Get subbuffers count in read list */
-/* XXX Think about locks */
-int get_full_buffers_count(void)
+
+/* Add subbuffer to busy list when it is read from out of the buffer */
+void add_to_busy_list(struct swap_subbuffer *subbuffer)
 {
-    int result = 0;
-    struct swap_buffer* buffer = queue_read_start_ptr;
+       /* Lock busy sync primitive */
+       sync_lock(&buffer_busy_sync);
 
-    /* >=0 - buffers count
-     */
+       subbuffer->next_in_queue = NULL;
+       queue_busy[queue_busy_last_element] = subbuffer;
+       queue_busy_last_element += 1;
 
-    while (buffer && buffer->full_buffer_part) {
-        result += 1;
-        buffer = buffer->next_in_queue;
-    }
+       /* Unlock busy sync primitive */
+       sync_unlock(&buffer_busy_sync);
+}
 
-    return result;
+/* Remove subbuffer from busy list when it is released */
+int remove_from_busy_list(struct swap_subbuffer *subbuffer)
+{
+       int result = -E_SB_NO_SUBBUFFER_IN_BUSY; // For sanitization
+       int i;
+
+       /* Lock busy list sync primitive */
+       sync_lock(&buffer_busy_sync);
+
+       /* Sanitization and removing */
+       for (i = 0; i < queue_busy_last_element; i++) {
+               if (queue_busy[i] == subbuffer) {
+                       /* Last element goes here and length is down 1 */
+                       queue_busy[i] = queue_busy[queue_busy_last_element - 1];
+                       queue_busy_last_element -= 1;
+                       result = E_SB_SUCCESS;
+                       break;
+               }
+       }
+
+       /* Unlock busy list sync primitive */
+       sync_unlock(&buffer_busy_sync);
+
+       return result;
 }
 
 /* Set all subbuffers in write list to read list */
-int set_all_to_read_list(void)
+void buffer_queue_flush(void)
 {
-    int result = 0;
-    struct swap_buffer *buffer = queue_write_start_ptr;
-
-    /*  0 - ok
-     * -1 - sem_wait() error
-     * -2 - sem_post() error
-     * -3 - problems with locking sync primitives
-     * -4 - problems with unlocking sync primitives
-     */
-
-    /* Locking write sync primitive */
-    if (buffer_access_lock(&buffer_write_sync)) {
-        result = -3;
-        return result;
-    }
-
-    while (queue_write_start_ptr) {
-        /* Waiting till semaphore should be posted */
-
-// TODO To think: It's not bad as it is, but maybe it would be better locking
-// semaphore while changing its list? (Not bad now, cause buffer should have
-// already been stopped).
-
-        if (buffer_rw_lock(&buffer->buffer_sync)) {
-            result = -1;
-            goto set_all_to_read_list_unlock;
-        }
-
-        if (buffer_rw_unlock(&buffer->buffer_sync)) {
-            result = -2;
-            goto set_all_to_read_list_unlock;
-        }
-
-        buffer = queue_write_start_ptr;
-
-        /* If we reached end of the list */
-        if (queue_write_start_ptr == queue_write_end_ptr) {
-            queue_write_end_ptr = NULL;
-        }
-        queue_write_start_ptr = queue_write_start_ptr->next_in_queue;
-
-        add_to_read_list(buffer);
-    }
-
-set_all_to_read_list_unlock:
-    /* Unlocking write primitive */
-    if (buffer_access_unlock(&buffer_write_sync)) {
-        result = -4;
-    }
-    return result;
+       struct swap_subbuffer *buffer = write_queue.start_ptr;
+
+       /* Locking write sync primitive */
+       sync_lock(&write_queue.queue_sync);
+
+       while (write_queue.start_ptr &&
+              write_queue.start_ptr->full_buffer_part) {
+
+               /* Lock buffer sync primitive to prevent writing to buffer if it had
+                * been selected for writing, but still wasn't wrote. */
+               sync_lock(&buffer->buffer_sync);
+
+               buffer = write_queue.start_ptr;
+               next_queue_element(&write_queue);
+               add_to_read_list(buffer);
+
+               /* Unlock buffer sync primitive */
+               sync_unlock(&buffer->buffer_sync);
+       }
+
+       /* Unlock write primitive */
+       sync_unlock(&write_queue.queue_sync);
 }
 
 /* Get subbuffers count in busy list */
-/* XXX Think abount lock */
 int get_busy_buffers_count(void)
 {
-    return queue_busy_last_element;
+       int result;
+
+       sync_lock(&buffer_busy_sync);
+       result = queue_busy_last_element;
+       sync_unlock(&buffer_busy_sync);
+
+       return result;
 }
 
 /* Get memory pages count in subbuffer */
-int get_pages_in_subbuffer(void)
+int get_pages_count_in_subbuffer(void)
 {
 /* Return 1 if pages order 0, or 2 of power pages_order_in_subbuffer otherwise */
-    return (pages_order_in_subbuffer) ? 2 << (pages_order_in_subbuffer - 1) : 1;
+       return (pages_order_in_subbuffer) ? 2 << (pages_order_in_subbuffer - 1) : 1;
 }