diff options
Diffstat (limited to 'src/pal/tests/palsuite/threading/DuplicateHandle/test4')
3 files changed, 277 insertions, 0 deletions
diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt new file mode 100644 index 0000000000..c3040d09ec --- /dev/null +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(SOURCES + test4.c +) + +add_executable(paltest_duplicatehandle_test4 + ${SOURCES} +) + +add_dependencies(paltest_duplicatehandle_test4 coreclrpal) + +target_link_libraries(paltest_duplicatehandle_test4 + pthread + m + coreclrpal +) diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.c b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.c new file mode 100644 index 0000000000..14a72db461 --- /dev/null +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/test4.c @@ -0,0 +1,239 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*===================================================================== +** +** Source: test4.c (DuplicateHandle) +** +** Purpose: Tests the PAL implementation of the DuplicateHandle function. +** This test duplication of a Mutex handle. The test will comprise +** of creating a Mutex and its duplicate and create a thread that +** will get ownership. Another thread will be create that will +** attempt to get ownership of the duplicate Mutex, this will +** fail, since the Mutex is owned by another thread. The Mutex +** will be released and then the thread will attempt to get +** ownership of the duplicate Mutex, this will succeed. +** +** +**===================================================================*/ +#include <palsuite.h> + +enum wait_results +{ + WR_WAITING, + WR_GOT_MUTEX, + WR_TIMED_OUT, + WR_RELEASED +}; + + +volatile int t1_result=WR_WAITING; +volatile int t2_result=WR_WAITING; + + +DWORD PALAPI ThreadTest1(LPVOID lpParam) +{ + DWORD dwWait; + + dwWait = WaitForSingleObject((HANDLE)lpParam, 0); + if (dwWait == WAIT_OBJECT_0) + { + /* tell the main thread we got the mutex */ + t1_result=WR_GOT_MUTEX; + + /* wait for main thread to tell us to release the mutex */ + while(WR_GOT_MUTEX == t1_result) + Sleep(1); + ReleaseMutex((HANDLE)lpParam); + + /* tell the main thread we released the mutex */ + t1_result = WR_RELEASED; + } + else + { + t1_result = WR_TIMED_OUT; + } + return 0; +} + +DWORD PALAPI ThreadTest2(LPVOID lpParam) +{ + DWORD dwWait; + + dwWait = WaitForSingleObject((HANDLE)lpParam, 0 ); + if (dwWait == WAIT_OBJECT_0) + { + ReleaseMutex((HANDLE)lpParam); + t2_result = WR_GOT_MUTEX; + } + else + { + t2_result = WR_TIMED_OUT; + } + + return 0; +} + + +int __cdecl main(int argc, char **argv) +{ + + HANDLE hDupMutex; + HANDLE hMutex; + HANDLE hThread; + HANDLE hThread2; + BOOL bDupHandle=FALSE; + DWORD dwThreadId = 0; + + if ((PAL_Initialize(argc,argv)) != 0) + { + return(FAIL); + } + + /*Create Mutex without ownership*/ + hMutex = CreateMutexW(NULL, // no security attributes + FALSE, // initially not owned + NULL); // name of mutex + if (hMutex == NULL) + { + Fail("ERROR:%u: Unable to create mutex\n", + GetLastError()); + } + + /*Create Duplicate of the Mutex above*/ + bDupHandle = DuplicateHandle(GetCurrentProcess(), + hMutex, + GetCurrentProcess(), + &hDupMutex, + GENERIC_READ|GENERIC_WRITE, + FALSE, + DUPLICATE_SAME_ACCESS); + if (!bDupHandle) + { + Trace("ERROR:%u: Created the duplicate handle to " + "closed event handle hMutex=0x%lx\n", + GetLastError(), + hMutex); + CloseHandle(hMutex); + Fail(""); + } + + /*Create a thread to test the Mutex*/ + hThread = CreateThread(NULL, + 0, + &ThreadTest1, + hMutex, + 0, + &dwThreadId); + if (hThread == NULL) + { + Trace("ERROR:%u: unable to create thread\n", + GetLastError()); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + Fail(""); + } + + /* wait until thread has taken the mutex */ + while (WR_WAITING == t1_result) + Sleep(1); + + if(WR_TIMED_OUT == t1_result) + { + Trace("ERROR: %u: thread 1 couldn't acquire the mutex\n"); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + Fail(""); + } + + /*Create a second thread to use the duplicate Mutex*/ + /*This should fail since the Mutex is owned hThread*/ + hThread2 = CreateThread(NULL, + 0, + &ThreadTest2, + hDupMutex, + 0, + &dwThreadId); + + if (hThread2 == NULL) + { + Trace("ERROR:%u: unable to create thread\n", + GetLastError()); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + Fail(""); + } + + /* wait until thread has tried to take the mutex */ + while (WR_WAITING == t2_result) + Sleep(1); + + if (WR_TIMED_OUT != t2_result ) + { + Trace("ERROR:%u: Able to take mutex %#x while its duplicate %#x is " + "held\n", hDupMutex, hMutex); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + CloseHandle(hThread2); + Fail(""); + } + + /* reset second thread status */ + t2_result = WR_WAITING; + + /* tell thread 1 to release the mutex */ + t1_result = WR_WAITING; + + /* wait for thread 1 to release the mutex */ + while (WR_WAITING == t1_result) + Sleep(1); + + CloseHandle(hThread2); + + /*Re-Create the second thread to reuse the duplicated Mutex*/ + /*This test should pass, the Mutex has since been released*/ + hThread2 = CreateThread(NULL, + 0, + &ThreadTest2, + hDupMutex, + 0, + &dwThreadId); + + if (hThread2 == NULL) + { + Trace("ERROR:%u: unable to create thread\n", + GetLastError()); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + Fail(""); + } + + /* wait until thread has taken the mutex */ + while (WR_WAITING == t2_result) + Sleep(1); + + if (WR_GOT_MUTEX != t2_result ) + { + Trace("ERROR:%u: Unable to take mutex %#x after its duplicate %#x was " + "released\n", hDupMutex, hMutex); + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + CloseHandle(hThread2); + Fail(""); + } + + /*Cleanup.*/ + CloseHandle(hMutex); + CloseHandle(hDupMutex); + CloseHandle(hThread); + CloseHandle(hThread2); + + PAL_Terminate(); + return (PASS); +} diff --git a/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat new file mode 100644 index 0000000000..64842f8713 --- /dev/null +++ b/src/pal/tests/palsuite/threading/DuplicateHandle/test4/testinfo.dat @@ -0,0 +1,19 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. + +Version = 1.0 +Section = Threading +Function = DuplicateHandle +Name = Test for DuplicateHandle (CreateMutex) +TYPE = DEFAULT +EXE1 = test4 +Description += Tests the PAL implementation of the DuplicateHandle function. += This test duplication of a Mutex handle. The test will comprise += of creating a Mutex and its duplicate and create a thread that will += get ownership. Another thread will be create that will attempt to += get ownership of the duplicate Mutex, this will fail, since the += Mutex is owned by another thread. The Mutex will be released and += then the thread will attempt to get ownership of the duplicate += Mutex, this will succeed. |