summaryrefslogtreecommitdiffstats
path: root/mysys/my_winthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'mysys/my_winthread.c')
-rw-r--r--mysys/my_winthread.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c
new file mode 100644
index 00000000..b74804fb
--- /dev/null
+++ b/mysys/my_winthread.c
@@ -0,0 +1,179 @@
+/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
+
+/*****************************************************************************
+** Simulation of posix threads calls for Windows
+*****************************************************************************/
+#if defined (_WIN32)
+/* SAFE_MUTEX will not work until the thread structure is up to date */
+
+#undef SAFE_MUTEX
+#include "mysys_priv.h"
+#include <process.h>
+#include <signal.h>
+
+struct thread_start_parameter
+{
+ pthread_handler func;
+ void *arg;
+};
+
+/**
+ Adapter to @c pthread_mutex_trylock()
+
+ @retval 0 Mutex was acquired
+ @retval EBUSY Mutex was already locked by a thread
+ */
+int
+win_pthread_mutex_trylock(pthread_mutex_t *mutex)
+{
+ if (TryEnterCriticalSection(mutex))
+ {
+ /* Don't allow recursive lock */
+ if (mutex->RecursionCount > 1){
+ LeaveCriticalSection(mutex);
+ return EBUSY;
+ }
+ return 0;
+ }
+ return EBUSY;
+}
+
+static unsigned int __stdcall pthread_start(void *p)
+{
+ struct thread_start_parameter *par= (struct thread_start_parameter *)p;
+ pthread_handler func= par->func;
+ void *arg= par->arg;
+ free(p);
+ (*func)(arg);
+ return 0;
+}
+
+
+int pthread_create(pthread_t *thread_id, const pthread_attr_t *attr,
+ pthread_handler func, void *param)
+{
+ uintptr_t handle;
+ struct thread_start_parameter *par;
+ unsigned int stack_size;
+ int error_no;
+ DBUG_ENTER("pthread_create");
+
+ par= (struct thread_start_parameter *)malloc(sizeof(*par));
+ if (!par)
+ goto error_return;
+
+ par->func= func;
+ par->arg= param;
+ stack_size= attr?attr->dwStackSize:0;
+
+ handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, (uint *)thread_id);
+ if (!handle)
+ goto error_return;
+ DBUG_PRINT("info", ("thread id=%lu",*thread_id));
+
+ /* Do not need thread handle, close it */
+ CloseHandle((HANDLE)handle);
+ DBUG_RETURN(0);
+
+error_return:
+ error_no= errno;
+ DBUG_PRINT("error",
+ ("Can't create thread to handle request (error %d)",error_no));
+ DBUG_RETURN(error_no);
+}
+
+
+void pthread_exit(void *a)
+{
+ _endthreadex(0);
+}
+
+int pthread_join(pthread_t thread, void **value_ptr)
+{
+ DWORD ret;
+ HANDLE handle;
+
+ handle= OpenThread(SYNCHRONIZE, FALSE, thread);
+ if (!handle)
+ {
+ errno= EINVAL;
+ goto error_return;
+ }
+
+ ret= WaitForSingleObject(handle, INFINITE);
+
+ if(ret != WAIT_OBJECT_0)
+ {
+ errno= EINVAL;
+ goto error_return;
+ }
+
+ if (!GetExitCodeThread(handle, &ret))
+ {
+ errno= EINVAL;
+ goto error_return;
+ }
+
+ if (value_ptr)
+ *value_ptr= (void *)(size_t)ret;
+
+ CloseHandle(handle);
+ return 0;
+
+error_return:
+ if(handle)
+ CloseHandle(handle);
+ return -1;
+}
+
+int pthread_cancel(pthread_t thread)
+{
+
+ HANDLE handle= 0;
+ BOOL ok= FALSE;
+
+ handle= OpenThread(THREAD_TERMINATE, FALSE, thread);
+ if (handle)
+ {
+ ok= TerminateThread(handle,0);
+ CloseHandle(handle);
+ }
+ if (ok)
+ return 0;
+
+ errno= EINVAL;
+ return -1;
+}
+
+
+
+/*
+ One time initialization.
+*/
+
+static BOOL CALLBACK init_once_callback(my_pthread_once_t *once_control, PVOID param, PVOID *context)
+{
+ typedef void(*void_f)(void);
+ ((void_f)param)();
+ return TRUE;
+}
+
+int my_pthread_once(my_pthread_once_t *once_control, void (*func)(void))
+{
+ InitOnceExecuteOnce(once_control, init_once_callback, func, NULL);
+ return 0;
+}
+#endif