Skip to content

Commit

Permalink
Backport of this changeset
Browse files Browse the repository at this point in the history
http://lists.mysql.com/commits/59686

Cleanup pthread_self(), pthread_create(), pthread_join() implementation on Windows.
Prior implementation is was unnecessarily complicated and even differs in embedded
and non-embedded case.
      
Improvements in this patch:
* pthread_t is now the unique thread ID, instead of HANDLE returned by beginthread
      
This simplifies pthread_self() to be just straight GetCurrentThreadId().
prior it was much  art involved in passing the beginthread() handle from the caller
to the TLS structure in the child thread ( did not work for the main thread of
course)
      
* remove MySQL specific my_thread_init()/my_thread_end() from pthread_create.
No automagic is done on Unix on pthread_create(). Having the same on Windows will 
improve portability and avoid extra #ifdef's
      
* remove redefinition of getpid() - it was defined as GetCurrentThreadId()
  • Loading branch information
vaintroub committed Sep 30, 2009
1 parent 2801599 commit 9cf8d12
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 138 deletions.
3 changes: 3 additions & 0 deletions include/config-win.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
#include <fcntl.h>
#include <io.h>
#include <malloc.h>
#include <sys/stat.h>
#include <process.h> /* getpid()*/


#define HAVE_SMEM 1

Expand Down
12 changes: 5 additions & 7 deletions include/my_pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ extern "C" {

#if defined(__WIN__)
typedef CRITICAL_SECTION pthread_mutex_t;
typedef HANDLE pthread_t;
typedef DWORD pthread_t;
typedef struct thread_attr {
DWORD dwStackSize ;
DWORD dwCreatingFlag ;
Expand Down Expand Up @@ -64,8 +64,7 @@ typedef struct {


typedef int pthread_mutexattr_t;
#define win_pthread_self my_thread_var->pthread_self
#define pthread_self() win_pthread_self
#define pthread_self() GetCurrentThreadId()
#define pthread_handler_t EXTERNC void * __cdecl
typedef void * (__cdecl *pthread_handler)(void *);

Expand Down Expand Up @@ -99,7 +98,7 @@ struct timespec {
(ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \
}

void win_pthread_init(void);

int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *);
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
Expand All @@ -116,11 +115,11 @@ int pthread_attr_destroy(pthread_attr_t *connect_att);
struct tm *localtime_r(const time_t *timep,struct tm *tmp);
struct tm *gmtime_r(const time_t *timep,struct tm *tmp);

void pthread_exit(void *a);
int pthread_join(pthread_t thread, void **value_ptr);

void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/

#define ETIMEDOUT 145 /* Win32 doesn't have this */
#define getpid() GetCurrentThreadId()
#define HAVE_LOCALTIME_R 1
#define _REENTRANT 1
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
Expand All @@ -145,7 +144,6 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B))
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)

#define pthread_join(A,B) (WaitForSingleObject((A), INFINITE) != WAIT_OBJECT_0)

/* Dummy defines for easier code */
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
Expand Down
2 changes: 1 addition & 1 deletion libmysqld/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
../sql/partition_info.cc ../sql/sql_connect.cc
../sql/scheduler.cc ../sql/event_parse_data.cc
./sql/sql_signal.cc
../sql/sql_signal.cc
${GEN_SOURCES}
${LIB_SOURCES})

Expand Down
43 changes: 35 additions & 8 deletions mysys/my_thr_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ pthread_mutexattr_t my_fast_mutexattr;
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
pthread_mutexattr_t my_errorcheck_mutexattr;
#endif

#ifdef _MSC_VER
static void install_sigabrt_handler();
#endif
#ifdef TARGET_OS_LINUX

/*
Expand Down Expand Up @@ -145,15 +147,18 @@ my_bool my_thread_global_init(void)
pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
pthread_cond_init(&THR_COND_threads, NULL);
#if defined( __WIN__) || defined(OS2)
win_pthread_init();
#endif

#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW);
#endif
#ifndef HAVE_GETHOSTBYNAME_R
pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
#endif

#ifdef _MSC_VER
install_sigabrt_handler();
#endif

if (my_thread_init())
{
my_thread_global_end(); /* Clean up */
Expand Down Expand Up @@ -268,11 +273,7 @@ my_bool my_thread_init(void)
goto end;
}
pthread_setspecific(THR_KEY_mysys,tmp);
#if defined(__WIN__) && defined(EMBEDDED_LIBRARY)
tmp->pthread_self= (pthread_t) getpid();
#else
tmp->pthread_self= pthread_self();
#endif
pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
pthread_cond_init(&tmp->suspend, NULL);
tmp->init= 1;
Expand Down Expand Up @@ -398,4 +399,30 @@ static uint get_thread_lib(void)
return THD_LIB_OTHER;
}

#ifdef _WIN32
/*
In Visual Studio 2005 and later, default SIGABRT handler will overwrite
any unhandled exception filter set by the application and will try to
call JIT debugger. This is not what we want, this we calling __debugbreak
to stop in debugger, if process is being debugged or to generate
EXCEPTION_BREAKPOINT and then handle_segfault will do its magic.
*/

#if (_MSC_VER >= 1400)
static void my_sigabrt_handler(int sig)
{
__debugbreak();
}
#endif /*_MSC_VER >=1400 */

static void install_sigabrt_handler(void)
{
#if (_MSC_VER >=1400)
/*abort() should not override our exception filter*/
_set_abort_behavior(0,_CALL_REPORTFAULT);
signal(SIGABRT,my_sigabrt_handler);
#endif /* _MSC_VER >=1400 */
}
#endif

#endif /* THREAD */
3 changes: 1 addition & 2 deletions mysys/my_wincond.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
/*****************************************************************************
** The following is a simple implementation of posix conditions
*****************************************************************************/
#if defined(_WIN32)

#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */
#include "mysys_priv.h"
#if defined(THREAD) && defined(__WIN__)
#include <m_string.h>
#undef getpid
#include <process.h>
#include <sys/timeb.h>

Expand Down
131 changes: 65 additions & 66 deletions mysys/my_winthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,23 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

/*****************************************************************************
** Simulation of posix threads calls for WIN95 and NT
** 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"
#if defined(THREAD) && defined(__WIN__)
#include <m_string.h>
#undef getpid
#include <process.h>
#include <signal.h>

static pthread_mutex_t THR_LOCK_thread;
static void install_sigabrt_handler(void);

struct pthread_map
struct thread_start_parameter
{
HANDLE pthreadself;
pthread_handler func;
void *param;
void *arg;
};

void win_pthread_init(void)
{
pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST);
}


/**
Adapter to @c pthread_mutex_trylock()
Expand All @@ -62,72 +52,81 @@ win_pthread_mutex_trylock(pthread_mutex_t *mutex)
return EBUSY;
}


/*
** We have tried to use '_beginthreadex' instead of '_beginthread' here
** but in this case the program leaks about 512 characters for each
** created thread !
** As we want to save the created thread handler for other threads to
** use and to be returned by pthread_self() (instead of the Win32 pseudo
** handler), we have to go trough pthread_start() to catch the returned handler
** in the new thread.
*/

pthread_handler_t pthread_start(void *param)
static unsigned int __stdcall pthread_start(void *p)
{
pthread_handler func=((struct pthread_map *) param)->func;
void *func_param=((struct pthread_map *) param)->param;
my_thread_init(); /* Will always succeed in windows */
pthread_mutex_lock(&THR_LOCK_thread); /* Wait for beginthread to return */
win_pthread_self=((struct pthread_map *) param)->pthreadself;
pthread_mutex_unlock(&THR_LOCK_thread);
free((char*) param); /* Free param from create */
pthread_exit((void*) (*func)(func_param));
return 0; /* Safety */
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, pthread_attr_t *attr,
pthread_handler func, void *param)
pthread_handler func, void *param)
{
HANDLE hThread;
struct pthread_map *map;
uintptr_t handle;
struct thread_start_parameter *par;
unsigned int stack_size;
DBUG_ENTER("pthread_create");

if (!(map=malloc(sizeof(*map))))
DBUG_RETURN(-1);
map->func=func;
map->param=param;
pthread_mutex_lock(&THR_LOCK_thread);
#ifdef __BORLANDC__
hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start,
attr->dwStackSize ? attr->dwStackSize :
65535, (void*) map);
#else
hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start,
attr->dwStackSize ? attr->dwStackSize :
65535, (void*) map);
#endif
DBUG_PRINT("info", ("hThread=%lu",(long) hThread));
*thread_id=map->pthreadself=hThread;
pthread_mutex_unlock(&THR_LOCK_thread);
par= (struct thread_start_parameter *)malloc(sizeof(*par));
if (!par)
goto error_return;

if (hThread == (HANDLE) -1)
{
int error=errno;
DBUG_PRINT("error",
("Can't create thread to handle request (error %d)",error));
DBUG_RETURN(error ? error : -1);
}
VOID(SetThreadPriority(hThread, attr->priority)) ;
par->func= func;
par->arg= param;
stack_size= attr?attr->dwStackSize:0;

handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id);
if (!handle)
goto error_return;
DBUG_PRINT("info", ("thread id=%u",*thread_id));

/* Do not need thread handle, close it */
CloseHandle((HANDLE)handle);
DBUG_RETURN(0);

error_return:
DBUG_PRINT("error",
("Can't create thread to handle request (error %d)",errno));
DBUG_RETURN(-1);
}


void pthread_exit(void *a)
{
_endthread();
_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;
}

CloseHandle(handle);
return 0;

error_return:
if(handle)
CloseHandle(handle);
return -1;
}

#endif
Loading

0 comments on commit 9cf8d12

Please sign in to comment.