OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [i386/] [gthr-win32.c] - Blame information for rev 734

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 734 jeremybenn
/* Implementation of W32-specific threads compatibility routines for
2
   libgcc2.  */
3
 
4
/* Copyright (C) 1999, 2000, 2002, 2004, 2008, 2009, 2011
5
   Free Software Foundation, Inc.
6
   Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
7
   Modified and moved to separate file by Danny Smith
8
   <dannysmith@users.sourceforge.net>.
9
 
10
This file is part of GCC.
11
 
12
GCC is free software; you can redistribute it and/or modify it under
13
the terms of the GNU General Public License as published by the Free
14
Software Foundation; either version 3, or (at your option) any later
15
version.
16
 
17
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18
WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
for more details.
21
 
22
Under Section 7 of GPL version 3, you are granted additional
23
permissions described in the GCC Runtime Library Exception, version
24
3.1, as published by the Free Software Foundation.
25
 
26
You should have received a copy of the GNU General Public License and
27
a copy of the GCC Runtime Library Exception along with this program;
28
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
29
<http://www.gnu.org/licenses/>.  */
30
 
31
#include <windows.h>
32
#ifndef __GTHREAD_HIDE_WIN32API
33
# define __GTHREAD_HIDE_WIN32API 1
34
#endif
35
#undef  __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
36
#define __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
37
#include "gthr-win32.h"
38
 
39
/* Windows32 threads specific definitions. The windows32 threading model
40
   does not map well into pthread-inspired gcc's threading model, and so
41
   there are caveats one needs to be aware of.
42
 
43
   1. The destructor supplied to __gthread_key_create is ignored for
44
      generic x86-win32 ports. This will certainly cause memory leaks
45
      due to unreclaimed eh contexts (sizeof (eh_context) is at least
46
      24 bytes for x86 currently).
47
 
48
      This memory leak may be significant for long-running applications
49
      that make heavy use of C++ EH.
50
 
51
      However, Mingw runtime (version 0.3 or newer) provides a mechanism
52
      to emulate pthreads key dtors; the runtime provides a special DLL,
53
      linked in if -mthreads option is specified, that runs the dtors in
54
      the reverse order of registration when each thread exits. If
55
      -mthreads option is not given, a stub is linked in instead of the
56
      DLL, which results in memory leak. Other x86-win32 ports can use
57
      the same technique of course to avoid the leak.
58
 
59
   2. The error codes returned are non-POSIX like, and cast into ints.
60
      This may cause incorrect error return due to truncation values on
61
      hw where sizeof (DWORD) > sizeof (int).
62
 
63
   3. We are currently using a special mutex instead of the Critical
64
      Sections, since Win9x does not support TryEnterCriticalSection
65
      (while NT does).
66
 
67
   The basic framework should work well enough. In the long term, GCC
68
   needs to use Structured Exception Handling on Windows32.  */
69
 
70
int
71
__gthr_win32_once (__gthread_once_t *once, void (*func) (void))
72
{
73
  if (once == NULL || func == NULL)
74
    return EINVAL;
75
 
76
  if (! once->done)
77
    {
78
      if (InterlockedIncrement (&(once->started)) == 0)
79
        {
80
          (*func) ();
81
          once->done = TRUE;
82
        }
83
      else
84
        {
85
          /* Another thread is currently executing the code, so wait for it
86
             to finish; yield the CPU in the meantime.  If performance
87
             does become an issue, the solution is to use an Event that
88
             we wait on here (and set above), but that implies a place to
89
             create the event before this routine is called.  */
90
          while (! once->done)
91
            Sleep (0);
92
        }
93
    }
94
  return 0;
95
}
96
 
97
/* Windows32 thread local keys don't support destructors; this leads to
98
   leaks, especially in threaded applications making extensive use of
99
   C++ EH. Mingw uses a thread-support DLL to work-around this problem.  */
100
 
101
int
102
__gthr_win32_key_create (__gthread_key_t *key,
103
                         void (*dtor) (void *) __attribute__((unused)))
104
{
105
  int status = 0;
106
  DWORD tls_index = TlsAlloc ();
107
  if (tls_index != 0xFFFFFFFF)
108
    {
109
      *key = tls_index;
110
#ifdef MINGW32_SUPPORTS_MT_EH
111
      /* Mingw runtime will run the dtors in reverse order for each thread
112
         when the thread exits.  */
113
      status = __mingwthr_key_dtor (*key, dtor);
114
#endif
115
    }
116
  else
117
    status = (int) GetLastError ();
118
  return status;
119
}
120
 
121
int
122
__gthr_win32_key_delete (__gthread_key_t key)
123
{
124
  return (TlsFree (key) != 0) ? 0 : (int) GetLastError ();
125
}
126
 
127
void *
128
__gthr_win32_getspecific (__gthread_key_t key)
129
{
130
  DWORD lasterror;
131
  void *ptr;
132
  lasterror = GetLastError();
133
  ptr = TlsGetValue(key);
134
  SetLastError( lasterror );
135
  return ptr;
136
}
137
 
138
int
139
__gthr_win32_setspecific (__gthread_key_t key, const void *ptr)
140
{
141
  if (TlsSetValue (key, CONST_CAST2(void *, const void *, ptr)) != 0)
142
    return 0;
143
  else
144
    return GetLastError ();
145
}
146
 
147
void
148
__gthr_win32_mutex_init_function (__gthread_mutex_t *mutex)
149
{
150
  mutex->counter = -1;
151
  mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
152
}
153
 
154
void
155
__gthr_win32_mutex_destroy (__gthread_mutex_t *mutex)
156
{
157
  CloseHandle ((HANDLE) mutex->sema);
158
}
159
 
160
int
161
__gthr_win32_mutex_lock (__gthread_mutex_t *mutex)
162
{
163
  if (InterlockedIncrement (&mutex->counter) == 0 ||
164
      WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
165
    return 0;
166
  else
167
    {
168
      /* WaitForSingleObject returns WAIT_FAILED, and we can only do
169
         some best-effort cleanup here.  */
170
      InterlockedDecrement (&mutex->counter);
171
      return 1;
172
    }
173
}
174
 
175
int
176
__gthr_win32_mutex_trylock (__gthread_mutex_t *mutex)
177
{
178
  if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
179
    return 0;
180
  else
181
    return 1;
182
}
183
 
184
int
185
__gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
186
{
187
  if (InterlockedDecrement (&mutex->counter) >= 0)
188
    return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
189
  else
190
    return 0;
191
}
192
 
193
void
194
__gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
195
{
196
  mutex->counter = -1;
197
  mutex->depth = 0;
198
  mutex->owner = 0;
199
  mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
200
}
201
 
202
int
203
__gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
204
{
205
  DWORD me = GetCurrentThreadId();
206
  if (InterlockedIncrement (&mutex->counter) == 0)
207
    {
208
      mutex->depth = 1;
209
      mutex->owner = me;
210
    }
211
  else if (mutex->owner == me)
212
    {
213
      InterlockedDecrement (&mutex->counter);
214
      ++(mutex->depth);
215
    }
216
  else if (WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
217
    {
218
      mutex->depth = 1;
219
      mutex->owner = me;
220
    }
221
  else
222
    {
223
      /* WaitForSingleObject returns WAIT_FAILED, and we can only do
224
         some best-effort cleanup here.  */
225
      InterlockedDecrement (&mutex->counter);
226
      return 1;
227
    }
228
  return 0;
229
}
230
 
231
int
232
__gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
233
{
234
  DWORD me = GetCurrentThreadId();
235
  if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
236
    {
237
      mutex->depth = 1;
238
      mutex->owner = me;
239
    }
240
  else if (mutex->owner == me)
241
    ++(mutex->depth);
242
  else
243
    return 1;
244
 
245
  return 0;
246
}
247
 
248
int
249
__gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
250
{
251
  --(mutex->depth);
252
  if (mutex->depth == 0)
253
    {
254
      mutex->owner = 0;
255
 
256
      if (InterlockedDecrement (&mutex->counter) >= 0)
257
        return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
258
    }
259
 
260
  return 0;
261
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.