Skip to content

Commit e2a965f

Browse files
committed
Mail/MemoryPool: blocking alloc
Mail and MemoryPool did not permit access to the blocking form of allocation available in CMSIS-RTOS 2 - give them new blocking methods.
1 parent f1e664b commit e2a965f

File tree

2 files changed

+142
-10
lines changed

2 files changed

+142
-10
lines changed

rtos/Mail.h

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "mbed_rtos_storage.h"
3232
#include "mbed_rtos1_types.h"
3333

34+
#include "platform/mbed_toolchain.h"
3435
#include "platform/NonCopyable.h"
3536

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

93-
/** Allocate a memory block of type T.
94+
/** Allocate a memory block of type T, without blocking.
9495
*
95-
* @param millisec Not used.
96+
* @param millisec Not used (see note).
9697
*
9798
* @return Pointer to memory block that you can fill with mail or NULL in case error.
9899
*
99100
* @note You may call this function from ISR context.
101+
* @note If blocking is required, use Mail::alloc_for or Mail::alloc_until
100102
*/
101-
T *alloc(uint32_t millisec = 0)
103+
T *alloc(MBED_UNUSED uint32_t millisec = 0)
102104
{
103105
return _pool.alloc();
104106
}
105107

108+
/** Allocate a memory block of type T, optionally blocking.
109+
*
110+
* @param millisec Timeout value, or osWaitForever.
111+
*
112+
* @return Pointer to memory block that you can fill with mail or NULL in case error.
113+
*
114+
* @note You may call this function from ISR context if the millisec parameter is set to 0.
115+
*/
116+
T *alloc_for(uint32_t millisec)
117+
{
118+
return _pool.alloc_for(millisec);
119+
}
120+
121+
/** Allocate a memory block of type T, blocking.
122+
*
123+
* @param millisec Absolute timeout time, referenced to Kernel::get_ms_count().
124+
*
125+
* @return Pointer to memory block that you can fill with mail or NULL in case error.
126+
*
127+
* @note You cannot call this function from ISR context.
128+
* @note the underlying RTOS may have a limit to the maximum wait time
129+
* due to internal 32-bit computations, but this is guaranteed to work if the
130+
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
131+
* the wait will time out earlier than specified.
132+
*/
133+
T *alloc_until(uint64_t millisec)
134+
{
135+
return _pool.alloc_until(millisec);
136+
}
137+
106138
/** Allocate a memory block of type T, and set memory block to zero.
107139
*
108-
* @param millisec Not used.
140+
* @param millisec Not used (see note).
109141
*
110142
* @return Pointer to memory block that you can fill with mail or NULL in case error.
111143
*
112-
* @note You may call this function from ISR context.
144+
* @note You may call this function from ISR context if the millisec parameter is set to 0.
145+
* @note If blocking is required, use Mail::calloc_for or Mail::calloc_until
113146
*/
114-
T *calloc(uint32_t millisec = 0)
147+
T *calloc(MBED_UNUSED uint32_t millisec = 0)
115148
{
116149
return _pool.calloc();
117150
}
118151

152+
/** Allocate a memory block of type T, optionally blocking, and set memory block to zero.
153+
*
154+
* @param millisec Timeout value, or osWaitForever.
155+
*
156+
* @return Pointer to memory block that you can fill with mail or NULL in case error.
157+
*
158+
* @note You may call this function from ISR context if the millisec parameter is set to 0.
159+
*/
160+
T *calloc_for(uint32_t millisec)
161+
{
162+
return _pool.calloc_for(millisec);
163+
}
164+
165+
/** Allocate a memory block of type T, blocking, and set memory block to zero.
166+
*
167+
* @param millisec Absolute timeout time, referenced to Kernel::get_ms_count().
168+
*
169+
* @return Pointer to memory block that you can fill with mail or NULL in case error.
170+
*
171+
* @note You cannot call this function from ISR context.
172+
* @note the underlying RTOS may have a limit to the maximum wait time
173+
* due to internal 32-bit computations, but this is guaranteed to work if the
174+
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
175+
* the wait will time out earlier than specified.
176+
*/
177+
T *calloc_until(uint64_t millisec)
178+
{
179+
return _pool.calloc_until(millisec);
180+
}
181+
119182
/** Put a mail in the queue.
120183
*
121184
* @param mptr Memory block previously allocated with Mail::alloc or Mail::calloc.

rtos/MemoryPool.h

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
7676
osMemoryPoolDelete(_id);
7777
}
7878

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

89-
/** Allocate a memory block of type T from a memory pool and set memory block to zero.
89+
/** Allocate a memory block from a memory pool, optionally blocking.
90+
@param millisec timeout value (osWaitForever to wait forever)
91+
@return address of the allocated memory block or NULL in case of no memory available.
92+
93+
@note You may call this function from ISR context if the millisec parameter is set to 0.
94+
*/
95+
T *alloc_for(uint32_t millisec)
96+
{
97+
return (T *)osMemoryPoolAlloc(_id, millisec);
98+
}
99+
100+
/** Allocate a memory block from a memory pool, blocking.
101+
@param millisec absolute timeout time, referenced to Kernel::get_ms_count().
102+
@return address of the allocated memory block or NULL in case of no memory available.
103+
104+
@note You cannot call this function from ISR context.
105+
@note the underlying RTOS may have a limit to the maximum wait time
106+
due to internal 32-bit computations, but this is guaranteed to work if the
107+
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
108+
the wait will time out earlier than specified.
109+
*/
110+
T *alloc_until(uint64_t millisec)
111+
{
112+
uint64_t now = Kernel::get_ms_count();
113+
uint32_t delay;
114+
if (now >= millisec) {
115+
delay = 0;
116+
} else if (millisec - now >= osWaitForever) {
117+
delay = osWaitForever - 1;
118+
} else {
119+
delay = millisec - now;
120+
}
121+
return alloc_for(delay);
122+
}
123+
124+
/** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
90125
@return address of the allocated memory block or NULL in case of no memory available.
91126
92127
@note You may call this function from ISR context.
93128
*/
94129
T *calloc(void)
95130
{
96-
T *item = (T *)osMemoryPoolAlloc(_id, 0);
131+
T *item = alloc();
132+
if (item != NULL) {
133+
memset(item, 0, sizeof(T));
134+
}
135+
return item;
136+
}
137+
138+
/** Allocate a memory block from a memory pool, optionally blocking, and set memory block to zero.
139+
@param millisec timeout value (osWaitForever to wait forever)
140+
@return address of the allocated memory block or NULL in case of no memory available.
141+
142+
@note You may call this function from ISR context if the millisec parameter is set to 0.
143+
*/
144+
T *calloc_for(uint32_t millisec)
145+
{
146+
T *item = alloc_for(millisec);
147+
if (item != NULL) {
148+
memset(item, 0, sizeof(T));
149+
}
150+
return item;
151+
}
152+
153+
/** Allocate a memory block from a memory pool, blocking, and set memory block to zero.
154+
@param millisec absolute timeout time, referenced to Kernel::get_ms_count().
155+
@return address of the allocated memory block or NULL in case of no memory available.
156+
157+
@note You cannot call this function from ISR context.
158+
@note the underlying RTOS may have a limit to the maximum wait time
159+
due to internal 32-bit computations, but this is guaranteed to work if the
160+
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
161+
the wait will time out earlier than specified.
162+
*/
163+
T *calloc_until(uint64_t millisec)
164+
{
165+
T *item = alloc_until(millisec);
97166
if (item != NULL) {
98167
memset(item, 0, sizeof(T));
99168
}
@@ -110,7 +179,7 @@ class MemoryPool : private mbed::NonCopyable<MemoryPool<T, pool_sz> > {
110179
*/
111180
osStatus free(T *block)
112181
{
113-
return osMemoryPoolFree(_id, (void *)block);
182+
return osMemoryPoolFree(_id, block);
114183
}
115184

116185
private:

0 commit comments

Comments
 (0)