Пример #1
0
 internal StWaitBlock (StParker pk, WaitType t, int r, int k)
 {
     parker = pk;
     waitType = t;
     request = r;
     waitKey = k;
 }
            private void Run()
            {
                VConsole.WriteLine("+++ r #{0} started...", id);
                Random r = new Random((id + 1) * Environment.TickCount);

                do
                {
                    try {
                        int idx = r.Next() % SEMAPHORES;
                        if (idx < sems.Length)
                        {
                            sems[idx].Release(1);
                        }
                        else
                        {
                            handles[idx - sems.Length].Release(1);
                        }
                        releases[id]++;
                    } catch (StSemaphoreFullException) {
                        StParker.Sleep(new StCancelArgs(10));
                    }
                    Thread.Sleep(0);
                } while (!shutdown.IsSet);
                VConsole.WriteLine("+++ releaser #{0} exiting, [{1}]", id, releases[id]);
                done.Signal();
            }
Пример #3
0
 internal StWaitBlock (WaitType t, int r, int k)
 {
     parker = new StParker ();
     waitType = t;
     request = r;
     waitKey = k;
 }
Пример #4
0
        //
        // Constructors.
        //

        public StTimer(bool notificationTimer) {
            if (notificationTimer) {
                tmrEvent = new StNotificationEvent();
            } else {
                tmrEvent = new StSynchronizationEvent();
            }
 
            state = INACTIVE;
            cbparker = new CbParker(TimerCallback);
            timer = new RawTimer(cbparker);        
        }
Пример #5
0
        //
        // Registers the specified parker with the alerter.
        //

        internal bool RegisterParker(StParker pk) {
            do {
                StParker s;

                //
                // If the alerter is already set, return false.
                //

                if ((s = state) == ALERTED) {
                    return false;
                }

                //
                // Try to insert the parker in the alert list.
                //

                pk.pnext = s;
                if (Interlocked.CompareExchange<StParker>(ref state, pk, s) == s) {
                    return true;
                }
            } while (true);
        }
Пример #6
0
		internal override StWaitBlock _WaitAnyPrologue (StParker pk, int key,
		                                                ref StWaitBlock hint, ref int sc)
		{
			StWaitBlock wb = null;
			do {
				if (_TryAcquire ()) {
					return null;
				}

				if (wb == null) {
					wb = new StWaitBlock (pk, WaitType.WaitAny, 1, key);
				}

				if (EnqueueWaiter (wb, out hint)) {
					sc = hint == head ? spinCount : 0;
					return wb;
				}
				
				if (head.next == INFLATED) {
					return null;
				}
			} while (true);
		}
		internal override WaitBlock _WaitAllPrologue(StParker pk, ref WaitBlock ignored,
													 ref int sc) {
			if (_AllowsAcquire) {
				return null;
			}

			var wb = new WaitBlock(pk, WaitType.WaitAll, 1, StParkStatus.StateChange);
			sc = EnqueueAcquire(wb, 1);
			return wb;
		}
		internal override WaitBlock _WaitAnyPrologue(StParker pk, int key,
													 ref WaitBlock ignored, ref int sc) {
			if (TryAcquireInternal(1)) {
				return null;
			}

			var  wb = new WaitBlock(pk, WaitType.WaitAny, 1, key);
			sc = EnqueueAcquire(wb, 1);
			return wb;
		}
        //
        // The construtor.
        //

        internal RawTimer(StParker pk) {
            parker = pk;
        }
Пример #10
0
        static TimerList() {

            //
            // Create the objects.
            //

            _lock = new SpinLock(TIMER_LIST_LOCK_SPINS);
            timerListHead = new RawTimer(null);
            limitTimer = new RawTimer(null);
            parker = new StParker(1);

            //
            // Initialize the limit timer as unlinked.
            //
            
            limitTimer.next = limitTimer;

            //
            // Initialize the timer list as empty.
            //

            timerListHead.next = timerListHead.prev = timerListHead;

            //
            // Set the start base time e set the *delay* sentinel.
            //

        	baseTime = Environment.TickCount;
            timerListHead.delay = Int32.MaxValue;

	        //
	        // Create and start the timer thread.
	        //

            new Thread(TimerThread).Start();
	    }
Пример #11
0
 public static int Sleep(StCancelArgs cargs) {
     int ws = new StParker().Park(0, cargs);
     StCancelArgs.ThrowIfException(ws);
     return ws;
 }
 internal override WaitBlock _WaitAnyPrologue(StParker pk, int key,
                                              ref WaitBlock hint, ref int sc) {
     return _TryAcquire() ? null : flock._WaitAnyPrologue(pk, key, ref hint, ref sc);
 }
        //
        // Executes the unpark callback.
        //

        private void UnparkCallback(int ws) {

            Debug.Assert(ws == StParkStatus.Success || ws == StParkStatus.Timeout ||
                         ws == StParkStatus.WaitCancelled);

            //
	        // If the registered wait was cancelled, cancel the acquire
            // attempt and return immediately.
	        //
        
            if (ws == StParkStatus.WaitCancelled) {
                waitable._CancelAcquire(waitBlock, hint);
		        return;
	        }

	        //
	        // Set state to *our busy* grabing the current state, and execute
	        // the unpark callback processing.
	        //

            StParker myBusy = new SentinelParker();
            StParker oldState = Interlocked.Exchange<StParker>(ref state, myBusy);

	        do {

		        //
		        // If the acquire operation was cancelled, cancel the acquire
		        // attempt on the waitable.
		        //

		        if (ws != StParkStatus.Success) {
                    waitable._CancelAcquire(waitBlock, hint);
		        }

		        //
		        // Execute the user callback routine.
		        //

                cbtid = Thread.CurrentThread.ManagedThreadId;
		        callback(cbState, ws == StParkStatus.Timeout);
                cbtid = 0;

		        //
		        // If the registered wait was configured to execute once or
                // there is an unregister in progress, set the state to INACTIVE.
                // If a thread is waiting to unregister, unpark it.
		        //

		        if (executeOnce || !(oldState is SentinelParker)) {
                    if (!(oldState is SentinelParker)) {
				        oldState.Unpark(StParkStatus.Success);
			        } else {
				        state = INACTIVE;
			        }
			        return;
		        }

		        //
		        // We must re-register with the Waitable.
		        // So, initialize the parker and execute the WaitAny prologue.
		        //

                cbparker.Reset(1);
                int ignored = 0;
                waitBlock = waitable._WaitAnyPrologue(cbparker, StParkStatus.Success, ref hint,
                                                      ref ignored);

		        //
		        // Enable the unpark callback.
		        //

                ws = cbparker.EnableCallback(timeout, toTimer);
                if (ws == StParkStatus.Pending) {

			        //
			        // If the *state* field constains still *my busy* set it to ACTIVE.
			        //

                    if (state == myBusy) {
                        Interlocked.CompareExchange<StParker>(ref state, ACTIVE, myBusy);
                    }
			        return;
		        }

		        //
		        // The waitable was already signalled. So, execute the unpark
		        // callback inline.
		        //

	        } while (true);
        }
Пример #14
0
 internal WaitBlock(WaitType t, int r) {
     parker = new StParker();
     waitType = t;
     request = r;
 }
Пример #15
0
        //
        // Executes the prologue of the Waitable.WaitAll method.
        //

        internal override WaitBlock _WaitAllPrologue(StParker pk, ref WaitBlock hint,
                                                     ref int sc) {
            return tmrEvent._WaitAllPrologue(pk, ref hint, ref sc);
        }
Пример #16
0
        //
        // Cancels the timer.
        //

        public bool Cancel() {

	        //
	        // If the timer is being cancelled from the user callback function,
	        // set the period to zero and return success. The timer will be
	        // cancelled on return from the callback function.
	        //

	        if (cbtid == Thread.CurrentThread.ManagedThreadId) {
		        period = 0;
		        return true;
	        }

	        //
	        // If the timer is active we must try to cancel the timer
	        // and return only after the timer is actually cancelled.
        	// if the timer is already inactive or a cancel or a set is taking
	        // place, this function returns FALSE. 
	        //

            StSpinWait spinner = new StSpinWait();
            StParker pk = new StParker(0);
            StParker oldState;
            do {
		        if ((oldState = state) == INACTIVE) {
			        return false;
		        }
                if (oldState == ACTIVE) {
			        if (Interlocked.CompareExchange<StParker>(ref state, pk, ACTIVE) == ACTIVE) {
				        break;
			        }
		        } if (!(oldState is SentinelParker)) {
			        return false;
		        }
		        spinner.SpinOnce();
	        } while (true);

	        //
	        // Try to cancel the timer's callback parker. If we can't
            // park the current thread until the timer callback finishes
            // execution.
	        //

	        if (cbparker.TryCancel()) {
		        cbparker.Unpark(StParkStatus.TimerCancelled);
	        } else {
                pk.Park(100, StCancelArgs.None);
            }

	        //
	        // Set the timer state to inactive and return success.
	        //

	        state = INACTIVE;
	        return true;
        }
Пример #17
0
        //
        // Sets the timer.
        //

        public bool Set(int dueTime, int period, WaitOrTimerCallback callback, object cbState) {

	        //
	        // If the timer is being set from the user callback function,
	        // we just save the new settings and return success.
	        //

	        if (cbtid == Thread.CurrentThread.ManagedThreadId) {
		        this.dueTime = dueTime;
		        this.period = period;
		        useDueTime = true;
		        this.callback = callback;
		        this.cbState = cbState;
		        return true;
	        }

	        //
	        // The timer is being set externally. So, we must first cancel the
	        // timer. If the timer is already being set or cancelled, we return
	        // failure.
	        //

            StSpinWait spinner = new StSpinWait();
            StParker pk = new StParker(0);
            StParker oldState;
	        do {
		        if ((oldState = state) == INACTIVE) {
			        if (Interlocked.CompareExchange<StParker>(ref state, SETTING,
                                                              INACTIVE) == INACTIVE) {
				        goto SetTimer;
			        }
		        } else if (oldState == ACTIVE) {
			        if (Interlocked.CompareExchange<StParker>(ref state, pk, ACTIVE) == ACTIVE) {
				        break;
			        }
		        } else if (!(oldState is SentinelParker)) {
			        return false;
		        }
		        spinner.SpinOnce();
	        } while (true);

	        //
	        // Try to cancel the timer's callback parker. If succeed,
            // call the unpark method; otherwise, the timer callback is
            // taking place, so we must synchronize with its end.
	        //

	        if (cbparker.TryCancel()) {
		        cbparker.Unpark(StParkStatus.TimerCancelled);
	        } else {
		        pk.Park(100, StCancelArgs.None);
	        }

	        //
	        // Here, we know that the timer is cancelled and no one else
	        // is trying to set or cancel the timer.
	        // So, set the timer state to *our busy state* and start it with
	        // the new settings.
	        //

            state = SETTING;

        SetTimer:

	        this.dueTime = dueTime;
	        this.period = period;
	        useDueTime = false;
	        this.callback = callback;
	        this.cbState = cbState;
            StNotificationEvent nev = tmrEvent as StNotificationEvent;
            if (nev != null) {
                nev.Reset();
            } else {
                ((StSynchronizationEvent)tmrEvent).Reset();
            }

	        //
	        // Initialize the timer's parker, set the timer state to ACTIVE
            // and enable the unpark callback.
	        //

            cbparker.Reset();
            state = ACTIVE;
            int ws = cbparker.EnableCallback(dueTime, timer);
            if (ws != StParkStatus.Pending) {
		
		        //
		        // If the timer already fired or cancelled, call the unpark
		        // callback inline.
		        //

		        TimerCallback(ws);
	        }
	        return true;
        }
Пример #18
0
		internal override StWaitBlock _WaitAllPrologue (StParker pk, ref StWaitBlock hint,
		                                                ref int sc)
		{
         if (_AllowsAcquire) {
            return null;
         }
                
			var wb = new StWaitBlock (pk, WaitType.WaitAll, 1, StParkStatus.StateChange);
         
         if (EnqueueWaiter (wb, out hint)) {
            sc = hint == head ? spinCount : 0;
            return wb;
         }

         return null;
		}
Пример #19
0
 public void Reset(int releasers) {
     pnext = null;
     state = releasers | WAIT_IN_PROGRESS;
 }
        //
        // Constructor: registers a wait with a Waitable synchronizer.
        //

        internal StRegisteredWait(StWaitable waitObject,  WaitOrTimerCallback callback,
                                  object cbState, int timeout, bool executeOnce) {

        	//
	        // Validate the arguments.
	        //

            if (timeout == 0) {
                throw new ArgumentOutOfRangeException("\"timeout\" can't be zero");
            }
            if (callback == null) {
                throw new ArgumentOutOfRangeException("\"callback\" can't be null");
            }
            if ((waitObject is StReentrantFairLock) || (waitObject is StReentrantReadWriteLock)) {
                throw new InvalidOperationException("can't register waits on reentrant locks");
            }
            if ((waitObject is StNotificationEvent) && !executeOnce) {
                throw new InvalidOperationException("Notification event can't register waits"
                            + " to execute more than once");
            }

	        //
	        // Initialize the register wait fields
	        //

            waitable = waitObject;
            cbparker = new CbParker(UnparkCallback);
            toTimer = new RawTimer(cbparker);
	        this.timeout = timeout;
            this.executeOnce = executeOnce;
	        this.callback = callback;
	        this.cbState = (cbState != null) ? cbState : this;
        
            //
	        // Execute the WaitAny prologue on the waitable.
	        //
            int ignored = 0;
            waitBlock  = waitObject._WaitAnyPrologue(cbparker, StParkStatus.Success, ref hint,
                                                     ref ignored);

            //
	        // Set the registered wait state to active and enable the
            // unpark callback.
	        //

	        state = ACTIVE;
            int ws = cbparker.EnableCallback(timeout, toTimer);
            if (ws != StParkStatus.Pending) {
		
                //
		        // The acquire operation was already accomplished. To prevent
                // uncontrolled reentrancy, the unpark callback is executed inline.
		        //

		        UnparkCallback(ws);
	        }
        }
Пример #21
0
 internal WaitBlock(int r) {
     parker = new StParker();
     request = r;
 }
        //
        // Unregisters the registered wait.
        //

        public bool Unregister() {

	        //
	        // If the unregister is being called from the callback method,
	        // we just set the *onlyOnce* to TRUE and return.
	        //

	        if (cbtid == Thread.CurrentThread.ManagedThreadId) {
		        executeOnce = true;
		        return true;
	        }

	        //
	        // If the wait is registered, we try to unregister it, and return
	        // only after the wait is actually unregistered.
	        // If the wait was already unregistered or an unregister is taking
            // place, this method returns false.
	        //

            StSpinWait spinner = new StSpinWait();
            StParker pk = new StParker(0);
            StParker oldState;
            do {
		        if ((oldState = state) == INACTIVE) {
			        return false;
		        }
                if (oldState == ACTIVE) {
			        if (Interlocked.CompareExchange<StParker>(ref state, pk, ACTIVE) == ACTIVE) {
				        break;
			        }
                } else if (!(oldState is SentinelParker)) {
                    return false;
                }
		        spinner.SpinOnce();
	        } while (true);

	        //
	        // Try to cancel the wait's callback parker. If we succeed, call
	        // the unpark with status disposed. Otherwise, a callback is taking
	        // place and we must synchronize with its end.
	        //

	        if (cbparker.TryCancel()) {
                cbparker.Unpark(StParkStatus.WaitCancelled);
	        } else {
                pk.Park(BUSY_SPINS, StCancelArgs.None);
	        }

	        //
	        // Set the registered wait object to inactive and return success.
	        //

	        state = INACTIVE;
	        return true;
        }
Пример #23
0
        public void Wait(StParker pk, StCancelArgs cargs) {
            bool interrupted = false;
            int lastTime = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0;
            int ws;
            do {
                try {
                    ws = waitBehavior.Park(psevent, cargs.Timeout);
                    break;
                } catch (ThreadInterruptedException) {
                    if (cargs.Interruptible) {
                        ws = StParkStatus.Interrupted;
                        break;
                    }
                    interrupted = true;
                    cargs.AdjustTimeout(ref lastTime);
                }
            } while (true);

            //
            // If the wait was cancelled due to an internal canceller, try
            // to cancel the park operation. If we fail, wait unconditionally
            // until the park spot is signalled.
            //

            if (ws != StParkStatus.Success) {
                if (pk.TryCancel()) {
                    pk.UnparkSelf(waitBehavior.ParkerCancelled(ws));
                } else {
                    if (ws == StParkStatus.Interrupted) {
                        interrupted = true;
                    }

                    waitBehavior.ParkerNotCancelled(ws);

                    do {
                        try {
                            psevent.WaitOne();
                            break;
                        } catch (ThreadInterruptedException) {
                            interrupted = true;
                        }
                    } while (true);
                }
            }

            //
            // If we were interrupted but can't return the *interrupted*
            // wait status, reassert the interrupt on the current thread.
            //

            if (interrupted) {
                Thread.CurrentThread.Interrupt();
            }

            factory.Free(this);
        }
        //
        // Executes the prologue of the Waitable.WaitAny method.
        //

        internal override WaitBlock _WaitAnyPrologue(StParker pk, int key,
                                                     ref WaitBlock hint, ref int sc) {
            return FastTryEnterWrite(Thread.CurrentThread.ManagedThreadId) 
                 ? null 
                 : rwlock._WaitAnyPrologue(pk, key, ref hint, ref sc);
        }
Пример #25
0
        //
        // Slow path to acquire the spin lock.
        //

        private void SlowEnter() {
            StParker pk = null;
            do {

                //
                // First, try to acquire the spin lock, spinning for the
                // specified number of cycles, if the wait queue is empty.
                //

                int sc = spinCount;
                do {
                    if (state == FREE &&
                        Interlocked.CompareExchange(ref state, BUSY, FREE) == FREE) {
                        return;
                    }
                    if (top != null || sc-- <= 0) {
                        break;
                    }
                    Platform.SpinWait(1);
                } while (true);

                //
                // The spin lock is busy. So, create, or reset, a parker and
                // insert it in the wait queue.
                //

                if (pk == null) {
                    pk = new StParker(0);
                } else {
                    pk.Reset(0);
                }
                do {
                    StParker t;
                    pk.pnext = (t = top);
                    if (Interlocked.CompareExchange<StParker>(ref top, pk, t) == t) {
                        break;
                    }
                } while (true);

                //
                // Since that the lock can become free after the parker is
                // inserted in the wait queue, we must retry to acquire the spinlock
                // if it seems free.
                //
                // NOTE: We don't remove the parker from the wait queue, because
                //       it will be surely removed next time the lock is release.
                //

                if (state == FREE &&
                    Interlocked.CompareExchange(ref state, BUSY, FREE) == FREE) {
                    return;
                }

                //
                // Park the current thread and, after release, retry the
                // spin lock acquire.
                //

                pk.Park();
            } while (true);
        }
 internal override WaitBlock _WaitAllPrologue(StParker pk, ref WaitBlock hint,
                                              ref int sc) {
     return _AllowsAcquire ? null : flock._WaitAllPrologue(pk, ref hint, ref sc);
 }
Пример #27
0
        //
        // CASes on the *pnext* field.
        //

        internal bool CasNext(StParker n, StParker nn) {
            return (pnext == n &&
                    Interlocked.CompareExchange(ref pnext, nn, n) == n);
        }
Пример #28
0
 internal WaitBlock(WaitType t) {
     parker = new StParker();
     waitType = t;
 }
Пример #29
0
        //
        // Executes the timer callback
        //

        internal void TimerCallback(int ws) {

            Debug.Assert(ws == StParkStatus.Timeout || ws == StParkStatus.TimerCancelled);
	
            //
	        // If the timer was cancelled, return immediately.
	        //

	        if (ws == StParkStatus.TimerCancelled) {
		        return;
	        }

	        //
	        // Set timer state to *our busy* state, grabing the current state and
	        // execute the timer callback processing.
	        //

            SentinelParker myBusy = new SentinelParker();
            StParker oldState = Interlocked.Exchange<StParker>(ref state, myBusy);

	        do {

		        //
		        // Signals the timer's event.
		        //

		        tmrEvent.Signal();
		
		        //
		        // Call the user-defined callback, if specified.
		        //

		        if (callback != null) {
			        cbtid = Thread.CurrentThread.ManagedThreadId;
			        callback(cbState, true);
			        cbtid = 0;
		        }

		        //
		        // If the  timer isn't periodic or if someone is trying to
                // cancel it, process cancellation.
		        //

		        if (period == 0 || !(oldState is SentinelParker)) {
			        if (!(oldState is SentinelParker)) {
				        oldState.Unpark(StParkStatus.Success);
                    } else {
				        state = INACTIVE;
			        }
			        return;
		        }

		        //
		        // Initialize the timer's parker.
		        //

                cbparker.Reset();
		        
                //
		        // Compute the timer delay and enable the unpark callback.
		        //

                int timeout;
		        if (useDueTime) {
			        timeout = dueTime;
			        useDueTime = false;
		        } else {
			        timeout = period | (1 << 31);
		        }
		        if ((ws = cbparker.EnableCallback(timeout, timer)) == StParkStatus.Pending) {
			        if (state == myBusy) {
				        Interlocked.CompareExchange<StParker>(ref state, ACTIVE, myBusy);
			        }
			        return;
		        }

		        //
		        // The timer already expired. So, execute the timer
                // callback inline.
		        //
	        } while (true);
        }
Пример #30
0
 internal WaitBlock(StParker pk, int r) {
     parker = pk;
     request = r;
 }
Пример #31
0
        //
        // Constructors.
        //

        public SpinLock(int sc) {
            state = FREE;
            top = null;
            spinCount = Platform.IsMultiProcessor ? sc : 0;
        }