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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [doc/] [html/] [ref/] [kernel-thread-create.html] - Blame information for rev 757

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

Line No. Rev Author Line
1 28 unneback
<!-- Copyright (C) 2003 Red Hat, Inc.                                -->
2
<!-- This material may be distributed only subject to the terms      -->
3
<!-- and conditions set forth in the Open Publication License, v1.0  -->
4
<!-- or later (the latest version is presently available at          -->
5
<!-- http://www.opencontent.org/openpub/).                           -->
6
<!-- Distribution of the work or derivative of the work in any       -->
7
<!-- standard (paper) book form is prohibited unless prior           -->
8
<!-- permission is obtained from the copyright holder.               -->
9
<HTML
10
><HEAD
11
><TITLE
12
>Thread creation</TITLE
13
><meta name="MSSmartTagsPreventParsing" content="TRUE">
14
<META
15
NAME="GENERATOR"
16
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
17
"><LINK
18
REL="HOME"
19
TITLE="eCos Reference Manual"
20
HREF="ecos-ref.html"><LINK
21
REL="UP"
22
TITLE="The eCos Kernel"
23
HREF="kernel.html"><LINK
24
REL="PREVIOUS"
25
TITLE="SMP Support"
26
HREF="kernel-smp.html"><LINK
27
REL="NEXT"
28
TITLE="Thread information"
29
HREF="kernel-thread-info.html"></HEAD
30
><BODY
31
CLASS="REFENTRY"
32
BGCOLOR="#FFFFFF"
33
TEXT="#000000"
34
LINK="#0000FF"
35
VLINK="#840084"
36
ALINK="#0000FF"
37
><DIV
38
CLASS="NAVHEADER"
39
><TABLE
40
SUMMARY="Header navigation table"
41
WIDTH="100%"
42
BORDER="0"
43
CELLPADDING="0"
44
CELLSPACING="0"
45
><TR
46
><TH
47
COLSPAN="3"
48
ALIGN="center"
49
>eCos Reference Manual</TH
50
></TR
51
><TR
52
><TD
53
WIDTH="10%"
54
ALIGN="left"
55
VALIGN="bottom"
56
><A
57
HREF="kernel-smp.html"
58
ACCESSKEY="P"
59
>Prev</A
60
></TD
61
><TD
62
WIDTH="80%"
63
ALIGN="center"
64
VALIGN="bottom"
65
></TD
66
><TD
67
WIDTH="10%"
68
ALIGN="right"
69
VALIGN="bottom"
70
><A
71
HREF="kernel-thread-info.html"
72
ACCESSKEY="N"
73
>Next</A
74
></TD
75
></TR
76
></TABLE
77
><HR
78
ALIGN="LEFT"
79
WIDTH="100%"></DIV
80
><H1
81
><A
82
NAME="KERNEL-THREAD-CREATE">Thread creation</H1
83
><DIV
84
CLASS="REFNAMEDIV"
85
><A
86
NAME="AEN256"
87
></A
88
><H2
89
>Name</H2
90
>cyg_thread_create&nbsp;--&nbsp;Create a new thread</DIV
91
><DIV
92
CLASS="REFSYNOPSISDIV"
93
><A
94
NAME="AEN259"><H2
95
>Synopsis</H2
96
><DIV
97
CLASS="FUNCSYNOPSIS"
98
><A
99
NAME="AEN260"><P
100
></P
101
><TABLE
102
BORDER="5"
103
BGCOLOR="#E0E0F0"
104
WIDTH="70%"
105
><TR
106
><TD
107
><PRE
108
CLASS="FUNCSYNOPSISINFO"
109
>#include &lt;cyg/kernel/kapi.h&gt;
110
        </PRE
111
></TD
112
></TR
113
></TABLE
114
><P
115
><CODE
116
><CODE
117
CLASS="FUNCDEF"
118
>void cyg_thread_create</CODE
119
>(cyg_addrword_t sched_info, cyg_thread_entry_t* entry, cyg_addrword_t entry_data, char* name, void* stack_base, cyg_ucount32 stack_size, cyg_handle_t* handle, cyg_thread* thread);</CODE
120
></P
121
><P
122
></P
123
></DIV
124
></DIV
125
><DIV
126
CLASS="REFSECT1"
127
><A
128
NAME="KERNEL-THREAD-CREATE-DESCRIPTION"
129
></A
130
><H2
131
>Description</H2
132
><P
133
>The <TT
134
CLASS="FUNCTION"
135
>cyg_thread_create</TT
136
> function allows application
137
code and eCos packages to create new threads. In many applications
138
this only happens during system initialization and all required data
139
is allocated statically.  However additional threads can be created at
140
any time, if necessary. A newly created thread is always in suspended
141
state and will not start running until it has been resumed via a call
142
to <TT
143
CLASS="FUNCTION"
144
>cyg_thread_resume</TT
145
>. Also, if threads are
146
created during system initialization then they will not start running
147
until the eCos scheduler has been started.
148
      </P
149
><P
150
>The <TT
151
CLASS="PARAMETER"
152
><I
153
>name</I
154
></TT
155
> argument is used
156
primarily for debugging purposes, making it easier to keep track of
157
which <SPAN
158
CLASS="STRUCTNAME"
159
>cyg_thread</SPAN
160
> structure is associated with
161
which application-level thread. The kernel configuration option
162
<TT
163
CLASS="VARNAME"
164
>CYGVAR_KERNEL_THREADS_NAME</TT
165
> controls whether or not
166
this name is actually used.
167
      </P
168
><P
169
>On creation each thread is assigned a unique handle, and this will be
170
stored in the location pointed at by the <TT
171
CLASS="PARAMETER"
172
><I
173
>handle</I
174
></TT
175
> argument. Subsequent operations on
176
this thread including the required
177
<TT
178
CLASS="FUNCTION"
179
>cyg_thread_resume</TT
180
> should use this handle to
181
identify the thread.
182
      </P
183
><P
184
>The kernel requires a small amount of space for each thread, in the
185
form of a <SPAN
186
CLASS="STRUCTNAME"
187
>cyg_thread</SPAN
188
> data structure, to hold
189
information such as the current state of that thread. To avoid any
190
need for dynamic memory allocation within the kernel this space has to
191
be provided by higher-level code, typically in the form of a static
192
variable. The <TT
193
CLASS="PARAMETER"
194
><I
195
>thread</I
196
></TT
197
> argument
198
provides this space.
199
      </P
200
></DIV
201
><DIV
202
CLASS="REFSECT1"
203
><A
204
NAME="KERNEL-THREAD-CREATE-ENTRY"
205
></A
206
><H2
207
>Thread Entry Point</H2
208
><P
209
>The entry point for a thread takes the form:
210
      </P
211
><TABLE
212
BORDER="5"
213
BGCOLOR="#E0E0F0"
214
WIDTH="70%"
215
><TR
216
><TD
217
><PRE
218
CLASS="PROGRAMLISTING"
219
>void
220
thread_entry_function(cyg_addrword_t data)
221
{
222
    &#8230;
223
}
224
      </PRE
225
></TD
226
></TR
227
></TABLE
228
><P
229
>The second argument to <TT
230
CLASS="FUNCTION"
231
>cyg_thread_create</TT
232
> is a
233
pointer to such a function. The third argument <TT
234
CLASS="PARAMETER"
235
><I
236
>entry_data</I
237
></TT
238
> is used to pass additional
239
data to the function. Typically this takes the form of a pointer to
240
some static data, or a small integer, or <TT
241
CLASS="LITERAL"
242
>0</TT
243
> if the
244
thread does not require any additional data.
245
      </P
246
><P
247
>If the thread entry function ever returns then this is equivalent to
248
the thread calling <TT
249
CLASS="FUNCTION"
250
>cyg_thread_exit</TT
251
>. Even though
252
the thread will no longer run again, it remains registered with the
253
scheduler. If the application needs to re-use the
254
<SPAN
255
CLASS="STRUCTNAME"
256
>cyg_thread</SPAN
257
> data structure then a call to
258
<TT
259
CLASS="FUNCTION"
260
>cyg_thread_delete</TT
261
> is required first.
262
      </P
263
></DIV
264
><DIV
265
CLASS="REFSECT1"
266
><A
267
NAME="KERNEL-THREAD-CREATE-PRIORITIES"
268
></A
269
><H2
270
>Thread Priorities</H2
271
><P
272
>The <TT
273
CLASS="PARAMETER"
274
><I
275
>sched_info</I
276
></TT
277
> argument
278
provides additional information to the scheduler. The exact details
279
depend on the scheduler being used. For the bitmap and mlqueue
280
schedulers it is a small integer, typically in the range 0 to 31, with
281
 
282
only by the system's idle thread. The exact number of priorities is
283
controlled by the kernel configuration option
284
<TT
285
CLASS="VARNAME"
286
>CYGNUM_KERNEL_SCHED_PRIORITIES</TT
287
>.
288
      </P
289
><P
290
>It is the responsibility of the application developer to be aware of
291
the various threads in the system, including those created by eCos
292
packages, and to ensure that all threads run at suitable priorities.
293
For threads created by other packages the documentation provided by
294
those packages should indicate any requirements.
295
      </P
296
><P
297
>The functions <TT
298
CLASS="FUNCTION"
299
>cyg_thread_set_priority</TT
300
>,
301
<TT
302
CLASS="FUNCTION"
303
>cyg_thread_get_priority</TT
304
>, and
305
<TT
306
CLASS="FUNCTION"
307
>cyg_thread_get_current_priority</TT
308
> can be used to
309
manipulate a thread's priority.
310
      </P
311
></DIV
312
><DIV
313
CLASS="REFSECT1"
314
><A
315
NAME="KERNEL-THREAD-CREATE-STACK"
316
></A
317
><H2
318
>Stacks and Stack Sizes</H2
319
><P
320
>Each thread needs its own stack for local variables and to keep track
321
of function calls and returns. Again it is expected that this stack is
322
provided by the calling code, usually in the form of static data, so
323
that the kernel does not need any dynamic memory allocation
324
facilities. <TT
325
CLASS="FUNCTION"
326
>cyg_thread_create</TT
327
> takes two arguments
328
related to the stack, a pointer to the base of the stack and the total
329
size of this stack. On many processors stacks actually descend from the
330
top down, so the kernel will add the stack size to the base address to
331
determine the starting location.
332
      </P
333
><P
334
>The exact stack size requirements for any given thread depend on a
335
number of factors. The most important is of course the code that will
336
be executed in the context of this code: if this involves significant
337
nesting of function calls, recursion, or large local arrays, then the
338
stack size needs to be set to a suitably high value. There are some
339
architectural issues, for example the number of cpu registers and the
340
calling conventions will have some effect on stack usage. Also,
341
depending on the configuration, it is possible that some other code
342
such as interrupt handlers will occasionally run on the current
343
thread's stack. This depends in part on configuration options such as
344
<TT
345
CLASS="VARNAME"
346
>CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK</TT
347
>
348
and <TT
349
CLASS="VARNAME"
350
>CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING</TT
351
>.
352
      </P
353
><P
354
>Determining an application's actual stack size requirements is the
355
responsibility of the application developer, since the kernel cannot
356
know in advance what code a given thread will run. However, the system
357
does provide some hints about reasonable stack sizes in the form of
358
two constants: <TT
359
CLASS="VARNAME"
360
>CYGNUM_HAL_STACK_SIZE_MINIMUM</TT
361
> and
362
<TT
363
CLASS="VARNAME"
364
>CYGNUM_HAL_STACK_SIZE_TYPICAL</TT
365
>. These are defined by
366
the appropriate HAL package. The <TT
367
CLASS="VARNAME"
368
>MINIMUM</TT
369
> value is
370
appropriate for a thread that just runs a single function and makes
371
very simple system calls. Trying to create a thread with a smaller
372
stack than this is illegal. The <TT
373
CLASS="VARNAME"
374
>TYPICAL</TT
375
> value is
376
appropriate for applications where application calls are nested no
377
more than half a dozen or so levels, and there are no large arrays on
378
the stack.
379
      </P
380
><P
381
>If the stack sizes are not estimated correctly and a stack overflow
382
occurs, the probably result is some form of memory corruption. This
383
can be very hard to track down. The kernel does contain some code to
384
help detect stack overflows, controlled by the configuration option
385
<TT
386
CLASS="VARNAME"
387
>CYGFUN_KERNEL_THREADS_STACK_CHECKING</TT
388
>: a small
389
amount of space is reserved at the stack limit and filled with a
390
special signature: every time a thread context switch occurs this
391
signature is checked, and if invalid that is a good indication (but
392
not absolute proof) that a stack overflow has occurred. This form of
393
stack checking is enabled by default when the system is built with
394
debugging enabled. A related configuration option is
395
<TT
396
CLASS="VARNAME"
397
>CYGFUN_KERNEL_THREADS_STACK_MEASUREMENT</TT
398
>: enabling
399
this option means that a thread can call the function
400
<TT
401
CLASS="FUNCTION"
402
>cyg_thread_measure_stack_usage</TT
403
> to find out the
404
maximum stack usage to date. Note that this is not necessarily the
405
true maximum because, for example, it is possible that in the current
406
run no interrupt occurred at the worst possible moment.
407
      </P
408
></DIV
409
><DIV
410
CLASS="REFSECT1"
411
><A
412
NAME="KERNEL-THREAD-CREATE-CONTEXT"
413
></A
414
><H2
415
>Valid contexts</H2
416
><P
417
><TT
418
CLASS="FUNCTION"
419
>cyg_thread_create</TT
420
> may be called during
421
initialization and from within thread context. It may not be called
422
from inside a DSR.
423
      </P
424
></DIV
425
><DIV
426
CLASS="REFSECT1"
427
><A
428
NAME="KERNEL-THREAD-CREATE-EXAMPLE"
429
></A
430
><H2
431
>Example</H2
432
><P
433
>A simple example of thread creation is shown below. This involves
434
creating five threads, one producer and four consumers or workers. The
435
threads are created in the system's
436
<TT
437
CLASS="FUNCTION"
438
>cyg_user_start</TT
439
>: depending on the configuration it
440
might be more appropriate to do this elsewhere, for example inside
441
<TT
442
CLASS="FUNCTION"
443
>main</TT
444
>.
445
      </P
446
><TABLE
447
BORDER="5"
448
BGCOLOR="#E0E0F0"
449
WIDTH="70%"
450
><TR
451
><TD
452
><PRE
453
CLASS="PROGRAMLISTING"
454
>#include &lt;cyg/hal/hal_arch.h&gt;
455
#include &lt;cyg/kernel/kapi.h&gt;
456
 
457
// These numbers depend entirely on your application
458
#define NUMBER_OF_WORKERS    4
459
#define PRODUCER_PRIORITY   10
460
#define WORKER_PRIORITY     11
461
#define PRODUCER_STACKSIZE  CYGNUM_HAL_STACK_SIZE_TYPICAL
462
#define WORKER_STACKSIZE    (CYGNUM_HAL_STACK_SIZE_MINIMUM + 1024)
463
 
464
static unsigned char producer_stack[PRODUCER_STACKSIZE];
465
static unsigned char worker_stacks[NUMBER_OF_WORKERS][WORKER_STACKSIZE];
466
static cyg_handle_t producer_handle, worker_handles[NUMBER_OF_WORKERS];
467
static cyg_thread_t producer_thread, worker_threads[NUMBER_OF_WORKERS];
468
 
469
static void
470
producer(cyg_addrword_t data)
471
{
472
    &#8230;
473
}
474
 
475
static void
476
worker(cyg_addrword_t data)
477
{
478
    &#8230;
479
}
480
 
481
void
482
cyg_user_start(void)
483
{
484
    int i;
485
 
486
    cyg_thread_create(PRODUCER_PRIORITY, &amp;producer, 0, "producer",
487
                      producer_stack, PRODUCER_STACKSIZE,
488
                      &amp;producer_handle, &amp;producer_thread);
489
    cyg_thread_resume(producer_handle);
490
    for (i = 0; i &#60; NUMBER_OF_WORKERS; i++) {
491
        cyg_thread_create(WORKER_PRIORITY, &amp;worker, i, "worker",
492
                          worker_stacks[i], WORKER_STACKSIZE,
493
                          &amp;(worker_handles[i]), &amp;(worker_threads[i]));
494
        cyg_thread_resume(worker_handles[i]);
495
    }
496
}
497
      </PRE
498
></TD
499
></TR
500
></TABLE
501
></DIV
502
><DIV
503
CLASS="REFSECT1"
504
><A
505
NAME="KERNEL-THREAD-CREATE-CXX"
506
></A
507
><H2
508
>Thread Entry Points and C++</H2
509
><P
510
>For code written in C++ the thread entry function must be either a
511
static member function of a class or an ordinary function outside any
512
class. It cannot be a normal member function of a class because such
513
member functions take an implicit additional argument
514
<TT
515
CLASS="VARNAME"
516
>this</TT
517
>, and the kernel has no way of knowing what
518
value to use for this argument. One way around this problem is to make
519
use of a special static member function, for example:
520
      </P
521
><TABLE
522
BORDER="5"
523
BGCOLOR="#E0E0F0"
524
WIDTH="70%"
525
><TR
526
><TD
527
><PRE
528
CLASS="PROGRAMLISTING"
529
>class fred {
530
  public:
531
    void thread_function();
532
    static void static_thread_aux(cyg_addrword_t);
533
};
534
 
535
void
536
fred::static_thread_aux(cyg_addrword_t objptr)
537
{
538
    fred* object = static_cast&lt;fred*&gt;(objptr);
539
    object-&gt;thread_function();
540
}
541
 
542
static fred instance;
543
 
544
extern "C" void
545
cyg_start( void )
546
{
547
    &#8230;
548
    cyg_thread_create( &#8230;,
549
                      &amp;fred::static_thread_aux,
550
                      static_cast&lt;cyg_addrword_t&gt;(&amp;instance),
551
                      &#8230;);
552
    &#8230;
553
}
554
      </PRE
555
></TD
556
></TR
557
></TABLE
558
><P
559
>Effectively this uses the <TT
560
CLASS="PARAMETER"
561
><I
562
>entry_data</I
563
></TT
564
> argument to
565
<TT
566
CLASS="FUNCTION"
567
>cyg_thread_create</TT
568
> to hold the
569
<TT
570
CLASS="VARNAME"
571
>this</TT
572
> pointer. Unfortunately this approach does
573
require the use of some C++ casts, so some of the type safety that can
574
be achieved when programming in C++ is lost.
575
      </P
576
></DIV
577
><DIV
578
CLASS="NAVFOOTER"
579
><HR
580
ALIGN="LEFT"
581
WIDTH="100%"><TABLE
582
SUMMARY="Footer navigation table"
583
WIDTH="100%"
584
BORDER="0"
585
CELLPADDING="0"
586
CELLSPACING="0"
587
><TR
588
><TD
589
WIDTH="33%"
590
ALIGN="left"
591
VALIGN="top"
592
><A
593
HREF="kernel-smp.html"
594
ACCESSKEY="P"
595
>Prev</A
596
></TD
597
><TD
598
WIDTH="34%"
599
ALIGN="center"
600
VALIGN="top"
601
><A
602
HREF="ecos-ref.html"
603
ACCESSKEY="H"
604
>Home</A
605
></TD
606
><TD
607
WIDTH="33%"
608
ALIGN="right"
609
VALIGN="top"
610
><A
611
HREF="kernel-thread-info.html"
612
ACCESSKEY="N"
613
>Next</A
614
></TD
615
></TR
616
><TR
617
><TD
618
WIDTH="33%"
619
ALIGN="left"
620
VALIGN="top"
621
>SMP Support</TD
622
><TD
623
WIDTH="34%"
624
ALIGN="center"
625
VALIGN="top"
626
><A
627
HREF="kernel.html"
628
ACCESSKEY="U"
629
>Up</A
630
></TD
631
><TD
632
WIDTH="33%"
633
ALIGN="right"
634
VALIGN="top"
635
>Thread information</TD
636
></TR
637
></TABLE
638
></DIV
639
></BODY
640
></HTML
641
>

powered by: WebSVN 2.1.0

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