diff options
author | Vladislav Vaintroub <vvaintroub@mysql.com> | 2009-09-30 17:40:12 +0200 |
---|---|---|
committer | Vladislav Vaintroub <vvaintroub@mysql.com> | 2009-09-30 17:40:12 +0200 |
commit | 9cf8d12c855e9713c5d3a170249c7d67935b2209 (patch) | |
tree | d211859561c812cd30d4143ce8099b8dc9cbaedf | |
parent | 28015993235d3a1a56f08de5b86c4e1ef59d4723 (diff) | |
download | mariadb-git-9cf8d12c855e9713c5d3a170249c7d67935b2209.tar.gz |
Backport of this changeset
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()
-rw-r--r-- | include/config-win.h | 3 | ||||
-rw-r--r-- | include/my_pthread.h | 12 | ||||
-rw-r--r-- | libmysqld/CMakeLists.txt | 2 | ||||
-rw-r--r-- | mysys/my_thr_init.c | 43 | ||||
-rw-r--r-- | mysys/my_wincond.c | 3 | ||||
-rw-r--r-- | mysys/my_winthread.c | 131 | ||||
-rw-r--r-- | sql/mysqld.cc | 60 | ||||
-rw-r--r-- | sql/sql_connect.cc | 9 | ||||
-rw-r--r-- | sql/sql_insert.cc | 5 |
9 files changed, 130 insertions, 138 deletions
diff --git a/include/config-win.h b/include/config-win.h index bcad4e04346..514a762d6d8 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -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 diff --git a/include/my_pthread.h b/include/my_pthread.h index 2928cb60c2d..b4fe1203d2b 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -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 ; @@ -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 *); @@ -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); @@ -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 @@ -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) diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 6e1ad17b808..bce14b38338 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -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}) diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 2c346145cf5..c59b2d51742 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -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 /* @@ -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 */ @@ -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; @@ -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 */ diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c index d1b07b61408..956d29a970b 100644 --- a/mysys/my_wincond.c +++ b/mysys/my_wincond.c @@ -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> diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index 543e1787fb6..9e8458b0799 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -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() @@ -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 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bb79f931fb3..3585539318d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -805,7 +805,10 @@ static void set_server_version(void); static int init_thread_environment(); static char *get_relative_path(const char *path); static int fix_paths(void); -pthread_handler_t handle_connections_sockets(void *arg); +void handle_connections_sockets(); +#ifdef _WIN32 +pthread_handler_t handle_connections_sockets_thread(void *arg); +#endif pthread_handler_t kill_server_thread(void *arg); static void bootstrap(FILE *file); static bool read_init_file(char *file_name); @@ -2034,29 +2037,7 @@ static BOOL WINAPI console_event_handler( DWORD type ) } -/* - 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 */ -void win_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 */ -} #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER #define DEBUGGER_ATTACH_TIMEOUT 120 @@ -2135,7 +2116,6 @@ LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers) static void init_signals(void) { - win_install_sigabrt_handler(); if(opt_console) SetConsoleCtrlHandler(console_event_handler,TRUE); @@ -4132,7 +4112,8 @@ static void create_shutdown_thread() #ifdef __WIN__ hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name); pthread_t hThread; - if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0)) + if (pthread_create(&hThread,&connection_attrib, + handle_connections_sockets_thread, 0)) sql_print_warning("Can't create thread to handle shutdown requests"); // On "Stop Service" we have to do regular shutdown @@ -4177,7 +4158,7 @@ static void handle_connections_methods() { handler_count++; if (pthread_create(&hThread,&connection_attrib, - handle_connections_sockets, 0)) + handle_connections_sockets_thread, 0)) { sql_print_warning("Can't create thread to handle TCP/IP"); handler_count--; @@ -4506,18 +4487,11 @@ we force server id to 2, but this MySQL server will not act as a slave."); pthread_cond_signal(&COND_server_started); pthread_mutex_unlock(&LOCK_server_started); -#if defined(__NT__) || defined(HAVE_SMEM) +#if defined(_WIN32) || defined(HAVE_SMEM) handle_connections_methods(); #else -#ifdef __WIN__ - if (!have_tcpip || opt_disable_networking) - { - sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces"); - unireg_abort(1); - } -#endif - handle_connections_sockets(0); -#endif /* __NT__ */ + handle_connections_sockets(); +#endif /* _WIN32 || HAVE_SMEM */ /* (void) pthread_attr_destroy(&connection_attrib); */ @@ -4992,7 +4966,7 @@ inline void kill_broken_server() /* Handle new connections and spawn new process to handle them */ #ifndef EMBEDDED_LIBRARY -pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) +void handle_connections_sockets() { my_socket sock,new_sock; uint error_count=0; @@ -5195,13 +5169,19 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) create_new_thread(thd); } + DBUG_VOID_RETURN; +} + +#ifdef _WIN32 +pthread_handler_t handle_connections_sockets_thread(void *arg) +{ + my_thread_init(); + handle_connections_sockets(); decrement_handler_count(); - DBUG_RETURN(0); + return 0; } - -#ifdef __NT__ pthread_handler_t handle_connections_namedpipes(void *arg) { HANDLE hConnectedPipe; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 404d734559f..a87d201d9ed 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -39,10 +39,6 @@ #define MIN_HANDSHAKE_SIZE 6 #endif /* HAVE_OPENSSL */ -#ifdef __WIN__ -extern void win_install_sigabrt_handler(); -#endif - /* Get structure for logging connection data for the current user */ @@ -612,13 +608,8 @@ void thd_init_client_charset(THD *thd, uint cs_number) bool init_new_connection_handler_thread() { pthread_detach_this_thread(); -#if defined(__WIN__) - win_install_sigabrt_handler(); -#else - /* Win32 calls this in pthread_create */ if (my_thread_init()) return 1; -#endif /* __WIN__ */ return 0; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7d2513bd419..1ef4d5827ec 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2498,7 +2498,6 @@ pthread_handler_t handle_delayed_insert(void *arg) since it does not find one in the list. */ pthread_mutex_lock(&di->mutex); -#if !defined( __WIN__) /* Win32 calls this in pthread_create */ if (my_thread_init()) { /* Can't use my_error since store_globals has not yet been called */ @@ -2506,13 +2505,9 @@ pthread_handler_t handle_delayed_insert(void *arg) ER(ER_OUT_OF_RESOURCES), NULL); goto end; } -#endif - handle_delayed_insert_impl(thd, di); -#ifndef __WIN__ end: -#endif /* di should be unlinked from the thread handler list and have no active clients |