diff options
-rw-r--r-- | include/libssh/threads.h | 7 | ||||
-rw-r--r-- | src/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/threads/noop.c | 2 | ||||
-rw-r--r-- | src/threads/winlocks.c | 123 |
4 files changed, 137 insertions, 1 deletions
diff --git a/include/libssh/threads.h b/include/libssh/threads.h index 750793b2..e8ccf7be 100644 --- a/include/libssh/threads.h +++ b/include/libssh/threads.h @@ -35,6 +35,13 @@ #define SSH_MUTEX_STATIC_INIT PTHREAD_MUTEX_INITIALIZER #endif +#elif (defined _WIN32) || (defined _WIN64) + +#include <windows.h> +#include <winbase.h> +#define SSH_MUTEX CRITICAL_SECTION * +#define SSH_MUTEX_STATIC_INIT NULL + #else # define SSH_MUTEX void * diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c37ce4d3..6cf44158 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -173,6 +173,12 @@ if (CMAKE_USE_PTHREADS_INIT) threads/noop.c threads/pthread.c ) +elseif (CMAKE_USE_WIN32_THREADS_INIT) + set(libssh_SRCS + ${libssh_SRCS} + threads/noop.c + threads/winlocks.c + ) else() set(libssh_SRCS ${libssh_SRCS} diff --git a/src/threads/noop.c b/src/threads/noop.c index aad4934e..63aca1e7 100644 --- a/src/threads/noop.c +++ b/src/threads/noop.c @@ -47,7 +47,7 @@ static struct ssh_threads_callbacks_struct ssh_threads_noop = /* Threads interface implementation */ -#if !(HAVE_PTHREAD) +#if !(HAVE_PTHREAD) && !(defined _WIN32 || defined _WIN64) void ssh_mutex_lock(SSH_MUTEX *mutex) { (void) mutex; diff --git a/src/threads/winlocks.c b/src/threads/winlocks.c new file mode 100644 index 00000000..a1799531 --- /dev/null +++ b/src/threads/winlocks.c @@ -0,0 +1,123 @@ +/* + * This file is part of the SSH Library + * + * Copyright (c) 2018 by Anderson Toshiyuki Sasaki + * + * The SSH Library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the SSH Library; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#include "config.h" +#include "libssh/threads.h" +#include <libssh/callbacks.h> + +#include <windows.h> +#include <winbase.h> +#include <errno.h> + +static int ssh_winlock_mutex_init (void **priv) +{ + CRITICAL_SECTION *lock = malloc(sizeof(CRITICAL_SECTION)); + + if (lock == NULL) { + return ENOMEM; + } + + InitializeCriticalSection(lock); + + *priv = lock; + + return 0; +} + +static int ssh_winlock_mutex_destroy (void **lock) +{ + DeleteCriticalSection((CRITICAL_SECTION *) *lock); + free(*lock); + + return 0; +} + +static int ssh_winlock_mutex_lock (void **lock) +{ + EnterCriticalSection((CRITICAL_SECTION *) *lock); + return 0; +} + +static int ssh_winlock_mutex_unlock (void **lock) +{ + LeaveCriticalSection((CRITICAL_SECTION *) *lock); + return 0; +} + +static unsigned long ssh_winlock_thread_id (void) +{ + return GetCurrentThreadId(); +} + +static struct ssh_threads_callbacks_struct ssh_threads_winlock = +{ + .type = "threads_winlock", + .mutex_init = ssh_winlock_mutex_init, + .mutex_destroy = ssh_winlock_mutex_destroy, + .mutex_lock = ssh_winlock_mutex_lock, + .mutex_unlock = ssh_winlock_mutex_unlock, + .thread_id = ssh_winlock_thread_id +}; + +/* Threads interface implementation */ + +void ssh_mutex_lock(SSH_MUTEX *mutex) +{ + void *rc; + + CRITICAL_SECTION *mutex_tmp = NULL; + + if (*mutex == NULL) { + mutex_tmp = malloc(sizeof(CRITICAL_SECTION)); + + if (mutex_tmp == NULL) { + exit(ENOMEM); + } + + InitializeCriticalSection(mutex_tmp); + + rc = InterlockedCompareExchangePointer((PVOID*)mutex, + (PVOID)mutex_tmp, + NULL); + if (rc != NULL) { + DeleteCriticalSection(mutex_tmp); + free(mutex_tmp); + exit(ENOMEM); + } + } + + EnterCriticalSection(*mutex); +} + +void ssh_mutex_unlock(SSH_MUTEX *mutex) +{ + LeaveCriticalSection(*mutex); +} + +struct ssh_threads_callbacks_struct *ssh_threads_get_winlock(void) +{ + return &ssh_threads_winlock; +} + +struct ssh_threads_callbacks_struct *ssh_threads_get_default(void) +{ + return &ssh_threads_winlock; +} |