OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [services/] [memalloc/] [common/] [current/] [include/] [mempolt2.inl] - Blame information for rev 819

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
#ifndef CYGONCE_MEMALLOC_MEMPOLT2_INL
2
#define CYGONCE_MEMALLOC_MEMPOLT2_INL
3
 
4
//==========================================================================
5
//
6
//      mempolt2.inl
7
//
8
//      Mempolt2 (Memory pool template) class declarations
9
//
10
//==========================================================================
11
// ####ECOSGPLCOPYRIGHTBEGIN####
12
// -------------------------------------------
13
// This file is part of eCos, the Embedded Configurable Operating System.
14
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
15
//
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
19
// version.
20
//
21
// eCos is distributed in the hope that it will be useful, but WITHOUT
22
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
// for more details.
25
//
26
// You should have received a copy of the GNU General Public License
27
// along with eCos; if not, write to the Free Software Foundation, Inc.,
28
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
29
//
30
// As a special exception, if other files instantiate templates or use
31
// macros or inline functions from this file, or you compile this file
32
// and link it with other works to produce a work based on this file,
33
// this file does not by itself cause the resulting work to be covered by
34
// the GNU General Public License. However the source code for this file
35
// must still be made available in accordance with section (3) of the GNU
36
// General Public License v2.
37
//
38
// This exception does not invalidate any other reasons why a work based
39
// on this file might be covered by the GNU General Public License.
40
// -------------------------------------------
41
// ####ECOSGPLCOPYRIGHTEND####
42
//==========================================================================
43
//#####DESCRIPTIONBEGIN####
44
//
45
// Author(s):    hmt
46
// Contributors: jlarmour
47
// Date:         2000-06-12
48
// Purpose:      Define Mempolt2 class interface
49
// Description:  The class defined here provides the APIs for thread-safe,
50
//               kernel-savvy memory managers; make a class with the
51
//               underlying allocator as the template parameter.
52
// Usage:        #include 
53
//
54
//
55
//####DESCRIPTIONEND####
56
//
57
//==========================================================================
58
 
59
#include     // assertion support
60
#include    // tracing support
61
#include   // implementation eg. Cyg_Thread::self();
62
#include    // implementation eg. Cyg_Scheduler::lock();
63
 
64
// -------------------------------------------------------------------------
65
// Constructor; we _require_ these arguments and just pass them through to
66
// the implementation memory pool in use.
67
template 
68
Cyg_Mempolt2::Cyg_Mempolt2(
69
    cyg_uint8 *base,
70
    cyg_int32 size,
71
    CYG_ADDRWORD arg_thru)              // Constructor
72
    : pool( base, size, arg_thru )
73
{
74
}
75
 
76
 
77
template 
78
Cyg_Mempolt2::~Cyg_Mempolt2()  // destructor
79
{
80
    // Prevent preemption
81
    Cyg_Scheduler::lock();
82
 
83
    while ( ! queue.empty() ) {
84
        Cyg_Thread *thread = queue.dequeue();
85
        thread->set_wake_reason( Cyg_Thread::DESTRUCT );
86
        thread->wake();
87
    }
88
 
89
    // Unlock the scheduler and maybe switch threads
90
    Cyg_Scheduler::unlock();
91
}
92
 
93
// -------------------------------------------------------------------------
94
// get some memory; wait if none available
95
template 
96
inline cyg_uint8 *
97
Cyg_Mempolt2::alloc( cyg_int32 size )
98
{
99
    CYG_REPORT_FUNCTION();
100
 
101
    // Prevent preemption
102
    Cyg_Scheduler::lock();
103
    CYG_ASSERTCLASS( this, "Bad this pointer");
104
 
105
    cyg_uint8 *ret;
106
    ret = pool.try_alloc( size );
107
    if ( ret ) {
108
        Cyg_Scheduler::unlock();
109
        CYG_ASSERTCLASS( this, "Bad this pointer");
110
        CYG_REPORT_RETVAL( ret );
111
        return ret;
112
    }
113
 
114
    Cyg_Thread *self = Cyg_Thread::self();
115
 
116
    Mempolt2WaitInfo waitinfo( size );
117
 
118
    CYG_MEMALLOC_FAIL(size);
119
 
120
    self->set_wait_info( (CYG_ADDRWORD)&waitinfo );
121
    self->set_sleep_reason( Cyg_Thread::WAIT );
122
    self->sleep();
123
    queue.enqueue( self );
124
 
125
    CYG_ASSERT( 1 == Cyg_Scheduler::get_sched_lock(),
126
                "Called with non-zero scheduler lock");
127
 
128
    // Unlock scheduler and allow other threads to run
129
    Cyg_Scheduler::unlock();
130
 
131
    cyg_bool result = true; // just used as a flag here
132
    switch( self->get_wake_reason() )
133
    {
134
    case Cyg_Thread::DESTRUCT:
135
    case Cyg_Thread::BREAK:
136
        result = false;
137
        break;
138
 
139
    case Cyg_Thread::EXIT:
140
        self->exit();
141
        break;
142
 
143
    default:
144
        break;
145
    }
146
 
147
    if ( ! result )
148
        ret = NULL;
149
    else
150
        ret = waitinfo.addr;
151
 
152
    CYG_ASSERT( (!result) || (NULL != ret), "Good result but no alloc!" );
153
    CYG_ASSERTCLASS( this, "Bad this pointer");
154
    CYG_REPORT_RETVAL( ret );
155
    return ret;
156
}
157
 
158
#ifdef CYGFUN_KERNEL_THREADS_TIMER
159
// -------------------------------------------------------------------------
160
// get some memory with a timeout
161
template 
162
inline cyg_uint8 *
163
Cyg_Mempolt2::alloc( cyg_int32 size, cyg_tick_count abs_timeout )
164
{
165
    CYG_REPORT_FUNCTION();
166
 
167
    // Prevent preemption
168
    Cyg_Scheduler::lock();
169
    CYG_ASSERTCLASS( this, "Bad this pointer");
170
 
171
    cyg_uint8 *ret;
172
    ret = pool.try_alloc( size );
173
    if ( ret ) {
174
        Cyg_Scheduler::unlock();
175
        CYG_ASSERTCLASS( this, "Bad this pointer");
176
        CYG_REPORT_RETVAL( ret );
177
        return ret;
178
    }
179
 
180
    Cyg_Thread *self = Cyg_Thread::self();
181
 
182
    Mempolt2WaitInfo waitinfo( size );
183
 
184
    self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT );
185
 
186
    // If the timeout is in the past, the wake reason will have been set to
187
    // something other than NONE already. If so, skip the wait and go
188
    // straight to unlock.
189
 
190
    if( Cyg_Thread::NONE == self->get_wake_reason() ) {
191
 
192
        CYG_MEMALLOC_FAIL(size);
193
 
194
        self->set_wait_info( (CYG_ADDRWORD)&waitinfo );
195
        self->sleep();
196
        queue.enqueue( self );
197
    }
198
 
199
    CYG_ASSERT( 1 == Cyg_Scheduler::get_sched_lock(),
200
                "Called with non-zero scheduler lock");
201
 
202
    // Unlock scheduler and allow other threads to run
203
    Cyg_Scheduler::unlock();
204
 
205
    // clear the timer; if it actually fired, no worries.
206
    self->clear_timer();
207
 
208
    cyg_bool result = true; // just used as a flag here
209
    switch( self->get_wake_reason() )
210
    {
211
    case Cyg_Thread::TIMEOUT:
212
        result = false;
213
        break;
214
 
215
    case Cyg_Thread::DESTRUCT:
216
    case Cyg_Thread::BREAK:
217
        result = false;
218
        break;
219
 
220
    case Cyg_Thread::EXIT:
221
        self->exit();
222
        break;
223
 
224
    default:
225
        break;
226
    }
227
 
228
    if ( ! result )
229
        ret = NULL;
230
    else
231
        ret = waitinfo.addr;
232
 
233
    CYG_ASSERT( (!result) || (NULL != ret), "Good result but no alloc!" );
234
    CYG_ASSERTCLASS( this, "Bad this pointer");
235
    CYG_REPORT_RETVAL( ret );
236
    return ret;
237
}
238
#endif
239
 
240
// -------------------------------------------------------------------------
241
// get some memory, return NULL if none available
242
template 
243
inline cyg_uint8 *
244
Cyg_Mempolt2::try_alloc( cyg_int32 size )
245
{
246
    CYG_REPORT_FUNCTION();
247
 
248
    // Prevent preemption
249
    Cyg_Scheduler::lock();
250
    CYG_ASSERTCLASS( this, "Bad this pointer");
251
 
252
    cyg_uint8 *ret = pool.try_alloc( size );
253
 
254
    CYG_ASSERTCLASS( this, "Bad this pointer");
255
 
256
    // Unlock the scheduler and maybe switch threads
257
    Cyg_Scheduler::unlock();
258
 
259
    CYG_MEMALLOC_FAIL_TEST(ret==NULL, size);
260
 
261
    return ret;
262
}
263
 
264
 
265
// -------------------------------------------------------------------------
266
// resize existing allocation, if oldsize is non-NULL, previous
267
// allocation size is placed into it. If previous size not available,
268
// it is set to 0. NB previous allocation size may have been rounded up.
269
// Occasionally the allocation can be adjusted *backwards* as well as,
270
// or instead of forwards, therefore the address of the resized
271
// allocation is returned, or NULL if no resizing was possible.
272
// Note that this differs from ::realloc() in that no attempt is
273
// made to call malloc() if resizing is not possible - that is left
274
// to higher layers. The data is copied from old to new though.
275
// The effects of alloc_ptr==NULL or newsize==0 are undefined
276
template 
277
cyg_uint8 *
278
Cyg_Mempolt2::resize_alloc( cyg_uint8 *alloc_ptr, cyg_int32 newsize,
279
                               cyg_int32 *oldsize )
280
{
281
    CYG_REPORT_FUNCTION();
282
 
283
    // Prevent preemption
284
    Cyg_Scheduler::lock();
285
    CYG_ASSERTCLASS( this, "Bad this pointer");
286
 
287
    cyg_uint8 *ret = pool.resize_alloc( alloc_ptr, newsize, oldsize );
288
 
289
    CYG_ASSERTCLASS( this, "Bad this pointer");
290
 
291
    // Unlock the scheduler and maybe switch threads
292
    Cyg_Scheduler::unlock();
293
 
294
    CYG_MEMALLOC_FAIL_TEST(ret==NULL, newsize);
295
 
296
    return ret;
297
}
298
 
299
 
300
// -------------------------------------------------------------------------
301
// free the memory back to the pool
302
template 
303
cyg_bool
304
Cyg_Mempolt2::free( cyg_uint8 *p, cyg_int32 size )
305
{
306
    CYG_REPORT_FUNCTION();
307
    // Prevent preemption
308
    Cyg_Scheduler::lock();
309
    CYG_ASSERTCLASS( this, "Bad this pointer");
310
 
311
    cyg_int32 ret = pool.free( p, size );
312
 
313
    // anyone waiting?
314
    if ( !(queue.empty()) ) {
315
        Mempolt2WaitInfo *p;
316
        Cyg_Thread     *thread;
317
 
318
#ifdef CYGIMP_MEM_T_ONEFREE_TO_ONEALLOC
319
        thread = queue.dequeue();
320
        p = (Mempolt2WaitInfo *)(thread->get_wait_info());
321
        CYG_ASSERT( NULL == p->addr, "Thread already awoken?" );
322
 
323
        cyg_uint8 *mem;
324
        mem = pool.try_alloc( p->size );
325
        CYG_ASSERT( NULL != mem, "That should have succeeded" );
326
        thread->set_wake_reason( Cyg_Thread::DONE );
327
        thread->wake();
328
        // return the successful value to it
329
        p->addr = mem;
330
#else
331
        Cyg_ThreadQueue holding;
332
        do {
333
            thread = queue.dequeue();
334
            p = (Mempolt2WaitInfo *)(thread->get_wait_info());
335
            CYG_ASSERT( NULL == p->addr, "Thread already awoken?" );
336
 
337
            cyg_uint8 *mem;
338
            if ( NULL != (mem = pool.try_alloc( p->size )) ) {
339
                // success!  awaken the thread
340
                thread->set_wake_reason( Cyg_Thread::DONE );
341
                thread->wake();
342
                // return the successful value to it
343
                p->addr = mem;
344
            }
345
            else {
346
                // preserve the entry on the holding queue
347
                holding.enqueue( thread );
348
            }
349
        } while ( !(queue.empty()) );
350
 
351
        // Now re-queue the unaffected threads back into the pool queue
352
        // (no pun intended)
353
        while ( !(holding.empty()) ) {
354
            queue.enqueue( holding.dequeue() );
355
        }
356
#endif // CYGIMP_MEM_T_ONEFREE_TO_ONEALLOC
357
    }
358
    // Unlock the scheduler and maybe switch threads
359
    Cyg_Scheduler::unlock();
360
    CYG_REPORT_RETVAL( ret );
361
    return ret;
362
}
363
 
364
// -------------------------------------------------------------------------
365
// Get memory pool status
366
// Needs atomicity protection (maybe)
367
template 
368
inline void
369
Cyg_Mempolt2::get_status( cyg_mempool_status_flag_t flags,
370
                             Cyg_Mempool_Status &status )
371
{
372
    // Prevent preemption
373
    Cyg_Scheduler::lock();
374
    CYG_ASSERTCLASS( this, "Bad this pointer");
375
 
376
    if (0 != (flags & CYG_MEMPOOL_STAT_WAITING)) {
377
        status.waiting = (0 == queue.empty());
378
    }
379
    pool.get_status(flags, status);
380
 
381
    // Unlock the scheduler and maybe switch threads
382
    Cyg_Scheduler::unlock();
383
}
384
 
385
// -------------------------------------------------------------------------
386
// debugging/assert function
387
 
388
#ifdef CYGDBG_USE_ASSERTS
389
 
390
template 
391
inline cyg_bool
392
Cyg_Mempolt2::check_this(cyg_assert_class_zeal zeal) const
393
{
394
    CYG_REPORT_FUNCTION();
395
 
396
    if ( Cyg_Thread::DESTRUCT == Cyg_Thread::self()->get_wake_reason() )
397
        // then the whole thing is invalid, and we know it.
398
        // so return OK, since this check should NOT make an error.
399
        return true;
400
 
401
    // check that we have a non-NULL pointer first
402
    if( this == NULL ) return false;
403
 
404
    return true;
405
}
406
#endif
407
 
408
// -------------------------------------------------------------------------
409
#endif // ifndef CYGONCE_MEMALLOC_MEMPOLT2_INL
410
// EOF mempolt2.inl

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.