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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [kernel/] [v2_0/] [tests/] [bin_sem2.cxx] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//        bin_sem2.cxx
4
//
5
//        Binary semaphore test 2
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,dsm
44
// Contributors:    dsm
45
// Date:          1998-03-10
46
// Description:
47
//     Dining philosophers test.  Based on philo.cxx
48
//####DESCRIPTIONEND####
49
 
50
#include <pkgconf/kernel.h>
51
 
52
#include <cyg/kernel/sched.hxx>
53
#include <cyg/kernel/thread.hxx>
54
#include <cyg/kernel/thread.inl>
55
#include <cyg/kernel/mutex.hxx>
56
 
57
#include <cyg/kernel/sema.hxx>
58
 
59
#include <cyg/infra/testcase.h>
60
 
61
#include <cyg/kernel/sched.inl>
62
 
63
static cyg_ucount16 PHILO_LOOPS = 1000;
64
 
65
#define PHILOSOPHERS 15
66
#define NTHREADS PHILOSOPHERS
67
#include "testaux.hxx"
68
 
69
static Cyg_Binary_Semaphore chopstick[PHILOSOPHERS];
70
 
71
static char pstate[PHILOSOPHERS+1];       // state of each philosopher
72
 
73
static cyg_ucount16 state_changes = 0;
74
// state_changes keep track of number of changes to pstate so
75
// we can exit after we've seen enough.
76
 
77
 
78
static Cyg_Mutex pstate_mutex;
79
static Cyg_Mutex cycle_mutex;
80
 
81
static inline int left(cyg_count8 i)
82
{
83
    return (0 == i) ? PHILOSOPHERS-1 : i-1 ;
84
}
85
static inline int right(cyg_count8 i)
86
{
87
    return (PHILOSOPHERS == i+1) ? 0 : i+1 ;
88
}
89
 
90
void change_state(int id, char newstate)
91
{
92
    if (PHILO_LOOPS == state_changes++)
93
        CYG_TEST_PASS_FINISH("Binary Semaphore 2 OK");
94
 
95
 
96
    pstate_mutex.lock(); {
97
        pstate[id] = newstate;
98
        bool all_hungry = true;         // until proved otherwise
99
        for(cyg_ucount8 i=0; i < PHILOSOPHERS; i++) {
100
            if('E' == pstate[i]) {
101
                CHECK('E' != pstate[left(i)]);
102
                CHECK('E' != pstate[right(i)]);
103
            }
104
            if('H' != pstate[i]) {
105
                all_hungry = false;
106
            }
107
        }
108
        // Theoretically it is possible for all the philosophers to be
109
        // hungry but not waiting on semaphores.  But in practice this
110
        // means something is wrong.
111
        CHECK(false == all_hungry);
112
    } pstate_mutex.unlock();
113
}
114
 
115
char get_state(int id)
116
{
117
    pstate_mutex.lock();
118
 
119
    char s = pstate[id];
120
 
121
    pstate_mutex.unlock();
122
 
123
    return s;
124
}
125
 
126
// -------------------------------------------------------------------------
127
// Thread to behave like a philosopher
128
 
129
void Philosopher( CYG_ADDRESS id )
130
{
131
    Cyg_Thread *self = Cyg_Thread::self();
132
    Cyg_Binary_Semaphore *first_stick = &chopstick[id];
133
    Cyg_Binary_Semaphore *second_stick = &chopstick[(id+1)%PHILOSOPHERS];
134
 
135
    CHECK( id >= 0 && id < PHILOSOPHERS);
136
 
137
    // Deadlock avoidance. The easiest way to make the philosophers
138
    // behave is to make each pick up the lowest numbered stick
139
    // first. This is how it works out anyway for all the philosophers
140
    // except the last, who must have his sticks swapped.
141
 
142
    if( id == PHILOSOPHERS-1 )
143
    {
144
        Cyg_Binary_Semaphore *t = first_stick;
145
        first_stick = second_stick;
146
        second_stick = t;
147
    }
148
 
149
 
150
    // The following variable is shared by all philosophers.
151
    // It is incremented unprotected, but this does not matter
152
    // since it is only present to introduce a little variability
153
    // into the think and eat times.
154
 
155
    static int cycle = 0;
156
 
157
    for(;;)
158
    {
159
        // Think for a bit
160
 
161
        self->delay((id+cycle++)%12);    // Cogito ergo sum...
162
 
163
        // I am now hungry, try to get the chopsticks
164
        change_state(id,'H');
165
 
166
        // Get the sticks
167
        first_stick->wait();
168
        second_stick->wait();
169
 
170
        // Got them, now eat
171
        change_state(id,'E');
172
 
173
        // Check that the world is as I think it is...
174
        CYG_TEST_CHECK( !first_stick->posted(),
175
                        "Not got first stick");
176
        CYG_TEST_CHECK( !second_stick->posted(),
177
                        "Not got second stick");
178
        CYG_TEST_CHECK( get_state(left(id)) != 'E',
179
                        "Left neighbour also eating!!");
180
        CYG_TEST_CHECK( get_state(right(id)) != 'E',
181
                        "Right neighbour also eating!!");
182
 
183
        self->delay((id+cycle++)%6);    // munch munch
184
 
185
        // Finished eating, put down sticks.
186
 
187
        change_state(id,'T');
188
 
189
        // put sticks back on table
190
        first_stick->post();
191
        second_stick->post();
192
    }
193
}
194
 
195
// -------------------------------------------------------------------------
196
 
197
void bin_sem2_main( void )
198
{
199
    CYG_TEST_INIT();
200
 
201
    if (cyg_test_is_simulator)
202
        PHILO_LOOPS = 100;
203
 
204
    for( int i = 0; i < PHILOSOPHERS; i++ )
205
    {
206
        pstate[i] = 'T';            // starting state
207
        new_thread(Philosopher, i);
208
 
209
        // make the matching chopstick present
210
        chopstick[i].post();
211
    }
212
 
213
    Cyg_Scheduler::scheduler.start();
214
}
215
 
216
externC void
217
cyg_start( void )
218
{
219
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
220
    cyg_hal_invoke_constructors();
221
#endif
222
    bin_sem2_main();
223
}
224
// EOF bin_sem2.cxx

powered by: WebSVN 2.1.0

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