#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;
+ 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,
+ .subbuffers_count = 0,
.queue_sync = {
.flags = 0x0
}
};
/* Read queue */
-struct queue read_queue = {
+struct queue_t read_queue = {
.start_ptr = NULL,
.end_ptr = NULL,
+ .subbuffers_count = 0,
.queue_sync = {
.flags = 0x0
}
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;
}
allocated_buffers++;
- print_msg(" Buffer allocated = 0x%p\n", write_queue.end_ptr->data_buffer);
-
sync_init(&write_queue.end_ptr->buffer_sync);
/* Buffer initialization */
}
allocated_buffers++;
- print_msg(" Buffer allocated = 0x%p, pages_order = %d\n",
- 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,
.queue_sync = {
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)) {
} 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)
{
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;
sync_lock(&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);
}
-
/* 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 */