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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [include/] [mboxt2.inl] - Blame information for rev 530

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

Line No. Rev Author Line
1 27 unneback
#ifndef CYGONCE_KERNEL_MBOXT2_INL
2
#define CYGONCE_KERNEL_MBOXT2_INL
3
//==========================================================================
4
//
5
//      mboxt2.inl
6
//
7
//      Mboxt2 mbox template class implementation
8
//
9
//==========================================================================
10
//####ECOSGPLCOPYRIGHTBEGIN####
11
// -------------------------------------------
12
// This file is part of eCos, the Embedded Configurable Operating System.
13
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
14
//
15
// eCos is free software; you can redistribute it and/or modify it under
16
// the terms of the GNU General Public License as published by the Free
17
// Software Foundation; either version 2 or (at your option) any later version.
18
//
19
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
21
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
22
// for more details.
23
//
24
// You should have received a copy of the GNU General Public License along
25
// with eCos; if not, write to the Free Software Foundation, Inc.,
26
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27
//
28
// As a special exception, if other files instantiate templates or use macros
29
// or inline functions from this file, or you compile this file and link it
30
// with other works to produce a work based on this file, this file does not
31
// by itself cause the resulting work to be covered by the GNU General Public
32
// License. However the source code for this file must still be made available
33
// in accordance with section (3) of the GNU General Public License.
34
//
35
// This exception does not invalidate any other reasons why a work based on
36
// this file might be covered by the GNU General Public License.
37
//
38
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
39
// at http://sources.redhat.com/ecos/ecos-license/
40
// -------------------------------------------
41
//####ECOSGPLCOPYRIGHTEND####
42
//==========================================================================
43
//#####DESCRIPTIONBEGIN####
44
//
45
// Author(s):   hmt
46
// Contributors:        hmt
47
// Date:        1998-02-10
48
// Purpose:     Mboxt2 template implementation
49
// Description: This file contains the implementations of the mboxt2
50
//              template classes.
51
//
52
//####DESCRIPTIONEND####
53
//
54
//==========================================================================
55
 
56
#include          // base kernel types
57
#include         // tracing macros
58
#include          // assertion macros
59
#include        // instrumentation
60
 
61
#include        // our header
62
 
63
#include        // thread inlines
64
#include         // scheduler inlines
65
#include         // clock inlines
66
 
67
// -------------------------------------------------------------------------
68
// inline function for awakening waiting threads
69
 
70
template 
71
inline void
72
Cyg_Mboxt2::wakeup_winner( const T &msg )
73
{
74
    CYG_ASSERT( !get_threadq.empty(), "Where did the winner go?" );
75
 
76
    // The queue is non-empty, so grab the next thread and wake it up.
77
    Cyg_Thread *thread = get_threadq.dequeue();
78
 
79
    CYG_ASSERTCLASS( thread, "Bad thread pointer");
80
 
81
    T *msg_ret = (T *)(thread->get_wait_info());
82
    *msg_ret = msg;
83
 
84
    thread->set_wake_reason( Cyg_Thread::DONE );
85
    thread->wake();
86
 
87
    CYG_INSTRUMENT_MBOXT(WAKE, this, thread);
88
}
89
 
90
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
91
template 
92
inline void
93
Cyg_Mboxt2::wakeup_putter( void )
94
{
95
    if( !put_threadq.empty() ) {
96
        // The queue is non-empty, so grab the next thread and wake it up.
97
        Cyg_Thread *thread = put_threadq.dequeue();
98
 
99
        CYG_ASSERTCLASS( thread, "Bad thread pointer");
100
 
101
        T *new_msg = (T *)(thread->get_wait_info());
102
 
103
        cyg_count32 in = base + (count++);
104
        if ( size <= in )
105
            in -= size;
106
 
107
        CYG_ASSERT( size > in, "in overflow" );
108
        CYG_ASSERT( 0 <= in, "in overflow" );
109
        CYG_ASSERT( size >= count, "count overflow" );
110
 
111
        itemqueue[ in ] = *new_msg;
112
 
113
        thread->set_wake_reason( Cyg_Thread::DONE );
114
        thread->wake();
115
 
116
        CYG_INSTRUMENT_MBOXT(WAKE, this, thread);
117
    }
118
}
119
#endif
120
 
121
// -------------------------------------------------------------------------
122
// Constructor
123
 
124
template 
125
Cyg_Mboxt2::Cyg_Mboxt2()
126
{
127
    CYG_REPORT_FUNCTION();
128
    base = 0;
129
    count = 0;
130
    CYG_REPORT_RETURN();
131
}
132
 
133
// -------------------------------------------------------------------------
134
// Destructor
135
 
136
template 
137
Cyg_Mboxt2::~Cyg_Mboxt2()
138
{
139
    CYG_REPORT_FUNCTION();
140
#if 0
141
    CYG_ASSERT( 0 == count, "Deleting mboxt2 with messages");
142
    CYG_ASSERT( get_threadq.empty(), "Deleting mboxt2 with threads waiting to get");
143
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
144
    CYG_ASSERT( put_threadq.empty(), "Deleting mboxt2 with threads waiting to put");
145
#endif
146
#endif
147
    // Prevent preemption
148
    Cyg_Scheduler::lock();
149
 
150
    while ( ! get_threadq.empty() ) {
151
        Cyg_Thread *thread = get_threadq.dequeue();
152
        thread->set_wake_reason( Cyg_Thread::DESTRUCT );
153
        thread->wake();
154
    }
155
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
156
    while ( ! put_threadq.empty() ) {
157
        Cyg_Thread *thread = put_threadq.dequeue();
158
        thread->set_wake_reason( Cyg_Thread::DESTRUCT );
159
        thread->wake();
160
    }
161
#endif
162
 
163
    // Unlock the scheduler and maybe switch threads
164
    Cyg_Scheduler::unlock();
165
    CYG_REPORT_RETURN();
166
}
167
 
168
// -------------------------------------------------------------------------
169
// debugging/assert function
170
 
171
#ifdef CYGDBG_USE_ASSERTS
172
 
173
template 
174
cyg_bool
175
Cyg_Mboxt2::check_this(cyg_assert_class_zeal zeal) const
176
{
177
    if ( Cyg_Thread::DESTRUCT == Cyg_Thread::self()->get_wake_reason() )
178
        // then the whole thing is invalid, and we know it.
179
        // so return OK, since this check should NOT make an error.
180
        return true;
181
 
182
    // check that we have a non-NULL pointer first
183
    if( this == NULL ) return false;
184
 
185
#if 0 // thread queues do not have checking funcs.
186
    if ( ! get_threadq.check_this( zeal ) ) return false;
187
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
188
    if ( ! put_threadq.check_this( zeal ) ) return false;
189
#endif
190
#endif
191
 
192
    switch( zeal )
193
    {
194
    case cyg_system_test:
195
    case cyg_extreme:
196
    case cyg_thorough:
197
    case cyg_quick:
198
    case cyg_trivial:
199
        // plenty of scope for fencepost problems here
200
        if ( size < count ) return false;
201
        if ( size <= base ) return false;
202
        if ( 0 > count ) return false;
203
        if ( 0 > base  ) return false;
204
 
205
        // Comments about needing 2 queues elided; they're not true in this
206
        // immediate-dispatch model.  I think we could get away with only
207
        // one queue now, biut is it worth it?  4 bytes of redundant info
208
        // buys a lot of correctness.
209
 
210
    case cyg_none:
211
    default:
212
        break;
213
    };
214
 
215
    return true;
216
}
217
 
218
#endif
219
 
220
 
221
// -------------------------------------------------------------------------
222
// From here downwards, these are the major functions of the template; if
223
// being genuinely used as a template they should probably not be inlined.
224
// If being used to construct a specific class, with explicit functions,
225
// then they should be.  This is controlled by:
226
 
227
#ifdef CYGIMP_MBOXT_INLINE
228
#define CYG_MBOXT_INLINE inline
229
#else
230
#define CYG_MBOXT_INLINE
231
#endif
232
 
233
// -------------------------------------------------------------------------
234
// Get an item, or wait for one to arrive
235
 
236
template 
237
CYG_MBOXT_INLINE cyg_bool
238
Cyg_Mboxt2::get( T &ritem )
239
{
240
    CYG_REPORT_FUNCTION();
241
    Cyg_Thread *self = Cyg_Thread::self();
242
 
243
    // Prevent preemption
244
    Cyg_Scheduler::lock();
245
 
246
    CYG_ASSERTCLASS( this, "Bad this pointer");
247
 
248
    CYG_INSTRUMENT_MBOXT(GET, this, count);
249
 
250
    if ( 0 < count ) {
251
        CYG_INSTRUMENT_MBOXT(GOT, this, count);
252
 
253
        ritem = itemqueue[ (count--, base++) ];
254
        CYG_ASSERT( 0 <= count, "Count went -ve" );
255
        CYG_ASSERT( size >= base, "Base overflow" );
256
 
257
        if ( size <= base )
258
            base = 0;
259
 
260
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
261
        wakeup_putter();
262
#endif
263
 
264
        // Unlock the scheduler and definitely switch threads
265
        Cyg_Scheduler::unlock();
266
 
267
        CYG_ASSERTCLASS( this, "Bad this pointer");
268
        CYG_REPORT_RETVAL( true );
269
        return true;
270
    }
271
 
272
    self->set_wait_info( (CYG_ADDRWORD)&ritem );
273
    self->set_sleep_reason( Cyg_Thread::WAIT );
274
    self->sleep();
275
    get_threadq.enqueue( self );
276
 
277
    CYG_INSTRUMENT_MBOXT(WAIT, this, count);
278
 
279
    // Unlock scheduler and allow other threads to run
280
    Cyg_Scheduler::unlock_reschedule();
281
 
282
    cyg_bool result = true;
283
    switch( self->get_wake_reason() )
284
    {
285
    case Cyg_Thread::DESTRUCT:
286
    case Cyg_Thread::BREAK:
287
        result = false;
288
        break;
289
 
290
    case Cyg_Thread::EXIT:
291
        self->exit();
292
        break;
293
 
294
    default:
295
        break;
296
    }
297
    CYG_ASSERTCLASS( this, "Bad this pointer");
298
    CYG_REPORT_RETVAL( result );
299
    return result;
300
}
301
 
302
 
303
// -------------------------------------------------------------------------
304
// Try to get an item with an absolute timeout and return success.
305
 
306
#ifdef CYGFUN_KERNEL_THREADS_TIMER
307
template 
308
CYG_MBOXT_INLINE cyg_bool
309
Cyg_Mboxt2::get( T &ritem, cyg_tick_count abs_timeout )
310
{
311
    CYG_REPORT_FUNCTION();
312
 
313
    Cyg_Thread *self = Cyg_Thread::self();
314
 
315
    // Prevent preemption
316
    Cyg_Scheduler::lock();
317
 
318
    CYG_ASSERTCLASS( this, "Bad this pointer");
319
 
320
    CYG_INSTRUMENT_MBOXT(GET, this, count);
321
 
322
    if ( 0 < count ) {
323
        CYG_INSTRUMENT_MBOXT(GOT, this, count);
324
 
325
        ritem = itemqueue[ (count--, base++) ];
326
        CYG_ASSERT( 0 <= count, "Count went -ve" );
327
        CYG_ASSERT( size >= base, "Base overflow" );
328
 
329
        if ( size <= base )
330
            base = 0;
331
 
332
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
333
        wakeup_putter();
334
#endif
335
 
336
        // Unlock the scheduler and maybe switch threads
337
        Cyg_Scheduler::unlock();
338
 
339
        CYG_ASSERTCLASS( this, "Bad this pointer");
340
        CYG_REPORT_RETVAL( true );
341
        return true;
342
    }
343
 
344
    // Set the timer
345
    self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT );
346
 
347
    // If the timeout is in the past, the wake reason will have been set to
348
    // something other than NONE already. If so, skip the wait and go
349
    // straight to unlock.
350
 
351
    if( Cyg_Thread::NONE == self->get_wake_reason() ) {
352
        self->set_wait_info( (CYG_ADDRWORD)&ritem );
353
        self->sleep();
354
        get_threadq.enqueue( self );
355
 
356
        CYG_INSTRUMENT_MBOXT(WAIT, this, count);
357
    }
358
 
359
    // Unlock scheduler and allow other threads to run
360
    Cyg_Scheduler::unlock_reschedule();
361
 
362
    // clear the timer; if it actually fired, no worries.
363
    self->clear_timer();
364
 
365
    CYG_ASSERTCLASS( this, "Bad this pointer");
366
 
367
    cyg_bool result = true;
368
    switch( self->get_wake_reason() )
369
    {
370
    case Cyg_Thread::TIMEOUT:
371
        result = false;
372
        CYG_INSTRUMENT_MBOXT(TIMEOUT, this, count);
373
        break;
374
 
375
    case Cyg_Thread::DESTRUCT:
376
    case Cyg_Thread::BREAK:
377
        result = false;
378
        break;
379
 
380
    case Cyg_Thread::EXIT:
381
        self->exit();
382
        break;
383
 
384
    default:
385
        break;
386
    }
387
 
388
    CYG_REPORT_RETVAL( result );
389
    return result;
390
}
391
#endif // CYGFUN_KERNEL_THREADS_TIMER
392
 
393
// -------------------------------------------------------------------------
394
// Try to get an item and return success.
395
 
396
template 
397
CYG_MBOXT_INLINE cyg_bool
398
Cyg_Mboxt2::tryget( T &ritem )
399
{
400
    CYG_REPORT_FUNCTION();
401
 
402
    CYG_ASSERTCLASS( this, "Bad this pointer");
403
 
404
    // Prevent preemption
405
    Cyg_Scheduler::lock();
406
 
407
    CYG_INSTRUMENT_MBOXT(TRY, this, count);
408
 
409
    cyg_bool result = ( 0 < count );
410
    // If the mboxt2 is not empty, grab an item and return it.
411
    if ( result ) {
412
        ritem = itemqueue[ (count--, base++) ];
413
        CYG_ASSERT( 0 <= count, "Count went -ve" );
414
        CYG_ASSERT( size >= base, "Base overflow" );
415
        if ( size <= base )
416
            base = 0;
417
 
418
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
419
        wakeup_putter();
420
#endif
421
    }
422
 
423
    // Unlock the scheduler and maybe switch threads
424
    Cyg_Scheduler::unlock();
425
    CYG_REPORT_RETVAL( result );
426
    return result;
427
}
428
 
429
// -------------------------------------------------------------------------
430
// get next item without removing it
431
template 
432
CYG_MBOXT_INLINE cyg_bool
433
Cyg_Mboxt2::peek_item( T &ritem )
434
{
435
    CYG_REPORT_FUNCTION();
436
 
437
    CYG_ASSERTCLASS( this, "Bad this pointer");
438
 
439
    // Prevent preemption
440
    Cyg_Scheduler::lock();
441
 
442
    CYG_INSTRUMENT_MBOXT(TRY, this, count);
443
 
444
    cyg_bool result = ( 0 < count );
445
    // If the mboxt2 is not empty, grab an item and return it.
446
    if ( result )
447
        ritem = itemqueue[ base ];
448
 
449
    // Unlock the scheduler and maybe switch threads
450
    Cyg_Scheduler::unlock();
451
    CYG_REPORT_RETVAL( result );
452
    return result;
453
}
454
 
455
// -------------------------------------------------------------------------
456
// Put an item in the queue; wait if full.
457
 
458
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
459
template 
460
CYG_MBOXT_INLINE cyg_bool
461
Cyg_Mboxt2::put( const T item )
462
{
463
    CYG_REPORT_FUNCTION();
464
 
465
    Cyg_Thread *self = Cyg_Thread::self();
466
 
467
    // Prevent preemption
468
    Cyg_Scheduler::lock();
469
 
470
    CYG_INSTRUMENT_MBOXT(PUT, this, count);
471
    CYG_ASSERTCLASS( this, "Bad this pointer");
472
 
473
    if ( size == count ) {
474
        CYG_ASSERT( get_threadq.empty(), "Threads waiting AND queue full?" );
475
 
476
        self->set_wait_info( (CYG_ADDRWORD)&item );
477
        self->set_sleep_reason( Cyg_Thread::WAIT );
478
        self->sleep();
479
        put_threadq.enqueue( self );
480
 
481
        CYG_INSTRUMENT_MBOXT(WAIT, this, count);
482
 
483
        // when this returns, our item is in the queue.
484
        Cyg_Scheduler::unlock_reschedule();        // unlock, switch threads
485
 
486
        CYG_ASSERTCLASS( this, "Bad this pointer");
487
 
488
        cyg_bool result = true;
489
        switch( self->get_wake_reason() )
490
        {
491
        case Cyg_Thread::DESTRUCT:
492
        case Cyg_Thread::BREAK:
493
            result = false;
494
            break;
495
 
496
        case Cyg_Thread::EXIT:
497
            self->exit();
498
            break;
499
 
500
        default:
501
            break;
502
        }
503
        CYG_REPORT_RETVAL( result );
504
        return result;
505
    }
506
 
507
    if ( !get_threadq.empty() ) {
508
        wakeup_winner( item );
509
        Cyg_Scheduler::unlock();        // unlock, maybe switch threads
510
        CYG_ASSERTCLASS( this, "Bad this pointer");
511
        CYG_REPORT_RETVAL( true );
512
        return true;
513
    }
514
 
515
    cyg_count32 in = base + (count++);
516
    if ( size <= in )
517
        in -= size;
518
 
519
    CYG_ASSERT( size > in, "in overflow" );
520
    CYG_ASSERT( 0 <= in, "in overflow" );
521
    CYG_ASSERT( size >= count, "count overflow" );
522
 
523
    itemqueue[ in ] = item;
524
 
525
    CYG_ASSERTCLASS( this, "Bad this pointer");
526
 
527
    // Unlock the scheduler and maybe switch threads
528
    Cyg_Scheduler::unlock();
529
    CYG_REPORT_RETVAL( true );
530
    return true;
531
}
532
 
533
// -------------------------------------------------------------------------
534
// Put an item in the queue; wait if full, with an absolute timeout;
535
// return success.
536
 
537
#ifdef CYGFUN_KERNEL_THREADS_TIMER
538
template 
539
CYG_MBOXT_INLINE cyg_bool
540
Cyg_Mboxt2::put( const T item, cyg_tick_count abs_timeout )
541
{
542
    CYG_REPORT_FUNCTION();
543
 
544
    Cyg_Thread *self = Cyg_Thread::self();
545
 
546
    // Prevent preemption
547
    Cyg_Scheduler::lock();
548
 
549
    CYG_INSTRUMENT_MBOXT(PUT, this, count);
550
    CYG_ASSERTCLASS( this, "Bad this pointer");
551
 
552
    if ( size == count ) {
553
 
554
        CYG_ASSERT( get_threadq.empty(), "Threads waiting AND queue full?" );
555
 
556
        // Set the timer
557
        self->set_timer( abs_timeout, Cyg_Thread::TIMEOUT );
558
 
559
        // If the timeout is in the past, the wake reason will have been set to
560
        // something other than NONE already. If so, skip the wait and go
561
        // straight to unlock.
562
 
563
        if( Cyg_Thread::NONE == self->get_wake_reason() ) {
564
            self->set_wait_info( (CYG_ADDRWORD)&item );
565
            self->sleep();
566
            put_threadq.enqueue( self );
567
 
568
            CYG_INSTRUMENT_MBOXT(WAIT, this, count);
569
        }
570
 
571
        // when this returns, our item is in the queue.
572
        Cyg_Scheduler::unlock_reschedule();        // unlock, switch threads
573
 
574
        // clear the timer; if it actually fired, no worries.
575
        self->clear_timer();
576
 
577
        cyg_bool result = true;
578
        switch( self->get_wake_reason() )
579
        {
580
        case Cyg_Thread::TIMEOUT:
581
            result = false;
582
            CYG_INSTRUMENT_MBOXT(TIMEOUT, this, count);
583
            break;
584
 
585
        case Cyg_Thread::DESTRUCT:
586
        case Cyg_Thread::BREAK:
587
            result = false;
588
            break;
589
 
590
        case Cyg_Thread::EXIT:
591
            self->exit();
592
            break;
593
 
594
        default:
595
            break;
596
        }
597
 
598
        CYG_ASSERTCLASS( this, "Bad this pointer");
599
        CYG_REPORT_RETVAL( result );
600
        return result;
601
    }
602
 
603
 
604
    if ( !get_threadq.empty() ) {
605
        wakeup_winner( item );
606
        Cyg_Scheduler::unlock();        // unlock, maybe switch threads
607
        CYG_ASSERTCLASS( this, "Bad this pointer");
608
        CYG_REPORT_RETVAL( true );
609
        return true;
610
    }
611
 
612
    cyg_count32 in = base + (count++);
613
    if ( size <= in )
614
        in -= size;
615
 
616
    CYG_ASSERT( size > in, "in overflow" );
617
    CYG_ASSERT( 0 <= in, "in overflow" );
618
    CYG_ASSERT( size >= count, "count overflow" );
619
 
620
    itemqueue[ in ] = item;
621
 
622
    // Unlock the scheduler and maybe switch threads
623
    Cyg_Scheduler::unlock();
624
    CYG_ASSERTCLASS( this, "Bad this pointer");
625
    CYG_REPORT_RETVAL( true );
626
    return true;
627
}
628
#endif // CYGFUN_KERNEL_THREADS_TIMER
629
#endif // CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
630
 
631
// -------------------------------------------------------------------------
632
// Try to put an item in the queue and return success; queue may be full.
633
 
634
template 
635
CYG_MBOXT_INLINE cyg_bool
636
Cyg_Mboxt2::tryput( const T item )
637
{
638
    CYG_REPORT_FUNCTION();
639
 
640
    // Prevent preemption
641
    Cyg_Scheduler::lock();
642
 
643
    CYG_INSTRUMENT_MBOXT(PUT, this, count);
644
    CYG_ASSERTCLASS( this, "Bad this pointer");
645
 
646
    if ( size == count ) {
647
        CYG_ASSERT( get_threadq.empty(), "Threads waiting AND queue full?" );
648
        Cyg_Scheduler::unlock();        // unlock, maybe switch threads
649
        CYG_REPORT_RETVAL( false );
650
        return false;                   // the mboxt2 is full
651
    }
652
 
653
    if ( !get_threadq.empty() ) {
654
        CYG_ASSERT( 0 == count, "Threads waiting AND queue not empty" );
655
        wakeup_winner( item );
656
        Cyg_Scheduler::unlock();        // unlock, maybe switch threads
657
        CYG_REPORT_RETVAL( true );
658
        return true;
659
    }
660
 
661
    cyg_count32 in = base + (count++);
662
    if ( size <= in )
663
        in -= size;
664
 
665
    CYG_ASSERT( size > in, "in overflow" );
666
    CYG_ASSERT( 0 <= in, "in overflow" );
667
    CYG_ASSERT( size >= count, "count overflow" );
668
 
669
    itemqueue[ in ] = item;
670
 
671
    CYG_ASSERTCLASS( this, "Bad this pointer");
672
 
673
    // Unlock the scheduler and maybe switch threads
674
    Cyg_Scheduler::unlock();
675
 
676
    CYG_REPORT_RETVAL( true );
677
    return true;
678
}
679
 
680
 
681
// -------------------------------------------------------------------------
682
#endif // ifndef CYGONCE_KERNEL_MBOXT2_INL
683
// EOF mboxt2.inl

powered by: WebSVN 2.1.0

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