source: rtems/doc/user/smp.t @ fab2f188

4.115
Last change on this file since fab2f188 was fab2f188, checked in by Sebastian Huber <sebastian.huber@…>, on 04/17/14 at 05:42:28

doc: Setting Affinity to a Single Processor

  • Property mode set to 100644
File size: 17.0 KB
Line 
1@c
2@c  COPYRIGHT (c) 2014.
3@c  On-Line Applications Research Corporation (OAR).
4@c  All rights reserved.
5@c
6
7@chapter Symmetric Multiprocessing Services
8
9@section Introduction
10
11This chapter describes the services related to Symmetric Multiprocessing
12provided by RTEMS.
13
14The application level services currently provided are:
15
16@itemize @bullet
17@item @code{rtems_get_processor_count} - Get processor count
18@item @code{rtems_get_current_processor} - Get current processor index
19@item @code{rtems_scheduler_ident} - Get ID of a scheduler
20@item @code{rtems_scheduler_get_processor_set} - Get processor set of a scheduler
21@item @code{rtems_task_get_scheduler} - Get scheduler of a task
22@item @code{rtems_task_set_scheduler} - Set scheduler of a task
23@item @code{rtems_task_get_affinity} - Get task processor affinity
24@item @code{rtems_task_set_affinity} - Set task processor affinity
25@end itemize
26
27@c
28@c
29@c
30@section Background
31
32@subsection Uniprocessor versus SMP Parallelism
33
34Uniprocessor systems have long been used in embedded systems. In this hardware
35model, there are some system execution characteristics which have long been
36taken for granted:
37
38@itemize @bullet
39@item one task executes at a time
40@item hardware events result in interrupts
41@end itemize
42
43There is no true parallelism. Even when interrupts appear to occur
44at the same time, they are processed in largely a serial fashion.
45This is true even when the interupt service routines are allowed to
46nest.  From a tasking viewpoint,  it is the responsibility of the real-time
47operatimg system to simulate parallelism by switching between tasks.
48These task switches occur in response to hardware interrupt events and explicit
49application events such as blocking for a resource or delaying.
50
51With symmetric multiprocessing, the presence of multiple processors
52allows for true concurrency and provides for cost-effective performance
53improvements. Uniprocessors tend to increase performance by increasing
54clock speed and complexity. This tends to lead to hot, power hungry
55microprocessors which are poorly suited for many embedded applications.
56
57The true concurrency is in sharp contrast to the single task and
58interrupt model of uniprocessor systems. This results in a fundamental
59change to uniprocessor system characteristics listed above. Developers
60are faced with a different set of characteristics which, in turn, break
61some existing assumptions and result in new challenges. In an SMP system
62with N processors, these are the new execution characteristics.
63
64@itemize @bullet
65@item N tasks execute in parallel
66@item hardware events result in interrupts
67@end itemize
68
69There is true parallelism with a task executing on each processor and
70the possibility of interrupts occurring on each processor. Thus in contrast
71to their being one task and one interrupt to consider on a uniprocessor,
72there are N tasks and potentially N simultaneous interrupts to consider
73on an SMP system.
74
75This increase in hardware complexity and presence of true parallelism
76results in the application developer needing to be even more cautious
77about mutual exclusion and shared data access than in a uniprocessor
78embedded system. Race conditions that never or rarely happened when an
79application executed on a uniprocessor system, become much more likely
80due to multiple threads executing in parallel. On a uniprocessor system,
81these race conditions would only happen when a task switch occurred at
82just the wrong moment. Now there are N-1 tasks executing in parallel
83all the time and this results in many more opportunities for small
84windows in critical sections to be hit.
85
86@subsection Task Affinity
87
88@cindex task affinity
89@cindex thread affinity
90
91RTEMS provides services to manipulate the affinity of a task. Affinity
92is used to specify the subset of processors in an SMP system on which
93a particular task can execute.
94
95By default, tasks have an affinity which allows them to execute on any
96available processor.
97
98Task affinity is a possible feature to be supported by SMP-aware
99schedulers. However, only a subset of the available schedulers support
100affinity. Although the behavior is scheduler specific, if the scheduler
101does not support affinity, it is likely to ignore all attempts to set
102affinity.
103
104@subsection Critical Section Techniques and SMP
105
106As discussed earlier, SMP systems have opportunities for true parallelism
107which was not possible on uniprocessor systems. Consequently, multiple
108techniques that provided adequate critical sections on uniprocessor
109systems are unsafe on SMP systems. In this section, some of these
110unsafe techniques will be discussed.
111
112In general, applications must use proper operating system provided mutual
113exclusion mechanisms to ensure correct behavior. This primarily means
114the use of binary semaphores or mutexes to implement critical sections.
115
116@subsubsection Disable Interrupts
117
118Again on a uniprocessor system, there is only a single processor which
119logically executes a single task and takes interrupts. On an SMP system,
120each processor may take an interrupt. When the application disables
121interrupts, it generally does so by altering a processor register to
122mask interrupts and later to re-enable them. On a uniprocessor system,
123changing this in the single processor is sufficient. However, on an SMP
124system, this register in @strong{ALL} processors must be changed. There
125are no comparable capabilities in an SMP system to disable all interrupts
126across all processors.
127
128@subsubsection Highest Priority Task Assumption
129
130On a uniprocessor system, it is safe to assume that when the highest
131priority task in an application executes, it will execute without being
132preempted until it voluntarily blocks. Interrupts may occur while it is
133executing, but there will be no context switch to another task unless
134the highest priority task voluntarily initiates it.
135
136Given the assumption that no other tasks will have their execution
137interleaved with the highest priority task, it is possible for this
138task to be constructed such that it does not need to acquire a binary
139semaphore or mutex for protected access to shared data.
140
141In an SMP system, it cannot be assumed there will never be a single task
142executing. It should be assumed that every processor is executing another
143application task. Further, those tasks will be ones which would not have
144been executed in a uniprocessor configuration and should be assumed to
145have data synchronization conflicts with what was formerly the highest
146priority task which executed without conflict.
147
148@subsubsection Disable Preemption
149
150On a uniprocessor system, disabling preemption in a task is very similar
151to making the highest priority task assumption. While preemption is
152disabled, no task context switches will occur unless the task initiates
153them voluntarily. And, just as with the highest priority task assumption,
154there are N-1 processors also running tasks. Thus the assumption that no
155other tasks will run while the task has preemption disabled is violated.
156
157@subsection Task Unique Data and SMP
158
159Per task variables are a service commonly provided by real-time operating
160systems for application use. They work by allowing the application
161to specify a location in memory (typically a @code{void *}) which is
162logically added to the context of a task. On each task switch, the
163location in memory is stored and each task can have a unique value in
164the same memory location. This memory location is directly accessed as a
165variable in a program.
166
167This works well in a uniprocessor environment because there is one task
168executing and one memory location containing a task-specific value. But
169it is fundamentally broken on an SMP system because there are always N
170tasks executing. With only one location in memory, N-1 tasks will not
171have the correct value.
172
173This paradigm for providing task unique data values is fundamentally
174broken on SMP systems.
175
176@subsubsection Classic API Per Task Variables
177
178The Classic API provides three directives to support per task variables. These are:
179
180@itemize @bullet
181@item @code{@value{DIRPREFIX}task_variable_add} - Associate per task variable
182@item @code{@value{DIRPREFIX}task_variable_get} - Obtain value of a a per task variable
183@item @code{@value{DIRPREFIX}task_variable_delete} - Remove per task variable
184@end itemize
185
186As task variables are unsafe for use on SMP systems, the use of these
187services should be eliminated in all software that is to be used in
188an SMP environment. It is recommended that the application developer
189consider the use of POSIX Keys or Thread Local Storage (TLS). POSIX Keys
190are not enabled in all RTEMS configurations.
191
192@b{STATUS}: As of March 2014, some support services in the
193@code{rtems/cpukit} use per task variables. When these uses are
194eliminated, the per task variable directives will be disabled when
195building RTEMS in SMP configuration.
196
197@c
198@c
199@c
200@section Operations
201
202@subsection Setting Affinity to a Single Processor
203
204On some embedded applications targeting SMP systems, it may be beneficial to
205lock individual tasks to specific processors.  In this way, one can designate a
206processor for I/O tasks, another for computation, etc..  The following
207illustrates the code sequence necessary to assign a task an affinity for
208processor with index @code{processor_index}.
209
210@example
211@group
212#include <rtems.h>
213#include <assert.h>
214
215void pin_to_processor(rtems_id task_id, int processor_index)
216@{
217  rtems_status_code sc;
218  cpu_set_t         cpuset;
219
220  CPU_ZERO(&cpuset);
221  CPU_SET(processor_index, &cpuset);
222
223  sc = rtems_task_set_affinity(task_id, sizeof(cpuset), &cpuset);
224  assert(sc == RTEMS_SUCCESSFUL);
225@}
226@end group
227@end example
228
229It is important to note that the @code{cpuset} is not validated until the
230@code{@value{DIRPREFIX}task_set_affinity} call is made. At that point,
231it is validated against the current system configuration.
232
233@c
234@c
235@c
236@section Directives
237
238This section details the symmetric multiprocessing services.  A subsection
239is dedicated to each of these services and describes the calling sequence,
240related constants, usage, and status codes.
241
242@c
243@c rtems_get_processor_count
244@c
245@page
246@subsection GET_PROCESSOR_COUNT - Get processor count
247
248@subheading CALLING SEQUENCE:
249
250@ifset is-C
251@example
252uint32_t rtems_get_processor_count(void);
253@end example
254@end ifset
255
256@ifset is-Ada
257@end ifset
258
259@subheading DIRECTIVE STATUS CODES:
260
261The count of processors in the system.
262
263@subheading DESCRIPTION:
264
265On uni-processor configurations a value of one will be returned.
266
267On SMP configurations this returns the value of a global variable set during
268system initialization to indicate the count of utilized processors.  The
269processor count depends on the physically or virtually available processors and
270application configuration.  The value will always be less than or equal to the
271maximum count of application configured processors.
272
273@subheading NOTES:
274
275None.
276
277@c
278@c rtems_get_current_processor
279@c
280@page
281@subsection GET_CURRENT_PROCESSOR - Get current processor index
282
283@subheading CALLING SEQUENCE:
284
285@ifset is-C
286@example
287uint32_t rtems_get_current_processor(void);
288@end example
289@end ifset
290
291@ifset is-Ada
292@end ifset
293
294@subheading DIRECTIVE STATUS CODES:
295
296The index of the current processor.
297
298@subheading DESCRIPTION:
299
300On uni-processor configurations a value of zero will be returned.
301
302On SMP configurations an architecture specific method is used to obtain the
303index of the current processor in the system.  The set of processor indices is
304the range of integers starting with zero up to the processor count minus one.
305
306Outside of sections with disabled thread dispatching the current processor
307index may change after every instruction since the thread may migrate from one
308processor to another.  Sections with disabled interrupts are sections with
309thread dispatching disabled.
310
311@subheading NOTES:
312
313None.
314
315@c
316@c rtems_scheduler_ident
317@c
318@page
319@subsection SCHEDULER_IDENT - Get ID of a scheduler
320
321@subheading CALLING SEQUENCE:
322
323@ifset is-C
324@example
325rtems_status_code rtems_scheduler_ident(
326  rtems_name  name,
327  rtems_id   *id
328);
329@end example
330@end ifset
331
332@ifset is-Ada
333@end ifset
334
335@subheading DIRECTIVE STATUS CODES:
336
337@code{@value{RPREFIX}SUCCESSFUL} - successful operation@*
338@code{@value{RPREFIX}INVALID_ADDRESS} - @code{id} is NULL@*
339@code{@value{RPREFIX}INVALID_NAME} - invalid scheduler name
340
341@subheading DESCRIPTION:
342
343Identifies a scheduler by its name.  The scheduler name is determined by the
344scheduler configuration.  @xref{Configuring a System Configuring
345Clustered/Partitioned Schedulers}.
346
347@subheading NOTES:
348
349None.
350
351@c
352@c rtems_scheduler_get_processor_set
353@c
354@page
355@subsection SCHEDULER_GET_PROCESSOR_SET - Get processor set of a scheduler
356
357@subheading CALLING SEQUENCE:
358
359@ifset is-C
360@example
361rtems_status_code rtems_scheduler_get_processor_set(
362  rtems_id   scheduler_id,
363  size_t     cpusetsize,
364  cpu_set_t *cpuset
365);
366@end example
367@end ifset
368
369@ifset is-Ada
370@end ifset
371
372@subheading DIRECTIVE STATUS CODES:
373
374@code{@value{RPREFIX}SUCCESSFUL} - successful operation@*
375@code{@value{RPREFIX}INVALID_ADDRESS} - @code{cpuset} is NULL@*
376@code{@value{RPREFIX}INVALID_ID} - invalid scheduler id@*
377@code{@value{RPREFIX}INVALID_NUMBER} - the affinity set buffer is too small for
378set of processors owned by the scheduler
379
380@subheading DESCRIPTION:
381
382Returns the processor set owned by the scheduler in @code{cpuset}.  A set bit
383in the processor set means that this processor is owned by the scheduler and a
384cleared bit means the opposite.
385
386@subheading NOTES:
387
388None.
389
390@c
391@c rtems_task_get_scheduler
392@c
393@page
394@subsection TASK_GET_SCHEDULER - Get scheduler of a task
395
396@subheading CALLING SEQUENCE:
397
398@ifset is-C
399@example
400rtems_status_code rtems_task_get_scheduler(
401  rtems_id  id,
402  rtems_id *scheduler_id
403);
404@end example
405@end ifset
406
407@ifset is-Ada
408@end ifset
409
410@subheading DIRECTIVE STATUS CODES:
411
412@code{@value{RPREFIX}SUCCESSFUL} - successful operation@*
413@code{@value{RPREFIX}INVALID_ADDRESS} - @code{scheduler_id} is NULL@*
414@code{@value{RPREFIX}INVALID_ID} - invalid task id
415
416@subheading DESCRIPTION:
417
418Returns the scheduler identifier of a task in @code{scheduler_id}.
419
420@subheading NOTES:
421
422None.
423
424@c
425@c rtems_task_set_scheduler
426@c
427@page
428@subsection TASK_SET_SCHEDULER - Set scheduler of a task
429
430@subheading CALLING SEQUENCE:
431
432@ifset is-C
433@example
434rtems_status_code rtems_task_set_scheduler(
435  rtems_id id,
436  rtems_id scheduler_id
437);
438@end example
439@end ifset
440
441@ifset is-Ada
442@end ifset
443
444@subheading DIRECTIVE STATUS CODES:
445
446@code{@value{RPREFIX}SUCCESSFUL} - successful operation@*
447@code{@value{RPREFIX}INVALID_ID} - invalid task or scheduler id@*
448@code{@value{RPREFIX}INCORRECT_STATE} - the task is in the wrong state to
449perform a scheduler change
450
451@subheading DESCRIPTION:
452
453Sets the scheduler of a task specified by @code{scheduler_id}.  The scheduler
454of a task is initialized to the scheduler of the task that created it.
455
456@subheading NOTES:
457
458None.
459
460@subheading EXAMPLE:
461
462@example
463@group
464#include <rtems.h>
465#include <assert.h>
466
467void task(rtems_task_argument arg);
468
469void example(void)
470@{
471  rtems_status_code sc;
472  rtems_id          task_id;
473  rtems_id          scheduler_id;
474  rtems_name        scheduler_name;
475
476  scheduler_name = rtems_build_name('W', 'O', 'R', 'K');
477
478  sc = rtems_scheduler_ident(scheduler_name, &scheduler_id);
479  assert(sc == RTEMS_SUCCESSFUL);
480
481  sc = rtems_task_create(
482    rtems_build_name('T', 'A', 'S', 'K'),
483    1,
484    RTEMS_MINIMUM_STACK_SIZE,
485    RTEMS_DEFAULT_MODES,
486    RTEMS_DEFAULT_ATTRIBUTES,
487    &task_id
488  );
489  assert(sc == RTEMS_SUCCESSFUL);
490
491  sc = rtems_task_set_scheduler(task_id, scheduler_id);
492  assert(sc == RTEMS_SUCCESSFUL);
493
494  sc = rtems_task_start(task_id, task, 0);
495  assert(sc == RTEMS_SUCCESSFUL);
496@}
497@end group
498@end example
499
500@c
501@c rtems_task_get_affinity
502@c
503@page
504@subsection TASK_GET_AFFINITY - Get task processor affinity
505
506@subheading CALLING SEQUENCE:
507
508@ifset is-C
509@example
510rtems_status_code rtems_task_get_affinity(
511  rtems_id   id,
512  size_t     cpusetsize,
513  cpu_set_t *cpuset
514);
515@end example
516@end ifset
517
518@ifset is-Ada
519@end ifset
520
521@subheading DIRECTIVE STATUS CODES:
522
523@code{@value{RPREFIX}SUCCESSFUL} - successful operation@*
524@code{@value{RPREFIX}INVALID_ADDRESS} - @code{cpuset} is NULL@*
525@code{@value{RPREFIX}INVALID_ID} - invalid task id@*
526@code{@value{RPREFIX}INVALID_NUMBER} - the affinity set buffer is too small for
527the current processor affinity set of the task
528
529@subheading DESCRIPTION:
530
531Returns the current processor affinity set of the task in @code{cpuset}.  A set
532bit in the affinity set means that the task can execute on this processor and a
533cleared bit means the opposite.
534
535@subheading NOTES:
536
537None.
538
539@c
540@c rtems_task_set_affinity
541@c
542@page
543@subsection TASK_SET_AFFINITY - Set task processor affinity
544
545@subheading CALLING SEQUENCE:
546
547@ifset is-C
548@example
549rtems_status_code rtems_task_set_affinity(
550  rtems_id         id,
551  size_t           cpusetsize,
552  const cpu_set_t *cpuset
553);
554@end example
555@end ifset
556
557@ifset is-Ada
558@end ifset
559
560@subheading DIRECTIVE STATUS CODES:
561
562@code{@value{RPREFIX}SUCCESSFUL} - successful operation@*
563@code{@value{RPREFIX}INVALID_ADDRESS} - @code{cpuset} is NULL@*
564@code{@value{RPREFIX}INVALID_ID} - invalid task id@*
565@code{@value{RPREFIX}INVALID_NUMBER} - invalid processor affinity set
566
567@subheading DESCRIPTION:
568
569Sets the processor affinity set for the task specified by @code{cpuset}.  A set
570bit in the affinity set means that the task can execute on this processor and a
571cleared bit means the opposite.
572
573@subheading NOTES:
574
575None.
Note: See TracBrowser for help on using the repository browser.