mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-30 18:36:12 +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
 | 
