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) {
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);
}
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,
}
/* 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;
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 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);
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);
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 */
};
#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 */
/* 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)
{
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;
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);
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;
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)
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);
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)
{
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();
return result;
}
-
static int __init swap_buffer_module_init(void)
{
printk(KERN_NOTICE "SWAP_BUFFER : Buffer module initialized\n");