~ubuntu-branches/ubuntu/trusty/mariadb-5.5/trusty-proposed

« back to all changes in this revision

Viewing changes to mysys/my_winthread.c

  • Committer: Package Import Robot
  • Author(s): Otto Kekäläinen
  • Date: 2013-12-22 10:27:05 UTC
  • Revision ID: package-import@ubuntu.com-20131222102705-mndw7s12mz0szrcn
Tags: upstream-5.5.32
Import upstream version 5.5.32

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
15
 
 
16
/*****************************************************************************
 
17
** Simulation of posix threads calls for Windows
 
18
*****************************************************************************/
 
19
#if defined (_WIN32)
 
20
/* SAFE_MUTEX will not work until the thread structure is up to date */
 
21
 
 
22
#undef SAFE_MUTEX
 
23
#include "mysys_priv.h"
 
24
#include <process.h>
 
25
#include <signal.h>
 
26
 
 
27
struct thread_start_parameter
 
28
{
 
29
  pthread_handler func;
 
30
  void *arg;
 
31
};
 
32
 
 
33
/**
 
34
   Adapter to @c pthread_mutex_trylock()
 
35
 
 
36
   @retval 0      Mutex was acquired
 
37
   @retval EBUSY  Mutex was already locked by a thread
 
38
 */
 
39
int
 
40
win_pthread_mutex_trylock(pthread_mutex_t *mutex)
 
41
{
 
42
  if (TryEnterCriticalSection(mutex))
 
43
  {
 
44
    /* Don't allow recursive lock */
 
45
    if (mutex->RecursionCount > 1){
 
46
      LeaveCriticalSection(mutex);
 
47
      return EBUSY;
 
48
    }
 
49
    return 0;
 
50
  }
 
51
  return EBUSY;
 
52
}
 
53
 
 
54
static unsigned int __stdcall pthread_start(void *p)
 
55
{
 
56
  struct thread_start_parameter *par= (struct thread_start_parameter *)p;
 
57
  pthread_handler func= par->func;
 
58
  void *arg= par->arg;
 
59
  free(p);
 
60
  (*func)(arg);
 
61
  return 0;
 
62
}
 
63
 
 
64
 
 
65
int pthread_create(pthread_t *thread_id, const pthread_attr_t *attr,
 
66
                   pthread_handler func, void *param)
 
67
{
 
68
  uintptr_t handle;
 
69
  struct thread_start_parameter *par;
 
70
  unsigned int  stack_size;
 
71
  DBUG_ENTER("pthread_create");
 
72
 
 
73
  par= (struct thread_start_parameter *)malloc(sizeof(*par));
 
74
  if (!par)
 
75
   goto error_return;
 
76
 
 
77
  par->func= func;
 
78
  par->arg= param;
 
79
  stack_size= attr?attr->dwStackSize:0;
 
80
 
 
81
  handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id);
 
82
  if (!handle)
 
83
    goto error_return;
 
84
  DBUG_PRINT("info", ("thread id=%u",*thread_id));
 
85
 
 
86
  /* Do not need thread handle, close it */
 
87
  CloseHandle((HANDLE)handle);
 
88
  DBUG_RETURN(0);
 
89
 
 
90
error_return:
 
91
  DBUG_PRINT("error",
 
92
         ("Can't create thread to handle request (error %d)",errno));
 
93
  DBUG_RETURN(-1);
 
94
}
 
95
 
 
96
 
 
97
void pthread_exit(void *a)
 
98
{
 
99
  _endthreadex(0);
 
100
}
 
101
 
 
102
int pthread_join(pthread_t thread, void **value_ptr)
 
103
{
 
104
  DWORD  ret;
 
105
  HANDLE handle;
 
106
 
 
107
  handle= OpenThread(SYNCHRONIZE, FALSE, thread);
 
108
  if (!handle)
 
109
  {
 
110
    errno= EINVAL;
 
111
    goto error_return;
 
112
  }
 
113
 
 
114
  ret= WaitForSingleObject(handle, INFINITE);
 
115
 
 
116
  if(ret != WAIT_OBJECT_0)
 
117
  {
 
118
    errno= EINVAL;
 
119
    goto error_return;
 
120
  }
 
121
 
 
122
  CloseHandle(handle);
 
123
  return 0;
 
124
 
 
125
error_return:
 
126
  if(handle)
 
127
    CloseHandle(handle);
 
128
  return -1;
 
129
}
 
130
 
 
131
int pthread_cancel(pthread_t thread)
 
132
{
 
133
 
 
134
  HANDLE handle= 0;
 
135
  BOOL ok= FALSE;
 
136
 
 
137
  handle= OpenThread(THREAD_TERMINATE, FALSE, thread);
 
138
  if (handle)
 
139
  {
 
140
     ok= TerminateThread(handle,0);
 
141
     CloseHandle(handle);
 
142
  }
 
143
  if (ok)
 
144
    return 0;
 
145
 
 
146
  errno= EINVAL;
 
147
  return -1;
 
148
}
 
149
 
 
150
/*
 
151
 One time initialization. For simplicity, we assume initializer thread
 
152
 does not exit within init_routine().
 
153
*/
 
154
int my_pthread_once(my_pthread_once_t *once_control, 
 
155
    void (*init_routine)(void))
 
156
{
 
157
  LONG state;
 
158
 
 
159
  /*
 
160
    Do "dirty" read to find out if initialization is already done, to
 
161
    save an interlocked operation in common case. Memory barriers are ensured by 
 
162
    Visual C++ volatile implementation.
 
163
  */
 
164
  if (*once_control == MY_PTHREAD_ONCE_DONE)
 
165
    return 0;
 
166
 
 
167
  state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS,
 
168
                                        MY_PTHREAD_ONCE_INIT);
 
169
 
 
170
  switch(state)
 
171
  {
 
172
  case MY_PTHREAD_ONCE_INIT:
 
173
    /* This is initializer thread */
 
174
    (*init_routine)();
 
175
    *once_control= MY_PTHREAD_ONCE_DONE;
 
176
    break;
 
177
 
 
178
  case MY_PTHREAD_ONCE_INPROGRESS:
 
179
    /* init_routine in progress. Wait for its completion */
 
180
    while(*once_control == MY_PTHREAD_ONCE_INPROGRESS)
 
181
    {
 
182
      Sleep(1);
 
183
    }
 
184
    break;
 
185
  case MY_PTHREAD_ONCE_DONE:
 
186
    /* Nothing to do */
 
187
    break;
 
188
  }
 
189
  return 0;
 
190
}
 
191
#endif