mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
179 lines
3.9 KiB
C
179 lines
3.9 KiB
C
/* 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
|