1 <!-- 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. -->
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
22 TITLE="HAL Interfaces"
23 HREF="hal-interfaces.html"><LINK
25 TITLE="Diagnostic Support"
26 HREF="hal-diagnostic-support.html"><LINK
28 TITLE="Exception Handling"
29 HREF="hal-exception-handling.html"></HEAD
40 SUMMARY="Header navigation table"
49 >eCos Reference Manual</TH
57 HREF="hal-diagnostic-support.html"
65 >Chapter 9. HAL Interfaces</TD
71 HREF="hal-exception-handling.html"
85 NAME="HAL-SMP-SUPPORT">SMP Support</H1
87 >eCos contains support for limited Symmetric Multi-Processing
88 (SMP). This is only available on selected architectures and platforms.</P
94 NAME="AEN8275">Target Hardware Limitations</H2
96 >To allow a reasonable implementation of SMP, and to reduce the
97 disruption to the existing source base, a number of assumptions have
98 been made about the features of the target hardware.</P
104 >Modest multiprocessing. The typical number of CPUs supported is two
105 to four, with an upper limit around eight. While there are no
106 inherent limits in the code, hardware and algorithmic limitations
107 will probably become significant beyond this point.</P
111 >SMP synchronization support. The hardware must supply a mechanism to
112 allow software on two CPUs to synchronize. This is normally provided
113 as part of the instruction set in the form of test-and-set,
114 compare-and-swap or load-link/store-conditional instructions. An
115 alternative approach is the provision of hardware semaphore
116 registers which can be used to serialize implementations of these
117 operations. Whatever hardware facilities are available, they are
118 used in eCos to implement spinlocks.</P
122 >Coherent caches. It is assumed that no extra effort will be required
123 to access shared memory from any processor. This means that either
124 there are no caches, they are shared by all processors, or are
125 maintained in a coherent state by the hardware. It would be too
126 disruptive to the eCos sources if every memory access had to be
127 bracketed by cache load/flush operations. Any hardware that requires
128 this is not supported.</P
132 >Uniform addressing. It is assumed that all memory that is
133 shared between CPUs is addressed at the same location from all
134 CPUs. Like non-coherent caches, dealing with CPU-specific address
135 translation is considered too disruptive to the eCos source
136 base. This does not, however, preclude systems with non-uniform
137 access costs for different CPUs.</P
141 >Uniform device addressing. As with access to memory, it is assumed
142 that all devices are equally accessible to all CPUs. Since device
143 access is often made from thread contexts, it is not possible to
144 restrict access to device control registers to certain CPUs, since
145 there is currently no support for binding or migrating threads to CPUs.</P
149 >Interrupt routing. The target hardware must have an interrupt
150 controller that can route interrupts to specific CPUs. It is
151 acceptable for all interrupts to be delivered to just one CPU, or
152 for some interrupts to be bound to specific CPUs, or for some
153 interrupts to be local to each CPU. At present dynamic routing,
154 where a different CPU may be chosen each time an interrupt is
155 delivered, is not supported. ECos cannot support hardware where all
156 interrupts are delivered to all CPUs simultaneously with the
157 expectation that software will resolve any conflicts.</P
161 >Inter-CPU interrupts. A mechanism to allow one CPU to interrupt
162 another is needed. This is necessary so that events on one CPU can
163 cause rescheduling on other CPUs.</P
167 >CPU Identifiers. Code running on a CPU must be able to determine
168 which CPU it is running on. The CPU Id is usually provided either in
169 a CPU status register, or in a register associated with the
170 inter-CPU interrupt delivery subsystem. ECos expects CPU Ids to be
171 small positive integers, although alternative representations, such
172 as bitmaps, can be converted relatively easily. Complex mechanisms
173 for getting the CPU Id cannot be supported. Getting the CPU Id must
174 be a cheap operation, since it is done often, and in performance
175 critical places such as interrupt handlers and the scheduler.</P
184 NAME="AEN8295">HAL Support</H2
186 >SMP support in any platform depends on the HAL supplying the
187 appropriate operations. All HAL SMP support is defined in the
190 >cyg/hal/hal_smp.h</TT
191 > header. Variant and platform
192 specific definitions will be in <TT
194 >cyg/hal/var_smp.h</TT
198 >cyg/hal/plf_smp.h</TT
199 > respectively. These files
200 are include automatically by this header, so need not be included
203 >SMP support falls into a number of functional groups.</P
209 NAME="AEN8302">CPU Control</H3
211 >This group consists of descriptive and control macros for managing the
212 CPUs in an SMP system.</P
221 >HAL_SMP_CPU_TYPE</TT
225 >A type that can contain a CPU id. A CPU id is
226 usually a small integer that is used to index
227 arrays of variables that are managed on an
237 >The maximum number of CPUs that can be
238 supported. This is used to provide the size of
239 any arrays that have an element per CPU.</P
244 >HAL_SMP_CPU_COUNT()</TT
248 >Returns the number of CPUs currently
249 operational. This may differ from
250 HAL_SMP_CPU_MAX depending on the runtime
256 >HAL_SMP_CPU_THIS()</TT
260 >Returns the CPU id of the current CPU.</P
265 >HAL_SMP_CPU_NONE</TT
269 >A value that does not match any real CPU
270 id. This is uses where a CPU type variable
271 must be set to a null value.</P
276 >HAL_SMP_CPU_START( cpu )</TT
280 >Starts the given CPU executing at a defined
281 HAL entry point. After performing any HAL
282 level initialization, the CPU calls up into
285 >cyg_kernel_cpu_startup()</TT
291 >HAL_SMP_CPU_RESCHEDULE_INTERRUPT( cpu, wait )</TT
295 >Sends the CPU a reschedule interrupt, and if
301 > is non-zero, waits for an
302 acknowledgment. The interrupted CPU should call
305 >cyg_scheduler_set_need_reschedule()</TT
307 cause the reschedule to occur.</P
312 >HAL_SMP_CPU_TIMESLICE_INTERRUPT( cpu, wait )</TT
316 >Sends the CPU a timeslice interrupt, and if
322 > is non-zero, waits for an
323 acknowledgment. The interrupted CPU should call
326 >cyg_scheduler_timeslice_cpu()</TT
328 timeslice event to be processed.</P
338 NAME="AEN8351">Test-and-set Support</H3
340 >Test-and-set is the foundation of the SMP synchronization
354 >The type for all test-and-set variables. The
355 test-and-set macros only support operations on
356 a single bit (usually the least significant
357 bit) of this location. This allows for maximum
358 flexibility in the implementation.</P
363 >HAL_TAS_SET( tas, oldb )</TT
367 >Performs a test and set operation on the
382 the location was already set, and <TT
391 >HAL_TAS_CLEAR( tas, oldb )</TT
395 >Performs a test and clear operation on the
410 the location was already set, and <TT
424 NAME="AEN8378">Spinlocks</H3
426 >Spinlocks provide inter-CPU locking. Normally they will be implemented
427 on top of the test-and-set mechanism above, but may also be
428 implemented by other means if, for example, the hardware has more
429 direct support for spinlocks.</P
438 >HAL_SPINLOCK_TYPE</TT
442 >The type for all spinlock variables.</P
447 >HAL_SPINLOCK_INIT_CLEAR</TT
451 >A value that may be assigned to a spinlock
452 variable to initialize it to clear.</P
457 >HAL_SPINLOCK_INIT_SET</TT
461 >A value that may be assigned to a spinlock
462 variable to initialize it to set.</P
467 >HAL_SPINLOCK_SPIN( lock )</TT
471 >The caller spins in a busy loop waiting for
472 the lock to become clear. It then sets it and
473 continues. This is all handled atomically, so
474 that there are no race conditions between CPUs.</P
479 >HAL_SPINLOCK_CLEAR( lock )</TT
483 >The caller clears the lock. One of any waiting
484 spinners will then be able to proceed.</P
489 >HAL_SPINLOCK_TRY( lock, val )</TT
493 >Attempts to set the lock. The value put in
503 claimed successfully, and <TT
512 >HAL_SPINLOCK_TEST( lock, val )</TT
516 >Tests the current value of the lock. The value
539 NAME="AEN8423">Scheduler Lock</H3
541 >The scheduler lock is the main protection for all kernel data
542 structures. By default the kernel implements the scheduler lock itself
543 using a spinlock. However, if spinlocks cannot be supported by the
544 hardware, or there is a more efficient implementation available, the
545 HAL may provide macros to implement the scheduler lock.</P
554 >HAL_SMP_SCHEDLOCK_DATA_TYPE</TT
558 >A data type, possibly a structure, that
559 contains any data items needed by the
560 scheduler lock implementation. A variable of
561 this type will be instantiated as a static
562 member of the Cyg_Scheduler_SchedLock class
563 and passed to all the following macros.</P
568 >HAL_SMP_SCHEDLOCK_INIT( lock, data )</TT
572 >Initialize the scheduler lock. The <TT
578 argument is the scheduler lock counter and the
584 > argument is a variable of
585 HAL_SMP_SCHEDLOCK_DATA_TYPE type.</P
590 >HAL_SMP_SCHEDLOCK_INC( lock, data )</TT
594 >Increment the scheduler lock. The first
595 increment of the lock from zero to one for any
596 CPU may cause it to wait until the lock is
597 zeroed by another CPU. Subsequent increments
598 should be less expensive since this CPU
599 already holds the lock.</P
604 >HAL_SMP_SCHEDLOCK_ZERO( lock, data )</TT
608 >Zero the scheduler lock. This operation will
609 also clear the lock so that other CPUs may
615 >HAL_SMP_SCHEDLOCK_SET( lock, data, new )</TT
619 >Set the lock to a different value, in
625 >. This is only called when the lock is
626 already known to be owned by the current CPU. It is never called to
627 zero the lock, or to increment it from zero.</P
637 NAME="AEN8455">Interrupt Routing</H3
639 >The routing of interrupts to different CPUs is supported by two new
640 interfaces in hal_intr.h.</P
642 >Once an interrupt has been routed to a new CPU, the existing vector
643 masking and configuration operations should take account of the CPU
644 routing. For example, if the operation is not invoked on the
645 destination CPU itself, then the HAL may need to arrange to transfer
646 the operation to the destination CPU for correct application.</P
655 >HAL_INTERRUPT_SET_CPU( vector, cpu )</TT
659 >Route the interrupt for the given <TT
675 >HAL_INTERRUPT_GET_CPU( vector, cpu )</TT
684 > to the id of the CPU to which this
697 SUMMARY="Footer navigation table"
708 HREF="hal-diagnostic-support.html"
726 HREF="hal-exception-handling.html"
736 >Diagnostic Support</TD
742 HREF="hal-interfaces.html"
750 >Exception Handling</TD