1 #ifndef CYGONCE_KERNEL_MEMPOOLT_INL
2 #define CYGONCE_KERNEL_MEMPOOLT_INL
4 //==========================================================================
8 // Mempoolt (Memory pool template) class declarations
10 //==========================================================================
11 //####ECOSGPLCOPYRIGHTBEGIN####
12 // -------------------------------------------
13 // This file is part of eCos, the Embedded Configurable Operating System.
14 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
16 // eCos is free software; you can redistribute it and/or modify it under
17 // the terms of the GNU General Public License as published by the Free
18 // Software Foundation; either version 2 or (at your option) any later version.
20 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
21 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 // You should have received a copy of the GNU General Public License along
26 // with eCos; if not, write to the Free Software Foundation, Inc.,
27 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29 // As a special exception, if other files instantiate templates or use macros
30 // or inline functions from this file, or you compile this file and link it
31 // with other works to produce a work based on this file, this file does not
32 // by itself cause the resulting work to be covered by the GNU General Public
33 // License. However the source code for this file must still be made available
34 // in accordance with section (3) of the GNU General Public License.
36 // This exception does not invalidate any other reasons why a work based on
37 // this file might be covered by the GNU General Public License.
39 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
40 // at http://sources.redhat.com/ecos/ecos-license/
41 // -------------------------------------------
42 //####ECOSGPLCOPYRIGHTEND####
43 //==========================================================================
44 //#####DESCRIPTIONBEGIN####
49 // Purpose: Define Mempoolt class interface
51 // Description: The class defined here provides the APIs for thread-safe,
52 // kernel-savvy memory managers; make a class with the
53 // underlying allocator as the template parameter.
54 // Usage: #include <cyg/kernel/mempoolt.hxx>
57 //####DESCRIPTIONEND####
59 //==========================================================================
61 #include <cyg/kernel/thread.inl> // implementation eg. Cyg_Thread::self();
62 #include <cyg/kernel/sched.inl> // implementation eg. Cyg_Scheduler::lock();
64 // -------------------------------------------------------------------------
65 // Constructor; we _require_ these arguments and just pass them through to
66 // the implementation memory pool in use.
68 Cyg_Mempoolt<T>::Cyg_Mempoolt(
71 CYG_ADDRWORD arg_thru) // Constructor
72 : pool( base, size, arg_thru )
78 Cyg_Mempoolt<T>::~Cyg_Mempoolt() // destructor
81 Cyg_Scheduler::lock();
83 while ( ! queue.empty() ) {
84 Cyg_Thread *thread = queue.dequeue();
85 thread->set_wake_reason( Cyg_Thread::DESTRUCT );
89 // Unlock the scheduler and maybe switch threads
90 Cyg_Scheduler::unlock();
93 // -------------------------------------------------------------------------
94 // get some memory; wait if none available
97 Cyg_Mempoolt<T>::alloc( cyg_int32 size )
99 CYG_REPORT_FUNCTION();
101 Cyg_Thread *self = Cyg_Thread::self();
103 // Prevent preemption
104 Cyg_Scheduler::lock();
105 CYG_ASSERTCLASS( this, "Bad this pointer");
107 // Loop while we got no memory, sleeping each time around the
108 // loop. This copes with the possibility of a higher priority thread
109 // grabbing the freed storage between the wakeup in free() and this
110 // thread actually starting.
112 cyg_bool result = true;
113 while( result && (NULL == (ret = pool.alloc( size ))) ) {
115 CYG_MEMALLOC_FAIL(size);
117 self->set_sleep_reason( Cyg_Thread::WAIT );
119 queue.enqueue( self );
121 CYG_ASSERT( 1 == Cyg_Scheduler::get_sched_lock(),
122 "Called with non-zero scheduler lock");
124 // Unlock scheduler and allow other threads to run
125 Cyg_Scheduler::unlock();
126 Cyg_Scheduler::lock();
128 CYG_ASSERTCLASS( this, "Bad this pointer");
130 switch( self->get_wake_reason() )
132 case Cyg_Thread::DESTRUCT:
133 case Cyg_Thread::BREAK:
137 case Cyg_Thread::EXIT:
145 CYG_ASSERTCLASS( this, "Bad this pointer");
150 // Unlock the scheduler and maybe switch threads
151 Cyg_Scheduler::unlock();
152 CYG_REPORT_RETVAL( ret );
156 #ifdef CYGFUN_KERNEL_THREADS_TIMER
157 // -------------------------------------------------------------------------
158 // get some memory with a timeout
161 Cyg_Mempoolt<T>::alloc( cyg_int32 size, cyg_tick_count abs_timeout )
163 CYG_REPORT_FUNCTION();
165 Cyg_Thread *self = Cyg_Thread::self();
167 // Prevent preemption
168 Cyg_Scheduler::lock();
169 CYG_ASSERTCLASS( this, "Bad this pointer");
171 // Loop while we got no memory, sleeping each time around the
172 // loop. This copes with the possibility of a higher priority thread
173 // grabbing the freed storage between the wakeup in free() and this
174 // thread actually starting.
176 cyg_bool result = true;
177 // Set the timer _once_ outside the loop.
178 self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT );
180 // If the timeout is in the past, the wake reason will have been
181 // set to something other than NONE already. Set the result false
182 // to force an immediate return.
184 if( self->get_wake_reason() != Cyg_Thread::NONE )
187 while( result && (NULL == (ret = pool.alloc( size ))) ) {
188 CYG_MEMALLOC_FAIL(size);
190 self->set_sleep_reason( Cyg_Thread::TIMEOUT );
192 queue.enqueue( self );
194 CYG_ASSERT( 1 == Cyg_Scheduler::get_sched_lock(),
195 "Called with non-zero scheduler lock");
197 // Unlock scheduler and allow other threads to run
198 Cyg_Scheduler::unlock();
199 Cyg_Scheduler::lock();
201 CYG_ASSERTCLASS( this, "Bad this pointer");
202 switch( self->get_wake_reason() )
204 case Cyg_Thread::TIMEOUT:
208 case Cyg_Thread::DESTRUCT:
209 case Cyg_Thread::BREAK:
213 case Cyg_Thread::EXIT:
222 CYG_ASSERTCLASS( this, "Bad this pointer");
227 // clear the timer; if it actually fired, no worries.
230 // Unlock the scheduler and maybe switch threads
231 Cyg_Scheduler::unlock();
232 CYG_REPORT_RETVAL( ret );
237 // -------------------------------------------------------------------------
238 // get some memory, return NULL if none available
241 Cyg_Mempoolt<T>::try_alloc( cyg_int32 size )
243 CYG_REPORT_FUNCTION();
245 // Prevent preemption
246 Cyg_Scheduler::lock();
247 CYG_ASSERTCLASS( this, "Bad this pointer");
249 cyg_uint8 *ret = pool.alloc( size );
251 CYG_ASSERTCLASS( this, "Bad this pointer");
253 // Unlock the scheduler and maybe switch threads
254 Cyg_Scheduler::unlock();
255 CYG_REPORT_RETVAL( ret );
257 CYG_MEMALLOC_FAIL_TEST(ret==NULL, size);
263 // -------------------------------------------------------------------------
264 // free the memory back to the pool
267 Cyg_Mempoolt<T>::free( cyg_uint8 *p, cyg_int32 size )
269 // Prevent preemption
270 Cyg_Scheduler::lock();
271 CYG_ASSERTCLASS( this, "Bad this pointer");
273 cyg_int32 ret = pool.free( p, size );
275 CYG_ASSERTCLASS( this, "Bad this pointer");
277 while ( ret && !queue.empty() ) {
278 // we succeeded and there are people waiting
279 Cyg_Thread *thread = queue.dequeue();
281 CYG_ASSERTCLASS( thread, "Bad thread pointer");
283 // we wake them all up (ie. broadcast) to cope with variable block
284 // allocators freeing a big block when lots of small allocs wait.
285 thread->set_wake_reason( Cyg_Thread::DONE );
287 // we cannot yield here; if a higher prio thread can't satisfy its
288 // request it would re-queue and we would loop forever
290 // Unlock the scheduler and maybe switch threads
291 Cyg_Scheduler::unlock();
295 // -------------------------------------------------------------------------
296 // if applicable: return -1 if not fixed size
299 Cyg_Mempoolt<T>::get_blocksize()
301 // there should not be any atomicity issues here
302 return pool.get_blocksize();
305 // -------------------------------------------------------------------------
306 // these two are obvious and generic, but need atomicity protection (maybe)
309 Cyg_Mempoolt<T>::get_totalmem()
311 // Prevent preemption
312 Cyg_Scheduler::lock();
313 CYG_ASSERTCLASS( this, "Bad this pointer");
315 cyg_int32 ret = pool.get_totalmem();
317 // Unlock the scheduler and maybe switch threads
318 Cyg_Scheduler::unlock();
324 Cyg_Mempoolt<T>::get_freemem()
326 // Prevent preemption
327 Cyg_Scheduler::lock();
328 CYG_ASSERTCLASS( this, "Bad this pointer");
330 cyg_int32 ret = pool.get_freemem();
332 // Unlock the scheduler and maybe switch threads
333 Cyg_Scheduler::unlock();
337 // -------------------------------------------------------------------------
338 // get information about the construction parameters for external
339 // freeing after the destruction of the holding object
342 Cyg_Mempoolt<T>::get_arena(
343 cyg_uint8 * &base, cyg_int32 &size, CYG_ADDRWORD &arg_thru )
345 // Prevent preemption
346 Cyg_Scheduler::lock();
347 CYG_ASSERTCLASS( this, "Bad this pointer");
349 pool.get_arena( base, size, arg_thru );
351 // Unlock the scheduler and maybe switch threads
352 Cyg_Scheduler::unlock();
355 // -------------------------------------------------------------------------
356 // Return the size of the memory allocation (previously returned
357 // by alloc() or try_alloc() ) at ptr. Returns -1 if not found
360 Cyg_Mempoolt<T>::get_allocation_size( cyg_uint8 *ptr )
364 // Prevent preemption
365 Cyg_Scheduler::lock();
366 CYG_ASSERTCLASS( this, "Bad this pointer");
368 ret = pool.get_allocation_size( ptr );
370 // Unlock the scheduler and maybe switch threads
371 Cyg_Scheduler::unlock();
376 // -------------------------------------------------------------------------
377 // debugging/assert function
379 #ifdef CYGDBG_USE_ASSERTS
383 Cyg_Mempoolt<T>::check_this(cyg_assert_class_zeal zeal) const
385 CYG_REPORT_FUNCTION();
387 if ( Cyg_Thread::DESTRUCT == Cyg_Thread::self()->get_wake_reason() )
388 // then the whole thing is invalid, and we know it.
389 // so return OK, since this check should NOT make an error.
392 // check that we have a non-NULL pointer first
393 if( this == NULL ) return false;
399 // -------------------------------------------------------------------------
400 #endif // ifndef CYGONCE_KERNEL_MEMPOOLT_INL