/* 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 #include 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