From b560dee8c9bf484c017e5f5a05733edcf0ce9551 Mon Sep 17 00:00:00 2001 From: Rafal Rudnicki Date: Wed, 18 Sep 2024 15:39:37 +0200 Subject: [PATCH] enable IPC tests and examples on Windows --- Testing/Temporary/CTestCostData.txt | 1 + examples/CMakeLists.txt | 13 ++- examples/ipc_ipcapi/CMakeLists.txt | 16 +++- examples/ipc_ipcapi/ipc_ipcapi_anon_fd.bat | 14 +++ examples/ipc_ipcapi/ipc_ipcapi_consumer.c | 50 ++++++++-- examples/ipc_ipcapi/ipc_ipcapi_producer.c | 56 +++++++++-- src/provider/provider_level_zero.c | 8 +- test/CMakeLists.txt | 46 +++++---- test/common/ipc_common.c | 105 +++++++++++++++++---- 9 files changed, 248 insertions(+), 61 deletions(-) create mode 100644 Testing/Temporary/CTestCostData.txt create mode 100644 examples/ipc_ipcapi/ipc_ipcapi_anon_fd.bat diff --git a/Testing/Temporary/CTestCostData.txt b/Testing/Temporary/CTestCostData.txt new file mode 100644 index 0000000000..7313caa747 --- /dev/null +++ b/Testing/Temporary/CTestCostData.txt @@ -0,0 +1 @@ +--- diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 8b61c82a56..37aee8bd9b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -135,6 +135,13 @@ function(build_umf_ipc_example name) ${UMF_CMAKE_SOURCE_DIR}/include) target_link_directories(${EX_NAME} PRIVATE ${LIBHWLOC_LIBRARY_DIRS}) + if (WINDOWS) + # link with Winsock2 lib + target_link_libraries(${EX_NAME} PRIVATE ws2_32) + # append PATH to DLLs + #set_property(TEST ${EX_NAME} PROPERTY ENVIRONMENT_MODIFICATION + # "${DLL_PATH_LIST}") + endif() endforeach(loop_var) endfunction() @@ -155,14 +162,16 @@ function(add_umf_ipc_example script) endif() endfunction() +# IPC API examples +build_umf_ipc_example(ipc_ipcapi) + if(LINUX) - build_umf_ipc_example(ipc_ipcapi) add_umf_ipc_example(ipc_ipcapi_anon_fd) add_umf_ipc_example(ipc_ipcapi_shm) else() message( STATUS - "IPC examples with UMF pool API are supported on Linux only - skipping" + "IPC anon_fd and shm examples with UMF pool API are supported on Linux only - skipping" ) endif() diff --git a/examples/ipc_ipcapi/CMakeLists.txt b/examples/ipc_ipcapi/CMakeLists.txt index 41fae58993..8ab2dbe9e5 100644 --- a/examples/ipc_ipcapi/CMakeLists.txt +++ b/examples/ipc_ipcapi/CMakeLists.txt @@ -37,6 +37,10 @@ function(build_umf_ipc_example name) target_include_directories(${EX_NAME} PRIVATE ${LIBUMF_INCLUDE_DIRS}) target_link_directories(${EX_NAME} PRIVATE ${LIBHWLOC_LIBRARY_DIRS}) target_link_libraries(${EX_NAME} PRIVATE ${LIBUMF_LIBRARIES} hwloc) + if(WINDOWS) + # link with Winsock lib + target_link_libraries(${EX_NAME} PRIVATE ${LIBUMF_LIBRARIES} ws2_32) + endif() endforeach(loop_var) endfunction() @@ -44,12 +48,20 @@ endfunction() function(add_test_for_umf_ipc_example script) set(EXAMPLE_NAME umf_example_${script}) - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${script}.sh + message(WARNING "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + + if(LINUX) + set(script_ext sh) + else() + set(script_ext bat) + endif() + + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${script}.${script_ext} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) add_test( NAME ${EXAMPLE_NAME} - COMMAND ${script}.sh + COMMAND ${script}.${script_ext} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) if(LINUX) diff --git a/examples/ipc_ipcapi/ipc_ipcapi_anon_fd.bat b/examples/ipc_ipcapi/ipc_ipcapi_anon_fd.bat new file mode 100644 index 0000000000..8bb24dc9cd --- /dev/null +++ b/examples/ipc_ipcapi/ipc_ipcapi_anon_fd.bat @@ -0,0 +1,14 @@ + +# port should be a number from the range <1024, 65535> +PORT=$(( 1024 + ( $$ % ( 65535 - 1024 )))) + +UMF_LOG_VAL="level:debug;flush:debug;output:stderr;pid:yes" + +echo "Starting ipc_ipcapi_anon_fd CONSUMER on port $PORT ..." +UMF_LOG=$UMF_LOG_VAL ./umf_example_ipc_ipcapi_consumer $PORT & + +echo "Waiting 1 sec ..." +sleep 1 + +echo "Starting ipc_ipcapi_anon_fd PRODUCER on port $PORT ..." +UMF_LOG=$UMF_LOG_VAL ./umf_example_ipc_ipcapi_producer $PORT diff --git a/examples/ipc_ipcapi/ipc_ipcapi_consumer.c b/examples/ipc_ipcapi/ipc_ipcapi_consumer.c index 05596bd161..713fae2923 100644 --- a/examples/ipc_ipcapi/ipc_ipcapi_consumer.c +++ b/examples/ipc_ipcapi/ipc_ipcapi_consumer.c @@ -5,12 +5,20 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#ifdef _WIN32 +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#include +typedef int socklen_t; +typedef SSIZE_T ssize_t; +#else #include +#include +#include +#endif + #include #include #include -#include -#include #include #include @@ -27,25 +35,40 @@ "shared memory!" int consumer_connect_to_producer(int port) { +#ifdef _WIN32 + WSADATA wsaData; + SOCKET producer_socket, consumer_socket; +#else + int producer_socket = -1; + int consumer_socket = -1; +#endif + struct sockaddr_in consumer_addr; struct sockaddr_in producer_addr; + int producer_addr_len; - int producer_socket = -1; - int consumer_socket = -1; int ret = -1; +#ifdef _WIN32 + // initialize Winsock + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + fprintf(stderr, "Failed. Error Code : %d", WSAGetLastError()); + return -1; + } +#endif + // create a socket consumer_socket = socket(AF_INET, SOCK_STREAM, 0); if (consumer_socket < 0) { fprintf(stderr, "[consumer] ERROR: creating socket failed\n"); - return -1; + goto err_WSA_cleanup; } fprintf(stderr, "[consumer] Socket created\n"); // set the IP address and the port consumer_addr.sin_family = AF_INET; - consumer_addr.sin_port = htons(port); + consumer_addr.sin_port = htons((u_short)port); consumer_addr.sin_addr.s_addr = inet_addr(INET_ADDR); // bind to the IP address and the port @@ -77,10 +100,19 @@ int consumer_connect_to_producer(int port) { fprintf(stderr, "[consumer] Producer connected at IP %s and port %i\n", inet_ntoa(producer_addr.sin_addr), ntohs(producer_addr.sin_port)); - ret = producer_socket; // success + ret = (int)producer_socket; // success err_close_consumer_socket: +#ifdef _WIN32 + closesocket(consumer_socket); +#else close(consumer_socket); +#endif + +err_WSA_cleanup: +#ifdef _WIN32 + WSACleanup(); +#endif return ret; } @@ -152,8 +184,8 @@ int main(int argc, char *argv[]) { len, size_IPC_handle); // send received size to the producer as a confirmation - recv_len = - send(producer_socket, &size_IPC_handle, sizeof(size_IPC_handle), 0); + recv_len = send(producer_socket, (BYTE *)&size_IPC_handle, + sizeof(size_IPC_handle), 0); if (recv_len < 0) { fprintf(stderr, "[consumer] ERROR: sending confirmation failed\n"); goto err_close_producer_socket; diff --git a/examples/ipc_ipcapi/ipc_ipcapi_producer.c b/examples/ipc_ipcapi/ipc_ipcapi_producer.c index fcb73650f2..1ade019769 100644 --- a/examples/ipc_ipcapi/ipc_ipcapi_producer.c +++ b/examples/ipc_ipcapi/ipc_ipcapi_producer.c @@ -5,12 +5,20 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#ifdef _WIN32 +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#include +typedef int socklen_t; +typedef SSIZE_T ssize_t; +#else #include +#include +#include +#endif + #include #include #include -#include -#include #include #include @@ -22,21 +30,35 @@ #define SIZE_SHM 1024 int producer_connect_to_consumer(int port) { - struct sockaddr_in consumer_addr; +#ifdef _WIN32 + WSADATA wsaData; + SOCKET producer_socket; +#else int producer_socket = -1; +#endif + + struct sockaddr_in consumer_addr; + +#ifdef _WIN32 + // initialize Winsock + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + fprintf(stderr, "Failed. Error Code : %d", WSAGetLastError()); + return -1; + } +#endif // create a producer socket producer_socket = socket(AF_INET, SOCK_STREAM, 0); if (producer_socket < 0) { fprintf(stderr, "[producer] ERROR: Unable to create socket\n"); - return -1; + goto err_WSA_cleanup; } fprintf(stderr, "[producer] Socket created\n"); // set IP address and port the same as for the consumer consumer_addr.sin_family = AF_INET; - consumer_addr.sin_port = htons(port); + consumer_addr.sin_port = htons((u_short)port); consumer_addr.sin_addr.s_addr = inet_addr(INET_ADDR); // send connection request to the consumer @@ -49,10 +71,19 @@ int producer_connect_to_consumer(int port) { fprintf(stderr, "[producer] Connected to the consumer\n"); - return producer_socket; // success + return (int)producer_socket; // success err_close_producer_socket_connect: +#ifdef _WIN32 + closesocket(producer_socket); +#else close(producer_socket); +#endif + +err_WSA_cleanup: +#ifdef _WIN32 + WSACleanup(); +#endif return -1; } @@ -131,8 +162,8 @@ int main(int argc, char *argv[]) { } // send a size of the IPC_handle to the consumer - ssize_t len = - send(producer_socket, &IPC_handle_size, sizeof(IPC_handle_size), 0); + ssize_t len = (ssize_t)send(producer_socket, (const char *)&IPC_handle_size, + sizeof(IPC_handle_size), 0); if (len < 0) { fprintf(stderr, "[producer] ERROR: unable to send the message\n"); goto err_close_producer_socket; @@ -147,7 +178,7 @@ int main(int argc, char *argv[]) { memset(recv_buffer, 0, sizeof(recv_buffer)); // receive the consumer's confirmation - len = recv(producer_socket, recv_buffer, sizeof(recv_buffer), 0); + len = (ssize_t)recv(producer_socket, recv_buffer, sizeof(recv_buffer), 0); if (len < 0) { fprintf(stderr, "[producer] ERROR: error while receiving the " "confirmation from the consumer\n"); @@ -169,7 +200,8 @@ int main(int argc, char *argv[]) { } // send the IPC_handle of IPC_handle_size to the consumer - len = send(producer_socket, IPC_handle, IPC_handle_size, 0); + len = (ssize_t)send(producer_socket, (const char *)IPC_handle, + (int)IPC_handle_size, 0); if (len < 0) { fprintf(stderr, "[producer] ERROR: unable to send the message\n"); goto err_close_producer_socket; @@ -221,7 +253,11 @@ int main(int argc, char *argv[]) { } err_close_producer_socket: +#ifdef _WIN32 + closesocket(producer_socket); +#else close(producer_socket); +#endif err_PutIPCHandle: umf_result = umfPutIPCHandle(IPC_handle); diff --git a/src/provider/provider_level_zero.c b/src/provider/provider_level_zero.c index 19a0dfb0da..527f583891 100644 --- a/src/provider/provider_level_zero.c +++ b/src/provider/provider_level_zero.c @@ -138,13 +138,13 @@ static umf_result_t ze_memory_provider_initialize(void *params, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - if ((ze_params->memory_type == UMF_MEMORY_TYPE_HOST) == - (bool)ze_params->level_zero_device_handle) { + if ((ze_params->memory_type == UMF_MEMORY_TYPE_HOST) && + (ze_params->level_zero_device_handle != NULL)) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - if ((bool)ze_params->resident_device_count != - (bool)ze_params->resident_device_handles) { + if ((ze_params->resident_device_count > 0) != + (ze_params->resident_device_handles != NULL)) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f486b6e157..c6d21c4aa1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -340,23 +340,35 @@ function(add_umf_ipc_test) endif() endfunction() +if(NOT UMF_DISABLE_HWLOC) + +if(WINDOWS) +set(UMF_IPC_LIBS ws2_32) +endif() + + build_umf_test( + NAME + ipc_os_prov_consumer + SRCS + ipc_os_prov_consumer.c + common/ipc_common.c + common/ipc_os_prov_common.c + LIBS + ${UMF_IPC_LIBS}) + build_umf_test( + NAME + ipc_os_prov_producer + SRCS + ipc_os_prov_producer.c + common/ipc_common.c + common/ipc_os_prov_common.c + LIBS + ${UMF_IPC_LIBS}) + add_umf_ipc_test(TEST ipc_os_prov_anon_fd) +endif() + if(LINUX) if(NOT UMF_DISABLE_HWLOC) - build_umf_test( - NAME - ipc_os_prov_consumer - SRCS - ipc_os_prov_consumer.c - common/ipc_common.c - common/ipc_os_prov_common.c) - build_umf_test( - NAME - ipc_os_prov_producer - SRCS - ipc_os_prov_producer.c - common/ipc_common.c - common/ipc_os_prov_common.c) - add_umf_ipc_test(TEST ipc_os_prov_anon_fd) add_umf_ipc_test(TEST ipc_os_prov_shm) build_umf_test( @@ -482,12 +494,12 @@ if(LINUX ) endif() - if(LINUX AND UMF_POOL_SCALABLE_ENABLED) + if(UMF_POOL_SCALABLE_ENABLED) set(EXAMPLES ${EXAMPLES} ipc_ipcapi) else() message( STATUS - "IPC examples with UMF pool API are supported on Linux with TBB installed only - skipping" + "IPC examples with UMF pool API are supported with TBB installed only - skipping" ) endif() diff --git a/test/common/ipc_common.c b/test/common/ipc_common.c index 18ce263d86..76f1160169 100644 --- a/test/common/ipc_common.c +++ b/test/common/ipc_common.c @@ -5,12 +5,20 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#ifdef _WIN32 +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#include +typedef int socklen_t; +typedef SSIZE_T ssize_t; +#else #include +#include +#include +#endif + #include #include #include -#include -#include #include "ipc_common.h" @@ -48,25 +56,40 @@ Generally communication between the producer and the consumer looks like: */ int consumer_connect(int port) { + +#ifdef _WIN32 + WSADATA wsaData; + SOCKET producer_socket, consumer_socket; +#else + int producer_socket = -1; + int consumer_socket = -1; +#endif + struct sockaddr_in consumer_addr; struct sockaddr_in producer_addr; int producer_addr_len; - int producer_socket = -1; - int consumer_socket = -1; int ret = -1; +#ifdef _WIN32 + // initialize Winsock + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + fprintf(stderr, "Failed. Error Code : %d", WSAGetLastError()); + return -1; + } +#endif + // create a socket consumer_socket = socket(AF_INET, SOCK_STREAM, 0); if (consumer_socket < 0) { fprintf(stderr, "[consumer] ERROR: creating socket failed\n"); - return -1; + goto err_WSA_cleanup; } fprintf(stderr, "[consumer] Socket created\n"); // set the IP address and the port consumer_addr.sin_family = AF_INET; - consumer_addr.sin_port = htons(port); + consumer_addr.sin_port = htons((u_short)port); consumer_addr.sin_addr.s_addr = inet_addr(INET_ADDR); // bind to the IP address and the port @@ -96,12 +119,22 @@ int consumer_connect(int port) { } fprintf(stderr, "[consumer] Producer connected at IP %s and port %i\n", - inet_ntoa(producer_addr.sin_addr), ntohs(producer_addr.sin_port)); + inet_ntoa(producer_addr.sin_addr), + (int)ntohs(producer_addr.sin_port)); - ret = producer_socket; // success + ret = (int)producer_socket; // success err_close_consumer_socket: +#ifdef _WIN32 + closesocket(consumer_socket); +#else close(consumer_socket); +#endif + +err_WSA_cleanup: +#ifdef _WIN32 + WSACleanup(); +#endif return ret; } @@ -110,7 +143,13 @@ int run_consumer(int port, umf_memory_provider_ops_t *provider_ops, void *provider_params, memcopy_callback_t memcopy_callback, void *memcopy_ctx) { char consumer_message[MSG_SIZE]; + +#ifdef _WIN32 + SOCKET producer_socket; +#else int producer_socket = -1; +#endif + int ret = -1; umf_memory_provider_handle_t provider = NULL; umf_result_t umf_result = UMF_RESULT_ERROR_UNKNOWN; @@ -149,7 +188,8 @@ int run_consumer(int port, umf_memory_provider_ops_t *provider_ops, } // receive a producer's message - ssize_t recv_len = recv(producer_socket, recv_buffer, IPC_handle_size, 0); + ssize_t recv_len = + (ssize_t)recv(producer_socket, recv_buffer, (int)IPC_handle_size, 0); if (recv_len < 0) { fprintf(stderr, "[consumer] ERROR: recv() failed\n"); goto err_close_producer_socket; @@ -182,8 +222,8 @@ int run_consumer(int port, umf_memory_provider_ops_t *provider_ops, strcpy(consumer_message, "SKIP"); // send the SKIP response to the producer - send(producer_socket, consumer_message, strlen(consumer_message) + 1, - 0); + send(producer_socket, consumer_message, + (int)strlen(consumer_message) + 1, 0); goto err_close_producer_socket; } @@ -217,8 +257,8 @@ int run_consumer(int port, umf_memory_provider_ops_t *provider_ops, strcpy(consumer_message, CONSUMER_MSG); // send response to the producer - if (send(producer_socket, consumer_message, strlen(consumer_message) + 1, - 0) < 0) { + if (send(producer_socket, consumer_message, + (int)strlen(consumer_message) + 1, 0) < 0) { fprintf(stderr, "[consumer] ERROR: send() failed\n"); goto err_closeIPCHandle; } @@ -239,7 +279,11 @@ int run_consumer(int port, umf_memory_provider_ops_t *provider_ops, "[consumer] Closed the IPC handle received from the producer\n"); err_close_producer_socket: +#ifdef _WIN32 + closesocket(producer_socket); +#else close(producer_socket); +#endif err_umfMemoryProviderDestroy: umfMemoryProviderDestroy(provider); @@ -258,20 +302,34 @@ int run_consumer(int port, umf_memory_provider_ops_t *provider_ops, int producer_connect(int port) { struct sockaddr_in consumer_addr; + +#ifdef _WIN32 + WSADATA wsaData; + SOCKET producer_socket; +#else int producer_socket = -1; +#endif + +#ifdef _WIN32 + // initialize Winsock + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + fprintf(stderr, "Failed. Error Code : %d", WSAGetLastError()); + return -1; + } +#endif // create a producer socket producer_socket = socket(AF_INET, SOCK_STREAM, 0); if (producer_socket < 0) { fprintf(stderr, "[producer] ERROR: Unable to create socket\n"); - return -1; + goto err_WSA_cleanup; } fprintf(stderr, "[producer] Socket created\n"); // set IP address and port the same as for the consumer consumer_addr.sin_family = AF_INET; - consumer_addr.sin_port = htons(port); + consumer_addr.sin_port = htons((u_short)port); consumer_addr.sin_addr.s_addr = inet_addr(INET_ADDR); // send connection request to the consumer @@ -284,10 +342,19 @@ int producer_connect(int port) { fprintf(stderr, "[producer] Connected to the consumer\n"); - return producer_socket; // success + return (int)producer_socket; // success err_close_producer_socket_connect: +#ifdef _WIN32 + closesocket(producer_socket); +#else close(producer_socket); +#endif + +err_WSA_cleanup: +#ifdef _WIN32 + WSACleanup(); +#endif return -1; } @@ -389,7 +456,7 @@ int run_producer(int port, umf_memory_provider_ops_t *provider_ops, } // send the IPC_handle of IPC_handle_size to the consumer - if (send(producer_socket, IPC_handle, IPC_handle_size, 0) < 0) { + if (send(producer_socket, IPC_handle, (int)IPC_handle_size, 0) < 0) { fprintf(stderr, "[producer] ERROR: unable to send the message\n"); goto err_close_producer_socket; } @@ -442,7 +509,11 @@ int run_producer(int port, umf_memory_provider_ops_t *provider_ops, } err_close_producer_socket: +#ifdef _WIN32 + closesocket(producer_socket); +#else close(producer_socket); +#endif err_PutIPCHandle: umf_result = umfMemoryProviderPutIPCHandle(provider, IPC_handle);