Semaphores values

2020-04-17 05:21发布

I have a question regarding using Semaphores

HANDLE WINAPI CreateSemaphore(...);

Is there anyway I can get the current value of the semaphore?

5条回答
家丑人穷心不美
3楼-- · 2020-04-17 05:32

You can always use:

//ReleaseSemaphore(Last Parameter- Previous Count)

If you want your Main thread to wait till all threads complete its execution.

//CreateEvent
//Assign threads
//ResetEvent
//WaitForSingleObject( hEvent, INFINITE) ;

//When you call the threads function and after releasing Semaphore.
//Check for the previousCount, if it is equal to MAX_SEMAPHORES-1, SetEvent()...

Hope it would help.

查看更多
劳资没心,怎么记你
4楼-- · 2020-04-17 05:33

Here the solution using Native Api, documented by http://undocumented.ntinternals.net/. I ommited a few thing because these would make the code even longer. The code is easy, when you understand the syntax of the native api. For example (nearly) all native api function, these exported by ntdll and not documented well by microsoft, return NTSTATUS, and dont use a functions simliar to get Set/GetLastError (). If NtQuerySemaphore fails (Status != STATUS_SUCCESS) you might want to look up the error code here: http://source.winehq.org/source/include/ntstatus.h.

Okay lets get to the code, its pretty straight forward, first defining some structs you can get from ntinernals.net. Then getting the address of NtQuerySemaphore in the ntdll.dll. You dont need to use LoadLibrary, because every process has ntdll.dll loaded.

NtQuerySemaphore is easy too, first parameter is the handle to the semaphore, second the information class you want to retrive (in our case SemaphoreBasicInformation = 0x0). Thee third parameter is an pointer to an struct, wich revieces the informations. Fourth paramwter is the sizeof the struct. Fifth would be the the ReturnLength, for example if you could recieve the name of the sempahore with this function, this parameter could hold the need buffer size after the first call with an incorrect SemaphoreInformationLength.

Enough! Code :)

#include <windows.h>
#include <stdio.h>

typedef LONG NTSTATUS;

typedef NTSTATUS (NTAPI *_NtQuerySemaphore)(
    HANDLE SemaphoreHandle, 
    DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */
    PVOID SemaphoreInformation,      /* but this is to much to dump here     */
    ULONG SemaphoreInformationLength, 
    PULONG ReturnLength OPTIONAL
); 

typedef struct _SEMAPHORE_BASIC_INFORMATION {   
    ULONG CurrentCount; 
    ULONG MaximumCount;
} SEMAPHORE_BASIC_INFORMATION;


int main (int argc, char *argv[])
{
    _NtQuerySemaphore NtQuerySemaphore;
    HANDLE Semaphore;
    SEMAPHORE_BASIC_INFORMATION BasicInfo;
    NTSTATUS Status;


    Semaphore = CreateSemaphore (NULL, 50, 100, "Test");

    NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress (GetModuleHandle ("ntdll.dll"), "NtQuerySemaphore");

    if (NtQuerySemaphore)
    {

        Status = NtQuerySemaphore (Semaphore, 0 /*SemaphoreBasicInformation*/, 
            &BasicInfo, sizeof (SEMAPHORE_BASIC_INFORMATION), NULL);

        if (Status == ERROR_SUCCESS)
        {       
            printf ("CurrentCount: %lu", BasicInfo.CurrentCount);
        }
    }

    CloseHandle (Semaphore);
}

One last thing, be warned, microsoft could remove or change the way this function works.

Cheers evilpie

查看更多
可以哭但决不认输i
5楼-- · 2020-04-17 05:36

I think you need to call

DWORD WINAPI WaitForSingleObject

with a second argument set to 0 (immediate result requested).

and take actions depending on the result.

I hope this will help you, Jerom Wagner

查看更多
\"骚年 ilove
6楼-- · 2020-04-17 05:41

No, and that's intentional. Even if you could get the "current" value, that value might very well have changed before you could do anything with it. The only way to do anything with it is to get and set the value atomically -- e.g., wait for the semaphore to be free and set it to "owned" (by that piece of code) in the same operation.

查看更多
登录 后发表回答