Beispiel #1
0
        ///
        /// <summary>
        /// Wait on a set of handles until one of them becomes signaled with a specified time out.
        ///
        /// !!! If you change this method, please review WaitHandle.WaitAny()
        /// and see if the changes need to be propagated there.
        /// </summary>
        ///
        public void InterruptAwareWaitOne()
        {
            // Retrieve current thread information
            Thread currentThread = Thread.CurrentThread;
            Thread target        = null;
            int    unblockedBy;

            ThreadEntry[] entries = currentThread.GetWaitEntries(1);

            // Before we attempting to enqueue ourselves into the wait queues make sure
            // we disable abort
            currentThread.DelayStop(true);

            // Perepare for a wait - enqueue ourselves into every wait handle
            unblockedBy = InterruptAwarePreWaitAnyInternal(currentThread, singleHandle, entries, 1);

            // If we are in the process of blocking: Block
            if (UninitWait == unblockedBy)
            {
                // Allow thread to be aborted at this point
                currentThread.DelayStop(false);

                // Write out log record
                Monitoring.Log(Monitoring.Provider.Thread,
                               (ushort)ThreadEvent.WaitAny, 0, 0, 0,
                               (uint)currentThread.threadIndex, 0, 0);


                // Let scheduler know that we are blocking
                Kernel.TheScheduler.OnThreadBlocked(currentThread, SchedulerTime.MaxValue);

                // Our thread is about to run so we can disassociate it from wait handles
                InterruptAwarePostWaitAnyInternal(currentThread, singleHandle, entries, 1);

                // Thread has the unblocked information
                unblockedBy = currentThread.UnblockedBy;
            }

            // Assert post condition: since there is no timeout, and we are waiting
            // on a single handle, the unblockedBy must be 0
            VTable.Assert(unblockedBy == 0);

            // Complete wait
            CompleteWait(currentThread);

            // When we were signalged delay abort has been set - now we can turn it off
            // For mutex complete wait will add delay abort. It will remain on until
            // mutex is released
            currentThread.DelayStop(false);

            // Make sure that we pay attention to abort
            currentThread.ProcessAbortIfRequired();
        }
Beispiel #2
0
        protected override void CompleteWait(Thread ownerThread)
        {
            // Assert preconditions
            VTable.Assert(Thread.CurrentThread == ownerThread);

            // Update recursion counter
            this.acquired++;

            //If this is first time we acquired mutex don't forget to update owner
            if (this.acquired == 1)
            {
                if (this.isKernelObject)
                {
                    // Kernel thread can't be stop if it owns mutex
                    ownerThread.DelayStop(true);
                }
                this.owner = ownerThread;
            }
        }
Beispiel #3
0
        ///
        /// <summary>
        ///     Constructor
        ///</summary>
        ///
        /// <param name="initiallyOwned">Initial state of a mutex</param>
        /// <param name="isKernelObject">
        ///     True if this mutex is created by kernel and therefore used by kernel threads.
        ///     False if this mutex is created by a SIP and therefore used only by the SIP.
        ///
        ///     A kernel thread is not allowed to be forcibly stopped while owning a mutex,
        ///     whereas SIP threads can be forcibly stopped while owning a mutex. This doesn't
        ///     create problems for SIPs because the only time a SIP thread is forced to stop is
        ///     during process torn down.
        /// </param>
        ///
        /// <remark> We assume that mutex can initially be owned by current thread only </remark>
        ///
        public Mutex(bool initiallyOwned, bool isKernelObject)
            : base(initiallyOwned ? WaitHandle.SignalState.Unsignaled :
                   WaitHandle.SignalState.Signaled,
                   WaitHandle.SignalState.Unsignaled,
                   SpinLock.Types.Mutex)

        {
            this.isKernelObject = isKernelObject;
            if (initiallyOwned)
            {
                Thread currentThread = Thread.CurrentThread;
                this.owner = Thread.CurrentThread;

                if (this.isKernelObject)
                {
                    // Kernel thread can't be stop if it owns mutex
                    currentThread.DelayStop(true);
                }

                this.acquired = 1;
            }
        }
        ///
        /// <summary>
        /// Wait on a set of handles until one of them becomes signaled with a specified time out.
        /// </summary>
        ///
        /// <param name="waitHandles">Wait handles to wait on </param>
        /// <param name="waitHandlesCount">A number of wait handles to wait on </param>
        /// <param name="stop">Time out </param>
        ///
        public static int WaitAny(
            WaitHandle[]        waitHandles,
            int waitHandlesCount,
            SchedulerTime stop)
        {
            // Retrieve current thread information
            Thread currentThread = Thread.CurrentThread;
            Thread target        = null;
            int    unblockedBy;

            ThreadEntry[] entries = currentThread.GetWaitEntries(
                waitHandlesCount);

            // Before we attempting to enqueue ourselves into the wait queues make sure
            // we disable abort
            currentThread.DelayStop(true);

            // Perepare for a wait - enqueue ourselves into every wait handle
            unblockedBy = PreWaitAnyInternal(currentThread,
                                             waitHandles,
                                             entries,
                                             waitHandlesCount);

            // If we are in the process of blocking: Block
            if (UninitWait == unblockedBy)
            {
                // Allow thread to be aborted at this point
                currentThread.DelayStop(false);

                // Update thread WaitFor information: Indicate every one that we waiting -
                // scheduler ones wakes us up is responsible for cleaning up wait information
                // by using ResetWaitInfo call
                //currentThread.UpdateWaitInfo (waitHandles,
                //                        waitHandlesCount,
                //                        entries,
                //                        stop);

                // Write out log record
                Monitoring.Log(Monitoring.Provider.Thread,
                               (ushort)ThreadEvent.WaitAny, 0,
                               (uint)stop.Ticks, (uint)(stop.Ticks >> 32),
                               (uint)currentThread.threadIndex, 0, 0);


                // Let scheduler know that we are blocking
                Kernel.TheScheduler.OnThreadBlocked(currentThread, stop);

                // Our thread is about to run so we can disassociate it from wait handles
                PostWaitAnyInternal(currentThread,
                                    waitHandles,
                                    entries,
                                    waitHandlesCount);

                // Thread has the unblocked information
                unblockedBy = currentThread.UnblockedBy;
            }

            // Assert post condition: unblocked by can't be uninitialized
            VTable.Assert(unblockedBy != WaitHandle.UninitWait);

            // If there are wait handles and we were unblocked by not the timeout
            if (waitHandles != null && unblockedBy >= 0 &&
                unblockedBy < waitHandlesCount)
            {
                // Complete wait
                waitHandles[unblockedBy].CompleteWait(currentThread);

                // When we were signalged delay abort has been set - now we can turn it off
                // For mutex complete wait will add delay abort. It will remain on until
                // mutex is released
                currentThread.DelayStop(false);
            }

            // Make sure that we pay attention to abort
            currentThread.ProcessAbortIfRequired();

            return(unblockedBy);
        }