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

Subversion Repositories openrisc

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

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

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

powered by: WebSVN 2.1.0

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