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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [compat/] [posix/] [v2_0/] [src/] [mutex.cxx] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      pthread.cxx
4
//
5
//      POSIX pthreads 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, jlarmour, Wade Jensen
45
// Date:                2000-03-27
46
// Purpose:             POSIX pthread implementation
47
// Description:         This file contains the implementation of the POSIX pthread
48
//                      functions.
49
//              
50
//              
51
//
52
//####DESCRIPTIONEND####
53
//
54
//==========================================================================
55
 
56
#include <pkgconf/posix.h>
57
 
58
#include <cyg/infra/cyg_trac.h>        // tracing macros
59
#include <cyg/infra/cyg_ass.h>         // assertion macros
60
 
61
#include "pprivate.h"                  // POSIX private header
62
 
63
#include <cyg/kernel/thread.hxx>       // thread definitions
64
#include <cyg/kernel/mutex.hxx>        // mutex definitions
65
#include <cyg/kernel/clock.hxx>        // clock definitions
66
#include <cyg/kernel/sched.hxx>        // scheduler primitives
67
#include <pthread.h>
68
 
69
#include <cyg/kernel/thread.inl>       // thread inlines
70
#include <cyg/kernel/sched.inl>        // scheduler inlines
71
 
72
//-----------------------------------------------------------------------------
73
// new operator to allow us to construct mutex objects
74
 
75
inline void *operator new(size_t size,  cyg_uint8 *ptr) { return (void *)ptr; };
76
 
77
//=============================================================================
78
// Mutexes
79
 
80
//-----------------------------------------------------------------------------
81
// Mutex attributes manipulation functions
82
 
83
//-----------------------------------------------------------------------------
84
// Initialize attribute object
85
 
86
externC int pthread_mutexattr_init ( pthread_mutexattr_t *attr)
87
{
88
    PTHREAD_ENTRY();
89
 
90
    PTHREAD_CHECK(attr);
91
 
92
    attr->protocol      = PTHREAD_PRIO_NONE;
93
#ifdef _POSIX_THREAD_PRIO_PROTECT    
94
    attr->prioceiling   = 0;
95
#endif
96
 
97
    PTHREAD_RETURN(0);
98
}
99
 
100
//-----------------------------------------------------------------------------
101
// Destroy attribute object
102
 
103
externC int pthread_mutexattr_destroy ( pthread_mutexattr_t *attr)
104
{
105
    PTHREAD_ENTRY();
106
 
107
    PTHREAD_CHECK(attr);
108
 
109
    // Nothing to do here...
110
 
111
    PTHREAD_RETURN(0);
112
}
113
 
114
//-----------------------------------------------------------------------------
115
// Optional functions depending on priority inversion protection options.
116
 
117
#if defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT)
118
 
119
// Set priority inversion protection protocol
120
externC int pthread_mutexattr_setprotocol ( pthread_mutexattr_t *attr,
121
                                            int protocol)
122
{
123
    PTHREAD_ENTRY();
124
 
125
    PTHREAD_CHECK(attr);
126
 
127
    switch( protocol )
128
    {
129
    case PTHREAD_PRIO_NONE:
130
#if defined(_POSIX_THREAD_PRIO_INHERIT)        
131
    case PTHREAD_PRIO_INHERIT:
132
#endif
133
#if defined(_POSIX_THREAD_PRIO_PROTECT)
134
    case PTHREAD_PRIO_PROTECT:
135
#endif        
136
        attr->protocol = protocol;
137
        PTHREAD_RETURN(0);
138
 
139
    default:
140
        PTHREAD_RETURN(EINVAL);
141
    }
142
 
143
    PTHREAD_RETURN(0);
144
}
145
 
146
// Get priority inversion protection protocol
147
externC int pthread_mutexattr_getprotocol ( pthread_mutexattr_t *attr,
148
                                            int *protocol)
149
{
150
    PTHREAD_ENTRY();
151
 
152
    PTHREAD_CHECK(attr);
153
 
154
    if( protocol != NULL )
155
        *protocol = attr->protocol;
156
 
157
    PTHREAD_RETURN(0);
158
}
159
 
160
#if defined(_POSIX_THREAD_PRIO_PROTECT)
161
 
162
// Set priority for priority ceiling protocol
163
externC int pthread_mutexattr_setprioceiling ( pthread_mutexattr_t *attr,
164
                                               int prioceiling)
165
{
166
    PTHREAD_ENTRY();
167
 
168
    PTHREAD_CHECK(attr);
169
 
170
 
171
    attr->prioceiling = prioceiling;
172
 
173
    PTHREAD_RETURN(0);
174
}
175
 
176
// Get priority for priority ceiling protocol
177
externC int pthread_mutexattr_getprioceiling ( pthread_mutexattr_t *attr,
178
                                               int *prioceiling)
179
{
180
    PTHREAD_ENTRY();
181
 
182
    PTHREAD_CHECK(attr);
183
 
184
    if( prioceiling != NULL )
185
        *prioceiling = attr->prioceiling;
186
 
187
    PTHREAD_RETURN(0);
188
}
189
 
190
// Set priority ceiling of given mutex, returning old ceiling.
191
externC int pthread_mutex_setprioceiling( pthread_mutex_t *mutex,
192
                                          int prioceiling,
193
                                          int *old_ceiling)
194
{
195
    PTHREAD_ENTRY();
196
 
197
    PTHREAD_CHECK(mutex);
198
 
199
    pthread_mutex_lock( mutex );
200
 
201
    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
202
 
203
    if( old_ceiling != NULL )
204
        *old_ceiling = mx->get_ceiling();
205
 
206
    mx->set_ceiling( prioceiling );
207
 
208
    pthread_mutex_unlock( mutex );
209
 
210
    PTHREAD_RETURN(0);
211
}
212
 
213
// Get priority ceiling of given mutex
214
externC int pthread_mutex_getprioceiling( pthread_mutex_t *mutex,
215
                                          int *prioceiling)
216
{
217
    PTHREAD_ENTRY();
218
 
219
    PTHREAD_CHECK(mutex);
220
 
221
    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
222
 
223
    if( prioceiling != NULL )
224
        *prioceiling = mx->get_ceiling();
225
 
226
    PTHREAD_RETURN(0);
227
}
228
 
229
#endif // defined(_POSIX_THREAD_PRIO_PROTECT)
230
 
231
#endif // defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT)
232
 
233
//-----------------------------------------------------------------------------
234
// Mutex functions
235
 
236
//-----------------------------------------------------------------------------
237
// Initialize mutex. If mutex_attr is NULL, use default attributes.
238
 
239
externC int pthread_mutex_init (pthread_mutex_t *mutex,
240
                                const pthread_mutexattr_t *mutex_attr)
241
{
242
    PTHREAD_ENTRY();
243
 
244
    PTHREAD_CHECK( mutex );
245
 
246
    pthread_mutexattr_t use_attr;
247
 
248
    // Set up the attributes we are going to use
249
    if( mutex_attr == NULL )
250
        pthread_mutexattr_init( &use_attr );
251
    else use_attr = *mutex_attr;
252
 
253
    // Now translate the POSIX protocol identifier into the eCos one.
254
    Cyg_Mutex::cyg_protcol protocol;
255
 
256
    switch( use_attr.protocol )
257
    {
258
#if defined(_POSIX_THREAD_PRIO_PROTECT)
259
    case PTHREAD_PRIO_PROTECT:
260
        protocol = Cyg_Mutex::CEILING;
261
        break;
262
#endif
263
#if defined(_POSIX_THREAD_PRIO_INHERIT)
264
    case PTHREAD_PRIO_INHERIT:
265
        protocol = Cyg_Mutex::INHERIT;
266
        break;
267
#endif        
268
    case PTHREAD_PRIO_NONE:
269
        protocol = Cyg_Mutex::NONE;
270
        break;
271
 
272
    default:
273
        PTHREAD_RETURN(EINVAL);
274
    }
275
 
276
    Cyg_Mutex *mx = new((cyg_uint8 *)mutex) Cyg_Mutex(  protocol );
277
 
278
    mx = mx; // silence compiler warning
279
#if defined(_POSIX_THREAD_PRIO_PROTECT)
280
    if ( protocol == Cyg_Mutex::CEILING )
281
        mx->set_ceiling( use_attr.prioceiling );
282
#endif
283
 
284
    PTHREAD_RETURN(0);
285
}
286
 
287
//-----------------------------------------------------------------------------
288
// Destroy mutex.
289
 
290
externC int pthread_mutex_destroy (pthread_mutex_t *mutex)
291
{
292
    PTHREAD_ENTRY();
293
 
294
    int err = ENOERR;
295
 
296
    PTHREAD_CHECK( mutex );
297
 
298
    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
299
 
300
    if( mx->get_owner() != NULL )
301
        err = EBUSY;
302
    else mx->~Cyg_Mutex();
303
 
304
    PTHREAD_RETURN(err);
305
}
306
 
307
//-----------------------------------------------------------------------------
308
// Lock mutex, waiting for it if necessary.
309
 
310
externC int pthread_mutex_lock (pthread_mutex_t *mutex)
311
{
312
    PTHREAD_ENTRY();
313
 
314
    PTHREAD_CHECK( mutex );
315
 
316
    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
317
 
318
    if( mx->get_owner() == Cyg_Thread::self() )
319
        PTHREAD_RETURN(EDEADLK);
320
 
321
    // Loop here until we acquire the mutex. Even if we are kicked out
322
    // of the wait by a signal or release we must retry.
323
    while( !mx->lock() )
324
        continue;
325
 
326
    PTHREAD_RETURN(0);
327
}
328
 
329
//-----------------------------------------------------------------------------
330
// Try to lock mutex.
331
 
332
externC int pthread_mutex_trylock (pthread_mutex_t *mutex)
333
{
334
    PTHREAD_ENTRY();
335
 
336
    PTHREAD_CHECK( mutex );
337
 
338
    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
339
 
340
    if( mx->get_owner() == Cyg_Thread::self() )
341
        PTHREAD_RETURN(EDEADLK);
342
 
343
    if( mx->trylock() )
344
        PTHREAD_RETURN(0);
345
 
346
    PTHREAD_RETURN(EBUSY);
347
}
348
 
349
 
350
//-----------------------------------------------------------------------------
351
// Unlock mutex.
352
 
353
externC int pthread_mutex_unlock (pthread_mutex_t *mutex)
354
{
355
    PTHREAD_ENTRY();
356
 
357
    PTHREAD_CHECK( mutex );
358
 
359
    Cyg_Mutex *mx = (Cyg_Mutex *)mutex;
360
 
361
    mx->unlock();
362
 
363
    PTHREAD_RETURN(0);
364
}
365
 
366
 
367
//=============================================================================
368
// Condition Variables
369
 
370
//-----------------------------------------------------------------------------
371
// Attribute manipulation functions
372
// We do not actually support any attributes at present, so these do nothing.
373
 
374
//-----------------------------------------------------------------------------
375
// Initialize condition variable attributes
376
 
377
externC int pthread_condattr_init (pthread_condattr_t *attr)
378
{
379
    PTHREAD_ENTRY();
380
 
381
    PTHREAD_CHECK(attr);
382
 
383
    // There are no condition variable attributes at present
384
 
385
    PTHREAD_RETURN(0);
386
}
387
 
388
//-----------------------------------------------------------------------------
389
// Destroy condition variable attributes
390
 
391
externC int pthread_condattr_destroy (pthread_condattr_t *attr)
392
{
393
    PTHREAD_ENTRY();
394
 
395
    PTHREAD_CHECK(attr);
396
 
397
    // nothing to do here...
398
 
399
    PTHREAD_RETURN(0);
400
}
401
 
402
//-----------------------------------------------------------------------------
403
// Condition variable functions
404
 
405
//-----------------------------------------------------------------------------
406
// Initialize condition variable.
407
 
408
externC int pthread_cond_init (pthread_cond_t *cond,
409
                               const pthread_condattr_t *attr)
410
{
411
    PTHREAD_ENTRY();
412
 
413
    PTHREAD_CHECK( cond );
414
 
415
    Cyg_Condition_Variable *cv =
416
        new((cyg_uint8 *)cond) Cyg_Condition_Variable();
417
 
418
    cv = cv;
419
 
420
    PTHREAD_RETURN(0);
421
}
422
 
423
//-----------------------------------------------------------------------------
424
// Destroy condition variable.
425
 
426
externC int pthread_cond_destroy (pthread_cond_t *cond)
427
{
428
    PTHREAD_ENTRY();
429
 
430
    PTHREAD_CHECK( cond );
431
 
432
    ((Cyg_Condition_Variable *)cond)->~Cyg_Condition_Variable();
433
 
434
    PTHREAD_RETURN(0);
435
}
436
 
437
//-----------------------------------------------------------------------------
438
// Wake up one thread waiting for condition variable
439
 
440
externC int pthread_cond_signal (pthread_cond_t *cond)
441
{
442
    PTHREAD_ENTRY();
443
 
444
    PTHREAD_CHECK( cond );
445
 
446
    ((Cyg_Condition_Variable *)cond)->signal();
447
 
448
    PTHREAD_RETURN(0);
449
}
450
 
451
//-----------------------------------------------------------------------------
452
// Wake up all threads waiting for condition variable
453
 
454
externC int pthread_cond_broadcast (pthread_cond_t *cond)
455
{
456
    PTHREAD_ENTRY();
457
 
458
    PTHREAD_CHECK( cond );
459
 
460
    ((Cyg_Condition_Variable *)cond)->broadcast();
461
 
462
    PTHREAD_RETURN(0);
463
}
464
 
465
//-----------------------------------------------------------------------------
466
// Block on condition variable until signalled. The mutex is
467
// assumed to be locked before this call, will be unlocked
468
// during the wait, and will be re-locked on wakeup.
469
 
470
externC int pthread_cond_wait (pthread_cond_t *cond,
471
                               pthread_mutex_t *mutex)
472
{
473
    PTHREAD_ENTRY();
474
 
475
    // check for cancellation first.
476
    PTHREAD_TESTCANCEL();
477
 
478
    PTHREAD_CHECK( cond );
479
    PTHREAD_CHECK( mutex );
480
 
481
    ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex );
482
 
483
    // check if we were woken because we were being cancelled
484
    PTHREAD_TESTCANCEL();
485
 
486
    PTHREAD_RETURN(0);
487
}
488
 
489
//-----------------------------------------------------------------------------
490
// Block on condition variable until signalled, or the timeout expires.
491
 
492
externC int pthread_cond_timedwait (pthread_cond_t *cond,
493
                                    pthread_mutex_t *mutex,
494
                                    const struct timespec *abstime)
495
{
496
    PTHREAD_ENTRY();
497
 
498
    // check for cancellation first.
499
    PTHREAD_TESTCANCEL();
500
 
501
    PTHREAD_CHECK( cond );
502
    PTHREAD_CHECK( mutex );
503
    PTHREAD_CHECK( abstime );
504
 
505
    // Only initialize the converters once or they will consume a huge
506
    // amount or runtime.
507
 
508
    static struct Cyg_Clock::converter ns_converter;
509
    static struct Cyg_Clock::converter sec_converter;
510
    static volatile cyg_atomic conv_init;
511
    if (!conv_init)
512
    {
513
 
514
        // Try to avoid unnecessarily locking the scheduler when we are not
515
        // initializing the converters.  Check the conv_init flag again to
516
        // avoid race conditions.
517
 
518
        struct Cyg_Clock::converter temp_ns_converter, temp_sec_converter;
519
 
520
        Cyg_Clock::real_time_clock
521
            ->get_other_to_clock_converter( 1, &temp_ns_converter );
522
        Cyg_Clock::real_time_clock
523
            ->get_other_to_clock_converter( 1000000000, &temp_sec_converter );
524
 
525
        Cyg_Scheduler::lock();
526
        if (!conv_init)
527
        {
528
            ns_converter = temp_ns_converter;
529
            sec_converter = temp_sec_converter;
530
            conv_init=1;
531
        }
532
        Cyg_Scheduler::unlock();
533
    }
534
 
535
    cyg_tick_count ticks;
536
    ticks = Cyg_Clock::convert( abstime->tv_sec, &sec_converter );
537
    ticks += Cyg_Clock::convert( abstime->tv_nsec, &ns_converter );
538
 
539
    ((Cyg_Condition_Variable *)cond)->wait( *(Cyg_Mutex *)mutex, ticks );
540
 
541
    // check if we were woken because we were being cancelled
542
    PTHREAD_TESTCANCEL();
543
 
544
    if ( Cyg_Thread::self()->get_wake_reason() == Cyg_Thread::TIMEOUT )
545
        PTHREAD_RETURN(ETIMEDOUT);
546
    else
547
        PTHREAD_RETURN(0);
548
}
549
 
550
// -------------------------------------------------------------------------
551
// EOF mutex.cxx

powered by: WebSVN 2.1.0

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