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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//        thread_gdb.c
4
//
5
//        A test for thread support in GDB
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:          1998-09-21
46
// Description:   GDB thread support test.
47
//####DESCRIPTIONEND####
48
// 
49
 
50
#include <cyg/kernel/kapi.h>
51
 
52
#include <cyg/infra/cyg_ass.h>
53
 
54
#include <cyg/infra/testcase.h>
55
 
56
#if defined(CYGFUN_KERNEL_API_C) && defined(CYGSEM_KERNEL_SCHED_MLQUEUE) &&\
57
    (CYGNUM_KERNEL_SCHED_PRIORITIES > 26)
58
 
59
#include <cyg/hal/hal_arch.h>           // for CYGNUM_HAL_STACK_SIZE_TYPICAL
60
 
61
// -------------------------------------------------------------------------
62
 
63
#define THREADS                 10
64
 
65
#ifdef CYGNUM_HAL_STACK_SIZE_TYPICAL
66
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
67
#else
68
#define STACKSIZE               (2*1024)
69
#endif
70
 
71
#define CONTROLLER_PRI_HI       0
72
#define CONTROLLER_PRI_LO       25
73
 
74
#define WORKER_PRI              3
75
#define WORKER_PRI_RANGE        20
76
 
77
 
78
// -------------------------------------------------------------------------
79
 
80
// array of stacks for threads
81
char thread_stack[THREADS][STACKSIZE];
82
 
83
// array of threads.
84
cyg_thread thread[THREADS];
85
 
86
cyg_handle_t thread_handle[THREADS];
87
 
88
volatile cyg_uint8 worker_state;
89
 
90
#define WORKER_STATE_WAIT       1
91
#define WORKER_STATE_BREAK      2
92
#define WORKER_STATE_EXIT       9
93
 
94
cyg_mutex_t worker_mutex;
95
cyg_cond_t worker_cv;
96
 
97
cyg_count32 workers_asleep = 0;
98
 
99
cyg_count32 thread_count[THREADS];
100
 
101
cyg_priority_t thread_pri[THREADS];
102
 
103
 
104
 
105
// -------------------------------------------------------------------------
106
 
107
extern void breakme(void)
108
{
109
}
110
 
111
// -------------------------------------------------------------------------
112
 
113
void worker( cyg_addrword_t id )
114
{
115
    for(;;)
116
    {
117
        thread_count[id]++;
118
        thread_pri[id] = cyg_thread_get_priority( cyg_thread_self() );
119
 
120
        switch( worker_state )
121
        {
122
        case WORKER_STATE_BREAK:
123
            if( 0 == (id % 4) )
124
                breakme();
125
 
126
        case WORKER_STATE_WAIT:
127
            cyg_mutex_lock( &worker_mutex );
128
            workers_asleep++;
129
            cyg_cond_wait( &worker_cv );
130
            workers_asleep--;
131
            cyg_mutex_unlock( &worker_mutex );
132
            break;
133
 
134
        case WORKER_STATE_EXIT:
135
            cyg_thread_exit();
136
 
137
        }
138
    }
139
}
140
 
141
// -------------------------------------------------------------------------
142
 
143
void controller( cyg_addrword_t id )
144
{
145
    cyg_priority_t pri;
146
    int i;
147
 
148
    cyg_mutex_init( &worker_mutex );
149
    cyg_cond_init( &worker_cv, &worker_mutex );
150
 
151
// 1 thread, it is running, it calls BREAKME();
152
//  +++ Thread status returned:
153
//  +++ 1 thread, running, is the current one
154
 
155
    breakme();
156
 
157
// Create N more threads; they are all suspended after creation.  Adjust
158
// the priorities of all the threads to lower than the controlling thread.
159
// Make them all be distinct priorities as far as possible.  BREAKME();
160
//  +++ 1 thread, running, + N suspended ones of different prios.
161
 
162
    for( i = 1; i < THREADS; i++ )
163
    {
164
        pri = CONTROLLER_PRI_HI + 1 + i % WORKER_PRI_RANGE;
165
 
166
        cyg_thread_create(pri, worker, (cyg_addrword_t)i, "worker",
167
                          (void *)(&thread_stack[i]), STACKSIZE,
168
                          &thread_handle[i], &thread[i]);
169
 
170
    }
171
 
172
    breakme();
173
 
174
// Adjust the priorities of all the threads to lower than the controlling
175
// thread.  Make them all be THE SAME priority.  BREAKME();
176
//  +++ 1 thread, running, + N suspended ones of same prio.
177
 
178
    for( i = 1; i < THREADS; i++ )
179
    {
180
        cyg_thread_set_priority( thread_handle[i], WORKER_PRI );
181
    }
182
 
183
    breakme();
184
 
185
// Release all the N threads, BREAKME();
186
//  +++ 1 thread, running, + N ready ones of same prio.
187
 
188
    for( i = 1; i < THREADS; i++ )
189
    {
190
        cyg_thread_resume( thread_handle[i] );
191
    }
192
 
193
    breakme();
194
 
195
// Adjust the priorities of all the threads, lower than the controlling
196
// thread.  Make them all be distinct priorities as far as possible.
197
// BREAKME();
198
//  +++ 1 thread, running, + N ready ones of different prios.
199
 
200
    for( i = 1; i < THREADS; i++ )
201
    {
202
        pri = CONTROLLER_PRI_HI + 1 + i % WORKER_PRI_RANGE;
203
 
204
        cyg_thread_set_priority( thread_handle[i], pri );
205
    }
206
 
207
    breakme();
208
 
209
// Command all the N threads to sleep; switch my own priority to lower
210
// than theirs so that they all run and sleep, then I get back in and
211
// BREAKME();
212
// +++ 1 thread, running, + N sleeping ones of different prios.
213
 
214
    worker_state = WORKER_STATE_WAIT;
215
 
216
    cyg_thread_set_priority( thread_handle[0], CONTROLLER_PRI_LO );
217
 
218
    breakme();
219
 
220
// Make them all be THE SAME priority; BREAKME();
221
//  +++ 1 thread, running, + N sleeping ones of same prio.
222
 
223
    for( i = 1; i < THREADS; i++ )
224
    {
225
        cyg_thread_set_priority( thread_handle[i], WORKER_PRI );
226
    }
227
 
228
    breakme();
229
 
230
// Wake them all up, they'll loop once and sleep again; I get in and
231
// BREAKME();
232
//  +++ 1 thread, running, + N sleeping ones of same prio.
233
 
234
    cyg_cond_broadcast( &worker_cv );
235
 
236
    breakme();
237
 
238
// Adjust the priorities of all the threads, higher than the controlling
239
// thread.  Make them all be distinct priorities as far as possible.
240
// BREAKME();
241
//  +++ 1 thread, running, + N sleeping ones of different prios.
242
 
243
    for( i = 1; i < THREADS; i++ )
244
    {
245
        pri = CONTROLLER_PRI_HI + 1 + i % WORKER_PRI_RANGE;
246
 
247
        cyg_thread_set_priority( thread_handle[i], pri );
248
    }
249
 
250
    breakme();
251
 
252
// Wake them all up, they'll loop once and sleep again; I get in and
253
// BREAKME();
254
//  +++ 1 thread, running, + N sleeping ones of different prios.
255
 
256
    cyg_cond_broadcast( &worker_cv );
257
 
258
    breakme();
259
 
260
// Set them all the same prio, set me to the same prio, BREAKME();
261
//  +++ 1 running, + N sleeping, *all* the same prio.
262
 
263
    for( i = 0; i < THREADS; i++ )
264
    {
265
        cyg_thread_set_priority( thread_handle[i], WORKER_PRI );
266
    }
267
 
268
    breakme();
269
 
270
// Wake them all up, they'll loop once and sleep again; I get in and
271
// BREAKME(); repeatedly until they have all slept again.
272
//  +++ 1 running, + some sleeping, some ready, *all* the same prio.
273
 
274
    cyg_cond_broadcast( &worker_cv );
275
 
276
//    cyg_thread_yield();
277
 
278
    do
279
    {
280
        breakme();
281
 
282
    } while( workers_asleep != THREADS-1 );
283
 
284
    breakme();
285
 
286
// Suspend some of the threads, BREAKME();
287
//  +++ 1 running, + some sleeping, some suspended, *all* the same prio.
288
 
289
    for( i = 1; i < THREADS; i++ )
290
    {
291
        // suspend every 3rd thread
292
        if( 0 == (i % 3) ) cyg_thread_suspend( thread_handle[i] );
293
    }
294
 
295
    breakme();
296
 
297
 
298
// Change the prios all different, change my prio to highest , BREAKME();
299
//  +++ 1 running, + some sleeping, some suspended, different prios.
300
 
301
    cyg_thread_set_priority( thread_handle[0], CONTROLLER_PRI_HI );
302
 
303
    for( i = 1; i < THREADS; i++ )
304
    {
305
        pri = CONTROLLER_PRI_HI + 1 + i % WORKER_PRI_RANGE;
306
 
307
        cyg_thread_set_priority( thread_handle[i], pri );
308
    }
309
 
310
    breakme();
311
 
312
// Wake up all the threads, BREAKME();
313
//  +++ 1 running, + some ready, some suspended/ready, different prios.
314
 
315
    cyg_cond_broadcast( &worker_cv );
316
 
317
    breakme();
318
 
319
 
320
// Change my prio to lowest, let all the threads run, BREAKME().
321
//  +++ 1 running + some sleeping, some suspended/ready, different prios.
322
 
323
    cyg_thread_set_priority( thread_handle[0], CONTROLLER_PRI_LO );
324
 
325
    breakme();
326
 
327
// Resume all the threads, BREAKME();
328
//  +++ 1 running, + N ready, different prios.
329
 
330
    for( i = 1; i < THREADS; i++ )
331
    {
332
        cyg_thread_resume( thread_handle[i] );
333
    }
334
 
335
    breakme();
336
 
337
// Command some of the N threads to call BREAKME(); themselves (then sleep
338
// again).  Change my prio to low, so that they all get to run and hit the
339
// breakpoint.
340
//  +++ A different one running every time, others in a mixture of
341
//      ready and sleeping states.
342
 
343
    worker_state = WORKER_STATE_BREAK;
344
 
345
    cyg_cond_broadcast( &worker_cv );
346
 
347
    cyg_thread_set_priority( thread_handle[0], CONTROLLER_PRI_LO );
348
 
349
    breakme();
350
 
351
// Command all the threads to exit; switch my own priority to lower
352
// than theirs so that they all run and exit, then I get back in and
353
// BREAKME();
354
//  +++ 1 thread, running, + N dormant ones.
355
 
356
    worker_state = WORKER_STATE_EXIT;
357
 
358
    cyg_cond_broadcast( &worker_cv );
359
 
360
    breakme();
361
 
362
#if 0
363
 
364
// Cannot do this yet...
365
 
366
// Destroy some of the N threads to invalidate their IDs.  Re-create them
367
// with new IDs, so that we get IDs 1,2,4,6,8,11,12,13,14,15 in use instead
368
// of 1,2,3,4,5,6,7,8,9, if you see what I mean.  Do all the above again.
369
// Loop forever, or whatever...
370
 
371
#endif
372
 
373
    breakme();
374
 
375
    CYG_TEST_PASS_FINISH("GDB Thread test OK");
376
 
377
}
378
 
379
// -------------------------------------------------------------------------
380
 
381
externC void
382
cyg_start( void )
383
{
384
 
385
    CYG_TEST_INIT();
386
 
387
    cyg_thread_create(CONTROLLER_PRI_HI, controller, (cyg_addrword_t)0, "controller",
388
                      (void *)(&thread_stack[0]), STACKSIZE,
389
                      &thread_handle[0], &thread[0]);
390
 
391
    // resume it
392
    cyg_thread_resume(thread_handle[0]);
393
 
394
 
395
    // Get the world going
396
    cyg_scheduler_start();
397
 
398
    CYG_TEST_FAIL_FINISH("Not reached");
399
 
400
}
401
 
402
#else /* def CYGFUN_KERNEL_API_C */
403
 
404
externC void
405
cyg_start( void )
406
{
407
    CYG_TEST_INIT();
408
    CYG_TEST_PASS_FINISH("Incorrect configuration for this test");
409
}
410
#endif /* def CYGFUN_KERNEL_API_C && ... */
411
 
412
// -------------------------------------------------------------------------
413
// EOF thread_gdb.c

powered by: WebSVN 2.1.0

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