From 93921b1c81cf218622525b49e35b8d99182fec22 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 3 Jul 2020 10:09:12 +0200 Subject: [PATCH] - HAL: added thread/semaphore support for MacOS --- hal/CMakeLists.txt | 375 ++++++++++++++++---------------- hal/ethernet/bsd/ethernet_bsd.c | 3 +- hal/thread/macos/thread_macos.c | 124 +++++++++++ 3 files changed, 318 insertions(+), 184 deletions(-) create mode 100644 hal/thread/macos/thread_macos.c diff --git a/hal/CMakeLists.txt b/hal/CMakeLists.txt index 14103988..b50f9937 100644 --- a/hal/CMakeLists.txt +++ b/hal/CMakeLists.txt @@ -1,183 +1,192 @@ -cmake_minimum_required(VERSION 2.8) - -# automagically detect if we should cross-compile -if(DEFINED ENV{TOOLCHAIN}) - set(CMAKE_C_COMPILER $ENV{TOOLCHAIN}gcc) - set(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN}g++) - set(CMAKE_AR "$ENV{TOOLCHAIN}ar" CACHE FILEPATH "CW archiver" FORCE) -endif() - -project(hal) - -set(LIBHAL_VERSION_MAJOR "2") -set(LIBHAL_VERSION_MINOR "0") -set(LIBHAL_VERSION_PATCH "0") - -# feature checks -include(CheckLibraryExists) -check_library_exists(rt clock_gettime "time.h" CONFIG_SYSTEM_HAS_CLOCK_GETTIME) - -# check if we are on a little or a big endian -include (TestBigEndian) -test_big_endian(PLATFORM_IS_BIGENDIAN) - -if(WIN32) - -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib") -message("Found winpcap -> compile ethernet HAL layer (required for GOOSE/SV support)") -set(WITH_WPCAP 1) -include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Include") -else() -message("winpcap not found -> skip ethernet HAL layer (no GOOSE/SV support)") -endif() - -endif(WIN32) - -include_directories( - ${CMAKE_CURRENT_LIST_DIR}/inc -) - -set (libhal_linux_SRCS - ${CMAKE_CURRENT_LIST_DIR}/socket/linux/socket_linux.c - ${CMAKE_CURRENT_LIST_DIR}/ethernet/linux/ethernet_linux.c - ${CMAKE_CURRENT_LIST_DIR}/thread/linux/thread_linux.c - ${CMAKE_CURRENT_LIST_DIR}/filesystem/linux/file_provider_linux.c - ${CMAKE_CURRENT_LIST_DIR}/time/unix/time.c - ${CMAKE_CURRENT_LIST_DIR}/serial/linux/serial_port_linux.c - ${CMAKE_CURRENT_LIST_DIR}/memory/lib_memory.c -) - -set (libhal_windows_SRCS - ${CMAKE_CURRENT_LIST_DIR}/socket/win32/socket_win32.c - ${CMAKE_CURRENT_LIST_DIR}/thread/win32/thread_win32.c - ${CMAKE_CURRENT_LIST_DIR}/filesystem/win32/file_provider_win32.c - ${CMAKE_CURRENT_LIST_DIR}/time/win32/time.c - ${CMAKE_CURRENT_LIST_DIR}/serial/win32/serial_port_win32.c - ${CMAKE_CURRENT_LIST_DIR}/memory/lib_memory.c -) - -if(WITH_WPCAP) -set (libhal_windows_SRCS ${libhal_windows_SRCS} - ${CMAKE_CURRENT_LIST_DIR}/ethernet/win32/ethernet_win32.c -) -endif(WITH_WPCAP) - -set (libhal_bsd_SRCS - ${CMAKE_CURRENT_LIST_DIR}/socket/bsd/socket_bsd.c - ${CMAKE_CURRENT_LIST_DIR}/ethernet/bsd/ethernet_bsd.c - ${CMAKE_CURRENT_LIST_DIR}/thread/bsd/thread_bsd.c - ${CMAKE_CURRENT_LIST_DIR}/filesystem/linux/file_provider_linux.c - ${CMAKE_CURRENT_LIST_DIR}/time/unix/time.c - ${CMAKE_CURRENT_LIST_DIR}/memory/lib_memory.c -) - -IF(WIN32) - -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib") -message("Found winpcap -> can compile with GOOSE support") -set(WITH_WPCAP 1) -endif() - -set (libhal_SRCS - ${libhal_windows_SRCS} -) - -IF(MSVC) -set_source_files_properties(${libhal_SRCS} - PROPERTIES LANGUAGE CXX) -ENDIF() - -ELSEIF(UNIX) -IF(APPLE) -set (libhal_SRCS - ${libhal_bsd_SRCS} -) -ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") -set (libhal_SRCS - ${libhal_bsd_SRCS} -) -ELSE() -set (libhal_SRCS - ${libhal_linux_SRCS} -) -ENDIF(APPLE) -ENDIF(WIN32) - -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" ) -#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC" ) - -if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../third_party/mbedtls/mbedtls-2.16) -message("Found mbedtls -> can compile with TLS support") -set(WITH_MBEDTLS 1) -endif(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../third_party/mbedtls/mbedtls-2.16) - -if(WITH_MBEDTLS) -include_directories( - ${CMAKE_CURRENT_LIST_DIR}/tls/mbedtls - ${CMAKE_CURRENT_LIST_DIR}/../third_party/mbedtls/mbedtls-2.16/include -) - -file(GLOB tls_SRCS ${CMAKE_CURRENT_LIST_DIR}/../third_party/mbedtls/mbedtls-2.16/library/*.c) - -add_definitions(-DMBEDTLS_CONFIG_FILE="mbedtls_config.h") - -set (libhal_SRCS ${libhal_SRCS} - ${CMAKE_CURRENT_LIST_DIR}/tls/mbedtls/tls_mbedtls.c -) - -IF(MSVC) -set_source_files_properties(${libhal_SRCS} - PROPERTIES LANGUAGE CXX) -ENDIF() - -list (APPEND libhal_SRCS ${tls_SRCS}) - -endif(WITH_MBEDTLS) - -add_library (hal STATIC ${libhal_SRCS}) - -add_library (hal-shared STATIC ${libhal_SRCS}) - -target_compile_definitions(hal-shared PRIVATE EXPORT_FUNCTIONS_FOR_DLL) - -SET_TARGET_PROPERTIES(hal-shared PROPERTIES - COMPILE_FLAGS "-fPIC" -) - -IF(UNIX) - IF (CONFIG_SYSTEM_HAS_CLOCK_GETTIME) - target_link_libraries (hal - -lpthread - -lrt - ) - ELSE () - target_link_libraries (hal - -lpthread - ) - ENDIF (CONFIG_SYSTEM_HAS_CLOCK_GETTIME) -ENDIF(UNIX) -IF(MINGW) - target_link_libraries(hal ws2_32 iphlpapi) -ENDIF(MINGW) - -iF(WITH_WPCAP) -target_link_libraries(hal - ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib - ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/packet.lib -) -ENDIF(WITH_WPCAP) - -set(BINDIR "bin") -set(LIBDIR "lib") -if(UNIX) - # GNUInstallDirs is required for Debian multiarch - include(GNUInstallDirs) - set(LIBDIR ${CMAKE_INSTALL_LIBDIR}) - set(BINDIR ${CMAKE_INSTALL_BINDIR}) -endif() - -install (TARGETS hal hal-shared - RUNTIME DESTINATION ${BINDIR} COMPONENT Applications - ARCHIVE DESTINATION ${LIBDIR} COMPONENT Libraries - LIBRARY DESTINATION ${LIBDIR} COMPONENT Libraries -) +cmake_minimum_required(VERSION 2.8) + +# automagically detect if we should cross-compile +if(DEFINED ENV{TOOLCHAIN}) + set(CMAKE_C_COMPILER $ENV{TOOLCHAIN}gcc) + set(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN}g++) + set(CMAKE_AR "$ENV{TOOLCHAIN}ar" CACHE FILEPATH "CW archiver" FORCE) +endif() + +project(hal) + +set(LIBHAL_VERSION_MAJOR "2") +set(LIBHAL_VERSION_MINOR "0") +set(LIBHAL_VERSION_PATCH "0") + +# feature checks +include(CheckLibraryExists) +check_library_exists(rt clock_gettime "time.h" CONFIG_SYSTEM_HAS_CLOCK_GETTIME) + +# check if we are on a little or a big endian +include (TestBigEndian) +test_big_endian(PLATFORM_IS_BIGENDIAN) + +if(WIN32) + +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib") +message("Found winpcap -> compile ethernet HAL layer (required for GOOSE/SV support)") +set(WITH_WPCAP 1) +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Include") +else() +message("winpcap not found -> skip ethernet HAL layer (no GOOSE/SV support)") +endif() + +endif(WIN32) + +include_directories( + ${CMAKE_CURRENT_LIST_DIR}/inc +) + +set (libhal_linux_SRCS + ${CMAKE_CURRENT_LIST_DIR}/socket/linux/socket_linux.c + ${CMAKE_CURRENT_LIST_DIR}/ethernet/linux/ethernet_linux.c + ${CMAKE_CURRENT_LIST_DIR}/thread/linux/thread_linux.c + ${CMAKE_CURRENT_LIST_DIR}/filesystem/linux/file_provider_linux.c + ${CMAKE_CURRENT_LIST_DIR}/time/unix/time.c + ${CMAKE_CURRENT_LIST_DIR}/serial/linux/serial_port_linux.c + ${CMAKE_CURRENT_LIST_DIR}/memory/lib_memory.c +) + +set (libhal_windows_SRCS + ${CMAKE_CURRENT_LIST_DIR}/socket/win32/socket_win32.c + ${CMAKE_CURRENT_LIST_DIR}/thread/win32/thread_win32.c + ${CMAKE_CURRENT_LIST_DIR}/filesystem/win32/file_provider_win32.c + ${CMAKE_CURRENT_LIST_DIR}/time/win32/time.c + ${CMAKE_CURRENT_LIST_DIR}/serial/win32/serial_port_win32.c + ${CMAKE_CURRENT_LIST_DIR}/memory/lib_memory.c +) + +if(WITH_WPCAP) +set (libhal_windows_SRCS ${libhal_windows_SRCS} + ${CMAKE_CURRENT_LIST_DIR}/ethernet/win32/ethernet_win32.c +) +endif(WITH_WPCAP) + +set (libhal_bsd_SRCS + ${CMAKE_CURRENT_LIST_DIR}/socket/bsd/socket_bsd.c + ${CMAKE_CURRENT_LIST_DIR}/ethernet/bsd/ethernet_bsd.c + ${CMAKE_CURRENT_LIST_DIR}/thread/bsd/thread_macos.c + ${CMAKE_CURRENT_LIST_DIR}/filesystem/linux/file_provider_linux.c + ${CMAKE_CURRENT_LIST_DIR}/time/unix/time.c + ${CMAKE_CURRENT_LIST_DIR}/memory/lib_memory.c +) + +set (libhal_macos_SRCS + ${CMAKE_CURRENT_LIST_DIR}/socket/bsd/socket_bsd.c + ${CMAKE_CURRENT_LIST_DIR}/ethernet/bsd/ethernet_bsd.c + ${CMAKE_CURRENT_LIST_DIR}/thread/macos/thread_macos.c + ${CMAKE_CURRENT_LIST_DIR}/filesystem/linux/file_provider_linux.c + ${CMAKE_CURRENT_LIST_DIR}/time/unix/time.c + ${CMAKE_CURRENT_LIST_DIR}/memory/lib_memory.c +) + +IF(WIN32) + +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib") +message("Found winpcap -> can compile with GOOSE support") +set(WITH_WPCAP 1) +endif() + +set (libhal_SRCS + ${libhal_windows_SRCS} +) + +IF(MSVC) +set_source_files_properties(${libhal_SRCS} + PROPERTIES LANGUAGE CXX) +ENDIF() + +ELSEIF(UNIX) +IF(APPLE) +set (libhal_SRCS + ${libhal_macos_SRCS} +) +ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") +set (libhal_SRCS + ${libhal_bsd_SRCS} +) +ELSE() +set (libhal_SRCS + ${libhal_linux_SRCS} +) +ENDIF(APPLE) +ENDIF(WIN32) + +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" ) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC" ) + +if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../third_party/mbedtls/mbedtls-2.16) +message("Found mbedtls -> can compile with TLS support") +set(WITH_MBEDTLS 1) +endif(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../third_party/mbedtls/mbedtls-2.16) + +if(WITH_MBEDTLS) +include_directories( + ${CMAKE_CURRENT_LIST_DIR}/tls/mbedtls + ${CMAKE_CURRENT_LIST_DIR}/../third_party/mbedtls/mbedtls-2.16/include +) + +file(GLOB tls_SRCS ${CMAKE_CURRENT_LIST_DIR}/../third_party/mbedtls/mbedtls-2.16/library/*.c) + +add_definitions(-DMBEDTLS_CONFIG_FILE="mbedtls_config.h") + +set (libhal_SRCS ${libhal_SRCS} + ${CMAKE_CURRENT_LIST_DIR}/tls/mbedtls/tls_mbedtls.c +) + +IF(MSVC) +set_source_files_properties(${libhal_SRCS} + PROPERTIES LANGUAGE CXX) +ENDIF() + +list (APPEND libhal_SRCS ${tls_SRCS}) + +endif(WITH_MBEDTLS) + +add_library (hal STATIC ${libhal_SRCS}) + +add_library (hal-shared STATIC ${libhal_SRCS}) + +target_compile_definitions(hal-shared PRIVATE EXPORT_FUNCTIONS_FOR_DLL) + +SET_TARGET_PROPERTIES(hal-shared PROPERTIES + COMPILE_FLAGS "-fPIC" +) + +IF(UNIX) + IF (CONFIG_SYSTEM_HAS_CLOCK_GETTIME) + target_link_libraries (hal + -lpthread + -lrt + ) + ELSE () + target_link_libraries (hal + -lpthread + ) + ENDIF (CONFIG_SYSTEM_HAS_CLOCK_GETTIME) +ENDIF(UNIX) +IF(MINGW) + target_link_libraries(hal ws2_32 iphlpapi) +ENDIF(MINGW) + +iF(WITH_WPCAP) +target_link_libraries(hal + ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib + ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/packet.lib +) +ENDIF(WITH_WPCAP) + +set(BINDIR "bin") +set(LIBDIR "lib") +if(UNIX) + # GNUInstallDirs is required for Debian multiarch + include(GNUInstallDirs) + set(LIBDIR ${CMAKE_INSTALL_LIBDIR}) + set(BINDIR ${CMAKE_INSTALL_BINDIR}) +endif() + +install (TARGETS hal hal-shared + RUNTIME DESTINATION ${BINDIR} COMPONENT Applications + ARCHIVE DESTINATION ${LIBDIR} COMPONENT Libraries + LIBRARY DESTINATION ${LIBDIR} COMPONENT Libraries +) diff --git a/hal/ethernet/bsd/ethernet_bsd.c b/hal/ethernet/bsd/ethernet_bsd.c index 635a20cd..6b51ea44 100644 --- a/hal/ethernet/bsd/ethernet_bsd.c +++ b/hal/ethernet/bsd/ethernet_bsd.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "lib_memory.h" #include "hal_ethernet.h" @@ -390,7 +391,7 @@ Ethernet_receivePacket(EthernetSocket self, uint8_t* buffer, int bufferSize) /* Check if the target buffer is big enough to hold the received ethernet frame. */ if ((unsigned int) bufferSize >= header->bh_caplen) { - /* Copy the frame to the target buffer. + /* Copy the frame to the target buffer. */ memcpy(buffer, self->bpfPositon + header->bh_hdrlen, header->bh_caplen); /* Move the read pointer to the next ethernet frame header WORD ALIGNED (Took me a while to find that out). */ diff --git a/hal/thread/macos/thread_macos.c b/hal/thread/macos/thread_macos.c new file mode 100644 index 00000000..e51035d7 --- /dev/null +++ b/hal/thread/macos/thread_macos.c @@ -0,0 +1,124 @@ +/** + * thread_macos.c + * + * Copyright 2013-2019 MZ Automation GmbH + * + * This file is part of Platform Abstraction Layer (libpal) + * for libiec61850, libmms, and lib60870. + */ + +/* + * NOTE: MacOS needs own thread layer because it doesn't support unnamed semaphores! + */ + +#include +#include +#include +#include +#include +#include +#include "hal_thread.h" +#include "lib_memory.h" + +struct sThread { + ThreadExecutionFunction function; + void* parameter; + pthread_t pthread; + int state; + bool autodestroy; +}; + +Semaphore +Semaphore_create(int initialValue) +{ + char tmpname[] = {"/tmp/libiec61850.XXXXXX"}; + mktemp(tmpname); + + Semaphore self = (Semaphore) sem_open(tmpname, O_CREAT, 0666, initialValue); + + if (self == SEM_FAILED) { + printf("ERROR: Failed to create semaphore (errno = %i)\n", errno); + } + + int ret = sem_unlink(tmpname); + + if (ret == -1) + printf("ERROR: Failed to unlink semaphore %s\n", tmpname); + + return self; +} + +/* Wait until semaphore value is more than zero. Then decrease the semaphore value. */ +void +Semaphore_wait(Semaphore self) +{ + sem_wait((sem_t*) self); +} + +void +Semaphore_post(Semaphore self) +{ + sem_post((sem_t*) self); +} + +void +Semaphore_destroy(Semaphore self) +{ + sem_close(self); +} + +Thread +Thread_create(ThreadExecutionFunction function, void* parameter, bool autodestroy) +{ + Thread thread = (Thread) GLOBAL_MALLOC(sizeof(struct sThread)); + + if (thread != NULL) { + thread->parameter = parameter; + thread->function = function; + thread->state = 0; + thread->autodestroy = autodestroy; + } + + return thread; +} + +static void* +destroyAutomaticThread(void* parameter) +{ + Thread thread = (Thread) parameter; + + thread->function(thread->parameter); + + GLOBAL_FREEMEM(thread); + + pthread_exit(NULL); +} + +void +Thread_start(Thread thread) +{ + if (thread->autodestroy == true) { + pthread_create(&thread->pthread, NULL, destroyAutomaticThread, thread); + pthread_detach(thread->pthread); + } + else + pthread_create(&thread->pthread, NULL, thread->function, thread->parameter); + + thread->state = 1; +} + +void +Thread_destroy(Thread thread) +{ + if (thread->state == 1) { + pthread_join(thread->pthread, NULL); + } + + GLOBAL_FREEMEM(thread); +} + +void +Thread_sleep(int millies) +{ + usleep(millies * 1000); +}