mempool: add API for malloc semantics

This works like k_malloc() but allows the user to designate
a specific memory pool to use instead of the kernel heap.

Test coverage provided by existing tests for k_malloc(), which is
now derived from this API.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
diff --git a/doc/kernel/memory/pools.rst b/doc/kernel/memory/pools.rst
index 7eb85f9..cdd0ff9 100644
--- a/doc/kernel/memory/pools.rst
+++ b/doc/kernel/memory/pools.rst
@@ -151,10 +151,15 @@
         printf("Memory allocation time-out");
     }
 
+Memory blocks may also be allocated with :cpp:func:`malloc()`-like semantics
+using :cpp:func:`k_mem_pool_malloc()`. Such allocations must be freed with
+:cpp:func:`k_free()`.
+
 Releasing a Memory Block
 ========================
 
-A memory block is released by calling :cpp:func:`k_mem_pool_free()`.
+A memory block is released by calling either :cpp:func:`k_mem_pool_free()`
+or :cpp:func:`k_free()`, depending on how it was allocated.
 
 The following code builds on the example above, and allocates a 75 byte
 memory block, then releases it once it is no longer needed. (A 256 byte
@@ -184,3 +189,5 @@
 * :c:macro:`K_MEM_POOL_DEFINE`
 * :cpp:func:`k_mem_pool_alloc()`
 * :cpp:func:`k_mem_pool_free()`
+* :cpp:func:`k_mem_pool_malloc()`
+* :cpp:func:`k_free()`
diff --git a/include/kernel.h b/include/kernel.h
index 2a9e779..27fa8ea 100644
--- a/include/kernel.h
+++ b/include/kernel.h
@@ -3653,6 +3653,17 @@
 			    size_t size, s32_t timeout);
 
 /**
+ * @brief Allocate memory from a memory pool with malloc() semantics
+ *
+ * Such memory must be released using k_free().
+ *
+ * @param pool Address of the memory pool.
+ * @param size Amount of memory to allocate (in bytes).
+ * @return Address of the allocated memory if successful, otherwise NULL
+ */
+extern void *k_mem_pool_malloc(struct k_mem_pool *pool, size_t size);
+
+/**
  * @brief Free memory allocated from a memory pool.
  *
  * This routine releases a previously allocated memory block back to its
@@ -3702,7 +3713,8 @@
  * @brief Free memory allocated from heap.
  *
  * This routine provides traditional free() semantics. The memory being
- * returned must have been allocated from the heap memory pool.
+ * returned must have been allocated from the heap memory pool or
+ * k_mem_pool_malloc().
  *
  * If @a ptr is NULL, no operation is performed.
  *
diff --git a/kernel/mempool.c b/kernel/mempool.c
index 91b7ff7..97f7886 100644
--- a/kernel/mempool.c
+++ b/kernel/mempool.c
@@ -119,6 +119,40 @@
 	k_mem_pool_free_id(&block->id);
 }
 
+void *k_mem_pool_malloc(struct k_mem_pool *pool, size_t size)
+{
+	struct k_mem_block block;
+
+	/*
+	 * get a block large enough to hold an initial (hidden) block
+	 * descriptor, as well as the space the caller requested
+	 */
+	if (__builtin_add_overflow(size, sizeof(struct k_mem_block_id),
+				   &size)) {
+		return NULL;
+	}
+	if (k_mem_pool_alloc(pool, &block, size, K_NO_WAIT) != 0) {
+		return NULL;
+	}
+
+	/* save the block descriptor info at the start of the actual block */
+	memcpy(block.data, &block.id, sizeof(struct k_mem_block_id));
+
+	/* return address of the user area part of the block to the caller */
+	return (char *)block.data + sizeof(struct k_mem_block_id);
+}
+
+void k_free(void *ptr)
+{
+	if (ptr != NULL) {
+		/* point to hidden block descriptor at start of block */
+		ptr = (char *)ptr - sizeof(struct k_mem_block_id);
+
+		/* return block to the heap memory pool */
+		k_mem_pool_free_id(ptr);
+	}
+}
+
 #if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
 
 /*
@@ -133,37 +167,7 @@
 
 void *k_malloc(size_t size)
 {
-	struct k_mem_block block;
-
-	/*
-	 * get a block large enough to hold an initial (hidden) block
-	 * descriptor, as well as the space the caller requested
-	 */
-	if (__builtin_add_overflow(size, sizeof(struct k_mem_block_id),
-				   &size)) {
-		return NULL;
-	}
-	if (k_mem_pool_alloc(_HEAP_MEM_POOL, &block, size, K_NO_WAIT) != 0) {
-		return NULL;
-	}
-
-	/* save the block descriptor info at the start of the actual block */
-	memcpy(block.data, &block.id, sizeof(struct k_mem_block_id));
-
-	/* return address of the user area part of the block to the caller */
-	return (char *)block.data + sizeof(struct k_mem_block_id);
-}
-
-
-void k_free(void *ptr)
-{
-	if (ptr != NULL) {
-		/* point to hidden block descriptor at start of block */
-		ptr = (char *)ptr - sizeof(struct k_mem_block_id);
-
-		/* return block to the heap memory pool */
-		k_mem_pool_free_id(ptr);
-	}
+	return k_mem_pool_malloc(_HEAP_MEM_POOL, size);
 }
 
 void *k_calloc(size_t nmemb, size_t size)