1 /* ---------------------------------------------------------------------------
3 * (c) The GHC Team, 2001
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.
19 * --------------------------------------------------------------------------*/
20 #include "PosixSource.h"
24 #include "Capability.h"
27 Capability MainCapability; /* for non-SMP, we have one global capability */
30 nat rts_n_free_capabilities;
34 initCapability( Capability *cap )
36 cap->f.stgChk0 = (F_)__stg_chk_0;
37 cap->f.stgChk1 = (F_)__stg_chk_1;
38 cap->f.stgGCEnter1 = (F_)__stg_gc_enter_1;
39 cap->f.stgUpdatePAP = (F_)__stg_update_PAP;
43 static void initCapabilities_(nat n);
52 initCapabilities_(RtsFlags.ParFlags.nNodes);
54 initCapability(&MainCapability);
55 rts_n_free_capabilities = 1;
61 /* Free capability list.
62 * Locks required: sched_mutex.
65 static Capability *free_capabilities; /* Available capabilities for running threads */
68 void grabCapability(Capability** cap)
71 rts_n_free_capabilities = 0;
72 *cap = &MainCapability;
74 *cap = free_capabilities;
75 free_capabilities = (*cap)->link;
76 rts_n_free_capabilities--;
81 * Letting go of a capability
83 * Locks required: sched_mutex
85 void releaseCapability(Capability* cap
92 cap->link = free_capabilities;
93 free_capabilities = cap;
94 rts_n_free_capabilities++;
96 rts_n_free_capabilities = 1;
99 #if defined(RTS_SUPPORTS_THREADS)
100 /* Check to see whether a worker thread can be given
101 the go-ahead to return the result of an external call..*/
102 if (rts_n_waiting_workers > 0) {
103 /* The worker is responsible for grabbing the capability and
104 * decrementing the rts_n_returning_workers count
106 signalCondition(&returning_worker_cond);
107 } else if ( !EMPTY_RUN_QUEUE() ) {
108 /* Signal that work is available */
109 signalCondition(&thread_ready_cond);
116 /* Allocate 'n' capabilities */
118 initCapabilities_(nat n)
121 Capability *cap, *prev;
124 for (i = 0; i < n; i++) {
125 cap = stgMallocBytes(sizeof(Capability), "initCapabilities");
130 free_capabilities = cap;
131 rts_n_free_capabilities = n;
132 IF_DEBUG(scheduler,fprintf(stderr,"scheduler: Allocated %d capabilities\n", n_free_capabilities););