From 39c4eec3c1154d031591883d0e4256856a121e19 Mon Sep 17 00:00:00 2001 From: NicJA Date: Mon, 18 May 2015 13:59:17 +0000 Subject: [PATCH] wip changes for execsmp. git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@50706 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- rom/exec/newaddtask.c | 66 ++++++++++++++++++++++++++++++++------------------- rom/exec/settaskpri.c | 41 +++++++++++++++++++++++++------- rom/exec/signal.c | 61 +++++++++++++++++++++++++++++++++++++---------- rom/exec/wait.c | 31 +++++++++++++++++------- 4 files changed, 145 insertions(+), 54 deletions(-) diff --git a/rom/exec/newaddtask.c b/rom/exec/newaddtask.c index b253aa4eec..5e661aacc8 100644 --- a/rom/exec/newaddtask.c +++ b/rom/exec/newaddtask.c @@ -18,6 +18,10 @@ #include "exec_debug.h" #include "taskstorage.h" +#if defined(__AROSEXEC_SMP__) +#include +#endif + /***************************************************************************** NAME */ @@ -75,9 +79,13 @@ ASSERT_VALID_PTR(task); +#if defined(__AROSEXEC_SMP__) + int cpunum = KrnGetCPUNumber(); +#endif + /* Sigh - you should provide a name for your task. */ - if(task->tc_Node.ln_Name==NULL) - task->tc_Node.ln_Name="unknown task"; + if (task->tc_Node.ln_Name == NULL) + task->tc_Node.ln_Name = "unknown task"; DADDTASK("NewAddTask (0x%p (\"%s\"), 0x%p, 0x%p)", task, task->tc_Node.ln_Name, initialPC, finalPC); @@ -88,31 +96,31 @@ DADDTASK("NewAddTask MemEntry head: 0x%p", GetHead(&task->tc_MemEntry.lh_Head)); /* Set node type to NT_TASK if not set to something else. */ - if(!task->tc_Node.ln_Type) - task->tc_Node.ln_Type=NT_TASK; + if (!task->tc_Node.ln_Type) + task->tc_Node.ln_Type = NT_TASK; /* This is moved into SysBase at the tasks's startup */ - task->tc_IDNestCnt=-1; - task->tc_TDNestCnt=-1; + task->tc_IDNestCnt = -1; + task->tc_TDNestCnt = -1; task->tc_State = TS_ADDED; task->tc_Flags = 0; - + task->tc_SigWait = 0; task->tc_SigRecvd = 0; task->tc_SigExcept = 0; - + /* Signals default to all system signals allocated. */ - if(task->tc_SigAlloc==0) - task->tc_SigAlloc=SysBase->TaskSigAlloc; + if (task->tc_SigAlloc == 0) + task->tc_SigAlloc = SysBase->TaskSigAlloc; /* Currently only used for segmentation violation */ - if(task->tc_TrapCode==NULL) - task->tc_TrapCode=SysBase->TaskTrapCode; + if (task->tc_TrapCode == NULL) + task->tc_TrapCode = SysBase->TaskTrapCode; + + if (task->tc_ExceptCode == NULL) + task->tc_ExceptCode = SysBase->TaskExceptCode; - if(task->tc_ExceptCode==NULL) - task->tc_ExceptCode=SysBase->TaskExceptCode; - /* * EXECF_StackSnoop can be set or reset at runtime. * However task's stack is either snooped or not, it's problematic @@ -126,7 +134,7 @@ return NULL; /* Get new stackpointer. */ - if (task->tc_SPReg==NULL) + if (task->tc_SPReg == NULL) task->tc_SPReg = (UBYTE *)(task->tc_SPUpper) - SP_OFFSET; #ifdef AROS_STACKALIGN @@ -145,15 +153,15 @@ startfill = (UBYTE *)task->tc_SPLower; endfill = ((UBYTE *)task->tc_SPReg) - 16; - while(startfill <= endfill) + while (startfill <= endfill) { *startfill++ = 0xE1; } } /* Default finalizer? */ - if(finalPC==NULL) - finalPC=SysBase->TaskExitCode; + if (finalPC == NULL) + finalPC = SysBase->TaskExitCode; /* Init new context. */ if (!PrepareContext(task, initialPC, finalPC, tagList, SysBase)) @@ -174,15 +182,15 @@ of Signal() which is usable from interrupts and may change those lists. */ - + #if defined(__AROSEXEC_SMP__) EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskReadySpinLock, SPINLOCK_MODE_WRITE); #endif Disable(); /* Add the new task to the ready list. */ - task->tc_State=TS_READY; - Enqueue(&SysBase->TaskReady,&task->tc_Node); + task->tc_State = TS_READY; + Enqueue(&SysBase->TaskReady, &task->tc_Node); #if defined(__AROSEXEC_SMP__) EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskReadySpinLock); #endif @@ -194,14 +202,24 @@ is already gone. */ - if (task->tc_Node.ln_Pri > GET_THIS_TASK->tc_Node.ln_Pri && - GET_THIS_TASK->tc_State == TS_RUN) + if ( +#if defined(__AROSEXEC_SMP__) + ((IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuAffinity & KrnGetCPUMask(cpunum)) == KrnGetCPUMask(cpunum)) && +#endif + task->tc_Node.ln_Pri > GET_THIS_TASK->tc_Node.ln_Pri && + GET_THIS_TASK->tc_State == TS_RUN) { D(bug("[AddTask] Rescheduling...\n")); /* Reschedule() will take care about disabled task switching automatically */ Reschedule(); } +#if defined(__AROSEXEC_SMP__) + else + { + bug("[Exec] AddTask:\n"); + } +#endif Enable(); diff --git a/rom/exec/settaskpri.c b/rom/exec/settaskpri.c index ad822b02b0..c7250853e0 100644 --- a/rom/exec/settaskpri.c +++ b/rom/exec/settaskpri.c @@ -5,12 +5,18 @@ Desc: Change the priority of a task. Lang: english */ +#define DEBUG 0 +#include #include #include #include #include "exec_intern.h" +#if defined(__AROSEXEC_SMP__) +#include +#include "etask.h" +#endif /***************************************************************************** @@ -55,9 +61,12 @@ #if defined(__AROSEXEC_SMP__) spinlock_t *task_listlock = NULL; + int cpunum = KrnGetCPUNumber(); #endif BYTE old; + D(bug("[Exec] SetTaskPri(0x%p, %d)\n", task, priority)); + /* Always Disable() when doing something with task lists. */ #if defined(__AROSEXEC_SMP__) switch (task->tc_State) @@ -92,19 +101,33 @@ Enqueue(&SysBase->TaskReady, &task->tc_Node); } - /* - I could check the task priorities here to determine if - the following is really necessary, but OTOH priority - changes are rare and the hassle isn't really worth it. - - This should be reconsidered, because of Executive [ldp]. - */ - Reschedule(); + if ( +#if defined(__AROSEXEC_SMP__) + (IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuNumber == cpunum) && +#endif + ((task->tc_State == TS_RUN) || ( task->tc_Node.ln_Pri > GET_THIS_TASK->tc_Node.ln_Pri)) + ) + { +#if defined(__AROSEXEC_SMP__) + EXEC_SPINLOCK_UNLOCK(task_listlock); + task_listlock = NULL; +#endif + Reschedule(); +#if defined(__AROSEXEC_SMP__) + } + else + { + bug("[Exec] SetTaskPri:\n"); + } +#endif } /* All done. */ #if defined(__AROSEXEC_SMP__) - EXEC_SPINLOCK_UNLOCK(task_listlock); + if (task_listlock) + { + EXEC_SPINLOCK_UNLOCK(task_listlock); + } #endif Enable(); diff --git a/rom/exec/signal.c b/rom/exec/signal.c index bfc8a30f04..c289012056 100644 --- a/rom/exec/signal.c +++ b/rom/exec/signal.c @@ -5,13 +5,18 @@ Desc: Send some signal to a given task Lang: english */ +#define DEBUG 0 +#include #include #include #include -#include #include "exec_intern.h" +#if defined(__AROSEXEC_SMP__) +#include +#include "etask.h" +#endif /***************************************************************************** @@ -57,8 +62,14 @@ #if defined(__AROSEXEC_SMP__) spinlock_t *task_listlock = NULL; + int cpunum = KrnGetCPUNumber(); #endif + D( + bug("[Exec] Signal(0x%p, %08lX)\n", task, signalSet); + bug("[Exec] Signal: '%s' state %08x\n", task->tc_Node.ln_Name, task->tc_State); + ) + /* Protect the task lists against other tasks that may use Signal(). */ #if defined(__AROSEXEC_SMP__) switch (task->tc_State) @@ -74,27 +85,44 @@ break; } EXEC_SPINLOCK_LOCK(task_listlock, SPINLOCK_MODE_WRITE); + D(bug("[Exec] Signal: initial lock @ 0x%p\n", task_listlock)); #endif Disable(); + D(bug("[Exec] Signal: multitasking disabled\n")); + /* Set the signals in the task structure. */ task->tc_SigRecvd |= signalSet; /* Do those bits raise exceptions? */ - if (task->tc_SigExcept & task->tc_SigRecvd) + if (task->tc_SigRecvd & task->tc_SigExcept) { /* Yes. Set the exception flag. */ task->tc_Flags |= TF_EXCEPT; - /* task is running (Signal() called from within interrupt)? Raise the exception or defer it for later. */ + D(bug("[Exec] Signal: TF_EXCEPT set\n")); + + /* + if the target task is running (called from within interrupt handler), + raise the exception or defer it for later. + */ if (task->tc_State == TS_RUN) { + D(bug("[Exec] Signal: signaling running task\n")); #if defined(__AROSEXEC_SMP__) EXEC_SPINLOCK_UNLOCK(task_listlock); + if (IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuNumber == cpunum) + { #endif /* Order a reschedule */ Reschedule(); - +#if defined(__AROSEXEC_SMP__) + } + else + { + D(bug("[Exec] Signal:\n")); + } +#endif /* All done. */ Enable(); @@ -107,11 +135,13 @@ (or on a exception) ? */ if ((task->tc_State == TS_WAIT) && - (task->tc_SigRecvd&(task->tc_SigWait | task->tc_SigExcept))) + (task->tc_SigRecvd & (task->tc_SigWait | task->tc_SigExcept))) { - /* Yes. Move him to the ready list. */ - task->tc_State = TS_READY; + D(bug("[Exec] Signal: signaling waiting task\n")); + + /* Yes. Move it to the ready list. */ Remove(&task->tc_Node); + task->tc_State = TS_READY; #if defined(__AROSEXEC_SMP__) EXEC_SPINLOCK_UNLOCK(task_listlock); Enable(); @@ -119,9 +149,16 @@ Disable(); #endif Enqueue(&SysBase->TaskReady, &task->tc_Node); - +#if defined(__AROSEXEC_SMP__) + EXEC_SPINLOCK_UNLOCK(task_listlock); + task_listlock = NULL; +#endif /* Has it a higher priority as the current one? */ - if (task->tc_Node.ln_Pri > GET_THIS_TASK->tc_Node.ln_Pri) + if ( +#if defined(__AROSEXEC_SMP__) + (IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuAffinity & KrnGetCPUMask(cpunum)) && +#endif + (task->tc_Node.ln_Pri > GET_THIS_TASK->tc_Node.ln_Pri)) { /* Yes. A taskswitch is necessary. Prepare one if possible. @@ -129,10 +166,6 @@ */ if (GET_THIS_TASK->tc_State == TS_RUN) { -#if defined(__AROSEXEC_SMP__) - EXEC_SPINLOCK_UNLOCK(task_listlock); - task_listlock = NULL; -#endif Reschedule(); } } @@ -146,6 +179,8 @@ #endif Enable(); + D(bug("[Exec] Signal: 0x%p finished signal processing\n", task)); + AROS_LIBFUNC_EXIT } diff --git a/rom/exec/wait.c b/rom/exec/wait.c index 9256918ee4..468fad2cc9 100644 --- a/rom/exec/wait.c +++ b/rom/exec/wait.c @@ -60,6 +60,9 @@ { AROS_LIBFUNC_INIT +#if defined(__AROSEXEC_SMP__) + spinlock_t *task_listlock = NULL; +#endif ULONG rcvd; struct Task *me; @@ -71,24 +74,32 @@ /* If at least one of the signals is already set do not wait. */ while (!(me->tc_SigRecvd & signalSet)) { + /* Set the wait signal mask */ + me->tc_SigWait = signalSet; #if defined(__AROSEXEC_SMP__) if (me->tc_State != TS_WAIT) { #endif D(bug("[Exec] Moving '%s' @ 0x%p to Task Wait queue\n", me->tc_Node.ln_Name, me)); D(bug("[Exec] Task state = %08x\n", me->tc_State)); - /* Set the wait signal mask */ - me->tc_SigWait = signalSet; /* Protect the task lists against access by other tasks. */ #if defined(__AROSEXEC_SMP__) - EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock, SPINLOCK_MODE_WRITE); + switch (me->tc_State) + { + case TS_RUN: + task_listlock = &PrivExecBase(SysBase)->TaskRunningSpinLock; + break; + default: + task_listlock = &PrivExecBase(SysBase)->TaskReadySpinLock; + break; + } + EXEC_SPINLOCK_LOCK(task_listlock, SPINLOCK_MODE_WRITE); #endif Disable(); - #if defined(__AROSEXEC_SMP__) Remove(&me->tc_Node); - EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock); + EXEC_SPINLOCK_UNLOCK(task_listlock); Enable(); EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock, SPINLOCK_MODE_WRITE); Disable(); @@ -105,6 +116,13 @@ Enqueue(&SysBase->TaskWait, &me->tc_Node); #if defined(__AROSEXEC_SMP__) EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock); + } + else + { + Disable(); + me->tc_TDNestCnt = TDNESTCOUNT_GET; + TDNESTCOUNT_SET(-1); + } #endif /* And switch to the next ready task. */ KrnSwitch(); @@ -119,9 +137,6 @@ TDNESTCOUNT_SET(me->tc_TDNestCnt); Enable(); -#if defined(__AROSEXEC_SMP__) - } - #endif } /* Get active signals. */ rcvd = (me->tc_SigRecvd & signalSet); -- 2.11.4.GIT