1 /* ---------------------------------------------------------------------------
3 * (c) The GHC Team, 2001-2003
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
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.
18 * This header file contains the functions for working with capabilities.
19 * (the main, and only, consumer of this interface is the scheduler).
21 * --------------------------------------------------------------------------*/
23 #ifndef __CAPABILITY_H__
24 #define __CAPABILITY_H__
28 // All the capabilities
29 extern Capability *capabilities;
31 // Initialised the available capabilities.
33 extern void initCapabilities( void );
35 // Releases a capability
37 extern void releaseCapability( Capability* cap );
39 // Signal that a thread has become runnable
41 extern void threadRunnable ( void );
43 // Return the capability that I own.
45 extern Capability *myCapability (void);
47 extern void prodWorker ( void );
49 #ifdef RTS_SUPPORTS_THREADS
50 // Gives up the current capability IFF there is a higher-priority
51 // thread waiting for it. This happens in one of two ways:
53 // (a) we are passing the capability to another OS thread, so
54 // that it can run a bound Haskell thread, or
56 // (b) there is an OS thread waiting to return from a foreign call
58 // On return: *pCap is NULL if the capability was released. The
59 // current worker thread should then re-acquire it using
60 // waitForCapability().
62 extern void yieldCapability( Capability** pCap, Condition *cond );
64 // Acquires a capability for doing some work.
66 // If the current OS thread is bound to a particular Haskell thread,
67 // then pThreadCond points to a condition variable for waking up this
68 // OS thread when its Haskell thread is ready to run.
70 // On return: pCap points to the capability.
71 extern void waitForCapability( Mutex* pMutex, Capability** pCap,
72 Condition *pThreadCond );
74 // Acquires a capability at a return point.
76 // OS threads waiting in this function get priority over those waiting
77 // in waitForWorkCapability().
79 // On return: pCap points to the capability.
80 extern void waitForReturnCapability(Mutex* pMutex, Capability** pCap);
82 // Signals that the next time a capability becomes free, it should
83 // be transfered to a particular OS thread, identified by the
84 // condition variable pTargetThreadCond.
86 extern void passCapability(Condition *pTargetThreadCond);
88 // Signals that the next time a capability becomes free, it should
89 // be transfered to an ordinary worker thread.
91 extern void passCapabilityToWorker( void );
93 extern nat rts_n_free_capabilities;
95 extern Capability *free_capabilities;
97 /* number of worker threads waiting for a return capability
99 extern nat rts_n_waiting_workers;
101 static inline rtsBool needToYieldToReturningWorker(void)
103 return rts_n_waiting_workers > 0;
106 static inline nat getFreeCapabilities (void)
108 return rts_n_free_capabilities;
111 static inline rtsBool noCapabilities (void)
113 return (rts_n_free_capabilities == 0);
116 static inline rtsBool allFreeCapabilities (void)
119 return (rts_n_free_capabilities == RTS_DEREF(RtsFlags).ParFlags.nNodes);
121 return (rts_n_free_capabilities == 1);
125 #else // !RTS_SUPPORTS_THREADS
127 // Grab a capability. (Only in the non-threaded RTS; in the threaded
128 // RTS one of the waitFor*Capability() functions must be used).
130 extern void grabCapability( Capability **pCap );
132 #endif /* !RTS_SUPPORTS_THREADS */
134 #endif /* __CAPABILITY_H__ */