diff options
author | sfraser%netscape.com <devnull@localhost> | 2001-09-26 02:34:20 +0000 |
---|---|---|
committer | sfraser%netscape.com <devnull@localhost> | 2001-09-26 02:34:20 +0000 |
commit | 452085d3e61d4385b6676bb85726ead304d556c2 (patch) | |
tree | 57538ab79499bc5d45595fc2d29f4bc417a9574c | |
parent | 419cc9a989164d0a54a9bdebfd52c44170134829 (diff) | |
download | nspr-hg-452085d3e61d4385b6676bb85726ead304d556c2.tar.gz |
More fixing for 71718. MPEnter/LeaveCriticalRegion don't work under Mac OS 10.0.x, so we need to use some hand-rolled critical sections that are just an MPSemaphore and a counter (which is all that MP critical sections are under the hood, I bet). Added a new file, mdcriticalregions.c, to the project. r=wtc/sdagley
-rw-r--r-- | macbuild/NSPR20PPC.mcp | bin | 167357 -> 163969 bytes | |||
-rw-r--r-- | pr/src/md/mac/macthr.c | 12 | ||||
-rw-r--r-- | pr/src/md/mac/mdcriticalregion.c | 169 | ||||
-rw-r--r-- | pr/src/md/mac/mdcriticalregion.h | 56 |
4 files changed, 232 insertions, 5 deletions
diff --git a/macbuild/NSPR20PPC.mcp b/macbuild/NSPR20PPC.mcp Binary files differindex a0a17543..aae83165 100644 --- a/macbuild/NSPR20PPC.mcp +++ b/macbuild/NSPR20PPC.mcp diff --git a/pr/src/md/mac/macthr.c b/pr/src/md/mac/macthr.c index 37cdb99e..b01eda61 100644 --- a/pr/src/md/mac/macthr.c +++ b/pr/src/md/mac/macthr.c @@ -44,6 +44,7 @@ #include <Multiprocessing.h> #include <Gestalt.h> +#include "mdcriticalregion.h" TimerUPP gTimerCallbackUPP = NULL; PRThread * gPrimaryThread = NULL; @@ -509,7 +510,7 @@ void _MD_SetIntsOff(PRInt32 ints) #if MAC_CRITICAL_REGIONS -MPCriticalRegionID gCriticalRegion; +MDCriticalRegionID gCriticalRegion; void InitCriticalRegion() { @@ -522,7 +523,7 @@ void InitCriticalRegion() if (!gUseCriticalRegions) return; - err = MPCreateCriticalRegion(&gCriticalRegion); + err = MD_CriticalRegionCreate(&gCriticalRegion); PR_ASSERT(err == noErr); } @@ -532,7 +533,7 @@ void TermCriticalRegion() if (!gUseCriticalRegions) return; - err = MPDeleteCriticalRegion(gCriticalRegion); + err = MD_CriticalRegionDelete(gCriticalRegion); PR_ASSERT(err == noErr); } @@ -545,7 +546,8 @@ void EnterCritialRegion() PR_ASSERT(gCriticalRegion != kInvalidID); - err = MPEnterCriticalRegion(gCriticalRegion, kDurationForever /* 10000 * kDurationMillisecond */ ); + /* Change to a non-infinite timeout for debugging purposes */ + err = MD_CriticalRegionEnter(gCriticalRegion, kDurationForever /* 10000 * kDurationMillisecond */ ); PR_ASSERT(err == noErr); } @@ -557,7 +559,7 @@ void LeaveCritialRegion() PR_ASSERT(gCriticalRegion != kInvalidID); - err = MPExitCriticalRegion(gCriticalRegion); + err = MD_CriticalRegionExit(gCriticalRegion); PR_ASSERT(err == noErr); } diff --git a/pr/src/md/mac/mdcriticalregion.c b/pr/src/md/mac/mdcriticalregion.c new file mode 100644 index 00000000..927b9246 --- /dev/null +++ b/pr/src/md/mac/mdcriticalregion.c @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: NULL; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * George Warner, Apple Computer Inc. + * Simon Fraser <sfraser@netscape.com> + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "mdcriticalregion.h" + +/* + This code is a replacement for MPEnterCriticalRegion/MPLeaveCriticalRegion, + which is broken on Mac OS 10.0.x builds, but fixed in 10.1. This code works + everywhere. +*/ + + +typedef struct MDCriticalRegionData_struct { + MPTaskID mMPTaskID; /* Who's in the critical region? */ + UInt32 mDepthCount; /* How deep? */ + MPSemaphoreID mMPSemaphoreID; /* ready semaphore */ +} MDCriticalRegionData, *MDCriticalRegionDataPtr; + + +OSStatus +MD_CriticalRegionCreate(MDCriticalRegionID * outCriticalRegionID) +{ + MDCriticalRegionDataPtr newCriticalRegionPtr; + MPSemaphoreID mpSemaphoreID; + OSStatus err = noErr; + + if (outCriticalRegionID == NULL) + return paramErr; + + *outCriticalRegionID = NULL; + + newCriticalRegionPtr = (MDCriticalRegionDataPtr)MPAllocateAligned(sizeof(MDCriticalRegionData), + kMPAllocateDefaultAligned, kMPAllocateClearMask); + if (newCriticalRegionPtr == NULL) + return memFullErr; + + // Note: this semaphore is pre-fired (ready!) + err = MPCreateBinarySemaphore(&mpSemaphoreID); + if (err == noErr) + { + newCriticalRegionPtr->mMPTaskID = kInvalidID; + newCriticalRegionPtr->mDepthCount = 0; + newCriticalRegionPtr->mMPSemaphoreID = mpSemaphoreID; + + *outCriticalRegionID = (MDCriticalRegionID)newCriticalRegionPtr; + } + else + { + MPFree((LogicalAddress)newCriticalRegionPtr); + } + + return err; +} + +OSStatus +MD_CriticalRegionDelete(MDCriticalRegionID inCriticalRegionID) +{ + MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID; + OSStatus err = noErr; + + if (criticalRegion == NULL) + return paramErr; + + if ((criticalRegion->mMPTaskID != kInvalidID) && (criticalRegion->mDepthCount > 0)) + return kMPInsufficientResourcesErr; + + if (criticalRegion->mMPSemaphoreID != kInvalidID) + err = MPDeleteSemaphore(criticalRegion->mMPSemaphoreID); + if (noErr != err) return err; + + criticalRegion->mMPSemaphoreID = kInvalidID; + MPFree((LogicalAddress) criticalRegion); + + return noErr; +} + +OSStatus +MD_CriticalRegionEnter(MDCriticalRegionID inCriticalRegionID, Duration inTimeout) +{ + MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID; + MPTaskID currentTaskID = MPCurrentTaskID(); + OSStatus err = noErr; + + if (criticalRegion == NULL) + return paramErr; + + // if I'm inside the critical region... + if (currentTaskID == criticalRegion->mMPTaskID) + { + // bump my depth + criticalRegion->mDepthCount++; + // and continue + return noErr; + } + + // wait for the ready semaphore + err = MPWaitOnSemaphore(criticalRegion->mMPSemaphoreID, inTimeout); + // we didn't get it. return the error + if (noErr != err) return err; + + // we got it! + criticalRegion->mMPTaskID = currentTaskID; + criticalRegion->mDepthCount = 1; + + return noErr; +} + +OSStatus +MD_CriticalRegionExit(MDCriticalRegionID inCriticalRegionID) +{ + MDCriticalRegionDataPtr criticalRegion = (MDCriticalRegionDataPtr)inCriticalRegionID; + MPTaskID currentTaskID = MPCurrentTaskID(); + OSStatus err = noErr; + + // if we don't own the critical region... + if (currentTaskID != criticalRegion->mMPTaskID) + return kMPInsufficientResourcesErr; + + // if we aren't at a depth... + if (criticalRegion->mDepthCount == 0) + return kMPInsufficientResourcesErr; + + // un-bump my depth + criticalRegion->mDepthCount--; + + // if we just bottomed out... + if (criticalRegion->mDepthCount == 0) + { + // release ownership of the structure + criticalRegion->mMPTaskID = kInvalidID; + // and signal the ready semaphore + err = MPSignalSemaphore(criticalRegion->mMPSemaphoreID); + } + return err; +} + diff --git a/pr/src/md/mac/mdcriticalregion.h b/pr/src/md/mac/mdcriticalregion.h new file mode 100644 index 00000000..eba4c82b --- /dev/null +++ b/pr/src/md/mac/mdcriticalregion.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * George Warner, Apple Computer Inc. + * Simon Fraser <sfraser@netscape.com> + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifndef mdcriticalregion_h___ +#define mdcriticalregion_h___ + + +#ifndef __MULTIPROCESSING__ +#include <Multiprocessing.h> +#endif + +typedef struct OpaqueMDCriticalRegionID* MDCriticalRegionID; + +OSStatus MD_CriticalRegionCreate(MDCriticalRegionID * pMDCriticalRegionID); + +OSStatus MD_CriticalRegionDelete(MDCriticalRegionID pMDCriticalRegionID); + +OSStatus MD_CriticalRegionEnter(MDCriticalRegionID pMDCriticalRegionID, Duration pTimeout); + +OSStatus MD_CriticalRegionExit(MDCriticalRegionID pMDCriticalRegionID); + +#endif /* mdcriticalregion_h___ */ + |