diff --git a/CMakeLists.txt b/CMakeLists.txt index ad8a8664..22923605 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,6 +134,8 @@ if(USE_LAPACK) endif() endif() +find_package(Threads REQUIRED) + if(USE_OPENMP) find_package(OpenMP) if(OpenMP_C_FOUND) @@ -262,7 +264,8 @@ target_compile_definitions(${${PROJECT_NAME}_DIRECT} PRIVATE ${COMPILER_OPTS}) target_link_libraries(${${PROJECT_NAME}_DIRECT} PRIVATE ${LAPACK_LINK_LIBRARIES} $<$>:m> - $<$:OpenMP::OpenMP_C>) + $<$:OpenMP::OpenMP_C> + Threads::Threads) set_target_properties( ${${PROJECT_NAME}_DIRECT} @@ -306,7 +309,8 @@ target_compile_definitions(${${PROJECT_NAME}_INDIRECT} PRIVATE ${COMPILER_OPTS} target_link_libraries(${${PROJECT_NAME}_INDIRECT} PRIVATE $<$>:m> ${LAPACK_LINK_LIBRARIES} - $<$:OpenMP::OpenMP_C>) + $<$:OpenMP::OpenMP_C> + Threads::Threads) set_target_properties( ${${PROJECT_NAME}_INDIRECT} @@ -352,7 +356,8 @@ if(USE_LAPACK) target_link_libraries(${${PROJECT_NAME}_DENSE} PRIVATE ${LAPACK_LINK_LIBRARIES} $<$>:m> - $<$:OpenMP::OpenMP_C>) + $<$:OpenMP::OpenMP_C> + Threads::Threads) set_target_properties( ${${PROJECT_NAME}_DENSE} @@ -411,7 +416,7 @@ if(DEFINED ENV{MKLROOT}) mkl_gnu_thread mkl_core gomp - pthread + Threads::Threads dl) set_target_properties( @@ -475,7 +480,8 @@ if(USE_CUDSS) target_link_libraries( ${${PROJECT_NAME}_CUDSS} PRIVATE CUDA::cudart cudss $<$>:m> - ${LAPACK_LINK_LIBRARIES}) + ${LAPACK_LINK_LIBRARIES} + Threads::Threads) set_target_properties( ${${PROJECT_NAME}_CUDSS} diff --git a/scs.mk b/scs.mk index 7bb54e16..4b7ce223 100644 --- a/scs.mk +++ b/scs.mk @@ -41,7 +41,7 @@ SHARED = dll SONAME = -soname else # we're on a linux system, use accurate timer provided by clock_gettime() -LDFLAGS += -lm -lrt +LDFLAGS += -lm -lrt -lpthread SHARED = so SONAME = -soname endif diff --git a/src/ctrlc.c b/src/ctrlc.c index 032b22de..f41f1754 100644 --- a/src/ctrlc.c +++ b/src/ctrlc.c @@ -33,49 +33,92 @@ int scs_is_interrupted(void) { #elif (defined _WIN32 || _WIN64 || defined _WINDLL) #include -static int int_detected; +static volatile LONG int_detected; +static INIT_ONCE ctrlc_init_once = INIT_ONCE_STATIC_INIT; +static CRITICAL_SECTION ctrlc_cs; +static int listener_count = 0; + +static BOOL CALLBACK init_ctrlc_cs(PINIT_ONCE once, PVOID param, PVOID *ctx) { + (void)once; + (void)param; + (void)ctx; + InitializeCriticalSection(&ctrlc_cs); + return TRUE; +} + static BOOL WINAPI scs_handle_ctrlc(DWORD dwCtrlType) { if (dwCtrlType != CTRL_C_EVENT) { return FALSE; } - int_detected = 1; + InterlockedExchange(&int_detected, 1); return TRUE; } void scs_start_interrupt_listener(void) { - int_detected = 0; - SetConsoleCtrlHandler(scs_handle_ctrlc, TRUE); + InitOnceExecuteOnce(&ctrlc_init_once, init_ctrlc_cs, NULL, NULL); + EnterCriticalSection(&ctrlc_cs); + if (listener_count == 0) { + InterlockedExchange(&int_detected, 0); + SetConsoleCtrlHandler(scs_handle_ctrlc, TRUE); + } + listener_count++; + LeaveCriticalSection(&ctrlc_cs); } void scs_end_interrupt_listener(void) { - SetConsoleCtrlHandler(scs_handle_ctrlc, FALSE); + InitOnceExecuteOnce(&ctrlc_init_once, init_ctrlc_cs, NULL, NULL); + EnterCriticalSection(&ctrlc_cs); + if (listener_count > 0) { + listener_count--; + if (listener_count == 0) { + SetConsoleCtrlHandler(scs_handle_ctrlc, FALSE); + } + } + LeaveCriticalSection(&ctrlc_cs); } int scs_is_interrupted(void) { - return int_detected; + return (int)InterlockedCompareExchange(&int_detected, 0, 0); } #else /* Unix */ #include -static int int_detected; -struct sigaction oact; +#include + +static volatile sig_atomic_t int_detected; +static struct sigaction oact; +static pthread_mutex_t ctrlc_mutex = PTHREAD_MUTEX_INITIALIZER; +static int listener_count = 0; + static void scs_handle_ctrlc(int dummy) { int_detected = dummy ? dummy : -1; } void scs_start_interrupt_listener(void) { - struct sigaction act; - int_detected = 0; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - act.sa_handler = scs_handle_ctrlc; - sigaction(SIGINT, &act, &oact); + pthread_mutex_lock(&ctrlc_mutex); + if (listener_count == 0) { + struct sigaction act; + int_detected = 0; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + act.sa_handler = scs_handle_ctrlc; + sigaction(SIGINT, &act, &oact); + } + listener_count++; + pthread_mutex_unlock(&ctrlc_mutex); } void scs_end_interrupt_listener(void) { - struct sigaction act; - sigaction(SIGINT, &oact, &act); + pthread_mutex_lock(&ctrlc_mutex); + if (listener_count > 0) { + listener_count--; + if (listener_count == 0) { + struct sigaction act; + sigaction(SIGINT, &oact, &act); + } + } + pthread_mutex_unlock(&ctrlc_mutex); } int scs_is_interrupted(void) { diff --git a/src/scs.c b/src/scs.c index 551ab51b..4144cbd9 100644 --- a/src/scs.c +++ b/src/scs.c @@ -1130,7 +1130,6 @@ static scs_int update_scale(ScsWork *w, const ScsCone *k, scs_int iter) { ScsWork *scs_init(const ScsData *d, const ScsCone *k, const ScsSettings *stgs) { ScsWork *w; SCS(timer) init_timer; - scs_start_interrupt_listener(); if (!d || !k) { scs_printf("ERROR: Missing ScsData or ScsCone input\n"); return SCS_NULL; @@ -1141,6 +1140,7 @@ ScsWork *scs_init(const ScsData *d, const ScsCone *k, const ScsSettings *stgs) { return SCS_NULL; } #endif + scs_start_interrupt_listener(); #if VERBOSITY > 0 scs_printf("size of scs_int = %lu, size of scs_float = %lu\n", sizeof(scs_int), sizeof(scs_float));