lib/mem_blocks: add allocation for contiguous memory blocks

Added allocation and freeing of a contiguous memory blocks

Signed-off-by: Marcin Szkudlinski <marcin.szkudlinski@intel.com>
diff --git a/include/sys/mem_blocks.h b/include/sys/mem_blocks.h
index bbca894..48821eb 100644
--- a/include/sys/mem_blocks.h
+++ b/include/sys/mem_blocks.h
@@ -218,6 +218,22 @@
 int sys_mem_blocks_alloc(sys_mem_blocks_t *mem_block, size_t count,
 			 void **out_blocks);
 
+/**
+ * @brief Allocate a contiguous set of memory blocks
+ *
+ * Allocate multiple memory blocks, and place their pointers into
+ * the output array.
+ *
+ * @param[in]  mem_block Pointer to memory block object.
+ * @param[in]  count     Number of blocks to allocate.
+ * @param[out] out_block Output pointer to the start of the allocated block set
+ *
+ * @retval 0       Successful
+ * @retval -EINVAL Invalid argument supplied.
+ * @retval -ENOMEM Not enough contiguous blocks for allocation.
+ */
+int sys_mem_blocks_alloc_contiguous(sys_mem_blocks_t *mem_block, size_t count,
+				   void **out_block);
 
 /**
  * @brief Force allocation of a specified blocks in a memory block object
@@ -255,6 +271,21 @@
 			void **in_blocks);
 
 /**
+ * @brief Free contiguous multiple memory blocks
+ *
+ * Free contiguous multiple memory blocks
+ *
+ * @param[in] mem_block Pointer to memory block object.
+ * @param[in] block     Pointer to the first memory block
+ * @param[in] count     Number of blocks to free.
+ *
+ * @retval 0       Successful
+ * @retval -EINVAL Invalid argument supplied.
+ * @retval -EFAULT Invalid pointer supplied.
+ */
+int sys_mem_blocks_free_contiguous(sys_mem_blocks_t *mem_block, void *block, size_t count);
+
+/**
  * @brief Initialize multi memory blocks allocator group
  *
  * Initialize a sys_multi_mem_block struct with the specified choice
diff --git a/lib/os/mem_blocks.c b/lib/os/mem_blocks.c
index b0ad5ab..6725a73 100644
--- a/lib/os/mem_blocks.c
+++ b/lib/os/mem_blocks.c
@@ -57,6 +57,45 @@
 	return ret;
 }
 
+int sys_mem_blocks_alloc_contiguous(sys_mem_blocks_t *mem_block, size_t count,
+				   void **out_block)
+{
+	int ret = 0;
+
+	if ((mem_block == NULL) || (out_block == NULL)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (count == 0) {
+		/* Nothing to allocate */
+		*out_block = NULL;
+		goto out;
+	}
+
+	if (count > mem_block->num_blocks) {
+		/* Definitely not enough blocks to be allocated */
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	void *ptr = alloc_blocks(mem_block, count);
+
+	if (ptr == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	*out_block = ptr;
+#ifdef CONFIG_SYS_MEM_BLOCKS_LISTENER
+	heap_listener_notify_alloc(HEAP_ID_FROM_POINTER(mem_block),
+				   ptr, count << mem_block->blk_sz_shift);
+#endif
+
+out:
+		return ret;
+}
+
 int sys_mem_blocks_alloc(sys_mem_blocks_t *mem_block, size_t count,
 			 void **out_blocks)
 {
@@ -204,6 +243,44 @@
 	return ret;
 }
 
+int sys_mem_blocks_free_contiguous(sys_mem_blocks_t *mem_block, void *block, size_t count)
+{
+	int ret = 0;
+
+	if (mem_block == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	CHECKIF((mem_block->bitmap == NULL) || (mem_block->buffer == NULL)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (count == 0) {
+		/* Nothing to be freed. */
+		goto out;
+	}
+
+	if (count > mem_block->num_blocks) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = free_blocks(mem_block, block, count);
+
+	if (ret != 0) {
+		goto out;
+	}
+#ifdef CONFIG_SYS_MEM_BLOCKS_LISTENER
+	heap_listener_notify_free(HEAP_ID_FROM_POINTER(mem_block),
+			block, count << mem_block->blk_sz_shift);
+#endif
+
+out:
+	return ret;
+}
+
 void sys_multi_mem_blocks_init(sys_multi_mem_blocks_t *group,
 			       sys_multi_mem_blocks_choice_fn_t choice_fn)
 {