[IMPROVE] Implement new buffer workstyle
authorAlexander Aksenov <a.aksenov@samsung.com>
Tue, 9 Jul 2013 14:25:34 +0000 (18:25 +0400)
committerAlexander Aksenov <a.aksenov@samsung.com>
Tue, 9 Jul 2013 14:25:34 +0000 (18:25 +0400)
buffer init - allocates memory only if it wasn't allocated before, or if
attributes (size, subbuffers number) changed. If memory was allocated,
just restarts buffer (moves all subbuffers to write queue and set them
zero full buffer part);
buffer uninit - free memory in all queues (also checks if memory was
allocated);
buffer flush - moves only non-empty buffers to read list and doesn't
stop buffer work (fixed, was implemented before).

buffer/buffer_queue.c
buffer/buffer_queue.h
buffer/swap_buffer_errors.h
buffer/swap_buffer_module.c

index c9a6d1f..db82a2c 100644 (file)
@@ -219,13 +219,55 @@ 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) {
@@ -233,7 +275,17 @@ void buffer_queue_free(void)
                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));
+                          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);
+               print_msg(" Buffer free = 0x%x\n", (unsigned long)
+                                                                                  tmp->data_buffer);
                memory_free(tmp);
        }
 
@@ -247,6 +299,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,
@@ -488,7 +545,7 @@ int get_full_buffers_count(void)
 }
 
 /* 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;
 
@@ -516,16 +573,20 @@ void set_all_to_read_list(void)
                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 */
index 3f66a4e..9a6e221 100644 (file)
@@ -31,6 +31,8 @@
 
 int buffer_queue_allocation(size_t subbuffer_size, unsigned int subbuffers_count);
 void buffer_queue_free(void);
+int buffer_queue_reset(void);
+void buffer_queue_flush(void);
 struct swap_subbuffer *get_from_write_list(size_t size, void **ptr_to_write);
 struct swap_subbuffer *get_from_read_list(void);
 void add_to_write_list(struct swap_subbuffer *subbuffer);
@@ -39,7 +41,6 @@ void add_to_busy_list(struct swap_subbuffer *subbuffer);
 int remove_from_busy_list(struct swap_subbuffer *subbuffer);
 int get_full_buffers_count(void);
 
-void set_all_to_read_list(void);
 int get_busy_buffers_count(void);
 int get_pages_count_in_subbuffer(void);
 
index 1faa97f..a78aae8 100644 (file)
@@ -42,5 +42,6 @@ enum _swap_buffer_errors {
                                        wasn't allocated */
     E_SB_NO_MEM_DATA_BUFFER = 10,   /* Memort for data buffer itself wasn't
                                        allocated */
-    E_SB_NO_SUBBUFFER_IN_BUSY = 11  /* No such subbuffer in busy_list */
+    E_SB_NO_SUBBUFFER_IN_BUSY = 11, /* No such subbuffer in busy_list */
+    E_SB_NOT_ALLOC = 12             /* Subbuffers aren't allocated */
 };
index f16bfe8..bc53c18 100644 (file)
 #include "swap_buffer_errors.h"
 
 /* Bitwise mask for buffer status */
-#define BUFFER_WORK     1
-#define BUFFER_ALLOC   2
-
-/* Current buffer status:
- * 00 - memory isn't allocated, buffer doesn't work
- * 10 - memory allocated, buffer doesn't work
- * 11 - memory allocated, buffer is working
- * 01 - memory isn't allocated, buffer is working. Never occurs. */
+enum _swap_buffer_status_mask {
+       BUFFER_FREE = 0,
+       BUFFER_ALLOC = 1,
+       BUFFER_STOP = 2,
+       BUFFER_WORK = 4
+};
+
+/* Buffer status masks:
+ *  0 - memory free
+ *  1 - memory allocated 
+ * 0  - buffer stop
+ * 1  - buffer work
+ * */
 static unsigned char swap_buffer_status = 0;
 
 /* Callback type */
@@ -51,7 +56,6 @@ static size_t subbuffers_size = 0;
 /* Subbuffers count */
 static unsigned int subbuffers_num = 0;
 
-//TODO Swap restart
 
 static inline int areas_overlap(const void *area1,const void *area2, size_t size)
 {
@@ -67,13 +71,18 @@ static inline int areas_overlap(const void *area1,const void *area2, size_t size
 int swap_buffer_init(size_t subbuffer_size, unsigned int nr_subbuffers,
                     int (*subbuffer_full_callback)(void))
 {
-       int result = 0;
+       int result = -1;
 
-       if (swap_buffer_status & BUFFER_WORK)
-               swap_buffer_flush();
+       swap_buffer_status &= ~BUFFER_WORK;
+       print_debug("status buffer stop = %d\n", swap_buffer_status);
 
-       if (swap_buffer_status & BUFFER_ALLOC)
-               swap_buffer_uninit();
+       if ((swap_buffer_status & BUFFER_ALLOC) &&
+               (subbuffers_size == subbuffer_size) &&
+               (subbuffers_num == nr_subbuffers) &&
+               (subbuffer_full_callback == subbuffer_callback)) {
+               result = buffer_queue_reset();
+               goto swap_buffer_init_work;
+       }
 
        // TODO Test if wrong function type
        subbuffer_callback = (subbuffer_callback_type)subbuffer_full_callback;
@@ -84,13 +93,15 @@ int swap_buffer_init(size_t subbuffer_size, unsigned int nr_subbuffers,
        if (result < 0)
                return result;
 
-       swap_buffer_status |= BUFFER_WORK;
-       print_debug("status buffer work = %d\n", swap_buffer_status);
        result = get_pages_count_in_subbuffer();
 
        swap_buffer_status |= BUFFER_ALLOC;
        print_debug("status buffer alloc = %d\n", swap_buffer_status);
 
+swap_buffer_init_work:
+       swap_buffer_status |= BUFFER_WORK;
+       print_debug("status buffer work = %d\n", swap_buffer_status);
+
        return result;
 }
 EXPORT_SYMBOL_GPL(swap_buffer_init);
@@ -98,11 +109,15 @@ EXPORT_SYMBOL_GPL(swap_buffer_init);
 
 int swap_buffer_uninit(void)
 {
-       /* Stop swap_buffer */
+       /* Check whether buffer is allocated */
+       if (!(swap_buffer_status & BUFFER_ALLOC))
+               return -E_SB_NOT_ALLOC;
+
+       /* Stop buffer */
        swap_buffer_status &= ~BUFFER_WORK;
        print_debug("status buffer stop = %d\n", swap_buffer_status);
 
-       /* Checking whether all buffers are released */
+       /* Check whether all buffers are released */
        if (get_busy_buffers_count())
                return -E_SB_UNRELEASED_BUFFERS;
 
@@ -127,14 +142,14 @@ ssize_t swap_buffer_write(size_t size, void *data)
        struct swap_subbuffer *buffer_to_write = NULL;
        void *ptr_to_write = NULL;
 
-       /* Check buffer status */
-       if (!(swap_buffer_status & BUFFER_WORK))
-               return -E_SB_IS_STOPPED;
-
        /* Size sanitization */
        if ((size > subbuffers_size) || (size == 0))
                return -E_SB_WRONG_DATA_SIZE;
 
+       /* Check buffer status */
+       if (!(swap_buffer_status & BUFFER_WORK))
+               return -E_SB_IS_STOPPED;
+
        /* Get next write buffer and occupying semaphore */
        buffer_to_write = get_from_write_list(size, &ptr_to_write);
        if (!buffer_to_write)
@@ -153,7 +168,7 @@ ssize_t swap_buffer_write(size_t size, void *data)
 
        result = size;
 
-       /* Unlock semaphpore (Locked in get_from_write_list()) */
+       /* Unlock sync (Locked in get_from_write_list()) */
 buf_write_sem_post:
        sync_unlock(&buffer_to_write->buffer_sync);
 
@@ -167,6 +182,10 @@ int swap_buffer_get(struct swap_subbuffer **subbuffer)
        int result = 0;
        struct swap_subbuffer *buffer_to_read = NULL;
 
+       /* Check buffer status */
+       if (!(swap_buffer_status & BUFFER_WORK))
+               return -E_SB_IS_STOPPED;
+
        /* Get next read buffer */
        buffer_to_read = get_from_read_list();
        if (!buffer_to_read)
@@ -206,8 +225,8 @@ int swap_buffer_flush(void)
 {
        int result = 0;
 
-       /* Set all write buffers to read list */
-       set_all_to_read_list();
+       /* Set all non-empty write buffers to read list */
+       buffer_queue_flush();
 
        /* Get count of all full buffers */
        result = get_full_buffers_count();
@@ -232,7 +251,6 @@ int swap_buffer_callback(void *buffer)
        return result;
 }
 
-
 static int __init swap_buffer_module_init(void)
 {
        printk(KERN_NOTICE "SWAP_BUFFER : Buffer module initialized\n");