List:Commits« Previous MessageNext Message »
From:Vladislav Vaintroub Date:November 24 2008 4:30pm
Subject:bzr commit into mysql-6.0 branch (vvaintroub:2681)
View as plain text  
#At file:///G:/bzr/mysql-6.0-wtf-winthread/

 2681 Vladislav Vaintroub	2008-11-24
      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()
modified:
  include/config-win.h
  include/my_pthread.h
  mysys/my_thr_init.c
  mysys/my_wincond.c
  mysys/my_winthread.c
  sql/mysqld.cc
  sql/sql_connect.cc
  sql/sql_insert.cc

per-file messages:
  include/config-win.h
    Include <process.h> for getpid()
  include/my_pthread.h
    - change pthread_t to be a real (OS) thread id, not handle
    - remove win_pthread_init
    - change pthread_yield from Sleep(0) to SwitchToThread(),
      as Sleep(0) does yield to threads of lower priority
  mysys/my_thr_init.c
    - remove win_pthread_init()
    - install per-thread SIGABRT handler in my_pthread_init
  mysys/my_wincond.c
    remove #undef getpid
  mysys/my_winthread.c
    - Simplify implementation of pthread_create and make it independent 
    of EMBEDDED_LIBRARY defintion
  sql/mysqld.cc
    - when handle_connections_sockets is run in a thread different from 
    the main thread, it needs my_thread_init.
    
    - Windows specific sigabrt handler initialization  moved to my_thread_init
    - fix warning (not all control paths return value from win_main)
  sql/sql_connect.cc
    Code for SIGABRT handler moved to my_thread_init()
  sql/sql_insert.cc
     my_thread_init() was not called for windows.
=== modified file 'include/config-win.h'
--- a/include/config-win.h	2008-07-23 08:52:08 +0000
+++ b/include/config-win.h	2008-11-24 15:30:37 +0000
@@ -37,6 +37,7 @@
 #include <io.h>
 #include <malloc.h>
 #include <sys/stat.h>
+#include <process.h>     /* getpid()*/
 
 #define HAVE_SMEM 1
 

=== modified file 'include/my_pthread.h'
--- a/include/my_pthread.h	2008-11-12 01:37:42 +0000
+++ b/include/my_pthread.h	2008-11-24 15:30:37 +0000
@@ -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 ;
@@ -63,8 +63,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 *);
 
@@ -100,7 +99,7 @@ struct timespec {
   set_timespec_time_nsec((ABSTIME), tv.i64, (NSEC));            \
 } while(0)
 
-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 
 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
@@ -144,7 +143,6 @@ void pthread_exit(void *a);	 /* was #def
 #define pthread_mutex_destroy(A) DeleteCriticalSection(A)
 #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)
@@ -152,10 +150,8 @@ void pthread_exit(void *a);	 /* was #def
 #define pthread_detach_this_thread()
 #define pthread_condattr_init(A)
 #define pthread_condattr_destroy(A)
-#define pthread_yield() Sleep(0) /* according to MSDN */
+#define pthread_yield() SwitchToThread() 
 
-/* per the platform's documentation */
-#define pthread_yield() Sleep(0)
 
 #else /* Normal threads */
 

=== modified file 'mysys/my_thr_init.c'
--- a/mysys/my_thr_init.c	2008-10-31 18:02:34 +0000
+++ b/mysys/my_thr_init.c	2008-11-24 15:30:37 +0000
@@ -47,7 +47,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
 
 /*
@@ -151,9 +153,7 @@ 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
@@ -269,17 +269,18 @@ my_bool my_thread_init(void)
 #endif
     goto end;
   }
+
+#ifdef _MSC_VER
+  install_sigabrt_handler();
+#endif
+
   if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
   {
     error= 1;
     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);
 
@@ -426,4 +427,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 */

=== modified file 'mysys/my_wincond.c'
--- a/mysys/my_wincond.c	2008-11-06 18:39:27 +0000
+++ b/mysys/my_wincond.c	2008-11-24 15:30:37 +0000
@@ -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>
 

=== modified file 'mysys/my_winthread.c'
--- a/mysys/my_winthread.c	2008-11-12 01:37:42 +0000
+++ b/mysys/my_winthread.c	2008-11-24 15:30:37 +0000
@@ -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,79 +52,81 @@ win_pthread_mutex_trylock(pthread_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)
-{
-  pthread_handler func=((struct pthread_map *) param)->func;
-  void *func_param=((struct pthread_map *) param)->param;
-  void *result;
-  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 */
-  result= (void*) (*func)(func_param);
-  my_thread_end();
-  pthread_exit(result);
-  return 0;				  /* Safety */
+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, pthread_attr_t *attr,
-		   pthread_handler func, void *param)
+     pthread_handler func, void *param)
 {
-  HANDLE hThread;
-  struct pthread_map *map;
-  DWORD StackSize= 0;
+  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;
-  if (attr != NULL)
-  {
-    StackSize= attr->dwStackSize;
-  }
-  if (StackSize == 0)
-    StackSize= PTHREAD_STACK_MIN;
-  pthread_mutex_lock(&THR_LOCK_thread);
-#ifdef __BORLANDC__
-  hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start,
-			       StackSize, (void*) map);
-#else
-  hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start,
-			       StackSize, (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;
+
+  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));
 
-  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);
-  }
+  /* 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

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2008-11-15 17:02:01 +0000
+++ b/sql/mysqld.cc	2008-11-24 15:30:37 +0000
@@ -841,7 +841,10 @@ static void set_server_version(void);
 static int init_thread_environment();
 static char *get_relative_path(const char *path);
 static void 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);
@@ -2129,29 +2132,6 @@ static BOOL WINAPI console_event_handler
 }
 
 
-/*
-  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
@@ -2230,7 +2210,6 @@ LONG WINAPI my_unhandler_exception_filte
 
 static void init_signals(void)
 {
-  win_install_sigabrt_handler();
   if(opt_console)
     SetConsoleCtrlHandler(console_event_handler,TRUE);
   else
@@ -4401,8 +4380,8 @@ static void handle_connections_methods()
   if (have_tcpip && !opt_disable_networking)
   {
     handler_count++;
-    if (pthread_create(&hThread,&connection_attrib,
-		       handle_connections_sockets, 0))
+    if (pthread_create(&hThread,&connection_attrib, 
+                       handle_connections_sockets_thread, 0))
     {
       sql_print_warning("Can't create thread to handle TCP/IP");
       handler_count--;
@@ -4678,14 +4657,7 @@ int main(int argc, char **argv)
 #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);
+  handle_connections_sockets();
 #endif /* _WIN32 || HAVE_SMEM */
 
   /* (void) pthread_attr_destroy(&connection_attrib); */
@@ -4724,6 +4696,7 @@ int main(int argc, char **argv)
 #endif
   clean_up(1);
   mysqld_exit(0);
+  return 0; /* purecov: inspected */
 }
 
 #endif /* !EMBEDDED_LIBRARY */
@@ -5137,7 +5110,8 @@ 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;
@@ -5339,13 +5313,19 @@ pthread_handler_t handle_connections_soc
 
     create_new_thread(thd);
   }
-
-  decrement_handler_count();
-  DBUG_RETURN(0);
+  DBUG_VOID_RETURN;
 }
 
 
 #ifdef _WIN32
+pthread_handler_t handle_connections_sockets_thread(void *arg)
+{
+  my_thread_init();
+  handle_connections_sockets();
+  decrement_handler_count();
+  return 0;
+}
+
 pthread_handler_t handle_connections_namedpipes(void *arg)
 {
   HANDLE hConnectedPipe;

=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc	2008-10-17 17:47:16 +0000
+++ b/sql/sql_connect.cc	2008-11-24 15:30:37 +0000
@@ -39,10 +39,6 @@
 #define MIN_HANDSHAKE_SIZE      6
 #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
-#ifdef __WIN__
-extern void win_install_sigabrt_handler();
-#endif
-
 /*
   Get structure for logging connection data for the current user
 */
@@ -636,13 +632,8 @@ void thd_init_client_charset(THD *thd, u
 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;
 }
 

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2008-11-06 18:39:27 +0000
+++ b/sql/sql_insert.cc	2008-11-24 15:30:37 +0000
@@ -2344,7 +2344,6 @@ pthread_handler_t handle_delayed_insert(
     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 */
@@ -2352,8 +2351,6 @@ pthread_handler_t handle_delayed_insert(
                                   ER(ER_OUT_OF_RESOURCES));
     goto end;
   }
-#endif
-
   DBUG_ENTER("handle_delayed_insert");
   thd->thread_stack= (char*) &thd;
   if (init_thr_lock() || thd->store_globals())
@@ -2544,9 +2541,7 @@ err:
    */
   trans_rollback_stmt(thd);
 
-#ifndef __WIN__
 end:
-#endif
   /*
     di should be unlinked from the thread handler list and have no active
     clients

Thread
bzr commit into mysql-6.0 branch (vvaintroub:2681)Vladislav Vaintroub24 Nov