os/kernelhwsrv/kernel/eka/nkernsmp/x86/ncsched.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\nkernsmp\x86\ncsched.cpp
    15 // 
    16 //
    17 
    18 // NThreadBase member data
    19 #define __INCLUDE_NTHREADBASE_DEFINES__
    20 
    21 #include <x86.h>
    22 #include <apic.h>
    23 
    24 
    25 // Called by a thread which has been forced to exit
    26 // Kernel locked on entry
    27 extern "C" void __fastcall do_forced_exit(NThreadBase* aT)
    28 	{
    29 	__NK_ASSERT_ALWAYS(aT->iFastMutexDefer != 1);
    30 	aT->iFastMutexDefer = 0;
    31 	aT->Exit();
    32 	}
    33 
    34 extern "C" NThreadBase* __fastcall select_next_thread(TSubScheduler* aS)
    35 	{
    36 	return aS->SelectNextThread();
    37 	}
    38 
    39 extern "C" void __fastcall queue_dfcs(TSubScheduler* aS)
    40 	{
    41 	aS->QueueDfcs();
    42 	}
    43 
    44 extern "C" void NewThreadTrace(NThread* a)
    45 	{
    46 	__ACQUIRE_BTRACE_LOCK();
    47 	BTraceData.iHandler(BTRACE_HEADER_C(4,BTrace::ECpuUsage,BTrace::ENewThreadContext),0,(TUint32)a,0,0,0,0,0);
    48 	__RELEASE_BTRACE_LOCK();
    49 	}
    50 
    51 extern "C" void __fastcall send_ipi(TUint32);
    52 extern "C" void __fastcall do_send_resched_ipis(TUint32);
    53 
    54 extern "C" void send_resched_ipi(TInt aCpu)
    55 	{
    56 	TSubScheduler& ss = TheSubSchedulers[aCpu];
    57 	__KTRACE_OPT(KSCHED2,DEBUGPRINT("@%d",aCpu));
    58 	send_ipi((TUint32)ss.i_APICID);
    59 	}
    60 
    61 extern "C" void send_resched_ipis(TUint32 aMask)
    62 	{
    63 	__KTRACE_OPT(KSCHED2,DEBUGPRINT("@%02x",aMask));
    64 #ifdef __USE_LOGICAL_DEST_MODE__
    65 	do_send_resched_ipis(aMask);
    66 #else
    67 	TInt i=0;
    68 	while (aMask)
    69 		{
    70 		if (aMask&1)
    71 			send_resched_ipi(i);
    72 		aMask>>=1;
    73 		++i;
    74 		}
    75 #endif
    76 	}
    77 
    78 extern "C" void send_resched_ipi_and_wait(TInt aCpu)
    79 	{
    80 	TSubScheduler& ss = TheSubSchedulers[aCpu];
    81 	__KTRACE_OPT(KSCHED2,DEBUGPRINT("@@%d",aCpu));
    82 	volatile TUint32& irqc = (volatile TUint32&)ss.i_IrqCount;
    83 	volatile TInt& irqn = (volatile TInt&)ss.i_IrqNestCount;
    84 	TUint32 irqc0 = irqc;
    85 	mb();
    86 	send_ipi((TUint32)ss.i_APICID);
    87 	mb();
    88 	while (!ss.iRescheduleNeededFlag || (irqn<0 && irqc==irqc0))
    89 		{
    90 		__chill();
    91 		}
    92 	mb();	// guaranteed to observe final thread state after this
    93 	}
    94 
    95 void TSubScheduler::SaveTimesliceTimer(NThreadBase* aT)
    96 	{
    97 	if (aT->iTime>0 && !aT->i_NThread_Initial)
    98 		{
    99 		TUint32 remain32 = read_apic_reg(CURRCNT);
   100 		TUint64 x(remain32);
   101 		x *= TUint32(i_TimerMultI);
   102 		x += 0x00800000u;
   103 		x >>= 24;
   104 		aT->iTime = (TInt)x;
   105 		}
   106 	write_apic_reg(INITCNT, 0);
   107 	}
   108 
   109 
   110 /*	Update aOld's execution time and set up the timer for aNew
   111 	Update this CPU's timestamp value
   112 
   113 	if (!aOld) aOld=iInitialThread
   114 	if (!aNew) aNew=iInitialThread
   115 	if new thread has a timeslice, start the timeslice timer
   116 	update the last reschedule time
   117 	update the run time for the old thread
   118 	update the reschedule count for the new thread and the current CPU
   119  */
   120 void TSubScheduler::UpdateThreadTimes(NThreadBase* aOld, NThreadBase* aNew)
   121 	{
   122 	if (!aOld)
   123 		aOld = iInitialThread;
   124 	if (!aNew)
   125 		aNew = iInitialThread;
   126 	if (aNew->iTime>0)
   127 		{
   128 		TUint32 remain32 = (TUint32)aNew->iTime;
   129 		TUint64 x(remain32);
   130 		x *= TUint32(i_TimerMultF);
   131 		x += 0x80000000u;
   132 		x >>= 32;
   133 		write_apic_reg(LVTTMR, TIMESLICE_VECTOR);
   134 		write_apic_reg(INITCNT, (TUint32)x);
   135 		}
   136 	if (aNew!=aOld)
   137 		{
   138 		TUint64 now = NKern::Timestamp();
   139 		aOld->iTotalCpuTime64 += (now - iLastTimestamp64);
   140 		iLastTimestamp64 = now;
   141 		++iReschedCount64;
   142 		++aNew->iRunCount64;
   143 		}
   144 	}
   145 
   146