How does context switching work?

Richi Dubey richidubey at gmail.com
Mon Nov 2 15:21:19 UTC 2020


Hi Mr. Dörfler,

Thanks for your reply.

When the first task is reactivated, it leaves the contextswitch function.
> Therefore all the code around the context switch function handles the same
> task it was called for.

When I am debugging sp16.exe,after TA1 calls task_wake_after, it calls the
_Context_Switch() function, and I think (correct me if I am wrong) TA5
follows the execution after TA1 calls _Context_Switch.

I have attached the gdb trace with this mail. Let me know what you think.

Thanks,
Richi.


On Sun, Nov 1, 2020 at 12:35 AM Thomas Dörfler <
thomas.doerfler at embedded-brains.de> wrote:

> Richi,
>
> inside the contextswitch function, the current context ist suspended (so
> it is stuck/frozen die nside the context switch code) and execution
> switches to a different task. When the first task is reactivated, it leaves
> the contextswitch function. Therefore all the code around the context
> switch function handles the same task it was called for.
>
> --------------------------------------------
> embedded brains GmbH
> Thomas Doerfler
> Dornierstr. 4
> D-82178 Puchheim
> Germany
> email: Thomas.Doerfler at embedded-brains.de
> Phone: +49-89-18 94 741-12
> Fax:   +49-89-18 94 741-09
> PGP: Public key available on request.
>
> Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
>
>
>
> Am 31.10.2020 16:49 schrieb Richi Dubey <richidubey at gmail.com>:
>
> Hi,
>
> I want to learn more about how context switching works in RTEMS. I saw the
> following lines in theaddispatch.c:
>
>     _Thread_Save_fp( executing );
>     _Context_Switch( &executing->Registers, &heir->Registers );
>     _Thread_Restore_fp( executing );
>
> I do not understand how it works. Here, the executing process saves its
> context by calling _Thread_Save_fp( executing ), then if a different
> process resumes execution after the context switch, why does it get the
> context of previous process (executing)?
>
> Can someone help me learn more about this?
>
> Thanks,
> Richi.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20201102/e2dca42b/attachment.html>
-------------- next part --------------
Right now we are in Task_1:

197	  puts( "TA1 - rtems_task_wake_after - yield processor" );
(gdb) 
0x00102590	197	  puts( "TA1 - rtems_task_wake_after - yield processor" );
(gdb) 
0x00102594	197	  puts( "TA1 - rtems_task_wake_after - yield processor" );
(gdb) 
198	  status = rtems_task_wake_after( RTEMS_YIELD_PROCESSOR );
(gdb) si
0x0010259a	198	  status = rtems_task_wake_after( RTEMS_YIELD_PROCESSOR );
(gdb) 
rtems_task_wake_after (ticks=46) at /home/richi/quick-start/src/rtems/c/src/../../cpukit/rtems/src/taskwakeafter.c:28
28	{
(gdb) ni
0x0010b27a	28	{
(gdb) 
0x0010b27c	28	{
(gdb) 
0x0010b27e	28	{
(gdb) 
36	  cpu_self = _Thread_Dispatch_disable();
(gdb) 
0x0010b284	36	  cpu_self = _Thread_Dispatch_disable();
(gdb) 
37	    executing = _Per_CPU_Get_executing( cpu_self );
(gdb) 
0x0010b288	37	    executing = _Per_CPU_Get_executing( cpu_self );
(gdb) 
0x0010b28c	37	    executing = _Per_CPU_Get_executing( cpu_self );
(gdb) 
39	    if ( ticks == 0 ) {
(gdb) 
0x0010b290	39	    if ( ticks == 0 ) {
(gdb) 
0x0010b292	39	    if ( ticks == 0 ) {
(gdb) 
40	      _Thread_Yield( executing );
(gdb) ni
0x0010b296	40	      _Thread_Yield( executing );
(gdb) 
0x0010b29a	40	      _Thread_Yield( executing );
(gdb) 
46	  _Thread_Dispatch_direct( cpu_self );
(gdb) si
0x0010b2ba	46	  _Thread_Dispatch_direct( cpu_self );
(gdb) 
_Thread_Dispatch_direct (cpu_self=0x202180 <_RTEMS_tasks_Objects+1280>) at /home/richi/quick-start/src/rtems/c/src/../../cpukit/score/src/threaddispatch.c:351
351	{
(gdb) ni
0x00110662	351	{
(gdb) 
0x00110664	351	{
(gdb) 
0x00110666	351	{
(gdb) 
354	  if ( cpu_self->thread_dispatch_disable_level != 1 ) {
(gdb) 
0x0011066a	354	  if ( cpu_self->thread_dispatch_disable_level != 1 ) {
(gdb) 
354	  if ( cpu_self->thread_dispatch_disable_level != 1 ) {
(gdb) 
0x0011066e	354	  if ( cpu_self->thread_dispatch_disable_level != 1 ) {
(gdb) 
358	  _ISR_Local_disable( level );
(gdb) 
0x0011067a	358	  _ISR_Local_disable( level );
(gdb) 
359	  _Thread_Do_dispatch( cpu_self, level );
(gdb) 
0x0011067e	359	  _Thread_Do_dispatch( cpu_self, level );
(gdb) si
0x00110680	359	  _Thread_Do_dispatch( cpu_self, level );
(gdb) 
_Thread_Do_dispatch (cpu_self=0x1, level=48) at /home/richi/quick-start/src/rtems/c/src/../../cpukit/score/src/threaddispatch.c:260
260	{
(gdb) ni
0x0011059a	260	{
(gdb) 
0x0011059c	260	{
(gdb) 
0x0011059e	260	{
(gdb) 
0x001105a0	260	{
(gdb) 
267	    !_ISR_Is_enabled( level )
(gdb) 
0x001105a4	267	    !_ISR_Is_enabled( level )
(gdb) 
0x001105a8	267	    !_ISR_Is_enabled( level )
(gdb) ni
267	    !_ISR_Is_enabled( level )
(gdb) 
0x001105ae	267	    !_ISR_Is_enabled( level )
(gdb) 
266	  if (
(gdb) 
0x001105b2	266	  if (
(gdb) 
276	  executing = cpu_self->executing;
(gdb) 
0x001105bc	276	  executing = cpu_self->executing;
(gdb) p executing
$1 = (Thread_Control *) 0x600f01d3
(gdb) ni
0x001105be	276	  executing = cpu_self->executing;
(gdb) 
281	    level = _Thread_Preemption_intervention( executing, cpu_self, level );
(gdb) p executing
$2 = (Thread_Control *) 0x202180 <_RTEMS_tasks_Objects+1280>
(gdb) ni
0x001105c2	281	    level = _Thread_Preemption_intervention( executing, cpu_self, level );
(gdb) 
0x001105c4	281	    level = _Thread_Preemption_intervention( executing, cpu_self, level );
(gdb) 
0x001105c6	281	    level = _Thread_Preemption_intervention( executing, cpu_self, level );
(gdb) 
0x001105ca	281	    level = _Thread_Preemption_intervention( executing, cpu_self, level );
(gdb) 
282	    heir = _Thread_Get_heir_and_make_it_executing( cpu_self );
(gdb) 
0x001105ce	282	    heir = _Thread_Get_heir_and_make_it_executing( cpu_self );
(gdb) 
0x001105d2	282	    heir = _Thread_Get_heir_and_make_it_executing( cpu_self );
(gdb) 
289	    if ( heir == executing )
(gdb) 
0x001105d6	289	    if ( heir == executing )
(gdb) 
0x001105d8	289	    if ( heir == executing )
(gdb) 
0x001105da	289	    if ( heir == executing )
(gdb) 
296	    if ( heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
(gdb) 
0x001105de	296	    if ( heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
(gdb) 
296	    if ( heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
(gdb) 
0x001105e4	296	    if ( heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
(gdb) 
299	    _ISR_Local_enable( level );
(gdb) 
0x001105f8	299	    _ISR_Local_enable( level );
(gdb) 
304	    _Thread_Save_fp( executing );
(gdb) 
0x001105fe	304	    _Thread_Save_fp( executing );
(gdb) 
305	    _Context_Switch( &executing->Registers, &heir->Registers );
(gdb) si
0x00110604	305	    _Context_Switch( &executing->Registers, &heir->Registers );
(gdb) 
0x00110608	305	    _Context_Switch( &executing->Registers, &heir->Registers );
(gdb) 
0x0011060a	305	    _Context_Switch( &executing->Registers, &heir->Registers );
(gdb) 
0x0011060e	305	    _Context_Switch( &executing->Registers, &heir->Registers );
(gdb) 
0x00110610	305	    _Context_Switch( &executing->Registers, &heir->Registers );
(gdb) 
0x00110612	305	    _Context_Switch( &executing->Registers, &heir->Registers );
(gdb) 
_CPU_Context_switch () at /home/richi/quick-start/src/rtems/c/src/../../cpukit/score/cpu/arm/cpu_asm.S:56
56	DEFINE_FUNCTION_ARM(_CPU_Context_switch)
(gdb) ni
_CPU_Context_switch_arm () at /home/richi/quick-start/src/rtems/c/src/../../cpukit/score/cpu/arm/cpu_asm.S:58
58		GET_SELF_CPU_CONTROL	r2
(gdb) 
59		ldr	r3, [r2, #PER_CPU_ISR_DISPATCH_DISABLE]
(gdb) 
60		stm	r0, {r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
(gdb) 
63		add	r5, r0, #ARM_CONTEXT_CONTROL_D8_OFFSET
(gdb) 
64		vstm	r5, {d8-d15}
(gdb) 
67		str	r3, [r0, #ARM_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE]
(gdb) 
75		dmb
(gdb) 
76		add	sp, r2, #(PER_CPU_INTERRUPT_FRAME_AREA + CPU_INTERRUPT_FRAME_SIZE)
(gdb) 
_CPU_Context_switch_arm () at /home/richi/quick-start/src/rtems/c/src/../../cpukit/score/cpu/arm/cpu_asm.S:77
77		mov	r3, #0
(gdb) 
78		strb	r3, [r0, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET]
(gdb) 
83		add	r3, r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET
(gdb) 
84		ldrexb	r4, [r3]
(gdb) 
85		cmp	r4, #0
(gdb) 
86		bne	.L_get_potential_new_heir
(gdb) 
89		mov	r4, #1
(gdb) 
90		strexb	r5, r4, [r3]
(gdb) 
91		cmp	r5, #0
(gdb) 
92		bne	.L_get_potential_new_heir
(gdb) 
93		dmb
(gdb) 
103		ldr	r3, [r1, #ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET]
(gdb) 
106		ldr	r4, [r1, #ARM_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE]
(gdb) 
109		add	r5, r1, #ARM_CONTEXT_CONTROL_D8_OFFSET
(gdb) 
110		vldm	r5, {d8-d15}
(gdb) 
114		mcr	p15, 0, r3, c13, c0, 3
(gdb) 
117		str	r4, [r2, #PER_CPU_ISR_DISPATCH_DISABLE]
(gdb) 
121		ldm	r1, {r4, r5, r6, r7, r8, r9, r10, r11, r13, pc}
(gdb) 
_Thread_Do_dispatch (cpu_self=0x200580 <_Per_CPU_Information>, level=1610678611) at /home/richi/quick-start/src/rtems/c/src/../../cpukit/score/src/threaddispatch.c:306
306	    _Thread_Restore_fp( executing );
(gdb) 
0x00110618	306	    _Thread_Restore_fp( executing );
(gdb) 
308	    _User_extensions_Thread_switch( NULL, executing );
(gdb) 
0x0011061e	308	    _User_extensions_Thread_switch( NULL, executing );
(gdb) 
0x00110620	308	    _User_extensions_Thread_switch( NULL, executing );
(gdb) 
316	    cpu_self = _Per_CPU_Get();
(gdb) 
0x00110628	316	    cpu_self = _Per_CPU_Get();
(gdb) 
318	    _ISR_Local_disable( level );
(gdb) 
0x0011062e	318	    _ISR_Local_disable( level );
(gdb) 
319	  } while ( cpu_self->dispatch_necessary );
(gdb) 
0x00110632	319	  } while ( cpu_self->dispatch_necessary );
(gdb) 
0x00110634	319	  } while ( cpu_self->dispatch_necessary );
(gdb) 
319	  } while ( cpu_self->dispatch_necessary );
(gdb) 
0x00110638	319	  } while ( cpu_self->dispatch_necessary );
(gdb) 
321	post_switch:
(gdb) 
323	  cpu_self->thread_dispatch_disable_level = 0;
(gdb) p cpu_self->executing;
Invalid character ';' in expression.
(gdb) p cpu_self->executing
$3 = (struct _Thread_Control *) 0x202680 <_RTEMS_tasks_Objects+2560>
(gdb) ni
0x00110640	323	  cpu_self->thread_dispatch_disable_level = 0;
(gdb) 
0x00110642	323	  cpu_self->thread_dispatch_disable_level = 0;
(gdb) 
324	  _Profiling_Thread_dispatch_enable( cpu_self, 0 );
(gdb) 
0x00110646	324	  _Profiling_Thread_dispatch_enable( cpu_self, 0 );
(gdb) 
0x00110648	324	  _Profiling_Thread_dispatch_enable( cpu_self, 0 );
(gdb) 
326	  _ISR_Local_enable( level );
(gdb) 
0x0011064e	326	  _ISR_Local_enable( level );
(gdb) 
328	  _Thread_Run_post_switch_actions( executing );
(gdb) ni
0x00110654	328	  _Thread_Run_post_switch_actions( executing );
(gdb) 
329	}
(gdb) 
0x0011065a	329	}
(gdb) 
0x0011065c	329	}
(gdb) 
0x0011065e	329	}
(gdb) 
_Thread_Dispatch_direct (cpu_self=0x200580 <_Per_CPU_Information>) at /home/richi/quick-start/src/rtems/c/src/../../cpukit/score/src/threaddispatch.c:360
360	}
(gdb) 
0x00110686	360	}
(gdb) 
0x00110688	360	}
(gdb) 
0x0011068a	360	}
(gdb) 
_Thread_queue_Enqueue (queue=0x200888 <_Region_Objects+16>, operations=0x123204 <_Thread_queue_Operations_FIFO>, the_thread=0x202680 <_RTEMS_tasks_Objects+2560>, queue_context=0x20fc38) at /home/richi/quick-start/src/rtems/c/src/../../cpukit/score/src/threadqenqueue.c:453
453	}
(gdb) 
0x001145ec	453	}
(gdb) 
0x001145ee	453	}
(gdb) 
rtems_region_get_segment (id=838926337, size=3072, option_set=0, timeout=0, segment=0x20fd14) at /home/richi/quick-start/src/rtems/c/src/../../cpukit/rtems/src/regiongetsegment.c:113
113	      return _Status_Get_after_wait( executing );
(gdb) 
0x0010a13c	113	      return _Status_Get_after_wait( executing );
(gdb) 
0x0010a140	113	      return _Status_Get_after_wait( executing );
(gdb) 
0x0010a142	113	      return _Status_Get_after_wait( executing );
(gdb) 
119	}
(gdb) 
0x0010a152	119	}
(gdb) 
0x0010a154	119	}
(gdb) 
0x0010a156	119	}
(gdb) 
0x00103c82 in Task5 (argument=0) at /home/richi/quick-start/src/rtems/c/src/../../testsuites/sptests/sp16/task5.c:53
53	  status = rtems_region_get_segment(
(gdb) 
60	  puts_nocr( "TA5 - got segment from region 1 - " );



More information about the devel mailing list