主页 > 软件开发  > 

ExpMoveFreeHandles函数分析和备用空闲表的关系

ExpMoveFreeHandles函数分析和备用空闲表的关系

第一部分:ExpMoveFreeHandles和备用空闲表的关系

ULONG ExpMoveFreeHandles (     IN PHANDLE_TABLE HandleTable     ) {     ULONG OldValue, NewValue;     ULONG Index, OldIndex, NewIndex, FreeSize;     PHANDLE_TABLE_ENTRY Entry, FirstEntry;     EXHANDLE Handle;     ULONG Idx;     BOOLEAN StrictFIFO;

    //     // First remove all the handles from the free list so we can add them to the     // list we use for allocates.     //

    OldValue = InterlockedExchange ((PLONG)&HandleTable->LastFree,                                     0);     Index = OldValue;     if (Index == 0) {         //         // There are no free handles.  Nothing to do.         //         return OldValue;     }

            //     // We are pushing old entries onto the free list.     // We have the A-B-A problem here as these items may have been moved here because     // another thread was using them in the pop code.     //     for (Idx = 1; Idx < HANDLE_TABLE_LOCKS; Idx++) {         ExAcquireReleasePushLockExclusive (&HandleTable->HandleTableLock[Idx]);     }     StrictFIFO = HandleTable->StrictFIFO;       //如果我们是严格的FIFO,那么反转列表以减少句柄重用。     // If we are strict FIFO then reverse the list to make handle reuse rare.     //

    if (!StrictFIFO) {         //         // We have a complete chain here. If there is no existing chain we         // can just push this one without any hassles. If we can't then         // we can just fall into the reversing code anyway as we need         // to find the end of the chain to continue it.         //

        //         // This is a push so create a new sequence number         //

        if (InterlockedCompareExchange ((PLONG)&HandleTable->FirstFree,                                         OldValue + GetNextSeq(),                                         0) == 0) {             return OldValue;         }     }

    //     // Loop over all the entries and reverse the chain.     //遍历所有条目并反转链。     FreeSize = OldIndex = 0;     FirstEntry = NULL;     while (1) {         FreeSize++;         Handle.Value = Index;         Entry = ExpLookupHandleTableEntry (HandleTable, Handle);

        EXASSERT (Entry->Object == NULL);

        NewIndex = Entry->NextFreeTableEntry;         Entry->NextFreeTableEntry = OldIndex;         if (OldIndex == 0) {             FirstEntry = Entry;         }         OldIndex = Index;         if (NewIndex == 0) {             break;         }         Index = NewIndex;     }

    NewValue = ExpInterlockedExchange (&HandleTable->FirstFree,                                        OldIndex,                                        FirstEntry);

    //     // If we haven't got a pool of a few handles then force     // table expansion to keep the free handle size high     //     if (FreeSize < 100 && StrictFIFO) {         OldValue = 0;     }     return OldValue; }

FORCEINLINE ULONG ExpInterlockedExchange (     IN OUT PULONG Index,     IN ULONG FirstIndex,     IN PHANDLE_TABLE_ENTRY Entry     ) /*++

Routine Description:

    This performs the following steps:     1. Set Entry->NextFreeTableEntry = *Index     2. Loops until *Index == (the value of *Index when we entered the function)        When they're equal, we set *Index = FirstIndex

Arguments:

    Index - Points to the ULONG we want to set.          FirstIndex - New value to set Index to.

    Entry - TableEntry that will get the initial value of *Index before it's             updated.

Return Value:

    New value of *Index (i.e. FirstIndex).

--*/ {     ULONG OldIndex, NewIndex;

    EXASSERT (Entry->Object == NULL);

    //     // Load new value and generate the sequence number on pushes     //

    NewIndex = FirstIndex + GetNextSeq();

    while (1) {

        //         // remember original value and         // archive it in NextFreeTableEntry.         //

        OldIndex = *Index;         Entry->NextFreeTableEntry = OldIndex;

                 //         // Swap in the new value, and if the swap occurs         // successfully, we're done.         //         if (OldIndex == (ULONG) InterlockedCompareExchange ((PLONG)Index,                                                             NewIndex,                                                             OldIndex)) {             return OldIndex;         }     } }

第二部分:ExpMoveFreeHandles函数的调用时机 PHANDLE_TABLE_ENTRY ExpAllocateHandleTableEntry (     IN PHANDLE_TABLE HandleTable,     OUT PEXHANDLE pHandle     ) {

......

    while (1) {

        OldValue = HandleTable->FirstFree;

        while (OldValue == 0) {             //             //  Lock the handle table for exclusive access as we will be             //  allocating a new table level.             //             ExpLockHandleTableExclusive (HandleTable, CurrentThread);

            //             // If we have multiple threads trying to expand the table at             // the same time then by just acquiring the table lock we             // force those threads to complete their allocations and             // populate the free list. We must check the free list here             // so we don't expand the list twice without needing to.             //

            OldValue = HandleTable->FirstFree;             if (OldValue != 0) {                 ExpUnlockHandleTableExclusive (HandleTable, CurrentThread);                 break;             }

            //看看我们在备用空闲列表上是否有句柄             // See if we have any handles on the alternate free list             // These handles need some locking to move them over.             //             OldValue = ExpMoveFreeHandles (HandleTable);             if (OldValue != 0) {                 ExpUnlockHandleTableExclusive (HandleTable, CurrentThread);                 break;             }

标签:

ExpMoveFreeHandles函数分析和备用空闲表的关系由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“ExpMoveFreeHandles函数分析和备用空闲表的关系