Пример #1
0
static int
scanHostlist (
    HostEntry	*h,
    ARRAY8Ptr	clientAddress,
    CARD16	connectionType,
    ChooserFunc	function,
    char	*closure,
    int		depth,
    int		broadcast)
{
    int	haveLocalhost = 0;

    for (; h; h = h->next)
    {
	switch (h->type) {
	case HOST_ALIAS:
	    if (indirectAlias (h->entry.aliasName, clientAddress,
			       connectionType, function, closure, depth,
			       broadcast))
		haveLocalhost = 1;
	    break;
	case HOST_ADDRESS:
	    if (XdmcpARRAY8Equal (getLocalAddress(), &h->entry.hostAddress))
		haveLocalhost = 1;
	    else if (function)
		(*function) (connectionType, &h->entry.hostAddress, closure);
	    break;
	case HOST_BROADCAST:
	    if (broadcast)
	    {
		ARRAY8	temp;

		if (function)
		{
		    temp.data = (BYTE *) BROADCAST_STRING;
		    temp.length = strlen ((char *)temp.data);
		    (*function) (connectionType, &temp, closure);
		}
	    }
	    break;
	}
    }
    return haveLocalhost;
}
Пример #2
0
    void __cdecl _UnrealizedChore::_UnstructuredChoreWrapper(_UnrealizedChore * pChore)
    {
        InternalContextBase *pContext = static_cast<InternalContextBase *> (SchedulerBase::FastCurrentContext());
        // The context could be canceled if it was already prepared for steal (this happens during a block unblock race) 
        ASSERT(pContext != NULL && (!pContext->HasInlineCancellation() || pContext->GetRootCollection() != NULL));

        _TaskCollection* pTaskCollection = static_cast<_TaskCollection *> (pChore->_M_pTaskCollection);

        //
        // pOriginContext is only safe to touch if the act of stealing from a non-detached context put a hold on that context
        // to block deletion until we are chained for cancellation.
        //
        ContextBase *pOriginContext = reinterpret_cast <ContextBase *> (pTaskCollection->_M_pOwningContext);
        SafeRWList<ListEntry> *pList = reinterpret_cast<SafeRWList<ListEntry> *> (pTaskCollection->_M_stealTracker);

        pChore->_PrepareStealUnstructured(pContext);

        _CancellationTokenState *pTokenState = pTaskCollection->_GetTokenState();
        _CancellationTokenRegistration *pRegistration = NULL;
        if (_CancellationTokenState::_IsValid(pTokenState))
        {
            pRegistration = pTokenState->_RegisterCallback(reinterpret_cast<TaskProc>(&_UnrealizedChore::_CancelViaToken), (ContextBase *)pContext);
        }

        //
        // Waiting on the indirect alias may throw (e.g.: the entire context may have been canceled). If it
        // throws, we need to deal with appropriate marshaling.
        //
        try
        {
            //
            // Set up an indirect alias for this task collection. Any usage of the original task collection
            // within this stolen chore will automatically redirect through the indirect alias. This allows
            // preservation of single-threaded semantics within the task collection while allowing it to be "accessed"
            // from stolen chores (multiple threads).
            //
            // This stack based collection will wait on stolen chores at destruction time. In the event the collection is not
            // used during the steal, this doesn't do much.
            //
            _TaskCollection indirectAlias(pTaskCollection, false);

            pContext->SetIndirectAlias(&indirectAlias);

            try
            {
                //
                // We need to consider this a possible interruption point. It's entirely possible that we stole and raced with a
                // cancellation thread. The collection was canceled after we stole(e.g.: removed from the WSQ) but before we added ourselves 
                // to the stealing chain list above. In this case, the entire context will wait until completion (bad). Immediately
                // after we go on the list (a memory barrier), we need to check the collection cancellation flag. If the collection is going away,
                // we need to get out *NOW* otherwise the entire subtree executes.
                //
                if (pTaskCollection->_M_pOriginalCollection->_M_exitCode != 0 ||
                    (_CancellationTokenState::_IsValid(pTokenState) && pTokenState->_IsCanceled()) ||
                    (pTaskCollection->_M_executionStatus != TASKCOLLECTION_EXECUTION_STATUS_CLEAR &&
                    pTaskCollection->_M_executionStatus != TASKCOLLECTION_EXECUTION_STATUS_INLINE &&
                    pTaskCollection->_M_executionStatus != TASKCOLLECTION_EXECUTION_STATUS_INLINE_WAIT_WITH_OVERFLOW_STACK)) 
                    throw _Interruption_exception();

                pChore->m_pFunction(pChore);
            }
            catch(const _Interruption_exception &)
            {
                //
                // If someone manually threw _Interruption_exception, we will have a cancel count but not a canceled context. This
                // means we need to apply the cancel one level up. Normally, the act of throwing would do that via being caught in the 
                // wait, but this is special "marshaling" for _Interruption_exception.
                //
                if (pContext->HasInlineCancellation() && !pContext->IsEntireContextCanceled())
                    pTaskCollection->_Cancel();
            }
            catch(...)
            {
                //
                // Track the exception that was thrown here and subsequently cancel all work. _RaisedException makes the decision on what
                // exceptions to keep and what to discard. The flags it sets will indicate to the thread calling ::Wait that it must rethrow.
                //
                pTaskCollection->_RaisedException();
                pTaskCollection->_Cancel();
            }

            indirectAlias._Wait();
        }
        catch(const _Interruption_exception &)
        {
            //
            // If someone manually threw _Interruption_exception out of a task on the indirect alias, the same thing applies as to
            // a directly stolen chore (above).
            //
            if (pContext->HasInlineCancellation() && !pContext->IsEntireContextCanceled())
                pTaskCollection->_Cancel();
        }
        catch(...)
        {
            //
            // Track the exception that was thrown here and subsequently cancel all work. _RaisedException makes the decision on what
            // exceptions to keep and what to discard. The flags it sets will indicate to the thread calling ::Wait that it must rethrow.
            //
            pTaskCollection->_RaisedException();
            pTaskCollection->_Cancel();
        }

        pContext->SetIndirectAlias(NULL);
        ASSERT(pContext->GetGoverningTokenState() == NULL);

        if ( !pChore->_M_fDetached)
        {
            //
            // pOriginContext may die at any point (detachment). When it does, it will transfer the stolen chore trace from the context to the
            // given task collection (us) under lock. We can, therefore, take this lock and check if we are still okay to check the context.
            //
            pList->AcquireWrite();

            if (pContext->IsContextChainedStealer())
                pOriginContext->RemoveStealer(pContext);
            else
                pList->UnlockedRemove(&(pContext->m_stealChain));

            pTaskCollection->_M_activeStealersForCancellation--;
            
            pList->ReleaseWrite();

        } 
        else
        {
            pList->Remove(&(pContext->m_stealChain));
        }

        if (pRegistration != NULL)
        {
            pTokenState->_DeregisterCallback(pRegistration);
            pRegistration->_Release();
        }

        pContext->ClearCancel();
        pContext->ClearAliasTable();
        pContext->SetRootCollection(NULL);
        pChore->_M_pTaskCollection = NULL;
        pTaskCollection->_NotifyCompletedChoreAndFree(pChore);
    }