root/includes/rts/OSThreads.h

Revision 8b48562e8cd773b4bc162edb4fc6d05a7654c7e1, 6.4 KB (checked in by Simon Marlow <marlowsd@…>, 6 months ago)

Define getNumberOfProcessors() even when !THREADED_RTS

  • Property mode set to 100644
Line 
1/* ---------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 2001-2009
4 *
5 * Accessing OS threads functionality in a (mostly) OS-independent
6 * manner.
7 *
8 * Do not #include this file directly: #include "Rts.h" instead.
9 *
10 * To understand the structure of the RTS headers, see the wiki:
11 *   http://hackage.haskell.org/trac/ghc/wiki/Commentary/SourceTree/Includes
12 *
13 * --------------------------------------------------------------------------*/
14
15#ifndef RTS_OSTHREADS_H
16#define RTS_OSTHREADS_H
17
18#if defined(THREADED_RTS) /* to the end */
19
20#if defined(HAVE_PTHREAD_H) && !defined(mingw32_HOST_OS)
21
22#if CMINUSMINUS
23
24#define ACQUIRE_LOCK(mutex) foreign "C" pthread_mutex_lock(mutex)
25#define RELEASE_LOCK(mutex) foreign "C" pthread_mutex_unlock(mutex)
26#define ASSERT_LOCK_HELD(mutex) /* nothing */
27
28#else
29
30#include <pthread.h>
31#include <errno.h>
32
33typedef pthread_cond_t  Condition;
34typedef pthread_mutex_t Mutex;
35typedef pthread_t       OSThreadId;
36typedef pthread_key_t   ThreadLocalKey;
37
38#define OSThreadProcAttr /* nothing */
39
40#define INIT_COND_VAR       PTHREAD_COND_INITIALIZER
41
42#ifdef LOCK_DEBUG
43#define LOCK_DEBUG_BELCH(what, mutex) \
44  debugBelch("%s(0x%p) %s %d\n", what, mutex, __FILE__, __LINE__)
45#else
46#define LOCK_DEBUG_BELCH(what, mutex) /* nothing */
47#endif
48
49/* Always check the result of lock and unlock. */
50#define ACQUIRE_LOCK(mutex) \
51  LOCK_DEBUG_BELCH("ACQUIRE_LOCK", mutex); \
52  if (pthread_mutex_lock(mutex) == EDEADLK) { \
53    barf("multiple ACQUIRE_LOCK: %s %d", __FILE__,__LINE__); \
54  }
55
56// Returns zero if the lock was acquired.
57EXTERN_INLINE int TRY_ACQUIRE_LOCK(pthread_mutex_t *mutex);
58EXTERN_INLINE int TRY_ACQUIRE_LOCK(pthread_mutex_t *mutex)
59{
60    LOCK_DEBUG_BELCH("TRY_ACQUIRE_LOCK", mutex);
61    return pthread_mutex_trylock(mutex);
62}
63
64#define RELEASE_LOCK(mutex) \
65  LOCK_DEBUG_BELCH("RELEASE_LOCK", mutex); \
66  if (pthread_mutex_unlock(mutex) != 0) { \
67    barf("RELEASE_LOCK: I do not own this lock: %s %d", __FILE__,__LINE__); \
68  }
69
70// Note: this assertion calls pthread_mutex_lock() on a mutex that
71// is already held by the calling thread.  The mutex should therefore
72// have been created with PTHREAD_MUTEX_ERRORCHECK, otherwise this
73// assertion will hang.  We always initialise mutexes with
74// PTHREAD_MUTEX_ERRORCHECK when DEBUG is on (see rts/posix/OSThreads.h).
75#define ASSERT_LOCK_HELD(mutex) ASSERT(pthread_mutex_lock(mutex) == EDEADLK)
76
77#endif // CMINUSMINUS
78
79# elif defined(HAVE_WINDOWS_H)
80
81#if CMINUSMINUS
82
83/* We jump through a hoop here to get a CCall EnterCriticalSection
84   and LeaveCriticalSection, as that's what C-- wants. */
85
86#define ACQUIRE_LOCK(mutex) foreign "stdcall" EnterCriticalSection(mutex)
87#define RELEASE_LOCK(mutex) foreign "stdcall" LeaveCriticalSection(mutex)
88#define ASSERT_LOCK_HELD(mutex) /* nothing */
89
90#else
91
92#include <windows.h>
93
94typedef HANDLE Condition;
95typedef DWORD OSThreadId;
96// don't be tempted to use HANDLE as the OSThreadId: there can be
97// many HANDLES to a given thread, so comparison would not work.
98typedef DWORD ThreadLocalKey;
99
100#define OSThreadProcAttr __stdcall
101
102#define INIT_COND_VAR  0
103
104// We have a choice for implementing Mutexes on Windows.  Standard
105// Mutexes are kernel objects that require kernel calls to
106// acquire/release, whereas CriticalSections are spin-locks that block
107// in the kernel after spinning for a configurable number of times.
108// CriticalSections are *much* faster, so we use those.  The Mutex
109// implementation is left here for posterity.
110#define USE_CRITICAL_SECTIONS 1
111
112#if USE_CRITICAL_SECTIONS
113
114typedef CRITICAL_SECTION Mutex;
115
116#ifdef LOCK_DEBUG
117
118#define ACQUIRE_LOCK(mutex) \
119  debugBelch("ACQUIRE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
120  EnterCriticalSection(mutex)
121#define RELEASE_LOCK(mutex) \
122  debugBelch("RELEASE_LOCK(0x%p) %s %d\n", mutex,__FILE__,__LINE__); \
123  LeaveCriticalSection(mutex)
124#define ASSERT_LOCK_HELD(mutex) /* nothing */
125
126#else
127
128#define ACQUIRE_LOCK(mutex)      EnterCriticalSection(mutex)
129#define TRY_ACQUIRE_LOCK(mutex)  (TryEnterCriticalSection(mutex) == 0)
130#define RELEASE_LOCK(mutex)      LeaveCriticalSection(mutex)
131
132// I don't know how to do this.  TryEnterCriticalSection() doesn't do
133// the right thing.
134#define ASSERT_LOCK_HELD(mutex) /* nothing */
135
136#endif
137
138#else
139
140typedef HANDLE Mutex;
141
142// casting to (Mutex *) here required due to use in .cmm files where
143// the argument has (void *) type.
144#define ACQUIRE_LOCK(mutex)                                     \
145    if (WaitForSingleObject(*((Mutex *)mutex),INFINITE) == WAIT_FAILED) { \
146        barf("WaitForSingleObject: %d", GetLastError());        \
147    }
148
149#define RELEASE_LOCK(mutex)                             \
150    if (ReleaseMutex(*((Mutex *)mutex)) == 0) {         \
151        barf("ReleaseMutex: %d", GetLastError());       \
152    }
153
154#define ASSERT_LOCK_HELD(mutex) /* nothing */
155#endif
156
157#endif // CMINUSMINUS
158
159# else
160#  error "Threads not supported"
161# endif
162
163
164#ifndef CMINUSMINUS
165//
166// General thread operations
167//
168extern OSThreadId osThreadId      ( void );
169extern void shutdownThread        ( void )   GNUC3_ATTRIBUTE(__noreturn__);
170extern void yieldThread           ( void );
171
172typedef void OSThreadProcAttr OSThreadProc(void *);
173
174extern int  createOSThread        ( OSThreadId* tid, 
175                                    OSThreadProc *startProc, void *param);
176extern rtsBool osThreadIsAlive    ( OSThreadId id );
177extern void interruptOSThread (OSThreadId id);
178
179//
180// Condition Variables
181//
182extern void initCondition         ( Condition* pCond );
183extern void closeCondition        ( Condition* pCond );
184extern rtsBool broadcastCondition ( Condition* pCond );
185extern rtsBool signalCondition    ( Condition* pCond );
186extern rtsBool waitCondition      ( Condition* pCond, Mutex* pMut );
187
188//
189// Mutexes
190//
191extern void initMutex             ( Mutex* pMut );
192extern void closeMutex            ( Mutex* pMut );
193
194//
195// Thread-local storage
196//
197void  newThreadLocalKey (ThreadLocalKey *key);
198void *getThreadLocalVar (ThreadLocalKey *key);
199void  setThreadLocalVar (ThreadLocalKey *key, void *value);
200void  freeThreadLocalKey (ThreadLocalKey *key);
201
202// Processors and affinity
203void setThreadAffinity     (nat n, nat m);
204#endif // !CMINUSMINUS
205
206#else
207
208#define ACQUIRE_LOCK(l)
209#define RELEASE_LOCK(l)
210#define ASSERT_LOCK_HELD(l)
211
212#endif /* defined(THREADED_RTS) */
213
214#ifndef CMINUSMINUS
215//
216// Support for forkOS (defined regardless of THREADED_RTS, but does
217// nothing when !THREADED_RTS).
218//
219int forkOS_createThread ( HsStablePtr entry );
220
221//
222// Returns the number of processor cores in the machine
223//
224nat getNumberOfProcessors (void);
225#endif
226
227#endif /* RTS_OSTHREADS_H */
Note: See TracBrowser for help on using the browser.