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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [memalloc/] [common/] [v2_0/] [include/] [mempolt2.inl] - Blame information for rev 232

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

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

powered by: WebSVN 2.1.0

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