[project @ 2005-04-06 15:27:06 by simonmar]
[ghc-hetmet.git] / ghc / rts / Capability.h
1 /* ---------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 2001-2003
4  *
5  * Capabilities
6  *
7  * The notion of a capability is used when operating in multi-threaded
8  * environments (which the SMP and Threads builds of the RTS do), to
9  * hold all the state an OS thread/task needs to run Haskell code:
10  * its STG registers, a pointer to its  TSO, a nursery etc. During
11  * STG execution, a pointer to the capabilitity is kept in a 
12  * register (BaseReg).
13  *
14  * Only in an SMP build will there be multiple capabilities, the threaded
15  * RTS and other non-threaded builds, there is one global capability,
16  * namely MainRegTable.
17  *
18  * This header file contains the functions for working with capabilities.
19  * (the main, and only, consumer of this interface is the scheduler).
20  * 
21  * --------------------------------------------------------------------------*/
22
23 #ifndef __CAPABILITY_H__
24 #define __CAPABILITY_H__
25
26 // Initialised the available capabilities.
27 //
28 extern void initCapabilities( void );
29
30 // Releases a capability
31 //
32 extern void releaseCapability( Capability* cap );
33
34 // Signal that a thread has become runnable
35 //
36 extern void threadRunnable ( void );
37
38 extern void prodWorker ( void );
39
40 #ifdef RTS_SUPPORTS_THREADS
41 // Gives up the current capability IFF there is a higher-priority
42 // thread waiting for it.  This happens in one of two ways:
43 //
44 //   (a) we are passing the capability to another OS thread, so
45 //       that it can run a bound Haskell thread, or
46 //
47 //   (b) there is an OS thread waiting to return from a foreign call
48 //
49 // On return: *pCap is NULL if the capability was released.  The
50 // current worker thread should then re-acquire it using
51 // waitForCapability().
52 //
53 extern void yieldCapability( Capability **pCap );
54
55 // Acquires a capability for doing some work.
56 //
57 // If the current OS thread is bound to a particular Haskell thread,
58 // then pThreadCond points to a condition variable for waking up this
59 // OS thread when its Haskell thread is ready to run.
60 //
61 // On return: pCap points to the capability.
62 extern void waitForCapability( Mutex* pMutex, Capability** pCap, 
63                                Condition *pThreadCond );
64
65 // Acquires a capability at a return point.  
66 //
67 // OS threads waiting in this function get priority over those waiting
68 // in waitForWorkCapability().
69 //
70 // On return: pCap points to the capability.
71 extern void waitForReturnCapability(Mutex* pMutex, Capability** pCap);
72
73 // Signals that the next time a capability becomes free, it should
74 // be transfered to a particular OS thread, identified by the
75 // condition variable pTargetThreadCond.
76 //
77 extern void passCapability(Condition *pTargetThreadCond);
78
79 // Signals that the next time a capability becomes free, it should
80 // be transfered to an ordinary worker thread.
81 //
82 extern void passCapabilityToWorker( void );
83
84 extern nat rts_n_free_capabilities;  
85
86 extern Capability *free_capabilities;
87
88 /* number of worker threads waiting for a return capability
89  */
90 extern nat rts_n_waiting_workers;
91
92 static inline rtsBool needToYieldToReturningWorker(void)
93 {
94         return rts_n_waiting_workers > 0;
95 }
96
97 static inline nat getFreeCapabilities (void)
98 {
99   return rts_n_free_capabilities;
100 }
101
102 static inline rtsBool noCapabilities (void)
103 {
104   return (rts_n_free_capabilities == 0);
105 }
106
107 static inline rtsBool allFreeCapabilities (void)
108 {
109 #if defined(SMP)
110   return (rts_n_free_capabilities == RTS_DEREF(RtsFlags).ParFlags.nNodes);
111 #else
112   return (rts_n_free_capabilities == 1);
113 #endif
114 }
115
116 #else // !RTS_SUPPORTS_THREADS
117
118 // Grab a capability.  (Only in the non-threaded RTS; in the threaded
119 // RTS one of the waitFor*Capability() functions must be used).
120 //
121 extern void grabCapability( Capability **pCap );
122
123 #endif /* !RTS_SUPPORTS_THREADS */
124
125 #endif /* __CAPABILITY_H__ */