views:

85

answers:

4
+1  Q: 

Semaphores values

I have a question regarding using Semaphores

HANDLE WINAPI CreateSemaphore(...);

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

A: 

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

Jerome WAGNER
+3  A: 

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.

Jerry Coffin
Will it be cumbersome then? You need to enter critical section; wait for semaphore; manipulate counter; exit critical section; ?
Yan Cheng CHEOK
@Yan Cheng CHEOK:When used as intended, most uses of semaphores aren't cumbersome, no. It would be quite unusual to enter a critical section, *then* wait for a semaphore -- rather the contrary, you'll typically use only one of those two constructs, not both.
Jerry Coffin
+1  A: 

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

evilpie