Example #1
0
UNDO_DEF *AllocateNewUndoBuffer(GEM_WINDOW *gwnd)
{
  UNDO_DEF *undo ;
  VXIMAGE *vimage ;

  vimage = (VXIMAGE *) gwnd->Extension ;
  if ( ( vimage->NbUndoBuffers >= config.nb_undo ) && !IsListEmpty( &vimage->UndoListHead ) )
  {
    LIST_ENTRY *entry ;

    entry = RemoveTailList( &vimage->UndoListHead ) ;
    undo  = GET_UNDO_DEF_FROM_LIST_ENTRY( entry ) ;
    FreeUndoBuffer( undo ) ;
  }

  undo = (UNDO_DEF *) calloc( 1, sizeof(UNDO_DEF) ) ;
  if ( undo )
  {
    undo->undo_num = UndoNum++ ;
    undo->gwindow  = gwnd ;
    vimage->NbUndoBuffers++ ;
  }

  return( undo ) ;
}
Example #2
0
/*
** Free all the resources allocated in PKT_Init()
*/
BOOL PKT_Deinit(DWORD dwContext)
{
	NDIS_STATUS			Status;
	PLIST_ENTRY			pHead;
	PLIST_ENTRY			pEntry;
    PADAPTER_NAME		pAName;
	POPEN_INSTANCE		pOI;
	
	pOI = g_pDeviceExtension->pOpenInstance;

	if (pOI != NULL) {
		PKTCloseAdapter (pOI);
	}

	//free the names' list
	if (!IsListEmpty (&g_pDeviceExtension->listAdapterNames)) {
	
		pHead = &(g_pDeviceExtension->listAdapterNames);
		if (pHead != NULL )
		{
			pEntry = RemoveTailList (pHead);
			while (!IsListEmpty(pEntry)){

				pAName = CONTAINING_RECORD (pEntry, ADAPTER_NAME, ListElement);

				NdisFreeMemory (pAName, sizeof(ADAPTER_NAME), 0);

				pEntry = RemoveTailList (pHead);
			}
		}
	}

	//unregister the protocol from NDIS
	NdisDeregisterProtocol (&Status, g_pDeviceExtension->NdisProtocolHandle);
	
	//free the global device extension
	NdisFreeMemory (g_pDeviceExtension, sizeof (DEVICE_EXTENSION), 0);
	g_pDeviceExtension = NULL;

	return TRUE;
}
Example #3
0
/*
 * Remove the current PnP event from the tail of the event queue
 * and signal IopPnpNotifyEvent if there is yet another event in the queue.
 */
static NTSTATUS
IopRemovePlugPlayEvent(VOID)
{
    /* Remove a pnp event entry from the tail of the queue */
    if (!IsListEmpty(&IopPnpEventQueueHead))
    {
        ExFreePool(CONTAINING_RECORD(RemoveTailList(&IopPnpEventQueueHead), PNP_EVENT_ENTRY, ListEntry));
    }

    /* Signal the next pnp event in the queue */
    if (!IsListEmpty(&IopPnpEventQueueHead))
    {
        KeSetEvent(&IopPnpNotifyEvent,
                   0,
                   FALSE);
    }

    return STATUS_SUCCESS;
}
NTSTATUS
CImageHardwareSimulation::
CompletePastBuffers()

/*++

Routine Description:

    Find and complete any history frames.

Arguments:

    None

Return Value:

    Success / Failure

--*/

{
    PAGED_CODE();

    ULONG ulNumBuffers = m_PastBufferCount;
    BOOLEAN bContinue = TRUE;
    LIST_ENTRY *listEntry = NULL;

    DBG_ENTER("()");
    DBG_TRACE("m_PastBufferCount=%d, m_TriggerTime=0x%016llX", m_PastBufferCount, m_TriggerTime );

    //  If we're in burst mode and have ISP settings, we can't
    //  really support changing the ISP settings in the past...
    //  ... so we'll just treat them all past frames.
    //  Note: The upper layer will determine past frames from the
    //  metadata FrameId.
    if( m_PinMode == PinBurstMode &&
            !m_pIspSettings )
    {
        //  Walk through the entire list of buffers, find the most
        //  recent frame presentation time and put all past buffers
        //  into another list.
        while( !IsListEmpty(&m_ScatterGatherMappings) )
        {
            listEntry = RemoveTailList(&m_ScatterGatherMappings);
            m_ScatterGatherMappingsQueued--;

            PSCATTER_GATHER_ENTRY SGEntry =
                reinterpret_cast <PSCATTER_GATHER_ENTRY> (
                    CONTAINING_RECORD (
                        listEntry,
                        SCATTER_GATHER_ENTRY,
                        ListEntry
                    )
                );

            NT_ASSERT(SGEntry);
            NT_ASSERT(SGEntry->CloneEntry);
            NT_ASSERT(SGEntry->CloneEntry->StreamHeader);

            //  We've found one that's not stamped.  We must be at the end.
            //  Push it back and exit the loop.
            if(SGEntry->CloneEntry->StreamHeader->PresentationTime.Time == 0)
            {
                InsertTailList(&m_ScatterGatherMappings, listEntry);
                m_ScatterGatherMappingsQueued++;
                DBG_TRACE( "No past frames found." );
                bContinue = FALSE;
                break;
            }

            //  Since we're walking from the most recent to least recent frame,
            //  This one is a valid "future" frame.
            DBG_TRACE( "Adding 'future frame' to the list" );
            PushCloneList(SGEntry);

            //  If the presentation time is less than the trigger time, stop here
            //  and use this as the first triggered frame.
            if((ULONGLONG)(SGEntry->CloneEntry->StreamHeader->PresentationTime.Time) < m_TriggerTime)
            {
                DBG_TRACE( "First matching frame time=0x%016llX", SGEntry->CloneEntry->StreamHeader->PresentationTime.Time );
                break;
            }

            //  Watch out!  We might actually need to pick up multiple frames since
            //  in theory we could have generated several since the trigger time.
        }
    }

    //  Grab N past frames from the queue, if we have them.
    while( bContinue &&
            !IsListEmpty(&m_ScatterGatherMappings) &&
            ulNumBuffers)
    {
        listEntry = RemoveTailList(&m_ScatterGatherMappings);
        m_ScatterGatherMappingsQueued--;

        PSCATTER_GATHER_ENTRY SGEntry =
            reinterpret_cast <PSCATTER_GATHER_ENTRY> (
                CONTAINING_RECORD (
                    listEntry,
                    SCATTER_GATHER_ENTRY,
                    ListEntry
                )
            );

        if(!(SGEntry -> CloneEntry -> StreamHeader -> OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEVALID) )
        {
            InsertTailList(&m_ScatterGatherMappings, listEntry);
            m_ScatterGatherMappingsQueued++;
            DBG_TRACE( "No more past frames found." );
            bContinue = FALSE;
        }
        else
        {
            PushCloneList(SGEntry);
            ulNumBuffers--;
            DBG_TRACE( "Past frame #%d found (%p)", ulNumBuffers, SGEntry->CloneEntry->StreamHeader );
        }
    }

    //  If we got all of the past frames we needed and didn't consume the entire queue...
    if(bContinue && (m_ScatterGatherMappingsQueued > 0))
    {
        //Mark the next tail as Time = 0 so that we don't output any super old frames.
        listEntry = RemoveTailList(&m_ScatterGatherMappings);
        m_ScatterGatherMappingsQueued--;

        PSCATTER_GATHER_ENTRY SGEntry =
            reinterpret_cast <PSCATTER_GATHER_ENTRY> (
                CONTAINING_RECORD (
                    listEntry,
                    SCATTER_GATHER_ENTRY,
                    ListEntry
                )
            );
        //  Mark the PTS as invalid.
        SGEntry->CloneEntry->StreamHeader->PresentationTime.Time = 0;
        SGEntry->CloneEntry->StreamHeader->OptionsFlags &= ~KSSTREAM_HEADER_OPTIONSF_TIMEVALID;

        InsertTailList(&m_ScatterGatherMappings, listEntry);
        m_ScatterGatherMappingsQueued++;
    }

    CompleteCloneList();

    m_bPastBufferTrigger = FALSE;

    DBG_LEAVE("()");

    return STATUS_SUCCESS;

}
Example #5
0
VOID
CmpDelayCloseWorker(
    IN PVOID Parameter
    )

/*++

Routine Description:
    
      The fun part. We need to walk the cache and look for kcbs with refcount == 0
      Get the oldest one and kick it out of cache.

Arguments:

    Parameter - not used.

Return Value:

    None.

--*/

{
    PCM_DELAYED_CLOSE_ENTRY     DelayedEntry;
    ULONG                       ConvKey;
    ULONG                       MaxIterations = MAX_DELAY_WORKER_ITERATIONS;

    CM_PAGED_CODE();

    UNREFERENCED_PARAMETER (Parameter);

    ASSERT(CmpDelayCloseWorkItemActive);

    BEGIN_LOCK_CHECKPOINT;
    CmpLockRegistry();
    
    //
    // process kick out every entry with RefCount == 0 && DelayCloseIndex == 0
    // ignore the others; we only do this while there is excess of delay - close kcbs
    //
    LOCK_DELAY_CLOSE();
    while( (CmpDelayedCloseElements > CmpDelayedCloseSize) && (MaxIterations--) ) {
        ASSERT( !CmpIsListEmpty(&CmpDelayedLRUListHead) );
        //
        // We first need to get the hash entry and attempt to lock it.
        //
        DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)(CmpDelayedLRUListHead.Blink);
        DelayedEntry = CONTAINING_RECORD(   DelayedEntry,
                                            CM_DELAYED_CLOSE_ENTRY,
                                            DelayedLRUList);
        ConvKey = DelayedEntry->KeyControlBlock->ConvKey;
        UNLOCK_DELAY_CLOSE();
        //
        // now lock the hash then recheck if the entry is still first on the list
        //
        CmpLockHashEntryExclusive(ConvKey);
        LOCK_DELAY_CLOSE();
        if( CmpDelayedCloseElements <= CmpDelayedCloseSize ) {
            //
            // just bail out; no need to kick them out
            //
            CmpUnlockHashEntry(ConvKey);
            break;
        }
        DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)(CmpDelayedLRUListHead.Blink);
        DelayedEntry = CONTAINING_RECORD(   DelayedEntry,
                                            CM_DELAYED_CLOSE_ENTRY,
                                            DelayedLRUList);
        if( ConvKey == DelayedEntry->KeyControlBlock->ConvKey ) {
            //
            // same hash entry; proceed
            // pull it out of the list
            //
            DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)RemoveTailList(&CmpDelayedLRUListHead);
    
            DelayedEntry = CONTAINING_RECORD(   DelayedEntry,
                                                CM_DELAYED_CLOSE_ENTRY,
                                                DelayedLRUList);
            CmpClearListEntry(&(DelayedEntry->DelayedLRUList));

            if( (DelayedEntry->KeyControlBlock->RefCount == 0) && (DelayedEntry->KeyControlBlock->DelayedCloseIndex == 0) ){
                //
                // free this kcb and the entry
                //
                UNLOCK_DELAY_CLOSE();
                DelayedEntry->KeyControlBlock->DelayCloseEntry = NULL;
                CmpCleanUpKcbCacheWithLock(DelayedEntry->KeyControlBlock,FALSE);
                CmpDelayCloseFreeEntry(DelayedEntry);
                InterlockedDecrement((PLONG)&CmpDelayedCloseElements);
            } else {
                //
                // put it back at the top
                //
                InsertHeadList( &CmpDelayedLRUListHead,
                                &(DelayedEntry->DelayedLRUList)
                            );
                UNLOCK_DELAY_CLOSE();
            }
        } else {
            UNLOCK_DELAY_CLOSE();
        }
        CmpUnlockHashEntry(ConvKey);

        LOCK_DELAY_CLOSE();
    }
    if( CmpDelayedCloseElements > CmpDelayedCloseSize ) {
        //
        // iteration run was too short, there are more elements to process, queue ourselves for later
        //
        CmpArmDelayedCloseTimer();
    } else {
        //
        // signal that we have finished our work.
        //
        CmpDelayCloseWorkItemActive = FALSE;
    }
    UNLOCK_DELAY_CLOSE();


    CmpUnlockRegistry();
    END_LOCK_CHECKPOINT;
}
Example #6
0
int TestInterlockedDList(int argc, char* argv[])
{
	ULONG Count;
	PLIST_ITEM pListItem;
	WINPR_PLIST_ENTRY pListHead;
	WINPR_PLIST_ENTRY pListEntry;

	pListHead = (WINPR_PLIST_ENTRY) _aligned_malloc(sizeof(WINPR_LIST_ENTRY), MEMORY_ALLOCATION_ALIGNMENT);

	if (!pListHead)
	{
		printf("Memory allocation failed.\n");
		return -1;
	}

	InitializeListHead(pListHead);

	if (!IsListEmpty(pListHead))
	{
		printf("Expected empty list\n");
		return -1;
	}

	/* InsertHeadList / RemoveHeadList */

	printf("InsertHeadList / RemoveHeadList\n");

	for (Count = 1; Count <= 10; Count += 1)
	{
		pListItem = (PLIST_ITEM) _aligned_malloc(sizeof(LIST_ITEM), MEMORY_ALLOCATION_ALIGNMENT);
		pListItem->Signature = Count;
		InsertHeadList(pListHead, &(pListItem->ItemEntry));
	}

	for (Count = 10; Count >= 1; Count -= 1)
	{
		pListEntry = RemoveHeadList(pListHead);
		pListItem = (PLIST_ITEM) pListEntry;
		_aligned_free(pListEntry);
	}

	/* InsertTailList / RemoveTailList */

	printf("InsertTailList / RemoveTailList\n");

	for (Count = 1; Count <= 10; Count += 1)
	{
		pListItem = (PLIST_ITEM) _aligned_malloc(sizeof(LIST_ITEM), MEMORY_ALLOCATION_ALIGNMENT);
		pListItem->Signature = Count;
		InsertTailList(pListHead, &(pListItem->ItemEntry));
	}

	for (Count = 10; Count >= 1; Count -= 1)
	{
		pListEntry = RemoveTailList(pListHead);
		pListItem = (PLIST_ITEM) pListEntry;
		_aligned_free(pListEntry);
	}

	_aligned_free(pListHead);

	return 0;
}
HRESULT CMSPThread::QueueWorkItem(
    LPTHREAD_START_ROUTINE Function,
    PVOID Context,
    BOOL  fSynchronous
    )
{
    LOG((MSP_TRACE, "CMSPThread::QueueWorkItem - enter"));


    //
    // Create a command block for this.
    //

    COMMAND_QUEUE_ITEM * pItem = new COMMAND_QUEUE_ITEM;

    if ( ! pItem )
    {
        LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - "
            "can't allocate new queue item - exit E_OUTOFMEMORY"));

        return E_OUTOFMEMORY;
    }


    //
    // Create an event to wait on if this is a synchronous work item.
    // Otherwise the thread proc gets a NULL event handle and it knows not to
    // signal it since it's an asynchronous work item.
    //

    TCHAR *ptczEventName = NULL;

#if DBG

    static LONG lSequenceNumber = 0;


    //
    // in debug build, use named events
    //

    TCHAR tszEventName[MAX_PATH];

    InterlockedIncrement(&lSequenceNumber);


    //
    // identify events by the address of the correspoding queue item, and by 
    // the sequence number
    //

    _stprintf_s(tszEventName,
        _T("CMSPThread_QueueWorkitemEvent_pid[0x%lx]_CMSPThread[%p]_Event[%p]_eventNumber[%lu]"),
        GetCurrentProcessId(), this, pItem, lSequenceNumber);

    LOG((MSP_TRACE, "CMSPThread::QueueWorkItem - creating event[%S]", tszEventName));

    ptczEventName = &tszEventName[0];

#endif


    HANDLE hEvent = NULL;

    if (fSynchronous)
    {
        hEvent = ::CreateEvent(NULL, 
                               FALSE,           // flag for manual-reset event 
                               FALSE,           // initial state is not set.
                               ptczEventName);  // No name in release, named in debug

        if ( hEvent == NULL )
        {
            LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - "
                "Can't create the Job Done event"));

            delete pItem;
            pItem = NULL;

            return E_FAIL;
        }
    }


    //
    // we already have the q item, now initialize it.
    //

    pItem->node.cmd        = WORK_ITEM;
    pItem->node.pfn        = Function;
    pItem->node.pContext   = Context;
    pItem->node.hEvent     = hEvent;


    //
    // Put the command block on the queue. The queue is protected by a
    // critical section.
    //

    m_QueueLock.Lock();
    InsertTailList(&m_CommandQueue, &(pItem->link));


    //
    // Signal the thread to process the command.
    //

    if (SignalThreadProc() == 0)
    {

        //
        // failed to signal processing thread
        // cleanup and return error
        //

        
        //
        // remove the queue entry we have submitted
        //

        RemoveTailList(&m_CommandQueue);


        //
        // unlock the queue so other threads can use it
        //

        m_QueueLock.Unlock();


        //
        // close handle and delete pItem that we have created -- 
        // no one else is going to do this for us
        //

        if (NULL != hEvent)
        {
            ::CloseHandle(hEvent);
            hEvent = NULL;
        }

        delete pItem;
        pItem = NULL;


        LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - "
            "can't signal the thread"));

        return E_FAIL;
    }


    //
    // unlock the event queue, so it can be used by processing and other 
    // threads
    //

    m_QueueLock.Unlock();


    //
    // If this is a sychronous work item, wait for it to complete and
    // then close the event handle.
    //
    // FEATUREFEATURE: Rather than creating and deleting an event for each
    // work item, have a cache of events that can be reused.
    //

    if (fSynchronous)
    {
        LOG((MSP_TRACE, "CMSPThread::QueueWorkItem - "
            "blocked waiting for synchronous work item to complete"));
        
        // Wait for the synchronous work item to complete.

        HANDLE hEvents[2];
        DWORD dwEvent;

        hEvents[0] = hEvent;
        hEvents[1] = m_hThread;

        dwEvent = WaitForMultipleObjects( 
            2,
            hEvents,
            FALSE,
            INFINITE);

        switch (dwEvent)
        {
        case WAIT_OBJECT_0 + 0:
            break;

        case WAIT_OBJECT_0 + 1:
            LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - "
                "thread exited"));

            //
            // if the item is still in the queue, remove it (since the thread 
            // won't)
            //

            m_QueueLock.Lock();
            
            if (IsNodeOnList(&m_CommandQueue, &(pItem->link)))
            {
                RemoveEntryList(&(pItem->link));
                delete pItem;
            }

            m_QueueLock.Unlock();
          

            //
            // time to close event and fail
            //

            ::CloseHandle(hEvent);

            return E_FAIL;        

        default:
            LOG((MSP_ERROR, "CMSPThread::QueueWorkItem - "
                "WaitForSingleObject failed"));
        }

        ::CloseHandle(hEvent);
    }

    LOG((MSP_TRACE, "CMSPThread::QueueWorkItem - exit S_OK"));

    return S_OK;
}
Example #8
0
ULONG 
RspWriteProbeGroup(
	IN HANDLE FileHandle
	)
{
	ULONG CompleteBytes;
	ULONG OnDiskLength;
	PRSP_PROBE_GROUP Group;
	PRSP_PROBE Probe;
	PLIST_ENTRY ListEntry;
	PLIST_ENTRY Entry;

	if (!RspProbeGroupCount) {
		return 0;
	}

	WriteFile(FileHandle, &RspProbeGroupCount, sizeof(ULONG), &CompleteBytes, NULL);
	
	ListEntry = RspProbeGroupList.Flink;
	OnDiskLength = FIELD_OFFSET(RSP_PROBE_GROUP, ListEntry);	

	while (ListEntry != &RspProbeGroupList) {
		Group = CONTAINING_RECORD(ListEntry, RSP_PROBE_GROUP, ListEntry);
		WriteFile(FileHandle, Group, OnDiskLength, &CompleteBytes, NULL);
		ListEntry = ListEntry->Flink;
	}
	
	ListEntry = RspProbeGroupList.Flink;
	while (ListEntry != &RspProbeGroupList) {

		Group = CONTAINING_RECORD(ListEntry, RSP_PROBE_GROUP, ListEntry);

		Entry = Group->ProbeListHead.Flink;
		while (Entry != &Group->ProbeListHead) {

			Probe = CONTAINING_RECORD(Entry, RSP_PROBE, Entry);
			WriteFile(FileHandle, Probe, sizeof(RSP_PROBE), &CompleteBytes, NULL);

			if (FlagOn(Probe->Flag, BTR_FLAG_MULTIVERSION)) {

				//
				// N.B. For multi-version probe, it's written to disk in order of number
				//

				while (IsListEmpty(&Probe->VariantList) != TRUE) {
					PRSP_PROBE Subversion;
					PLIST_ENTRY Entry2;
					Entry2 = RemoveTailList(&Probe->VariantList);
					Subversion = CONTAINING_RECORD(Entry2, RSP_PROBE, VariantList);
					ASSERT(FlagOn(Subversion->Flag, BTR_FLAG_VARIANT));
					WriteFile(FileHandle, Subversion, sizeof(RSP_PROBE), &CompleteBytes, NULL);
				}

			}

			Entry = Entry->Flink;
		}

		ListEntry = ListEntry->Flink;
	}

	return 0;	
}