From 04cc7b769a359ca2afdcfc0b70b5e8a17849b556 Mon Sep 17 00:00:00 2001 From: Anderson Toshiyuki Sasaki Date: Mon, 2 Jul 2018 14:01:46 +0200 Subject: threads: Add Windows threads implementation Added Windows threads implementation based on CriticalSection. Signed-off-by: Anderson Toshiyuki Sasaki Reviewed-by: Andreas Schneider --- src/threads/noop.c | 2 +- src/threads/winlocks.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/threads/winlocks.c (limited to 'src/threads') 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 + +#include +#include +#include + +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; +} -- cgit v1.2.3