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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [kernel/] [current/] [tests/] [kmutex3.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//        kmutex3.c
4
//
5
//        Mutex test 3 - priority inheritance
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 Free Software Foundation, 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      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):     hmt
43
// Contributors:  hmt
44
// Date:          2000-01-06, 2001-08-10
45
// Description:   Tests mutex priority inheritance.  This is simply a
46
//                translation of the similarly named kernel test to the
47
//                KAPI, with the intention of also testing the new
48
//                "set the protocol at run-time" extensions.
49
//####DESCRIPTIONEND####
50
 
51
#include <pkgconf/hal.h>
52
#include <pkgconf/kernel.h>
53
 
54
#include <cyg/infra/testcase.h>
55
 
56
#include <cyg/hal/hal_arch.h>           // CYGNUM_HAL_STACK_SIZE_TYPICAL
57
 
58
#include <cyg/infra/diag.h>             // diag_printf
59
 
60
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
61
externC void
62
cyg_hal_invoke_constructors();
63
#endif
64
 
65
// ------------------------------------------------------------------------
66
//
67
// These checks should be enough; any other scheduler which has priorities
68
// should manifest as having no priority inheritance, but otherwise fine,
69
// so the test should work correctly.
70
 
71
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK) &&    \
72
    (CYGNUM_KERNEL_SCHED_PRIORITIES > 20) &&    \
73
    defined(CYGFUN_KERNEL_API_C) &&             \
74
    !defined(CYGPKG_KERNEL_SMP_SUPPORT)
75
 
76
 
77
#include <cyg/kernel/kapi.h>
78
 
79
#include <cyg/infra/cyg_ass.h>
80
#include <cyg/infra/cyg_trac.h>
81
#include <cyg/infra/diag.h>             // diag_printf
82
#include CYGHWR_MEMORY_LAYOUT_H
83
 
84
 
85
// ------------------------------------------------------------------------
86
// manufacture a simpler feature test macro for priority inheritance than
87
// the configuration gives us. We have priority inheritance if it is configured
88
// as the only protocol, or if it is the default protocol for dynamic protocol
89
// choice.
90
 
91
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
92
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
93
#  ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_INHERIT
94
#   define PRIORITY_INHERITANCE "dynamic-default-inherit"
95
#  endif
96
# else
97
#  define PRIORITY_INHERITANCE "static-inherit"
98
# endif
99
#endif
100
 
101
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
102
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
103
#  ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_CEILING
104
#   if CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY <= 5
105
#    define PRIORITY_INHERITANCE "dynamic-default-ceiling-high"
106
#   elif CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY >= 15
107
#    define NO_PRIORITY_INHERITANCE "dynamic-default-ceiling-low"
108
#   else
109
#    define PRIORITY_UNKNOWN "dynamic-default-ceiling-mid"
110
#   endif
111
#  endif
112
# else
113
#  if CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY <= 5
114
#   define PRIORITY_INHERITANCE "static-ceiling-high"
115
#  elif CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY >= 15
116
#   define NO_PRIORITY_INHERITANCE "static-ceiling-low"
117
#  else
118
#   define PRIORITY_UNKNOWN "static-ceiling-mid"
119
#  endif
120
# endif
121
#endif
122
 
123
#ifndef PRIORITY_INHERITANCE
124
# ifndef NO_PRIORITY_INHERITANCE
125
#  define NO_PRIORITY_INHERITANCE "no scheme selected"
126
# endif
127
#endif
128
 
129
// ------------------------------------------------------------------------
130
// Management functions
131
//
132
// Stolen from testaux.hxx and copied in here because I want to be able to
133
// reset the world also.
134
//
135
// Translated into KAPI also.
136
 
137
#if (CYGMEM_REGION_ram_SIZE <= 32768)
138
# define NTHREADS 5
139
#else
140
# define NTHREADS 7
141
#endif
142
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
143
 
144
static  cyg_handle_t thread[NTHREADS] = { 0 };
145
 
146
typedef cyg_uint64 CYG_ALIGNMENT_TYPE;
147
 
148
static cyg_thread thread_obj[NTHREADS];
149
 
150
static CYG_ALIGNMENT_TYPE stack[NTHREADS] [
151
   (STACKSIZE+sizeof(CYG_ALIGNMENT_TYPE)-1)
152
     / sizeof(CYG_ALIGNMENT_TYPE)                     ];
153
 
154
static volatile int nthreads = 0;
155
 
156
#undef NULL
157
#define NULL (0)
158
 
159
static cyg_handle_t new_thread( cyg_thread_entry_t *entry,
160
                                cyg_addrword_t data,
161
                                cyg_addrword_t priority,
162
                                int do_resume )
163
{
164
    int _nthreads = nthreads++;
165
 
166
    CYG_ASSERT(_nthreads < NTHREADS,
167
               "Attempt to create more than NTHREADS threads");
168
 
169
    cyg_thread_create( priority,
170
                       entry,
171
                       data,
172
                       NULL,                // no name
173
                       (void *)(stack[_nthreads]),
174
                       STACKSIZE,
175
                       &thread[_nthreads],
176
                       &thread_obj[_nthreads] );
177
 
178
    if ( do_resume )
179
        cyg_thread_resume( thread[_nthreads] );
180
 
181
    return thread[_nthreads];
182
}
183
 
184
 
185
static void kill_threads( void )
186
{
187
    CYG_ASSERT(nthreads <= NTHREADS,
188
               "More than NTHREADS threads");
189
    CYG_ASSERT( cyg_thread_self() == thread[0],
190
                "kill_threads() not called from thread 0");
191
    while ( nthreads > 1 ) {
192
        nthreads--;
193
        if ( NULL != thread[nthreads] ) {
194
            do
195
                cyg_thread_kill( thread[nthreads] );
196
            while ( ! cyg_thread_delete ( thread[nthreads] ) );
197
            thread[nthreads] = NULL;
198
        }
199
    }
200
    CYG_ASSERT(nthreads == 1,
201
               "No threads left");
202
}
203
 
204
// ------------------------------------------------------------------------
205
 
206
#define DELAYFACTOR 1 // for debugging
207
 
208
// ------------------------------------------------------------------------
209
 
210
static cyg_mutex_t mutex_obj;
211
static cyg_mutex_t *mutex;
212
 
213
// These are for reporting back to the master thread
214
volatile int got_it  = 0;
215
volatile int t3ran   = 0;
216
volatile int t3ended = 0;
217
volatile int extras[4] = {0,0,0,0};
218
 
219
volatile int go_flag = 0; // but this one controls thread 3 from thread 2
220
 
221
// ------------------------------------------------------------------------
222
// 0 to 3 of these run generally to interfere with the other processing,
223
// to cause multiple prio inheritances, and clashes in any orders.
224
 
225
static void extra_thread( cyg_addrword_t data )
226
{
227
    cyg_handle_t self = cyg_thread_self();
228
 
229
#define XINFO( z ) \
230
    do { z[13] = '0' + data; CYG_TEST_INFO( z ); } while ( 0 )
231
 
232
    static char running[]  = "Extra thread Xa running";
233
    static char exiting[]  = "Extra thread Xa exiting";
234
    static char resumed[]  = "Extra thread Xa resumed";
235
    static char locked[]   = "Extra thread Xa locked";
236
    static char unlocked[] = "Extra thread Xa unlocked";
237
 
238
    XINFO( running );
239
 
240
    cyg_thread_suspend( self );
241
 
242
    XINFO( resumed );
243
 
244
    cyg_mutex_lock( mutex );
245
 
246
    XINFO( locked );
247
 
248
    cyg_mutex_unlock( mutex );
249
 
250
    XINFO( unlocked );
251
 
252
    extras[ data ] ++;
253
 
254
    XINFO( exiting );
255
 
256
}
257
 
258
// ------------------------------------------------------------------------
259
 
260
static void t1( cyg_addrword_t data )
261
{
262
    cyg_handle_t self = cyg_thread_self();
263
 
264
    CYG_TEST_INFO( "Thread 1 running" );
265
 
266
    cyg_thread_suspend( self );
267
 
268
    cyg_mutex_lock( mutex );
269
 
270
    got_it++;
271
 
272
    CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,1]" );
273
 
274
    cyg_mutex_unlock( mutex );
275
 
276
    CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,2]" );
277
 
278
    // That's all.
279
 
280
    CYG_TEST_INFO( "Thread 1 exit" );
281
}
282
 
283
// ------------------------------------------------------------------------
284
 
285
static void t2( cyg_addrword_t data )
286
{
287
    cyg_handle_t self = cyg_thread_self();
288
    int i;
289
    cyg_tick_count_t then, now;
290
 
291
    CYG_TEST_INFO( "Thread 2 running" );
292
 
293
    CYG_TEST_CHECK( 0 == (data & ~0x77), "Bad T2 arg: extra bits" );
294
    CYG_TEST_CHECK( 0 == (data & (data >> 4)), "Bad T2 arg: overlap" );
295
 
296
    cyg_thread_suspend( self );
297
 
298
    // depending on our config argument, optionally restart some of the
299
    // extra threads to throw noise into the scheduler:
300
    for ( i = 0; i < 3; i++ )
301
        if ( (1 << i) & data )          // bits 0-2 control
302
            cyg_thread_resume( thread[i+4] ); // extras are thread[4-6]
303
 
304
    cyg_thread_delay( DELAYFACTOR * 10 ); // let those threads run
305
 
306
    cyg_scheduler_lock();               // do this next lot atomically
307
 
308
    go_flag = 1;                        // unleash thread 3
309
    cyg_thread_resume( thread[1] );     // resume thread 1
310
 
311
    // depending on our config argument, optionally restart some of the
312
    // extra threads to throw noise into the scheduler at this later point:
313
    for ( i = 4; i < 7; i++ )
314
        if ( (1 << i) & data )          // bits 4-6 control
315
            cyg_thread_resume( thread[i] ); // extras are thread[4-6]
316
 
317
    cyg_scheduler_unlock();             // let scheduling proceed
318
 
319
    // Need a delay (but not a CPU yield) to allow t3 to awaken and act on
320
    // the go_flag, otherwise we check these details below too soon.
321
    // Actually, waiting for the clock to tick a couple of times would be
322
    // better, so that is what we will do.  Must be a busy-wait.
323
    then = cyg_current_time();
324
    do {
325
        now = cyg_current_time();
326
        // Wait longer than the delay in t3 waiting on go_flag
327
    } while ( now < (then + 3) );
328
 
329
#ifdef PRIORITY_UNKNOWN
330
    CYG_TEST_INFO( "Not checking: " PRIORITY_UNKNOWN );
331
#else
332
#ifdef PRIORITY_INHERITANCE
333
    CYG_TEST_INFO( "Checking priority scheme: " PRIORITY_INHERITANCE );
334
    CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
335
    CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
336
#else
337
    CYG_TEST_INFO( "Checking NO priority scheme: " NO_PRIORITY_INHERITANCE );
338
    CYG_TEST_CHECK( 0 == t3ran, "Thread 3 DID run" );
339
    CYG_TEST_CHECK( 0 == got_it, "Thread 1 DID get the mutex" );
340
#endif
341
#endif
342
 
343
    CYG_TEST_CHECK( 0 == t3ended, "Thread 3 ended prematurely [T2,1]" );
344
 
345
    cyg_thread_delay( DELAYFACTOR * 20 ); // let those threads run
346
 
347
    CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
348
    CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
349
    CYG_TEST_CHECK( 1 == t3ended, "Thread 3 has not ended" );
350
 
351
    for ( i = 0; i < 3; i++ )
352
        if ( (1 << i) & (data | data >> 4) ) // bits 0-2 and 4-6 control
353
            CYG_TEST_CHECK( 1 == extras[i+1], "Extra thread did not run" );
354
        else
355
            CYG_TEST_CHECK( 0 == extras[i+1], "Extra thread ran" );
356
 
357
    CYG_TEST_PASS( "Thread 2 exiting, AOK" );
358
    // That's all: restart the control thread.
359
    cyg_thread_resume( thread[0] );
360
}
361
 
362
// ------------------------------------------------------------------------
363
 
364
static void t3( cyg_addrword_t data )
365
{
366
    CYG_TEST_INFO( "Thread 3 running" );
367
 
368
    cyg_mutex_lock( mutex );
369
 
370
    cyg_thread_delay( DELAYFACTOR * 5 ); // let thread 3a run
371
 
372
    cyg_thread_resume( thread[2] );     // resume thread 2
373
 
374
    while ( 0 == go_flag )
375
        cyg_thread_delay(1);            // wait until we are told to go
376
 
377
    t3ran ++;                           // record the fact
378
 
379
    CYG_TEST_CHECK( 0 == got_it, "Thread 1 claims to have got my mutex" );
380
 
381
    cyg_mutex_unlock( mutex );
382
 
383
    t3ended ++;                         // record that we came back
384
 
385
    CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
386
 
387
    CYG_TEST_INFO( "Thread 3 exit" );
388
}
389
 
390
// ------------------------------------------------------------------------
391
 
392
static void control_thread( cyg_addrword_t data )
393
{
394
    cyg_handle_t self = cyg_thread_self();
395
    int i, z;
396
 
397
    CYG_TEST_INIT();
398
    CYG_TEST_INFO( "Control Thread running" );
399
 
400
    // Go through the 27 possibilities of resuming the extra threads
401
    //     0: not at all
402
    //     1: early in the process
403
    //     2: later on
404
    // which are represented by bits 0-3 and 4-6 resp in the argument to
405
    // thread 2 (none set means no resume at all).
406
    for ( i = 0; i < 27; i++ ) {
407
        static int xx[] = { 0, 1, 16 };
408
        int j = i % 3;
409
        int k = (i / 3) % 3;
410
        int l = (i / 9) % 3;
411
 
412
        int d = xx[j] | (xx[k]<<1) | (xx[l]<<2) ;
413
 
414
        if ( cyg_test_is_simulator && (0 != i && 13 != i && 26 != i) )
415
            continue;    // 13 is 111 base 3, 26 is 222 base 3
416
 
417
#ifdef PRIORITY_INHERITANCE
418
        // If the simple scheme plus relay enhancement, or any other
419
        // *complete* scheme, we can run all three ancillary threads no
420
        // problem, so no special action here.
421
 
422
#else
423
        // If no priority inheritance at all, running threads 1a and 2a is
424
        // OK, but not thread 3a; it blocks the world.
425
        if ( l )                        // Cannot run thread 3a if no
426
            break;                      //     priority inheritance at all.
427
#endif
428
 
429
        mutex = &mutex_obj;
430
        cyg_mutex_init( mutex );
431
 
432
        got_it  = 0;
433
        t3ran   = 0;
434
        t3ended = 0;
435
        for ( z = 0; z < 4; z++ ) extras[z] = 0;
436
        go_flag = 0;
437
 
438
        new_thread( t1, 0,  5, 1 );            // Slot 1
439
        new_thread( t2, d, 10, 1 );            // Slot 2
440
        new_thread( t3, 0, 15, 1 );            // Slot 3
441
 
442
        new_thread( extra_thread, 1,  8, j );  // Slot 4
443
        new_thread( extra_thread, 2, 12, k );  // Slot 5
444
        new_thread( extra_thread, 3, 17, l );  // Slot 6
445
 
446
        {
447
            static char *a[] = { "inactive", "run early", "run late" };
448
            diag_printf( "\n----- [%2d] New Cycle: 0x%02x, Threads 1a %s, 2a %s, 3a %s -----\n",
449
                         i, d,  a[j], a[k], a[l] );
450
        }
451
 
452
        cyg_thread_suspend( self );
453
 
454
        kill_threads();
455
        cyg_mutex_destroy( mutex );
456
    }
457
    CYG_TEST_EXIT( "Control Thread exit" );
458
}
459
 
460
// ------------------------------------------------------------------------
461
 
462
externC void
463
cyg_user_start( void )
464
{
465
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
466
    cyg_hal_invoke_constructors();
467
#endif
468
    new_thread( control_thread, 0, 2, 1 );
469
}
470
 
471
#else // CYGVAR_KERNEL_COUNTERS_CLOCK &c
472
 
473
externC void
474
cyg_start( void )
475
{
476
    CYG_TEST_INIT();
477
    CYG_TEST_INFO("KMutex3 test requires:\n"
478
                         "CYGFUN_KERNEL_API_C &&\n"
479
                         "CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
480
                         "(CYGNUM_KERNEL_SCHED_PRIORITIES > 20) &&\n"
481
                         "!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
482
    CYG_TEST_NA("KMutex3 test requirements");
483
}
484
#endif // CYGVAR_KERNEL_COUNTERS_CLOCK &c
485
 
486
 
487
// ------------------------------------------------------------------------
488
// Documentation: enclosed is the design of this test.
489
//
490
// It has been carefully constructed so that it does NOT use other kernel
491
// facilities (aside from delay-task) to test that priority inheritance is
492
// working, or not, as intended by the configuration.
493
//
494
// These notes describe the flow of control in one run of the test with the
495
// ancillary tasks optionally interspersed.  The details of how those extra
496
// tasks are or are not allowed to run are not described.
497
// 
498
// 
499
// 
500
// The only change in the test that depends on whether there is inheritance or
501
// not is the check in thread 2 on "3-ran" and "got it" flags marked ****
502
// 
503
// 
504
// volatile &c booleans:
505
//         "got it"     = FALSE
506
//         "3-ran"      = FALSE
507
//         "3-ended"    = FALSE
508
//         "extras"[3]  = FALSE
509
// 
510
// thread 1.  prio 5, self-suspend.
511
// 
512
// thread 1a, prio 8, self-suspend.
513
// 
514
// thread 2.  prio 10, self-suspend.
515
// 
516
// thread 2a, prio 12, self-suspend.
517
// 
518
// thread 3.  prio 15, runs, lock mutex, resume(2)
519
// 
520
// thread 3a, prio 17, self-suspend.
521
// 
522
//        2.  runs,
523
//        2.  resume(3a) +++OPTIONAL
524
//        2.  resume(2a) +++OPTIONAL
525
//        2.  resume(1a) +++OPTIONAL
526
//        [1a lock-fail]        thread 3->prio := 8
527
// 
528
//        [3. runs maybe, does the looping thing]
529
// 
530
//        2.  sleep a while...
531
// 
532
//        [2a lock-fail]        thread 3->prio := 12
533
// 
534
//        [3. runs maybe, does the looping thing]
535
// 
536
//        [3a lock-fail]   thread 3->prio unchanged
537
// 
538
//        [3. runs maybe, does the looping thing]
539
// 
540
//        2.  lock scheduler
541
//        2.  set "go-flag"
542
//        2.  resume(1)
543
//        2.  resume(1a) +++OPTIONAL
544
//        2.  resume(2a) +++OPTIONAL
545
//        2.  resume(3a) +++OPTIONAL
546
//        2.  unlock scheduler
547
// 
548
//        1.  runs, lock mutex - thread 3 has it locked
549
//
550
//        2.  busy-waits a bit for thread 3 to come out of its delay() loop.
551
//            This must be a *busy*wait so that 3 can only run via the
552
//            inherited raised priority.
553
// 
554
//        [xa. all do the same: lock mutex,                ]
555
//        [xa. unlock mutex                                ]
556
//        [xa. set a flag "extras"[x] to say we are done.  ]
557
//        [xa. exit                                        ]
558
// 
559
// 
560
// 
561
// INHERIT
562
// -------
563
// 
564
//                 thread 3->prio := 5
565
// 
566
//        3.  runs,
567
//        3.  set a flag to say "3-ran",
568
//        3.  loop with a sleep(1) until "go-flag" is set.
569
//        3.  check "got it" is false,
570
//        3.  then unlock mutex,
571
// 
572
//                 thread 3->prio := 15
573
// 
574
//        1.  runs, set a flag to say "got it",
575
//        1.  check "3-ended" flag is false
576
//        1.  unlock mutex,
577
//        1.  check "3-ended" flag is still false
578
//        1.  exit.
579
// 
580
//        [1a locks, unlocks, exits]
581
// 
582
//        2.  runs, check "3-ran" and "got it" flags are TRUE ****
583
//        2.  check "3-ended" flag is false
584
//        2.  sleeps for a while so that...
585
// 
586
//        [2a locks, unlocks, exits]
587
//            
588
//        3.  runs, set "3-ended" flag,
589
//        3.  check "3-ran" and "got it" flags
590
//        3.  exit
591
// 
592
//        [3a locks, unlocks, exits]
593
// 
594
//        2.  awakens, checks all flags true,
595
//        2.  check that all "extra" threads that we started have indeed run
596
//        2.  end of test.
597
// 
598
// 
599
// 
600
// 
601
// NO-INHERIT
602
// ----------
603
//                 thread 1 is waiting on the mutex
604
// 
605
//        [1a lock-fail]
606
// 
607
//        2.  runs, checks that "3-ran" and "got it" flags are FALSE ****
608
//        2.  check "3-ended" flag is false
609
//        2.  sleeps for a while so that...
610
// 
611
//        [2a. lock-fail]
612
//            
613
//        3.  runs, set a flag to say "3-ran",
614
//        3.  check "got it" is false,
615
//        3.  then unlock mutex,
616
// 
617
//        1.  runs, set a flag to say "got it",
618
//        1.  check "3-ended" flag is false
619
//        1.  unlock mutex,
620
//        1.  check "3-ended" flag is still false
621
//        1.  exit.
622
// 
623
//        [1a locks, unlocks, exits]
624
//        [2a locks, unlocks, exits]
625
// 
626
//        3.  runs, set "3-ended" flag,
627
//        3.  check "3-ran" and "got it" flags
628
//        3.  exit
629
// 
630
//        [3a locks, unlocks, exits]
631
//                
632
//        2.  awakens, checks all flags true, 
633
//        2.  check that all "extra" threads that we started have indeed run
634
//        2.  end of test.
635
// 
636
// 
637
// (the end)
638
// 
639
// 
640
// ------------------------------------------------------------------------
641
 
642
// EOF mutex3.c

powered by: WebSVN 2.1.0

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