Skip to content

Commit

Permalink
Mail/MemoryPool: blocking alloc
Browse files Browse the repository at this point in the history
Mail and MemoryPool did not permit access to the blocking form of
allocation available in CMSIS-RTOS 2 - give them new blocking methods.
  • Loading branch information
kjbracey committed Mar 26, 2019
1 parent 6b84b14 commit 86e177f
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 10 deletions.
75 changes: 69 additions & 6 deletions rtos/Mail.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "mbed_rtos_storage.h"
#include "mbed_rtos1_types.h"

#include "platform/mbed_toolchain.h"
#include "platform/NonCopyable.h"

#ifndef MBED_NO_GLOBAL_USING_DIRECTIVE
Expand Down Expand Up @@ -90,32 +91,94 @@ class Mail : private mbed::NonCopyable<Mail<T, queue_sz> > {
return _queue.full();
}

/** Allocate a memory block of type T.
/** Allocate a memory block of type T, without blocking.
*
* @param millisec Not used.
* @param millisec Not used (see note).
*
* @return Pointer to memory block that you can fill with mail or NULL in case error.
*
* @note You may call this function from ISR context.
* @note If blocking is required, use Mail::alloc_for or Mail::alloc_until
*/
T *alloc(uint32_t millisec = 0)
T *alloc(MBED_UNUSED uint32_t millisec = 0)
{
return _pool.alloc();
}

/** Allocate a memory block of type T, optionally blocking.
*
* @param millisec Timeout value, or osWaitForever.
*
* @return Pointer to memory block that you can fill with mail or NULL in case error.
*
* @note You may call this function from ISR context if the millisec parameter is set to 0.
*/
T *alloc_for(uint32_t millisec)
{
return _pool.alloc_for(millisec);
}

/** Allocate a memory block of type T, blocking.
*
* @param millisec Absolute timeout time, referenced to Kernel::get_ms_count().
*
* @return Pointer to memory block that you can fill with mail or NULL in case error.
*
* @note You cannot call this function from ISR context.
* @note the underlying RTOS may have a limit to the maximum wait time
* due to internal 32-bit computations, but this is guaranteed to work if the
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
* the wait will time out earlier than specified.
*/
T *alloc_until(uint64_t millisec)
{
return _pool.alloc_until(millisec);
}

/** Allocate a memory block of type T, and set memory block to zero.
*
* @param millisec Not used.
* @param millisec Not used (see note).
*
* @return Pointer to memory block that you can fill with mail or NULL in case error.
*
* @note You may call this function from ISR context.
* @note You may call this function from ISR context if the millisec parameter is set to 0.
* @note If blocking is required, use Mail::calloc_for or Mail::calloc_until
*/
T *calloc(uint32_t millisec = 0)
T *calloc(MBED_UNUSED uint32_t millisec = 0)
{
return _pool.calloc();
}

/** Allocate a memory block of type T, optionally blocking, and set memory block to zero.
*
* @param millisec Timeout value, or osWaitForever.
*
* @return Pointer to memory block that you can fill with mail or NULL in case error.
*
* @note You may call this function from ISR context if the millisec parameter is set to 0.
*/
T *calloc_for(uint32_t millisec)
{
return _pool.calloc_for(millisec);
}

/** Allocate a memory block of type T, blocking, and set memory block to zero.
*
* @param millisec Absolute timeout time, referenced to Kernel::get_ms_count().
*
* @return Pointer to memory block that you can fill with mail or NULL in case error.
*
* @note You cannot call this function from ISR context.
* @note the underlying RTOS may have a limit to the maximum wait time
* due to internal 32-bit computations, but this is guaranteed to work if the
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
* the wait will time out earlier than specified.
*/
T *calloc_until(uint64_t millisec)
{
return _pool.calloc_until(millisec);
}

/** Put a mail in the queue.
*
* @param mptr Memory block previously allocated with Mail::alloc or Mail::calloc.
Expand Down
76 changes: 72 additions & 4 deletions rtos/MemoryPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
osMemoryPoolDelete(_id);
}

/** Allocate a memory block of type T from a memory pool.
/** Allocate a memory block from a memory pool, without blocking.
@return address of the allocated memory block or NULL in case of no memory available.
@note You may call this function from ISR context.
Expand All @@ -86,14 +86,82 @@ class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
return (T *)osMemoryPoolAlloc(_id, 0);
}

/** Allocate a memory block of type T from a memory pool and set memory block to zero.
/** Allocate a memory block from a memory pool, optionally blocking.
@param millisec timeout value (osWaitForever to wait forever)
@return address of the allocated memory block or NULL in case of no memory available.
@note You may call this function from ISR context if the millisec parameter is set to 0.
*/
T *alloc_for(uint32_t millisec)
{
return (T *)osMemoryPoolAlloc(_id, millisec);
}

/** Allocate a memory block from a memory pool, blocking.
@param millisec absolute timeout time, referenced to Kernel::get_ms_count().
@return address of the allocated memory block or NULL in case of no memory available.
@note You cannot call this function from ISR context.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
*/
T *alloc_until(uint64_t millisec)
{
uint64_t now = Kernel::get_ms_count();
uint32_t delay;
if (now >= millisec) {
delay = 0;
} else if (millisec - now >= osWaitForever) {
delay = osWaitForever - 1;
} else {
delay = millisec - now;
}
return alloc_for(delay);
}

/** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
@return address of the allocated memory block or NULL in case of no memory available.
@note You may call this function from ISR context.
*/
T *calloc(void)
{
T *item = (T *)osMemoryPoolAlloc(_id, 0);
T *item = alloc();
if (item != NULL) {
memset(item, 0, sizeof(T));
}
return item;
}

/** Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero.
@return address of the allocated memory block or NULL in case of no memory available.
@note You may call this function from ISR context if the millisec parameter is set to 0.
*/
T *calloc_for(uint32_t millisec)
{
T *item = alloc_for(millisec);
if (item != NULL) {
memset(item, 0, sizeof(T));
}
return item;
}

/** Allocate a memory block from a memory pool, blocking, and set memory block to zero.
@param millisec absolute timeout time, referenced to Kernel::get_ms_count().
@return address of the allocated memory block or NULL in case of no memory available.
@note You cannot call this function from ISR context.
@note the underlying RTOS may have a limit to the maximum wait time
due to internal 32-bit computations, but this is guaranteed to work if the
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
the wait will time out earlier than specified.
*/
T *calloc_until(uint64_t millisec)
{
T *item = alloc_until(millisec);
if (item != NULL) {
memset(item, 0, sizeof(T));
}
Expand All @@ -110,7 +178,7 @@ class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
*/
osStatus free(T *block)
{
return osMemoryPoolFree(_id, (void *)block);
return osMemoryPoolFree(_id, block);
}

private:
Expand Down

0 comments on commit 86e177f

Please sign in to comment.