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.
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.
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.
댓글
댓글 쓰기