Ticket #1796: InterprocessorPatch.txt

File InterprocessorPatch.txt, 11.7 KB (added by Jennifer Averett, on 05/12/11 at 18:22:10)

SMP Interprocessor communications

Line 
1Index: cpukit/sapi/src/exshutdown.c
2===================================================================
3RCS file: /usr1/CVS/rtems/cpukit/sapi/src/exshutdown.c,v
4retrieving revision 1.4
5diff -u -r1.4 exshutdown.c
6--- cpukit/sapi/src/exshutdown.c        10 Aug 2010 22:56:35 -0000      1.4
7+++ cpukit/sapi/src/exshutdown.c        12 May 2011 19:13:16 -0000
8@@ -1,7 +1,7 @@
9 /*
10  *  Initialization Manager
11  *
12- *  COPYRIGHT (c) 1989-1999.
13+ *  COPYRIGHT (c) 1989-2011.
14  *  On-Line Applications Research Corporation (OAR).
15  *
16  *  The license and distribution terms for this file may be
17@@ -20,6 +20,10 @@
18 #include <rtems/score/thread.h>
19 #include <rtems/score/interr.h>
20 
21+#if defined(RTEMS_SMP)
22+  #include <rtems/score/smp.h>
23+#endif
24+
25 /*
26  *  rtems_shutdown_executive
27  *
28@@ -37,6 +41,9 @@
29 )
30 {
31   if ( _System_state_Is_up( _System_state_Get() ) ) {
32+    #if defined(RTEMS_SMP)
33+      _SMP_Request_other_cores_to_shutdown();
34+    #endif
35     _System_state_Set( SYSTEM_STATE_SHUTDOWN );
36     _Thread_Stop_multitasking();
37   }
38Index: cpukit/score/include/rtems/score/percpu.h
39===================================================================
40RCS file: /usr1/CVS/rtems/cpukit/score/include/rtems/score/percpu.h,v
41retrieving revision 1.6
42diff -u -r1.6 percpu.h
43--- cpukit/score/include/rtems/score/percpu.h   11 May 2011 14:22:35 -0000      1.6
44+++ cpukit/score/include/rtems/score/percpu.h   12 May 2011 19:13:16 -0000
45@@ -76,9 +76,15 @@
46 
47   /**
48    *  This defines the constant used to indicate that the cpu code has
49+   *  completed basic initialization and awaits further commands.
50+   */
51+  RTEMS_BSP_SMP_CPU_UP = 3,
52+
53+  /**
54+   *  This defines the constant used to indicate that the cpu code has
55    *  shut itself down.
56    */
57-  RTEMS_BSP_SMP_CPU_SHUTDOWN = 3
58+  RTEMS_BSP_SMP_CPU_SHUTDOWN = 4
59 } bsp_smp_cpu_state;
60 
61 /**
62Index: cpukit/score/include/rtems/score/smp.h
63===================================================================
64RCS file: /usr1/CVS/rtems/cpukit/score/include/rtems/score/smp.h,v
65retrieving revision 1.1
66diff -u -r1.1 smp.h
67--- cpukit/score/include/rtems/score/smp.h      27 Apr 2011 17:18:59 -0000      1.1
68+++ cpukit/score/include/rtems/score/smp.h      12 May 2011 19:13:16 -0000
69@@ -87,6 +87,14 @@
70 );
71 
72 /**
73+ *  @brief Request Other Cores to Perform First Context Switch
74+ *
75+ *  Send message to other cores requesting them to perform
76+ *  their first context switch operation.
77+ */
78+void _SMP_Request_other_cores_to_perform_first_context_switch(void);
79+
80+/**
81  *  @brief Request Dispatch on Other Cores
82  *
83  *  Send message to other cores requesting them to perform
84Index: cpukit/score/src/smp.c
85===================================================================
86RCS file: /usr1/CVS/rtems/cpukit/score/src/smp.c,v
87retrieving revision 1.3
88diff -u -r1.3 smp.c
89--- cpukit/score/src/smp.c      27 Apr 2011 17:18:59 -0000      1.3
90+++ cpukit/score/src/smp.c      12 May 2011 19:13:16 -0000
91@@ -19,30 +19,35 @@
92 #include <rtems/score/thread.h>
93 
94 #if defined(RTEMS_SMP)
95-#define SMP_DEBUG
96+  #define RTEMS_DEBUG
97+#endif
98 
99-#if defined(SMP_DEBUG)
100+#if defined(RTEMS_DEBUG)
101   #include <rtems/bspIo.h>
102 #endif
103 
104+/*
105+ *  Process request to switch to the first task on a secondary core.
106+ */
107 void rtems_smp_run_first_task(int cpu)
108 {
109   Thread_Control *heir;
110 
111   /*
112-   *  This CPU has an heir thread so we need to dispatch it.
113+   *  The Scheduler will have selected the heir thread for each CPU core.
114+   *  Now we have been requested to perform the first context switch.  So
115+   *  force a switch to the designated heir and make it executing on
116+   *  THIS core.
117    */
118-  heir = _Thread_Heir;
119-
120-  /*
121-   *  This is definitely a hack until we have SMP scheduling.  Since there
122-   *  is only one executing and heir right now, we have to fake this out.
123-   */
124-  _Thread_Dispatch_set_disable_level(1);
125+  heir              = _Thread_Heir;
126   _Thread_Executing = heir;
127+
128   _CPU_Context_switch_to_first_task_smp( &heir->Registers );
129 }
130 
131+/*
132+ *  Process request to initialize this secondary core.
133+ */
134 void rtems_smp_secondary_cpu_initialize(void)
135 {
136   int cpu;
137@@ -63,15 +68,26 @@
138   _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_INITIALIZED;
139 
140   /*
141-   *  HACK: Should not have to enable interrupts in real system here.
142-   *        It should happen as part of switching to the first task.
143+   *  With this secondary core out of reset, we can wait for the
144+   *  request to switch to the first task.
145+   *
146+   *  XXX When SMP ISR code is complete, do we want interrupts on
147+   *  XXX or off at this point?
148    */
149-   
150-  _Per_CPU_Information[cpu].isr_nest_level = 1;
151   _ISR_Set_level( 0 );
152-  while(1) ;
153+  while(1) {
154+    bsp_smp_wait_for(
155+      (volatile unsigned int *)&_Per_CPU_Information[cpu].message,
156+      RTEMS_BSP_SMP_FIRST_TASK,
157+      10000
158+    );
159+  }
160 }
161 
162+/*
163+ *  Process an interrupt processor interrupt which indicates a request
164+ *  from another core.
165+ */
166 void rtems_smp_process_interrupt(void)
167 {
168   int        cpu;
169@@ -81,30 +97,52 @@
170   cpu = bsp_smp_processor_id();
171 
172   level = _SMP_lock_Spinlock_Obtain( &_Per_CPU_Information[cpu].lock );
173-    message = _Per_CPU_Information[cpu].message;
174-    _Per_CPU_Information[cpu].message &= ~message;
175-  _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
176+  message = _Per_CPU_Information[cpu].message;
177 
178   #if defined(SMP_DEBUG)
179     {
180       void *sp = __builtin_frame_address(0);
181-      if ( !(message & RTEMS_BSP_SMP_SHUTDOWN) )
182-       printk( "ISR on CPU %d -- (0x%02x) (0x%p)\n", cpu, message, sp );
183-      printk( "Dispatch level %d\n", _Thread_Dispatch_disable_level );
184+      if ( !(message & RTEMS_BSP_SMP_SHUTDOWN) ) {
185+        printk( "ISR on CPU %d -- (0x%02x) (0x%p)\n", cpu, message, sp );
186+       if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY )
187+         printk( "context switch necessary\n" );
188+       if ( message & RTEMS_BSP_SMP_SIGNAL_TO_SELF )
189+         printk( "signal to self\n" );
190+       if ( message & RTEMS_BSP_SMP_SHUTDOWN )
191+         printk( "shutdown\n" );
192+       if ( message & RTEMS_BSP_SMP_FIRST_TASK )
193+         printk( "switch to first task\n" );
194+      }
195+
196+      printk( "Dispatch level %d\n", _Thread_Dispatch_get_disable_level() );
197     }
198   #endif
199 
200   if ( message & RTEMS_BSP_SMP_FIRST_TASK ) {
201+    /*
202+     * XXX Thread dispatch disable level at this point will have to be
203+     * XXX revisited when Interrupts on SMP is addressed.
204+     */
205+    _Thread_Dispatch_disable_level--; /* undo ISR code */
206     _Per_CPU_Information[cpu].isr_nest_level = 0;
207-    _Per_CPU_Information[cpu].message = 0;
208-    _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_INITIALIZED;
209+    _Per_CPU_Information[cpu].message &= ~message;
210+    _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_UP;
211+
212+    _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
213+    _Thread_Disable_dispatch();
214     rtems_smp_run_first_task(cpu);
215     /* does not return */
216   }
217 
218   if ( message & RTEMS_BSP_SMP_SHUTDOWN ) {
219-    ISR_Level level;
220-    _Thread_Dispatch_set_disable_level(0);
221+    /*
222+     * XXX Thread dispatch disable level at this point will have to be
223+     * XXX revisited when Interrupts on SMP is addressed.
224+     */
225+    _Per_CPU_Information[cpu].message &= ~message;
226+    _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
227+
228+    _Thread_Dispatch_disable_level--; /* undo ISR code */
229     _Per_CPU_Information[cpu].isr_nest_level = 0;
230     _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_SHUTDOWN;
231     _ISR_Disable( level );
232@@ -114,12 +152,22 @@
233   }
234 
235   if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY ) {
236-    printk( "switch needed\n" );
237-    _Per_CPU_Information[cpu].dispatch_necessary = true;
238+    #if defined(SMP_DEBUG)
239+      printk( "switch needed\n" );
240+    #endif
241+    /*
242+     * XXX Thread dispatch disable level at this point will have to be
243+     * XXX revisited when Interrupts on SMP is addressed.
244+     */
245+    _Per_CPU_Information[cpu].message &= ~message;
246+    _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
247   }
248 }
249 
250-void rtems_smp_send_message(
251+/*
252+ *  Send an interrupt processor request to another cpu.
253+ */
254+void _SMP_send_message(
255   int       cpu,
256   uint32_t  message
257 )
258@@ -132,7 +180,10 @@
259   bsp_smp_interrupt_cpu( cpu );
260 }
261 
262-void rtems_smp_broadcast_message(
263+/*
264+ *  Send interrupt processor request to all other nodes
265+ */
266+void _SMP_Broadcast_message(
267   uint32_t  message
268 )
269 {
270@@ -151,4 +202,80 @@
271   }
272   bsp_smp_broadcast_interrupt();
273 }
274-#endif
275+
276+/*
277+ *  Send interrupt processor requests to perform first context switch
278+ */
279+void _SMP_Request_other_cores_to_perform_first_context_switch(void)
280+{
281+  int    cpu;
282+
283+  for (cpu=1 ; cpu < _SMP_Processor_count ; cpu++ ) {
284+    _SMP_send_message( cpu, RTEMS_BSP_SMP_FIRST_TASK );
285+    while (_Per_CPU_Information[cpu].state != RTEMS_BSP_SMP_CPU_UP ) {
286+      bsp_smp_wait_for(
287+        (volatile unsigned int *)&_Per_CPU_Information[cpu].state,
288+        RTEMS_BSP_SMP_CPU_UP,
289+        10000
290+      );
291+    }
292+  }
293+}
294+
295+/*
296+ *  Send message to other cores requesting them to perform
297+ *  a thread dispatch operation.
298+ */
299+void _SMP_Request_other_cores_to_dispatch(void)
300+{
301+  int i;
302+  int cpu_num;
303+
304+  cpu_num = bsp_smp_processor_id();
305+
306+  if ( !_System_state_Is_up (_System_state_Current) )
307+    return;
308+  for (i=1 ; i < _SMP_Processor_count ; i++ ) {
309+    if ( cpu_num == i )
310+      continue;
311+    if ( _Per_CPU_Information[i].state != RTEMS_BSP_SMP_CPU_UP )
312+      continue;
313+    if ( !_Per_CPU_Information[i].dispatch_necessary )
314+      continue;
315+    _SMP_send_message( i, RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY );
316+    bsp_smp_wait_for(
317+      (volatile unsigned int *)&_Per_CPU_Information[i].message,
318+      0,
319+      10000
320+    );
321+  }
322+}
323+
324+/*
325+ *  Send message to other cores requesting them to shutdown.
326+ */
327+void _SMP_Request_other_cores_to_shutdown(void)
328+{
329+  bool allDown;
330+  int  ncpus;
331+  int  n;
332+
333+  ncpus = _SMP_Processor_count;
334+
335+  _SMP_Broadcast_message( RTEMS_BSP_SMP_SHUTDOWN );
336+
337+  allDown = true;
338+  for (n=1 ; n<ncpus ; n++ ) {
339+     bsp_smp_wait_for(
340+       (unsigned int *)&_Per_CPU_Information[n].state,
341+       RTEMS_BSP_SMP_CPU_SHUTDOWN,
342+       10000
343+    );
344+    if ( _Per_CPU_Information[n].state != RTEMS_BSP_SMP_CPU_SHUTDOWN )
345+      allDown = false;
346+  }
347+  if ( !allDown )
348+    printk( "not all down -- timed out\n" );
349+  else
350+    printk( "All CPUs shutdown successfully\n" );
351+}
352Index: cpukit/score/src/threadhandler.c
353===================================================================
354RCS file: /usr1/CVS/rtems/cpukit/score/src/threadhandler.c,v
355retrieving revision 1.32
356diff -u -r1.32 threadhandler.c
357--- cpukit/score/src/threadhandler.c    28 Jan 2011 20:24:53 -0000      1.32
358+++ cpukit/score/src/threadhandler.c    12 May 2011 19:13:16 -0000
359@@ -2,7 +2,7 @@
360  *  Thread Handler
361  *
362  *
363- *  COPYRIGHT (c) 1989-2009.
364+ *  COPYRIGHT (c) 1989-2011.
365  *  On-Line Applications Research Corporation (OAR).
366  *
367  *  The license and distribution terms for this file may be
368@@ -51,6 +51,11 @@
369   #define EXECUTE_GLOBAL_CONSTRUCTORS
370 #endif
371 
372+#if defined(RTEMS_SMP)
373+  #include <rtems/score/smp.h>
374+#endif
375+
376+
377 /*PAGE
378  *
379  *  _Thread_Handler
380@@ -138,8 +143,15 @@
381      */
382     if (!doneCons) /* && (volatile void *)_init) */ {
383       INIT_NAME ();
384+   
385+      #if defined(RTEMS_SMP)
386+        _Thread_Disable_dispatch();
387+          _SMP_Request_other_cores_to_perform_first_context_switch();
388+        _Thread_Enable_dispatch();
389+      #endif
390+
391     }
392-  #endif
393+ #endif
394 
395   if ( executing->Start.prototype == THREAD_START_NUMERIC ) {
396     executing->Wait.return_argument =