示例#1
0
        private bool TryEnterUpgradeableReadLockCore(int millisecondsTimeout)
        {
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("millisecondsTimeout");
            }

            if (fDisposed)
            {
                throw new ObjectDisposedException(null);
            }

            int id = Thread.CurrentThread.ManagedThreadId;
            ReaderWriterCount lrwc;

            if (!fIsReentrant)
            {
                if (id == upgradeLockOwnerId)
                {
                    //Check for AU->AU
                    throw new LockRecursionException(SR.GetString(SR.LockRecursionException_RecursiveUpgradeNotAllowed));
                }
                else if (id == writeLockOwnerId)
                {
                    //Check for AU->AW
                    throw new LockRecursionException(SR.GetString(SR.LockRecursionException_UpgradeAfterWriteNotAllowed));
                }

                EnterMyLock();
                lrwc = GetThreadRWCount(id, true);
                //Can't acquire upgrade lock with reader lock held.
                if (lrwc != null && lrwc.readercount > 0)
                {
                    ExitMyLock();
                    throw new LockRecursionException(SR.GetString(SR.LockRecursionException_UpgradeAfterReadNotAllowed));
                }
            }
            else
            {
                EnterMyLock();
                lrwc = GetThreadRWCount(id, false);

                if (id == upgradeLockOwnerId)
                {
                    lrwc.rc.upgradecount++;
                    ExitMyLock();
                    return(true);
                }
                else if (id == writeLockOwnerId)
                {
                    //Write lock is already held, Just update the global state
                    //to show presence of upgrader.
                    Debug.Assert((owners & WRITER_HELD) > 0);
                    owners++;
                    upgradeLockOwnerId = id;
                    lrwc.rc.upgradecount++;
                    if (lrwc.readercount > 0)
                    {
                        fUpgradeThreadHoldingRead = true;
                    }
                    ExitMyLock();
                    return(true);
                }
                else if (lrwc.readercount > 0)
                {
                    //Upgrade locks may not be acquired if only read locks have been
                    //acquired.
                    ExitMyLock();
                    throw new LockRecursionException(SR.GetString(SR.LockRecursionException_UpgradeAfterReadNotAllowed));
                }
            }

            bool retVal = true;

            int spincount = 0;

            for (;;)
            {
                //Once an upgrade lock is taken, it's like having a reader lock held
                //until upgrade or downgrade operations are performed.

                if ((upgradeLockOwnerId == -1) && (owners < MAX_READER))
                {
                    owners++;
                    upgradeLockOwnerId = id;
                    break;
                }

                if (spincount < MaxSpinCount)
                {
                    ExitMyLock();
                    if (millisecondsTimeout == 0)
                    {
                        return(false);
                    }
                    spincount++;
                    SpinWait(spincount);
                    EnterMyLock();
                    continue;
                }

                // Drat, we need to wait.  Mark that we have waiters and wait.
                if (upgradeEvent == null)   // Create the needed event
                {
                    LazyCreateEvent(ref upgradeEvent, true);
                    continue;   // since we left the lock, start over.
                }

                //Only one thread with the upgrade lock held can proceed.
                retVal = WaitOnEvent(upgradeEvent, ref numUpgradeWaiters, millisecondsTimeout);
                if (!retVal)
                {
                    return(false);
                }
            }

            if (fIsReentrant)
            {
                //The lock may have been dropped getting here, so make a quick check to see whether some other
                //thread did not grab the entry.
                if (IsRwHashEntryChanged(lrwc, id))
                {
                    lrwc = GetThreadRWCount(id, false);
                }
                lrwc.rc.upgradecount++;
            }

            ExitMyLock();

            return(true);
        }
示例#2
0
        private bool TryEnterWriteLockCore(int millisecondsTimeout)
        {
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("millisecondsTimeout");
            }

            if (fDisposed)
            {
                throw new ObjectDisposedException(null);
            }

            int id = Thread.CurrentThread.ManagedThreadId;
            ReaderWriterCount lrwc;
            bool upgradingToWrite = false;

            if (!fIsReentrant)
            {
                if (id == writeLockOwnerId)
                {
                    //Check for AW->AW
                    throw new LockRecursionException(SR.GetString(SR.LockRecursionException_RecursiveWriteNotAllowed));
                }
                else if (id == upgradeLockOwnerId)
                {
                    //AU->AW case is allowed once.
                    upgradingToWrite = true;
                }

                EnterMyLock();
                lrwc = GetThreadRWCount(id, true);

                //Can't acquire write lock with reader lock held.
                if (lrwc != null && lrwc.readercount > 0)
                {
                    ExitMyLock();
                    throw new LockRecursionException(SR.GetString(SR.LockRecursionException_WriteAfterReadNotAllowed));
                }
            }
            else
            {
                EnterMyLock();
                lrwc = GetThreadRWCount(id, false);

                if (id == writeLockOwnerId)
                {
                    lrwc.rc.writercount++;
                    ExitMyLock();
                    return(true);
                }
                else if (id == upgradeLockOwnerId)
                {
                    upgradingToWrite = true;
                }
                else if (lrwc.readercount > 0)
                {
                    //Write locks may not be acquired if only read locks have been
                    //acquired.
                    ExitMyLock();
                    throw new LockRecursionException(SR.GetString(SR.LockRecursionException_WriteAfterReadNotAllowed));
                }
            }

            int  spincount = 0;
            bool retVal    = true;

            for (;;)
            {
                if (IsWriterAcquired())
                {
                    // Good case, there is no contention, we are basically done
                    SetWriterAcquired();
                    break;
                }

                //Check if there is just one upgrader, and no readers.
                //Assumption: Only one thread can have the upgrade lock, so the
                //following check will fail for all other threads that may sneak in
                //when the upgrading thread is waiting.

                if (upgradingToWrite)
                {
                    uint readercount = GetNumReaders();

                    if (readercount == 1)
                    {
                        //Good case again, there is just one upgrader, and no readers.
                        SetWriterAcquired();    // indicate we have a writer.
                        break;
                    }
                    else if (readercount == 2)
                    {
                        if (lrwc != null)
                        {
                            if (IsRwHashEntryChanged(lrwc, id))
                            {
                                lrwc = GetThreadRWCount(id, false);
                            }

                            if (lrwc.readercount > 0)
                            {
                                //This check is needed for EU->ER->EW case, as the owner count will be two.
                                Debug.Assert(fIsReentrant);
                                Debug.Assert(fUpgradeThreadHoldingRead);

                                //Good case again, there is just one upgrader, and no readers.
                                SetWriterAcquired();   // indicate we have a writer.
                                break;
                            }
                        }
                    }
                }

                if (spincount < MaxSpinCount)
                {
                    ExitMyLock();
                    if (millisecondsTimeout == 0)
                    {
                        return(false);
                    }
                    spincount++;
                    SpinWait(spincount);
                    EnterMyLock();
                    continue;
                }

                if (upgradingToWrite)
                {
                    if (waitUpgradeEvent == null)   // Create the needed event
                    {
                        LazyCreateEvent(ref waitUpgradeEvent, true);
                        continue;   // since we left the lock, start over.
                    }

                    Debug.Assert(numWriteUpgradeWaiters == 0, "There can be at most one thread with the upgrade lock held.");

                    retVal = WaitOnEvent(waitUpgradeEvent, ref numWriteUpgradeWaiters, millisecondsTimeout);

                    //The lock is not held in case of failure.
                    if (!retVal)
                    {
                        return(false);
                    }
                }
                else
                {
                    // Drat, we need to wait.  Mark that we have waiters and wait.
                    if (writeEvent == null)     // create the needed event.
                    {
                        LazyCreateEvent(ref writeEvent, true);
                        continue;   // since we left the lock, start over.
                    }

                    retVal = WaitOnEvent(writeEvent, ref numWriteWaiters, millisecondsTimeout);
                    //The lock is not held in case of failure.
                    if (!retVal)
                    {
                        return(false);
                    }
                }
            }

            Debug.Assert((owners & WRITER_HELD) > 0);

            if (fIsReentrant)
            {
                if (IsRwHashEntryChanged(lrwc, id))
                {
                    lrwc = GetThreadRWCount(id, false);
                }
                lrwc.rc.writercount++;
            }

            ExitMyLock();

            writeLockOwnerId = id;

            return(true);
        }
示例#3
0
文件: semaphore.cs 项目: nsivov/mono
        private static OpenExistingResult OpenExistingWorker(
            string name,
#if !FEATURE_PAL && !FEATURE_NETCORE
            SemaphoreRights rights,
#endif
            out Semaphore result)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if (name.Length == 0)
            {
                throw new ArgumentException(SR.GetString(SR.InvalidNullEmptyArgument, "name"), "name");
            }
            if (null != name && MAX_PATH < name.Length)
            {
                throw new ArgumentException(SR.GetString(SR.Argument_WaitHandleNameTooLong));
            }

            result = null;
#if MOBILE
            throw new NotSupportedException();
#else
#if MONO
            int errorCode;
            var myHandle = new SafeWaitHandle(OpenSemaphore_internal(name, rights, out errorCode), true);
#else
            //Pass false to OpenSemaphore to prevent inheritedHandles
#if FEATURE_PAL || FEATURE_NETCORE
            const int SYNCHRONIZE            = 0x00100000;
            const int SEMAPHORE_MODIFY_STATE = 0x00000002;

            SafeWaitHandle myHandle = SafeNativeMethods.OpenSemaphore(SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, false, name);
#else
            SafeWaitHandle myHandle = SafeNativeMethods.OpenSemaphore((int)rights, false, name);
#endif
#endif

            if (myHandle.IsInvalid)
            {
#if !MONO
                int errorCode = Marshal.GetLastWin32Error();
#endif

                if (NativeMethods.ERROR_FILE_NOT_FOUND == errorCode || NativeMethods.ERROR_INVALID_NAME == errorCode)
                {
                    return(OpenExistingResult.NameNotFound);
                }
                if (NativeMethods.ERROR_PATH_NOT_FOUND == errorCode)
                {
                    return(OpenExistingResult.PathNotFound);
                }
                if (null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode)
                {
                    return(OpenExistingResult.NameInvalid);
                }
                //this is for passed through NativeMethods Errors
#if MONO
                InternalResources.WinIOError(errorCode, "");
#else
                InternalResources.WinIOError();
#endif
            }
            result = new Semaphore(myHandle);
            return(OpenExistingResult.Success);
#endif
        }
示例#4
0
        private bool TryEnterReadLockCore(int millisecondsTimeout)
        {
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("millisecondsTimeout");
            }

            if (fDisposed)
            {
                throw new ObjectDisposedException(null);
            }

            ReaderWriterCount lrwc = null;
            int id = Thread.CurrentThread.ManagedThreadId;

            if (!fIsReentrant)
            {
                if (id == writeLockOwnerId)
                {
                    //Check for AW->AR
                    throw new LockRecursionException(SR.GetString(SR.LockRecursionException_ReadAfterWriteNotAllowed));
                }

                EnterMyLock();

                lrwc = GetThreadRWCount(id, false);

                //Check if the reader lock is already acquired. Note, we could
                //check the presence of a reader by not allocating rwc (But that
                //would lead to two lookups in the common case. It's better to keep
                //a count in the struucture).
                if (lrwc.readercount > 0)
                {
                    ExitMyLock();
                    throw new LockRecursionException(SR.GetString(SR.LockRecursionException_RecursiveReadNotAllowed));
                }
                else if (id == upgradeLockOwnerId)
                {
                    //The upgrade lock is already held.
                    //Update the global read counts and exit.

                    lrwc.readercount++;
                    owners++;
                    ExitMyLock();
                    return(true);
                }
            }
            else
            {
                EnterMyLock();
                lrwc = GetThreadRWCount(id, false);
                if (lrwc.readercount > 0)
                {
                    lrwc.readercount++;
                    ExitMyLock();
                    return(true);
                }
                else if (id == upgradeLockOwnerId)
                {
                    //The upgrade lock is already held.
                    //Update the global read counts and exit.
                    lrwc.readercount++;
                    owners++;
                    ExitMyLock();
                    fUpgradeThreadHoldingRead = true;
                    return(true);
                }
                else if (id == writeLockOwnerId)
                {
                    //The write lock is already held.
                    //Update global read counts here,
                    lrwc.readercount++;
                    owners++;
                    ExitMyLock();
                    return(true);
                }
            }

            bool retVal = true;

            int spincount = 0;

            for (;;)
            {
                // We can enter a read lock if there are only read-locks have been given out
                // and a writer is not trying to get in.

                if (owners < MAX_READER)
                {
                    // Good case, there is no contention, we are basically done
                    owners++;       // Indicate we have another reader
                    lrwc.readercount++;
                    break;
                }

                if (spincount < MaxSpinCount)
                {
                    ExitMyLock();
                    if (millisecondsTimeout == 0)
                    {
                        return(false);
                    }
                    spincount++;
                    SpinWait(spincount);
                    EnterMyLock();
                    //The per-thread structure may have been recycled as the lock is released, load again.
                    if (IsRwHashEntryChanged(lrwc, id))
                    {
                        lrwc = GetThreadRWCount(id, false);
                    }
                    continue;
                }

                // Drat, we need to wait.  Mark that we have waiters and wait.
                if (readEvent == null)      // Create the needed event
                {
                    LazyCreateEvent(ref readEvent, false);
                    if (IsRwHashEntryChanged(lrwc, id))
                    {
                        lrwc = GetThreadRWCount(id, false);
                    }
                    continue;   // since we left the lock, start over.
                }

                retVal = WaitOnEvent(readEvent, ref numReadWaiters, millisecondsTimeout);
                if (!retVal)
                {
                    return(false);
                }
                if (IsRwHashEntryChanged(lrwc, id))
                {
                    lrwc = GetThreadRWCount(id, false);
                }
            }

            ExitMyLock();
            return(retVal);
        }
示例#5
0
文件: semaphore.cs 项目: nsivov/mono
        public unsafe Semaphore(int initialCount, int maximumCount, string name, out bool createdNew, SemaphoreSecurity semaphoreSecurity)
#endif
        {
            if (initialCount < 0)
            {
                throw new ArgumentOutOfRangeException("initialCount", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
            }

            if (maximumCount < 1)
            {
                throw new ArgumentOutOfRangeException("maximumCount", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
            }

            if (initialCount > maximumCount)
            {
                throw new ArgumentException(SR.GetString(SR.Argument_SemaphoreInitialMaximum));
            }

            if (null != name && MAX_PATH < name.Length)
            {
                throw new ArgumentException(SR.GetString(SR.Argument_WaitHandleNameTooLong));
            }
            SafeWaitHandle myHandle;

#if MONO
            int errorCode;
            myHandle = new SafeWaitHandle(CreateSemaphore_internal(initialCount, maximumCount, name, out errorCode), true);
#else
#if !FEATURE_PAL && !FEATURE_NETCORE
            // For ACL's, get the security descriptor from the SemaphoreSecurity.
            if (semaphoreSecurity != null)
            {
                NativeMethods.SECURITY_ATTRIBUTES secAttrs = null;
                secAttrs         = new NativeMethods.SECURITY_ATTRIBUTES();
                secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
                byte[] sd = semaphoreSecurity.GetSecurityDescriptorBinaryForm();
                fixed(byte *pSecDescriptor = sd)
                {
                    secAttrs.lpSecurityDescriptor = new SafeLocalMemHandle((IntPtr)pSecDescriptor, false);
                    myHandle = SafeNativeMethods.CreateSemaphore(secAttrs, initialCount, maximumCount, name);
                }
            }
            else
            {
#endif
            myHandle = SafeNativeMethods.CreateSemaphore(null, initialCount, maximumCount, name);
#if !FEATURE_PAL && !FEATURE_NETCORE
        }
#endif

            int errorCode = Marshal.GetLastWin32Error();
#endif
            if (myHandle.IsInvalid)
            {
                if (null != name && 0 != name.Length && NativeMethods.ERROR_INVALID_HANDLE == errorCode)
                {
                    throw new WaitHandleCannotBeOpenedException(SR.GetString(SR.WaitHandleCannotBeOpenedException_InvalidHandle, name));
                }

#if MONO
                InternalResources.WinIOError(errorCode, "");
#else
                InternalResources.WinIOError();
#endif
            }
            createdNew          = errorCode != NativeMethods.ERROR_ALREADY_EXISTS;
            this.SafeWaitHandle = myHandle;
        }