[FIX] Ksyms: Fix warnings
[kernel/swap-modules.git] / buffer / buffer_queue.c
index bfbc01e..8744b21 100644 (file)
 #include "buffer_queue.h"
 #include "swap_buffer_to_buffer_queue.h"
 #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 {
+struct queue_t {
        struct swap_subbuffer *start_ptr;
        struct swap_subbuffer *end_ptr;
-       sync_t queue_sync;
+       unsigned int subbuffers_count;
+       struct sync_t queue_sync;
 };
 
 /* Write queue */
-struct queue write_queue = {NULL, NULL};
+struct queue_t write_queue = {
+       .start_ptr = NULL,
+       .end_ptr = NULL,
+       .subbuffers_count = 0,
+       .queue_sync = {
+               .flags = 0x0
+       }
+};
 
 /* Read queue */
-struct queue read_queue = {NULL, NULL};
+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_buffer **queue_busy = NULL;
+static struct swap_subbuffer **queue_busy = NULL;
 
 /* Store last busy element */
 static unsigned int queue_busy_last_element;
@@ -73,7 +89,9 @@ static unsigned int queue_subbuffer_count = 0;
 static size_t queue_subbuffer_size = 0;
 
 /* Busy list sync */
-static sync_t buffer_busy_sync;
+static struct sync_t buffer_busy_sync = {
+       .flags = 0x0
+};
 
 /* Memory pages count in one subbuffer */
 static int pages_order_in_subbuffer = 0;
@@ -105,20 +123,20 @@ int buffer_queue_allocation(size_t subbuffer_size,
        sync_init(&buffer_busy_sync);
 
        /* Memory allocation for queue_busy */
-       queue_busy = memory_allocation(sizeof(&queue_busy) * queue_subbuffer_count);
+       queue_busy = memory_allocation(sizeof(*queue_busy) * queue_subbuffer_count);
 
        if (!queue_busy) {
-               result = E_SB_NO_MEM_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));
+       write_queue.start_ptr = memory_allocation(sizeof(*write_queue.start_ptr));
 
        if (!write_queue.start_ptr) {
-               result = E_SB_NO_MEM_BUFFER_STRUCT;
+               result = -E_SB_NO_MEM_BUFFER_STRUCT;
                goto buffer_allocation_queue_busy_free;
        }
        allocated_structs++;
@@ -131,13 +149,11 @@ int buffer_queue_allocation(size_t subbuffer_size,
        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;
+               result = -E_SB_NO_MEM_DATA_BUFFER;
                goto buffer_allocation_error_free;
        }
        allocated_buffers++;
 
-       print_msg(" Buffer allocated = 0x%x\n", (unsigned long)write_queue.end_ptr->data_buffer);
-
        sync_init(&write_queue.end_ptr->buffer_sync);
 
        /* Buffer initialization */
@@ -146,9 +162,9 @@ int buffer_queue_allocation(size_t 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));
+                   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;
+                       result = -E_SB_NO_MEM_BUFFER_STRUCT;
                        goto buffer_allocation_error_free;
                }
                allocated_structs++;
@@ -161,15 +177,11 @@ int buffer_queue_allocation(size_t subbuffer_size,
                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;
+                       result = -E_SB_NO_MEM_DATA_BUFFER;
                        goto buffer_allocation_error_free;
                }
                allocated_buffers++;
 
-               print_msg(" Buffer allocated = 0x%x, pages_order = %d\n", 
-                         (unsigned long)buffer_address(write_queue.end_ptr->data_buffer), 
-                         pages_order_in_subbuffer);
-
                sync_init(&write_queue.end_ptr->buffer_sync);
 
                /* Buffer initialization */
@@ -177,6 +189,9 @@ int buffer_queue_allocation(size_t subbuffer_size,
                       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 */
@@ -205,21 +220,69 @@ buffer_allocation_error_ret:
        return result;
 }
 
+int buffer_queue_reset(void)
+{
+       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;
+}
+
 void buffer_queue_free(void)
 {
        struct swap_subbuffer *tmp = NULL;
 
-       //TODO Lock read list semaphore to prevent getting subbuffer from read list 
-       /* Set all write buffers to read list */
-       set_all_to_read_list();
+       /* 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);
-               print_msg(" Buffer free = 0x%x\n", (unsigned long)
-                          buffer_address(tmp->data_buffer));
+               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);
        }
 
@@ -233,6 +296,11 @@ void buffer_queue_free(void)
        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,
@@ -244,6 +312,16 @@ static unsigned int is_buffer_enough(struct swap_subbuffer *subbuffer,
        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_subbuffer *get_from_read_list(void)
 {
@@ -259,13 +337,7 @@ struct swap_subbuffer *get_from_read_list(void)
 
        result = read_queue.start_ptr;
 
-       /* If this is the last readable buffer, read_queue.start_ptr next time will 
-        * points to NULL and that case is handled in the beginning of function
-        */
-       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;
+       next_queue_element(&read_queue);
 
 get_from_read_list_unlock:
        /* Unlock read sync primitive */
@@ -277,7 +349,6 @@ get_from_read_list_unlock:
 /* Add subbuffer to read list */
 void add_to_read_list(struct swap_subbuffer *subbuffer)
 {
-
        /* Lock read sync primitive */
        sync_lock(&read_queue.queue_sync);
 
@@ -292,6 +363,7 @@ void add_to_read_list(struct swap_subbuffer *subbuffer)
                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);
@@ -309,14 +381,26 @@ int add_to_read_list_with_callback(struct swap_subbuffer *subbuffer)
        return result;
 }
 
+/* Returns subbuffers to read count */
+unsigned int get_readable_buf_cnt(void)
+{
+       return read_queue.subbuffers_count;
+}
+
+
 /* Get first writable subbuffer from write list */
 struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write)
 {
        struct swap_subbuffer *result = NULL;
 
        /* Callbacks are called at the end of the function to prevent deadlocks */
-       struct swap_subbuffer *queue_callback_start_ptr = NULL;
-       struct swap_subbuffer *queue_callback_end_ptr = NULL;
+       struct queue_t callback_queue = {
+               .start_ptr = NULL,
+               .end_ptr = NULL,
+               .queue_sync = {
+                       .flags = 0x0
+               }
+       };
        struct swap_subbuffer *tmp_buffer = NULL;
 
        /* Init pointer */
@@ -326,11 +410,6 @@ struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write)
        sync_lock(&write_queue.queue_sync);
 
        while (write_queue.start_ptr) {
-               /* If start points to NULL => list is empty => exit */
-               if (!write_queue.start_ptr) {
-                       result = NULL;
-                       goto get_from_write_list_unlock;
-               }
 
                /* We're found subbuffer */
                if (is_buffer_enough(write_queue.start_ptr, size)) {
@@ -346,45 +425,35 @@ struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write)
 
                        /* 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;
-                       /* If we reached end of the list */
-                       if (write_queue.start_ptr == write_queue.end_ptr) {
-                               write_queue.end_ptr = NULL;
-                       }
-                       /* Move start write pointer */
-                       write_queue.start_ptr = write_queue.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;
+                       next_queue_element(&write_queue);
 
-                       queue_callback_end_ptr = result;
-                       queue_callback_end_ptr->next_in_queue = NULL;
+                       /* 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;
                }
        }
 
-get_from_write_list_unlock:
        /* Unlock write list sync primitive */
        sync_unlock(&write_queue.queue_sync);
 
        /* 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;
+       for (tmp_buffer = NULL; callback_queue.start_ptr; ) {
+               if (callback_queue.start_ptr == callback_queue.end_ptr)
+                       callback_queue.end_ptr = NULL;
 
-               tmp_buffer = queue_callback_start_ptr;
-               queue_callback_start_ptr = queue_callback_start_ptr->next_in_queue;
+               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);
        }
@@ -398,8 +467,6 @@ void add_to_write_list(struct swap_subbuffer *subbuffer)
        sync_lock(&write_queue.queue_sync);
 
        /* Reinitialize */
-       // TODO Useless memset
-//     memset(buffer_address(subbuffer->data_buffer), 0, queue_subbuffer_size);
        subbuffer->full_buffer_part = 0;
 
        if (!write_queue.start_ptr)
@@ -412,10 +479,18 @@ void add_to_write_list(struct swap_subbuffer *subbuffer)
                write_queue.end_ptr = subbuffer;
        }
        write_queue.end_ptr->next_in_queue = NULL;
+       ++write_queue.subbuffers_count;
 
        sync_unlock(&write_queue.queue_sync);
 }
 
+/* Returns subbuffers to write count */
+unsigned int get_writable_buf_cnt(void)
+{
+       return write_queue.subbuffers_count;
+}
+
+
 /* Add subbuffer to busy list when it is read from out of the buffer */
 void add_to_busy_list(struct swap_subbuffer *subbuffer)
 {
@@ -433,7 +508,7 @@ void add_to_busy_list(struct swap_subbuffer *subbuffer)
 /* 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 result = -E_SB_NO_SUBBUFFER_IN_BUSY; // For sanitization
        int i;
 
        /* Lock busy list sync primitive */
@@ -456,60 +531,43 @@ int remove_from_busy_list(struct swap_subbuffer *subbuffer)
        return result;
 }
 
-/* Get subbuffers count in read list */
-/* XXX Think about locks */
-int get_full_buffers_count(void)
-{
-       int result = 0;
-       struct swap_subbuffer *buffer = read_queue.start_ptr;
-
-       while (buffer && buffer->full_buffer_part) {
-               result += 1;
-               buffer = buffer->next_in_queue;
-       }
-
-       return result;
-}
-
 /* Set all subbuffers in write list to read list */
-void set_all_to_read_list(void)
+void buffer_queue_flush(void)
 {
        struct swap_subbuffer *buffer = write_queue.start_ptr;
 
        /* Locking write sync primitive */
        sync_lock(&write_queue.queue_sync);
 
-       while (write_queue.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).
+       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);
 
-               sync_unlock(&buffer->buffer_sync);
-
                buffer = write_queue.start_ptr;
-
-               /* If we reached end of the list */
-               if (write_queue.start_ptr == write_queue.end_ptr) {
-                       write_queue.end_ptr = NULL;
-               }
-               write_queue.start_ptr = write_queue.start_ptr->next_in_queue;
-
+               next_queue_element(&write_queue);
                add_to_read_list(buffer);
+
+               /* Unlock buffer sync primitive */
+               sync_unlock(&buffer->buffer_sync);
        }
 
-       /* Unlocking write primitive */
+       /* 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 */