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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [src/] [sync/] [cnt_sem.cxx] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      sync/cnt_sem.cxx
4
//
5
//      Counting semaphore implementation
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):   nickg
44
// Contributors:        nickg
45
// Date:        1997-09-24
46
// Purpose:     Cyg_Counting_Semaphore implementation
47
// Description: This file contains the implementations of the counting semaphore
48
//              class.
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
#include <pkgconf/kernel.h>
55
 
56
#include <cyg/kernel/ktypes.h>         // base kernel types
57
#include <cyg/infra/cyg_trac.h>        // tracing macros
58
#include <cyg/infra/cyg_ass.h>         // assertion macros
59
#include <cyg/kernel/instrmnt.h>       // instrumentation
60
 
61
#include <cyg/kernel/thread.inl>       // Cyg_Thread inlines
62
 
63
#include <cyg/kernel/sema.hxx>         // our header
64
 
65
#include <cyg/kernel/sched.inl>        // scheduler inlines
66
 
67
// -------------------------------------------------------------------------
68
// Constructor
69
 
70
Cyg_Counting_Semaphore::Cyg_Counting_Semaphore(
71
    cyg_count32 init_count              // Initial count value
72
    )
73
{
74
    count       = init_count;
75
}
76
 
77
// -------------------------------------------------------------------------
78
// Destructor
79
 
80
Cyg_Counting_Semaphore::~Cyg_Counting_Semaphore()
81
{
82
    CYG_ASSERT( queue.empty(), "Destroying semaphore with waiting threads");
83
}
84
 
85
// -------------------------------------------------------------------------
86
// Wait until the count can be decremented without it becoming
87
// negative.
88
 
89
cyg_bool Cyg_Counting_Semaphore::wait()
90
{
91
    cyg_bool result = true;
92
    Cyg_Thread *self = Cyg_Thread::self();
93
 
94
    // Prevent preemption
95
    Cyg_Scheduler::lock();
96
 
97
    CYG_INSTRUMENT_CNTSEM( CLAIM, this, count );
98
 
99
    while( count == 0 && result )
100
    {
101
        self->set_sleep_reason( Cyg_Thread::WAIT );
102
 
103
        self->sleep();
104
 
105
        queue.enqueue( self );
106
 
107
        CYG_INSTRUMENT_CNTSEM( WAIT, this, 0 );
108
 
109
        // Allow other threads to run
110
        Cyg_Scheduler::reschedule();
111
 
112
        CYG_INSTRUMENT_CNTSEM( WOKE, this, count );
113
 
114
        switch( self->get_wake_reason() )
115
        {
116
        case Cyg_Thread::DESTRUCT:
117
        case Cyg_Thread::BREAK:
118
            result = false;
119
            break;
120
 
121
        case Cyg_Thread::EXIT:
122
            self->exit();
123
            break;
124
 
125
        default:
126
            break;
127
        }
128
    }
129
 
130
    if( result ) count--;
131
 
132
    // Unlock the scheduler
133
    Cyg_Scheduler::unlock();
134
 
135
    return result;
136
}
137
 
138
// -------------------------------------------------------------------------
139
// Wait until the count can be decremented without it becoming
140
// negative.
141
 
142
#ifdef CYGFUN_KERNEL_THREADS_TIMER
143
 
144
cyg_bool
145
Cyg_Counting_Semaphore::wait( cyg_tick_count timeout )
146
{
147
    cyg_bool result = true;
148
    Cyg_Thread *self = Cyg_Thread::self();
149
 
150
    // Prevent preemption
151
    Cyg_Scheduler::lock();
152
 
153
    CYG_INSTRUMENT_CNTSEM( CLAIM, this, count );
154
 
155
    // Set the timer _once_ outside the loop.
156
    self->set_timer( timeout, Cyg_Thread::TIMEOUT  );
157
 
158
    // If the timeout is in the past, the wake reason will have been
159
    // set to something other than NONE already. Set the result false
160
    // to force an immediate return.
161
 
162
    if( self->get_wake_reason() != Cyg_Thread::NONE )
163
        result = false;
164
 
165
    while ( 0 == count && result ) {
166
 
167
        // must reset the sleep reason every time
168
        self->set_sleep_reason( Cyg_Thread::TIMEOUT );
169
 
170
        self->sleep();
171
 
172
        queue.enqueue( self );
173
 
174
        CYG_INSTRUMENT_CNTSEM( WAIT, this, 0 );
175
 
176
        // Allow other threads to run
177
        Cyg_Scheduler::reschedule();
178
 
179
        CYG_INSTRUMENT_CNTSEM( WOKE, this, count );
180
 
181
        switch( self->get_wake_reason() )
182
        {
183
        case Cyg_Thread::TIMEOUT:
184
            result = false;
185
            CYG_INSTRUMENT_CNTSEM( TIMEOUT, this, count);
186
            break;
187
 
188
        case Cyg_Thread::DESTRUCT:
189
        case Cyg_Thread::BREAK:
190
            result = false;
191
            break;
192
 
193
        case Cyg_Thread::EXIT:
194
            self->exit();
195
            break;
196
 
197
        default:
198
            break;
199
        }
200
    }
201
 
202
    // Clear the timeout. It is irrelevant whether the alarm has
203
    // actually gone off or not.
204
    self->clear_timer();
205
 
206
    if ( result ) count--;
207
 
208
    // Unlock the scheduler and maybe switch threads
209
    Cyg_Scheduler::unlock();
210
 
211
    return result;
212
}
213
 
214
#endif // CYGFUN_KERNEL_THREADS_TIMER
215
 
216
// -------------------------------------------------------------------------
217
// Try to decrement, but fail if not possible
218
 
219
cyg_bool Cyg_Counting_Semaphore::trywait()
220
{
221
    cyg_bool result = true;
222
 
223
    // Prevent preemption
224
    Cyg_Scheduler::lock();
225
 
226
    if( count > 0 ) count--;
227
    else            result = false;
228
 
229
    CYG_INSTRUMENT_CNTSEM( TRY, this, result );
230
 
231
    // Unlock the scheduler and maybe switch threads
232
    Cyg_Scheduler::unlock();
233
 
234
    return result;
235
}
236
 
237
// -------------------------------------------------------------------------
238
// Increment count
239
 
240
void Cyg_Counting_Semaphore::post()
241
{
242
    // Prevent preemption
243
    Cyg_Scheduler::lock();
244
 
245
    CYG_INSTRUMENT_CNTSEM( POST, this, 0 );
246
 
247
    count++;
248
 
249
    if( !queue.empty() ) {
250
 
251
        // The queue is non-empty, so grab the next
252
        // thread from it and wake it up. The waiter
253
        // will decrement the count when he is awakened.
254
 
255
        Cyg_Thread *thread = queue.dequeue();
256
 
257
        thread->set_wake_reason( Cyg_Thread::DONE );
258
 
259
        thread->wake();
260
 
261
        CYG_INSTRUMENT_CNTSEM( WAKE, this, thread );
262
    }
263
 
264
    // Unlock the scheduler and maybe switch threads
265
    Cyg_Scheduler::unlock();
266
}
267
 
268
// -------------------------------------------------------------------------
269
// Get current count value
270
 
271
cyg_count32 Cyg_Counting_Semaphore::peek() const
272
{
273
    // This is a single read of the value of count.
274
    // This is already atomic, hence there is no need
275
    // to lock the scheduler.
276
 
277
    return count;
278
}
279
 
280
// -------------------------------------------------------------------------
281
// EOF sync/cnt_sem.cxx

powered by: WebSVN 2.1.0

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