OSThreads.c 3.9 KB
Newer Older
sof's avatar
sof committed
1 2
/* ---------------------------------------------------------------------------
 *
3
 * (c) The GHC Team, 2001-2005
sof's avatar
sof committed
4 5 6 7 8
 *
 * Accessing OS threads functionality in a (mostly) OS-independent
 * manner. 
 *
 * --------------------------------------------------------------------------*/
9

sof's avatar
sof committed
10
#include "Rts.h"
11
#if defined(THREADED_RTS)
sof's avatar
sof committed
12
#include "OSThreads.h"
sof's avatar
sof committed
13
#include "RtsUtils.h"
sof's avatar
sof committed
14

15 16 17 18
/* For reasons not yet clear, the entire contents of process.h is protected 
 * by __STRICT_ANSI__ not being defined.
 */
#undef __STRICT_ANSI__
sof's avatar
sof committed
19 20
#include <process.h>

sof's avatar
sof committed
21 22
/* Win32 threads and synchronisation objects */

sof's avatar
sof committed
23 24
/* A Condition is represented by a Win32 Event object;
 * a Mutex by a Mutex kernel object.
sof's avatar
sof committed
25 26 27 28 29
 *
 * ToDo: go through the defn and usage of these to
 * make sure the semantics match up with that of 
 * the (assumed) pthreads behaviour. This is really
 * just a first pass at getting something compilable.
sof's avatar
sof committed
30 31
 */

sof's avatar
sof committed
32 33
void
initCondition( Condition* pCond )
sof's avatar
sof committed
34 35
{
  HANDLE h =  CreateEvent(NULL, 
sof's avatar
sof committed
36 37
			  FALSE,  /* auto reset */
			  FALSE,  /* initially not signalled */
sof's avatar
sof committed
38 39
			  NULL); /* unnamed => process-local. */
  
sof's avatar
sof committed
40
  if ( h == NULL ) {
41 42
      sysErrorBelch("initCondition: unable to create");
      stg_exit(EXIT_FAILURE);
sof's avatar
sof committed
43 44
  }
  *pCond = h;
sof's avatar
sof committed
45 46 47
  return;
}

sof's avatar
sof committed
48 49
void
closeCondition( Condition* pCond )
sof's avatar
sof committed
50
{
sof's avatar
sof committed
51
  if ( CloseHandle(*pCond) == 0 ) {
52
      sysErrorBelch("closeCondition: failed to close");
sof's avatar
sof committed
53
  }
sof's avatar
sof committed
54 55 56 57
  return;
}

rtsBool
sof's avatar
sof committed
58
broadcastCondition ( Condition* pCond )
sof's avatar
sof committed
59
{
sof's avatar
sof committed
60 61
  PulseEvent(*pCond);
  return rtsTrue;
sof's avatar
sof committed
62 63 64
}

rtsBool
sof's avatar
sof committed
65
signalCondition ( Condition* pCond )
sof's avatar
sof committed
66
{
67
    if (SetEvent(*pCond) == 0) {
68 69
	sysErrorBelch("SetEvent");
	stg_exit(EXIT_FAILURE);
70 71
    }
    return rtsTrue;
sof's avatar
sof committed
72 73 74
}

rtsBool
sof's avatar
sof committed
75
waitCondition ( Condition* pCond, Mutex* pMut )
sof's avatar
sof committed
76
{
77
  RELEASE_LOCK(pMut);
sof's avatar
sof committed
78 79
  WaitForSingleObject(*pCond, INFINITE);
  /* Hmm..use WaitForMultipleObjects() ? */
80
  ACQUIRE_LOCK(pMut);
sof's avatar
sof committed
81
  return rtsTrue;
sof's avatar
sof committed
82 83
}

sof's avatar
sof committed
84 85 86 87 88 89 90
void
yieldThread()
{
  Sleep(0);
  return;
}

sof's avatar
sof committed
91 92
void
shutdownThread()
sof's avatar
sof committed
93
{
sof's avatar
sof committed
94 95 96
  _endthreadex(0);
}

sof's avatar
sof committed
97
int
98
createOSThread (OSThreadId* pId, OSThreadProc *startProc, void *param)
sof's avatar
sof committed
99
{
sof's avatar
sof committed
100
  
sof's avatar
sof committed
101 102
  return (_beginthreadex ( NULL,  /* default security attributes */
			   0,
103
			   (unsigned (__stdcall *)(void *)) startProc,
104
			   param,
sof's avatar
sof committed
105
			   0,
sof's avatar
sof committed
106
			   (unsigned*)pId) == 0);
sof's avatar
sof committed
107 108
}

sof's avatar
sof committed
109 110
OSThreadId
osThreadId()
sof's avatar
sof committed
111
{
sof's avatar
sof committed
112
  return GetCurrentThreadId();
sof's avatar
sof committed
113 114
}

115 116 117 118 119 120
#ifdef USE_CRITICAL_SECTIONS
void
initMutex (Mutex* pMut)
{
    InitializeCriticalSectionAndSpinCount(pMut,4000);
}
121 122 123 124 125
void
closeMutex (Mutex* pMut)
{
    DeleteCriticalSection(pMut);
}
126
#else
sof's avatar
sof committed
127 128
void
initMutex (Mutex* pMut)
sof's avatar
sof committed
129
{
sof's avatar
sof committed
130 131 132 133 134
  HANDLE h = CreateMutex ( NULL,  /* default sec. attributes */
			   FALSE, /* not owned => initially signalled */
			   NULL
			   );
  *pMut = h;
sof's avatar
sof committed
135 136
  return;
}
137 138 139 140 141
void
closeMutex (Mutex* pMut)
{
    CloseHandle(*pMut);
}
142
#endif
sof's avatar
sof committed
143

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
void
newThreadLocalKey (ThreadLocalKey *key)
{
    DWORD r;
    r = TlsAlloc();
    if (r == TLS_OUT_OF_INDEXES) {
	barf("newThreadLocalKey: out of keys");
    }
    *key = r;
}

void *
getThreadLocalVar (ThreadLocalKey *key)
{
    void *r;
    r = TlsGetValue(*key);
160 161 162 163
#ifdef DEBUG
    // r is allowed to be NULL - it can mean that either there was an
    // error or the stored value is in fact NULL.
    if (GetLastError() != NO_ERROR) {
164 165
	barf("getThreadLocalVar: key not found");
    }
166
#endif
167 168 169 170 171 172 173 174 175 176 177 178 179 180
    return r;
}

void
setThreadLocalVar (ThreadLocalKey *key, void *value)
{
    BOOL b;
    b = TlsSetValue(*key, value);
    if (!b) {
	barf("setThreadLocalVar: %d", GetLastError());
    }
}


181 182 183
static unsigned __stdcall
forkOS_createThreadWrapper ( void * entry )
{
184 185
    Capability *cap;
    cap = rts_lock();
186
    cap = rts_evalStableIO(cap, (HsStablePtr) entry, NULL);
187
    rts_unlock(cap);
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
    return 0;
}

int
forkOS_createThread ( HsStablePtr entry )
{
    unsigned long pId;
    return (_beginthreadex ( NULL,  /* default security attributes */
			   0,
			   forkOS_createThreadWrapper,
			   (void*)entry,
			   0,
			   (unsigned*)&pId) == 0);
}

203
#else /* !defined(THREADED_RTS) */
204 205

int
206
forkOS_createThread ( HsStablePtr entry STG_UNUSED )
207 208 209 210
{
    return -1;
}

211
#endif /* !defined(THREADED_RTS) */