#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 = {
+struct queue_t write_queue = {
.start_ptr = NULL,
- .end_ptr = NULL
+ .end_ptr = NULL,
+ .subbuffers_count = 0,
+ .queue_sync = {
+ .flags = 0x0
+ }
};
/* Read queue */
-struct queue read_queue = {
+struct queue_t read_queue = {
.start_ptr = NULL,
- .end_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;
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;
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++;
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 */
/* 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++;
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 */
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 */
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);
}
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,
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)
{
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 */
/* Add subbuffer to read list */
void add_to_read_list(struct swap_subbuffer *subbuffer)
{
-
/* Lock read sync primitive */
sync_lock(&read_queue.queue_sync);
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);
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 queue callback_queue = {
+ struct queue_t callback_queue = {
.start_ptr = NULL,
- .end_ptr = NULL
+ .end_ptr = NULL,
+ .queue_sync = {
+ .flags = 0x0
+ }
};
struct swap_subbuffer *tmp_buffer = NULL;
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)) {
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;
+ next_queue_element(&write_queue);
/* Add to callback list */
if (!callback_queue.start_ptr)
}
}
-get_from_write_list_unlock:
/* Unlock write list sync primitive */
sync_unlock(&write_queue.queue_sync);
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)
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)
{
/* 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 */
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 */