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/] [tests/] [kmutex3.c] - Blame information for rev 228

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

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

powered by: WebSVN 2.1.0

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