Porting to OS/2: Case #15 fast mutex

Mutex(mutual-exclusive) is used to synchronize executions of threads. Of course, OS/2 supports mutex very well. But, there is one caution. OS/2 mutex is a recursive mutex. That is, if a thread requests a mutex which is already owned by a different thread, that thread is blocked. But if a thread which already owns a mutex requests the same mutex, then it succeeds. This is a recursive mutex. In general, this works well. However, sometimes a non-recursive mutex, so called fast mutex, is needed. That is, even if an owner thread requests its owning mutex, that thread should be blocked, get an error at least.

A fast mutex can be implemented easily with a recursive mutex of OS/2. The following are the codes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#define INCL_DOS
#include <os2.h>

#include <assert.h>

static
APIRET DosRequestFastMutexSem( HMTX hmtx, ULONG ulTimeout )
{
    ULONG rc;

    rc = DosRequestMutexSem( hmtx, ulTimeout );
    if( !rc )
    {
        PID   pid;
        TID   tid;
        ULONG ulCount;

        if( !DosQueryMutexSem( hmtx, &pid, &tid, &ulCount ))
        {
            if( ulCount > 1 )
            {
                assert(!"Ooops... DEADLOCK!!!");

                /* Mimic DEADLOCK */
                for(;;) DosSleep( 1 );
            }
        }
    }

    return rc;
}

#include <stdio.h>

#define DEAD_LOCK_TEST 1

int main( void )
{
    HMTX hmtx;

    DosCreateMutexSem( NULL, &hmtx, 0, FALSE );

    printf("Request recursive mutex level 1\n");
    DosRequestMutexSem( hmtx, -1 );

    printf("Request recursive mutex level 2\n");
    DosRequestMutexSem( hmtx, -1 );

    printf("Release recursive mutex level 2\n");
    DosReleaseMutexSem( hmtx );

#if DEAD_LOCK_TEST
    printf("Request fast mutex\n");
    DosRequestFastMutexSem( hmtx, -1 );

    printf("Release fast mutex\n");
    DosReleaseMutexSem( hmtx );
#endif

    printf("Release recursive mutex level 1\n");
    DosReleaseMutexSem( hmtx );

#if !DEAD_LOCK_TEST
    printf("Request fast mutex\n");
    DosRequestFastMutexSem( hmtx, -1 );

    printf("Release fast mutex\n");
    DosReleaseMutexSem( hmtx );
#endif

    DosCloseMutexSem( hmtx );

    return 0;
}


The principle is simple. Check recursive level, and if it is greater than 1, then it must be DEADLOCK. Line 18 to 27 are the parts. If you build the above source without defining NDEBUG, then the executable will crash due to dead lock. If you define NDEBUG, it will blocked.

If you want to return an error instead of blocking a thread, then replace line 22 to 25 with the codes of releasing mutex and returning an error code.

댓글

이 블로그의 인기 게시물

토렌트: < 왕좌의 게임 > 시즌 1 ~ 시즌 8 완결편 마그넷

토렌트: < 스타워즈 > Ep.1 ~ Ep.6 마그넷

토렌트: NGC < 코스모스 > 우리말 더빙 전편(1편~13편) 마그넷