#define __SWAP_BUFFER_ERRORS_H__
enum _swap_buffer_errors {
- E_SB_SUCCESS = 0, /* Success */
- E_SB_UNRELEASED_BUFFERS = 1, /* There are some unreleased buffers. Mainly
+ E_SB_SUCCESS = 0, /* Success */
+ E_SB_UNRELEASED_BUFFERS = 1, /* There are some unreleased buffers. Mainly
returned by swap_buffer_uninit */
E_SB_NO_WRITABLE_BUFFERS = 2, /* No buffers for writing */
- E_SB_WRONG_DATA_SIZE = 3, /* Wrong data size: size == 0 or
+ E_SB_WRONG_DATA_SIZE = 3, /* Wrong data size: size == 0 or
size > subbuffer size */
- E_SB_IS_STOPPED = 4, /* Trying to write data after SWAP buffer
+ E_SB_IS_STOPPED = 4, /* Trying to write data after SWAP buffer
has been stopped. */
- E_SB_OVERLAP = 5, /* Memory areas of data to be written and
+ E_SB_OVERLAP = 5, /* Memory areas of data to be written and
subbuffer itself are overlap */
E_SB_NO_READABLE_BUFFERS = 6, /* No buffers for reading */
- E_SB_NO_CALLBACK = 7, /* Callback function ptr == NULL */
- E_SB_NO_MEM_QUEUE_BUSY = 8, /* Memory for queue_busy wasn't allocated */
+ E_SB_NO_CALLBACK = 7, /* Callback function ptr == NULL */
+ E_SB_NO_MEM_QUEUE_BUSY = 8, /* Memory for queue_busy wasn't allocated */
E_SB_NO_MEM_BUFFER_STRUCT = 9, /* Memory for one of struct swap_buffer
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_NOT_ALLOC = 12 /* Subbuffers aren't allocated */
+ E_SB_NOT_ALLOC = 12, /* Subbuffers aren't allocated */
+ E_SB_WRONG_THRESHOLD = 13 /* Thresholds > 100, top < lower */
};
#endif /* __SWAP_BUFFER_ERRORS_H__ */
enum _swap_buffer_status_mask {
BUFFER_FREE = 0,
BUFFER_ALLOC = 1,
- BUFFER_STOP = 2,
+ BUFFER_PAUSE = 2,
BUFFER_WORK = 4
};
/* Buffer status masks:
- * 0 - memory free
- * 1 - memory allocated
- * 0 - buffer stop
- * 1 - buffer work
+ * 0 - memory free
+ * 1 - memory allocated
+ * 10 - buffer overflow
+ * 100 - buffer work
* */
-static unsigned char swap_buffer_status = 0;
+static unsigned char swap_buffer_status = BUFFER_FREE;
/* Callback type */
-typedef int(*subbuffer_callback_type)(void *);
+typedef int(*subbuffer_callback_type)(void);
/* Callback that is called when full subbuffer appears */
static subbuffer_callback_type subbuffer_callback = NULL;
/* Subbuffers count */
static unsigned int subbuffers_num = 0;
+static unsigned int enough_writable_bufs = 0;
+static unsigned int min_writable_bufs = 0;
+static int (*low_mem_cb)(void) = NULL;
+static int (*enough_mem_cb)(void) = NULL;
+
static inline int areas_overlap(const void *area1,const void *area2, size_t size)
{
return 0;
}
-int swap_buffer_init(size_t subbuffer_size, unsigned int nr_subbuffers,
- int (*subbuffer_full_callback)(void))
+static inline unsigned int percent_to_count(unsigned char percent,
+ unsigned int cnt)
+{
+ return (percent * cnt) / 100;
+}
+
+int swap_buffer_init(struct buffer_init_t *buf_init)
{
int result = -1;
swap_buffer_status &= ~BUFFER_WORK;
print_debug("status buffer stop = %d\n", swap_buffer_status);
+ if ((buf_init->top_threshold > 100) || (buf_init->lower_threshold > 100) ||
+ (buf_init->top_threshold < buf_init->lower_threshold))
+ return -E_SB_WRONG_THRESHOLD;
+
+ min_writable_bufs = percent_to_count(buf_init->lower_threshold,
+ buf_init->nr_subbuffers);
+
+ enough_writable_bufs = percent_to_count(buf_init->top_threshold,
+ buf_init->nr_subbuffers);
+
+ low_mem_cb = buf_init->low_mem_cb;
+ enough_mem_cb = buf_init->enough_mem_cb;
+
if ((swap_buffer_status & BUFFER_ALLOC) &&
- (subbuffers_size == subbuffer_size) &&
- (subbuffers_num == nr_subbuffers) &&
- ((subbuffer_callback_type)subbuffer_full_callback ==
- subbuffer_callback)) {
+ (subbuffers_size == buf_init->subbuffer_size) &&
+ (subbuffers_num == buf_init->nr_subbuffers) &&
+ ((subbuffer_callback_type)subbuffer_callback ==
+ buf_init->subbuffer_full_cb)) {
result = buffer_queue_reset();
goto swap_buffer_init_work;
}
- // TODO Test if wrong function type
- subbuffer_callback = (subbuffer_callback_type)subbuffer_full_callback;
- subbuffers_size = subbuffer_size;
- subbuffers_num = nr_subbuffers;
+ subbuffer_callback = buf_init->subbuffer_full_cb;
+ subbuffers_size = buf_init->subbuffer_size;
+ subbuffers_num = buf_init->nr_subbuffers;
result = buffer_queue_allocation(subbuffers_size, subbuffers_num);
if (result < 0)
subbuffer_callback = NULL;
subbuffers_size = 0;
subbuffers_num = 0;
+ min_writable_bufs = 0;
+ enough_writable_bufs = 0;
+ low_mem_cb = NULL;
+ enough_mem_cb = NULL;
swap_buffer_status &= ~BUFFER_ALLOC;
print_debug("status buffer dealloc = %d\n", swap_buffer_status);
return -E_SB_NO_CALLBACK;
}
- result = subbuffer_callback(buffer);
+ result = subbuffer_callback();
if (result < 0)
print_err("Callback error! Error code: %d\n", result);
struct swap_subbuffer;
+struct buffer_init_t {
+ size_t subbuffer_size;
+ unsigned int nr_subbuffers;
+ int (*subbuffer_full_cb)(void);
+
+ /* Lower threshold in percent. When buffers fall below this limit
+ * low_mem_cb is called and swap_buffer is suspended. */
+ unsigned char lower_threshold;
+ int (*low_mem_cb)(void);
+
+ /* Top threshold in percent. When buffers exceed this limit
+ * enough_mem_cb is called */
+ unsigned char top_threshold;
+ int (*enough_mem_cb)(void);
+};
+
/* SWAP Buffer initialization function. Call it before using buffer.
* Returns memory pages count (>0) in one subbuffer on success, or error code
* (<0) otherwise. */
-int swap_buffer_init(size_t subbuffer_size, unsigned int nr_subbuffers,
- int (*subbuffer_full_callback)(void));
+int swap_buffer_init(struct buffer_init_t *buf_init);
/* SWAP Buffer uninitialization function. Call it every time before removing
* this module.
/* Flush swap_buffer */
int driver_to_buffer_flush(void)
{
- int result;
-
- result = swap_buffer_flush();
-
- if (result >= 0)
- set_buffers_to_read(result);
- else if (result < 0)
- return -E_SD_BUFFER_ERROR;
+ unsigned int flushed;
+ flushed = swap_buffer_flush();
+ set_buffers_to_read(flushed);
swap_device_wake_up_process();
return E_SD_SUCCESS;
int driver_to_buffer_initialize(size_t size, unsigned int count)
{
int result;
+ struct buffer_init_t buf_init = {
+ .subbuffer_size = size,
+ .nr_subbuffers = count,
+ .subbuffer_full_cb = driver_to_buffer_callback,
+ .lower_threshold = 20,
+ .low_mem_cb = NULL,
+ .top_threshold = 80,
+ .enough_mem_cb = NULL,
+ };
if (size == 0 && count == 0) {
return -E_SD_WRONG_ARGS;
}
- result = swap_buffer_init(size, count, (void*)&driver_to_buffer_callback);
+ result = swap_buffer_init(&buf_init);
if (result == -E_SB_NO_MEM_QUEUE_BUSY
|| result == -E_SB_NO_MEM_BUFFER_STRUCT) {
return -E_SD_NO_MEMORY;