OSThreads.c 3.73 KB
Newer Older
sof's avatar
sof committed
1 2 3 4 5 6 7 8 9 10 11 12
/* ---------------------------------------------------------------------------
 *
 * (c) The GHC Team, 2001
 *
 * Accessing OS threads functionality in a (mostly) OS-independent
 * manner. 
 *
 * 
 * --------------------------------------------------------------------------*/
#include "Rts.h"
#if defined(RTS_SUPPORTS_THREADS)
#include "OSThreads.h"
sof's avatar
sof committed
13
#include "RtsUtils.h"
sof's avatar
sof committed
14 15 16 17 18 19 20 21 22

#if defined(HAVE_PTHREAD_H) && !defined(WANT_NATIVE_WIN32_THREADS)
/*
 * This (allegedly) OS threads independent layer was initially
 * abstracted away from code that used Pthreads, so the functions
 * provided here are mostly just wrappers to the Pthreads API.
 *
 */

sof's avatar
sof committed
23 24
void
initCondition( Condition* pCond )
sof's avatar
sof committed
25 26 27 28 29
{
  pthread_cond_init(pCond, NULL);
  return;
}

sof's avatar
sof committed
30 31
void
closeCondition( Condition* pCond )
sof's avatar
sof committed
32 33 34 35 36 37
{
  pthread_cond_destroy(pCond);
  return;
}

rtsBool
sof's avatar
sof committed
38
broadcastCondition ( Condition* pCond )
sof's avatar
sof committed
39 40 41 42 43
{
  return (pthread_cond_broadcast(pCond) == 0);
}

rtsBool
sof's avatar
sof committed
44
signalCondition ( Condition* pCond )
sof's avatar
sof committed
45 46 47 48 49
{
  return (pthread_cond_signal(pCond) == 0);
}

rtsBool
sof's avatar
sof committed
50
waitCondition ( Condition* pCond, Mutex* pMut )
sof's avatar
sof committed
51 52 53 54
{
  return (pthread_cond_wait(pCond,pMut) == 0);
}

sof's avatar
sof committed
55 56 57 58 59 60 61 62 63
void
yieldThread()
{
  sched_yield();
  return;
}

void
shutdownThread()
sof's avatar
sof committed
64 65 66 67
{
  pthread_exit(NULL);
}

sof's avatar
sof committed
68 69 70 71 72 73 74 75 76 77 78 79
/* Don't need the argument nor the result, at least not yet. */
static void* startProcWrapper(void* pProc);
static void*
startProcWrapper(void* pProc)
{
  ((void (*)(void))pProc)();
  return NULL;
}


int
createOSThread ( OSThreadId* pId, void (*startProc)(void))
sof's avatar
sof committed
80
{
81 82 83 84
  int result = pthread_create(pId, NULL, startProcWrapper, (void*)startProc);
  if(!result)
    pthread_detach(*pId);
  return result;
sof's avatar
sof committed
85 86
}

sof's avatar
sof committed
87 88
OSThreadId
osThreadId()
sof's avatar
sof committed
89 90 91 92
{
  return pthread_self();
}

sof's avatar
sof committed
93 94
void
initMutex(Mutex* pMut)
sof's avatar
sof committed
95 96 97 98 99 100
{
  pthread_mutex_init(pMut,NULL);
  return;
}

#elif defined(HAVE_WINDOWS_H)
sof's avatar
sof committed
101 102
#include <process.h>

sof's avatar
sof committed
103 104
/* Win32 threads and synchronisation objects */

sof's avatar
sof committed
105 106
/* A Condition is represented by a Win32 Event object;
 * a Mutex by a Mutex kernel object.
sof's avatar
sof committed
107 108 109 110 111
 *
 * 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
112 113
 */

sof's avatar
sof committed
114 115
void
initCondition( Condition* pCond )
sof's avatar
sof committed
116 117
{
  HANDLE h =  CreateEvent(NULL, 
sof's avatar
sof committed
118 119
			  FALSE,  /* auto reset */
			  FALSE,  /* initially not signalled */
sof's avatar
sof committed
120 121
			  NULL); /* unnamed => process-local. */
  
sof's avatar
sof committed
122
  if ( h == NULL ) {
sof's avatar
sof committed
123
    belch("initCondition: unable to create");
sof's avatar
sof committed
124 125
  }
  *pCond = h;
sof's avatar
sof committed
126 127 128
  return;
}

sof's avatar
sof committed
129 130
void
closeCondition( Condition* pCond )
sof's avatar
sof committed
131
{
sof's avatar
sof committed
132
  if ( CloseHandle(*pCond) == 0 ) {
sof's avatar
sof committed
133
    belch("closeCondition: failed to close");
sof's avatar
sof committed
134
  }
sof's avatar
sof committed
135 136 137 138
  return;
}

rtsBool
sof's avatar
sof committed
139
broadcastCondition ( Condition* pCond )
sof's avatar
sof committed
140
{
sof's avatar
sof committed
141 142
  PulseEvent(*pCond);
  return rtsTrue;
sof's avatar
sof committed
143 144 145
}

rtsBool
sof's avatar
sof committed
146
signalCondition ( Condition* pCond )
sof's avatar
sof committed
147
{
sof's avatar
sof committed
148 149
  SetEvent(*pCond);
  return rtsTrue;
sof's avatar
sof committed
150 151 152
}

rtsBool
sof's avatar
sof committed
153
waitCondition ( Condition* pCond, Mutex* pMut )
sof's avatar
sof committed
154
{
sof's avatar
sof committed
155 156 157 158 159
  ReleaseMutex(*pMut);
  WaitForSingleObject(*pCond, INFINITE);
  /* Hmm..use WaitForMultipleObjects() ? */
  WaitForSingleObject(*pMut, INFINITE);
  return rtsTrue;
sof's avatar
sof committed
160 161
}

sof's avatar
sof committed
162 163 164 165 166 167 168
void
yieldThread()
{
  Sleep(0);
  return;
}

sof's avatar
sof committed
169 170
void
shutdownThread()
sof's avatar
sof committed
171
{
sof's avatar
sof committed
172 173 174 175
  _endthreadex(0);
}

static unsigned __stdcall startProcWrapper(void* pReal);
sof's avatar
sof committed
176 177
static unsigned __stdcall
startProcWrapper(void* pReal)
sof's avatar
sof committed
178
{
sof's avatar
sof committed
179
  ((void (*)(void))pReal)();
sof's avatar
sof committed
180
  return 0;
sof's avatar
sof committed
181 182
}

sof's avatar
sof committed
183
int
sof's avatar
sof committed
184
createOSThread ( OSThreadId* pId, void (*startProc)(void))
sof's avatar
sof committed
185
{
sof's avatar
sof committed
186
  
sof's avatar
sof committed
187 188 189 190 191
  return (_beginthreadex ( NULL,  /* default security attributes */
			   0,
			   startProcWrapper,
			   (void*)startProc,
			   0,
sof's avatar
sof committed
192
			   (unsigned*)pId) == 0);
sof's avatar
sof committed
193 194
}

sof's avatar
sof committed
195 196
OSThreadId
osThreadId()
sof's avatar
sof committed
197
{
sof's avatar
sof committed
198
  return GetCurrentThreadId();
sof's avatar
sof committed
199 200
}

sof's avatar
sof committed
201 202
void
initMutex (Mutex* pMut)
sof's avatar
sof committed
203
{
sof's avatar
sof committed
204 205 206 207 208
  HANDLE h = CreateMutex ( NULL,  /* default sec. attributes */
			   FALSE, /* not owned => initially signalled */
			   NULL
			   );
  *pMut = h;
sof's avatar
sof committed
209 210 211 212 213 214
  return;
}

#endif /* defined(HAVE_PTHREAD_H) */

#endif /* defined(RTS_SUPPORTS_THREADS) */