From 47f92a1d7b8d223b3941b573e46b2e44e3593059 Mon Sep 17 00:00:00 2001 From: NicJA Date: Mon, 13 Mar 2017 16:10:21 +0000 Subject: [PATCH] write protect access to the timers lists on smp builds. git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@54107 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- rom/timer/lowlevel.c | 74 +++++++++++++++++++++++++++++++++++------------- rom/timer/timer_init.c | 8 +++++- rom/timer/timer_intern.h | 12 +++++++- 3 files changed, 73 insertions(+), 21 deletions(-) diff --git a/rom/timer/lowlevel.c b/rom/timer/lowlevel.c index 0c64c5aac1..96afb6f53a 100644 --- a/rom/timer/lowlevel.c +++ b/rom/timer/lowlevel.c @@ -1,5 +1,5 @@ /* - Copyright © 1995-2011, The AROS Development Team. All rights reserved. + Copyright © 1995-2017, The AROS Development Team. All rights reserved. $Id$ Desc: Common IORequest processing routines @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "timer_intern.h" @@ -155,6 +156,10 @@ BOOL common_BeginIO(struct timerequest *timereq, struct TimerBase *TimerBase) } else { +#if defined(__AROSEXEC_SMP__) + struct ExecLockBase *ExecLockBase = TimerBase->tb_ExecLockBase; + if (ExecLockBase) ObtainLock(TimerBase->tb_ListLock, SPINLOCK_MODE_WRITE, 0); +#endif /* Ok, we add this to the list */ addToWaitList(&TimerBase->tb_Lists[TL_WAITVBL], timereq, SysBase); @@ -166,6 +171,9 @@ BOOL common_BeginIO(struct timerequest *timereq, struct TimerBase *TimerBase) if (TimerBase->tb_Lists[TL_WAITVBL].mlh_Head == (struct MinNode *)timereq) addedhead = TRUE; +#if defined(__AROSEXEC_SMP__) + if (ExecLockBase) ReleaseLock(TimerBase->tb_ListLock, 0); +#endif replyit = FALSE; timereq->tr_node.io_Flags &= ~IOF_QUICK; } @@ -175,30 +183,41 @@ BOOL common_BeginIO(struct timerequest *timereq, struct TimerBase *TimerBase) case UNIT_VBLANK: case UNIT_MICROHZ: - Disable(); + { +#if defined(__AROSEXEC_SMP__) + struct ExecLockBase *ExecLockBase = TimerBase->tb_ExecLockBase; +#endif - /* Query the hardware first */ - EClockUpdate(TimerBase); + Disable(); + /* Query the hardware first */ + EClockUpdate(TimerBase); - /* - * Adjust the time request to be relative to the - * the elapsed time counter that we keep. - */ - ADDTIME(&timereq->tr_time, &TimerBase->tb_Elapsed); - /* Slot it into the list. Use unit number as index. */ - addToWaitList(&TimerBase->tb_Lists[unitNum], timereq, SysBase); + /* + * Adjust the time request to be relative to the + * the elapsed time counter that we keep. + */ + ADDTIME(&timereq->tr_time, &TimerBase->tb_Elapsed); - /* Indicate if HW need to be reprogrammed */ - if (TimerBase->tb_Lists[unitNum].mlh_Head == (struct MinNode *)timereq) - addedhead = TRUE; +#if defined(__AROSEXEC_SMP__) + if (ExecLockBase) ObtainLock(TimerBase->tb_ListLock, SPINLOCK_MODE_WRITE, 0); +#endif + /* Slot it into the list. Use unit number as index. */ + addToWaitList(&TimerBase->tb_Lists[unitNum], timereq, SysBase); - Enable(); - timereq->tr_node.io_Flags &= ~IOF_QUICK; - replyit = FALSE; - break; + /* Indicate if HW need to be reprogrammed */ + if (TimerBase->tb_Lists[unitNum].mlh_Head == (struct MinNode *)timereq) + addedhead = TRUE; +#if defined(__AROSEXEC_SMP__) + if (ExecLockBase) ReleaseLock(TimerBase->tb_ListLock, 0); +#endif + Enable(); + timereq->tr_node.io_Flags &= ~IOF_QUICK; + replyit = FALSE; + break; + } case UNIT_ECLOCK: case UNIT_WAITECLOCK: /* TODO: implement these (backport from m68k-Amiga) */ @@ -240,6 +259,9 @@ BOOL common_BeginIO(struct timerequest *timereq, struct TimerBase *TimerBase) void handleMicroHZ(struct TimerBase *TimerBase, struct ExecBase *SysBase) { +#if defined(__AROSEXEC_SMP__) + struct ExecLockBase *ExecLockBase = TimerBase->tb_ExecLockBase; +#endif struct MinList *unit = &TimerBase->tb_Lists[TL_MICROHZ]; struct timerequest *tr, *next; @@ -247,6 +269,9 @@ void handleMicroHZ(struct TimerBase *TimerBase, struct ExecBase *SysBase) * Go through the list and return requests that have completed. * A completed request is one whose time is less than that of the elapsed time. */ +#if defined(__AROSEXEC_SMP__) + if (ExecLockBase) ObtainLock(TimerBase->tb_ListLock, SPINLOCK_MODE_WRITE, 0); +#endif ForeachNodeSafe(unit, tr, next) { if (CMPTIME(&TimerBase->tb_Elapsed, &tr->tr_time) <= 0) @@ -306,10 +331,16 @@ void handleMicroHZ(struct TimerBase *TimerBase, struct ExecBase *SysBase) break; } } +#if defined(__AROSEXEC_SMP__) + if (ExecLockBase) ReleaseLock(TimerBase->tb_ListLock, 0); +#endif } void handleVBlank(struct TimerBase *TimerBase, struct ExecBase *SysBase) { +#if defined(__AROSEXEC_SMP__) + struct ExecLockBase *ExecLockBase = TimerBase->tb_ExecLockBase; +#endif /* * VBlank handler is the same as above, with two differences: * 1. We don't check for VBlank emulation request. @@ -324,6 +355,9 @@ void handleVBlank(struct TimerBase *TimerBase, struct ExecBase *SysBase) * that have completed. A completed request is one whose time * is less than that of the elapsed time. */ +#if defined(__AROSEXEC_SMP__) + if (ExecLockBase) ObtainLock(TimerBase->tb_ListLock, SPINLOCK_MODE_WRITE, 0); +#endif ForeachNodeSafe(&TimerBase->tb_Lists[TL_VBLANK], tr, next) { if (CMPTIME(&TimerBase->tb_Elapsed, &tr->tr_time) <= 0) @@ -339,7 +373,6 @@ void handleVBlank(struct TimerBase *TimerBase, struct ExecBase *SysBase) else break; } - /* * The other this is the "wait until a specified time". Here a request * is complete if the time we are waiting for is before the current time. @@ -359,6 +392,9 @@ void handleVBlank(struct TimerBase *TimerBase, struct ExecBase *SysBase) else break; } +#if defined(__AROSEXEC_SMP__) + if (ExecLockBase) ReleaseLock(TimerBase->tb_ListLock, 0); +#endif } /****************************************************************************************/ diff --git a/rom/timer/timer_init.c b/rom/timer/timer_init.c index 8f849241c8..6f864d7450 100644 --- a/rom/timer/timer_init.c +++ b/rom/timer/timer_init.c @@ -1,5 +1,5 @@ /* - Copyright © 1995-2011, The AROS Development Team. All rights reserved. + Copyright © 1995-2017, The AROS Development Team. All rights reserved. $Id$ Desc: Timer startup and device commands, reference code @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -63,6 +64,11 @@ static int GM_UNIQUENAME(Init)(LIBBASETYPEPTR LIBBASE) { struct Interrupt *is; +#if defined(__AROSEXEC_SMP__) + if ((LIBBASE->tb_ExecLockBase = OpenResource("execlock.resource")) != NULL) + LIBBASE->tb_ListLock = AllocLock(); +#endif + /* If no frequency is set, assume 50Hz */ if (SysBase->VBlankFrequency == 0) SysBase->VBlankFrequency = 50; diff --git a/rom/timer/timer_intern.h b/rom/timer/timer_intern.h index e8bc2fda39..18018344e2 100644 --- a/rom/timer/timer_intern.h +++ b/rom/timer/timer_intern.h @@ -2,13 +2,15 @@ #define _TIMER_INTERN_H /* - Copyright © 1995-2011, The AROS Development Team. All rights reserved. + Copyright © 1995-2017, The AROS Development Team. All rights reserved. $Id$ Desc: Internal information about the timer.device and HIDD's Lang: english */ +#include + #include #include #include @@ -23,6 +25,10 @@ /* Platform-specific portion */ #include +#if defined(__AROSEXEC_SMP__) +#include +#endif + /* * First two of these correspond to UNIT_MICROHZ and UNIT_VBLANK. * This is important. @@ -61,6 +67,10 @@ struct TimerBase #endif struct PlatformTimer tb_Platform; /* Platform-specific data */ +#if defined(__AROSEXEC_SMP__) + void *tb_ExecLockBase; + void *tb_ListLock; +#endif }; #define GetTimerBase(tb) ((struct TimerBase *)(tb)) -- 2.11.4.GIT