on fa75664 help sign in
patch/bench-cbits/checkCapability.c
208 lines 7.8 kB history raw
1#include <Rts.h>
3// The InCall structure represents either a single in-call from C to
4// Haskell, or a worker thread.
5typedef struct InCall_ {
6 StgTSO * tso; // the bound TSO (or NULL for a worker)
8 StgTSO * suspended_tso; // the TSO is stashed here when we
9 // make a foreign call (NULL otherwise);
11 Capability *suspended_cap; // The capability that the
12 // suspended_tso is on, because
13 // we can't read this from the TSO
14 // without owning a Capability in the
15 // first place.
17 SchedulerStatus rstat; // return status
18 StgClosure ** ret; // return value
20 struct Task_ *task;
22 // When a Haskell thread makes a foreign call that re-enters
23 // Haskell, we end up with another Task associated with the
24 // current thread. We have to remember the whole stack of InCalls
25 // associated with the current Task so that we can correctly
26 // save & restore the InCall on entry to and exit from Haskell.
27 struct InCall_ *prev_stack;
29 // Links InCalls onto suspended_ccalls, spare_incalls
30 struct InCall_ *prev;
31 struct InCall_ *next;
32} InCall;
34typedef struct Task_ {
35#if defined(THREADED_RTS)
36 OSThreadId id; // The OS Thread ID of this task
38 Condition cond; // used for sleeping & waking up this task
39 Mutex lock; // lock for the condition variable
41 // this flag tells the task whether it should wait on task->cond
42 // or just continue immediately. It's a workaround for the fact
43 // that signalling a condition variable doesn't do anything if the
44 // thread is already running, but we want it to be sticky.
45 HsBool wakeup;
46#endif
48 // This points to the Capability that the Task "belongs" to. If
49 // the Task owns a Capability, then task->cap points to it. If
50 // the task does not own a Capability, then either (a) if the task
51 // is a worker, then task->cap points to the Capability it belongs
52 // to, or (b) it is returning from a foreign call, then task->cap
53 // points to the Capability with the returning_worker queue that this
54 // this Task is on.
55 //
56 // When a task goes to sleep, it may be migrated to a different
57 // Capability. Hence, we always check task->cap on wakeup. To
58 // syncrhonise between the migrater and the migratee, task->lock
59 // must be held when modifying task->cap.
60 struct Capability_ *cap;
62 // The current top-of-stack InCall
63 struct InCall_ *incall;
65 uint32_t n_spare_incalls;
66 struct InCall_ *spare_incalls;
68 HsBool worker; // == rtsTrue if this is a worker Task
69 HsBool stopped; // this task has stopped or exited Haskell
71 // So that we can detect when a finalizer illegally calls back into Haskell
72 HsBool running_finalizers;
74 // Links tasks on the returning_tasks queue of a Capability, and
75 // on spare_workers.
76 struct Task_ *next;
78 // Links tasks on the all_tasks list; need ACQUIRE_LOCK(&all_tasks_mutex)
79 struct Task_ *all_next;
80 struct Task_ *all_prev;
82} Task;
84struct Capability_ {
85 // State required by the STG virtual machine when running Haskell
86 // code. During STG execution, the BaseReg register always points
87 // to the StgRegTable of the current Capability (&cap->r).
88 StgFunTable f;
89 StgRegTable r;
91 uint32_t no; // capability number.
93 // The Task currently holding this Capability. This task has
94 // exclusive access to the contents of this Capability (apart from
95 // returning_tasks_hd/returning_tasks_tl).
96 // Locks required: cap->lock.
97 Task *running_task;
99 // true if this Capability is running Haskell code, used for
100 // catching unsafe call-ins.
101 HsBool in_haskell;
103 // Has there been any activity on this Capability since the last GC?
104 uint32_t idle;
106 HsBool disabled;
108 // The run queue. The Task owning this Capability has exclusive
109 // access to its run queue, so can wake up threads without
110 // taking a lock, and the common path through the scheduler is
111 // also lock-free.
112 StgTSO *run_queue_hd;
113 StgTSO *run_queue_tl;
115 // Tasks currently making safe foreign calls. Doubly-linked.
116 // When returning, a task first acquires the Capability before
117 // removing itself from this list, so that the GC can find all
118 // the suspended TSOs easily. Hence, when migrating a Task from
119 // the returning_tasks list, we must also migrate its entry from
120 // this list.
121 InCall *suspended_ccalls;
123 // One mutable list per generation, so we don't need to take any
124 // locks when updating an old-generation thunk. This also lets us
125 // keep track of which closures this CPU has been mutating, so we
126 // can traverse them using the right thread during GC and avoid
127 // unnecessarily moving the data from one cache to another.
128 bdescr **mut_lists;
129 bdescr **saved_mut_lists; // tmp use during GC
131 // block for allocating pinned objects into
132 bdescr *pinned_object_block;
133 // full pinned object blocks allocated since the last GC
134 bdescr *pinned_object_blocks;
136 // per-capability weak pointer list associated with nursery (older
137 // lists stored in generation object)
138 StgWeak *weak_ptr_list_hd;
139 StgWeak *weak_ptr_list_tl;
141 // Context switch flag. When non-zero, this means: stop running
142 // Haskell code, and switch threads.
143 int context_switch;
145 // Interrupt flag. Like the context_switch flag, this also
146 // indicates that we should stop running Haskell code, but we do
147 // *not* switch threads. This is used to stop a Capability in
148 // order to do GC, for example.
149 //
150 // The interrupt flag is always reset before we start running
151 // Haskell code, unlike the context_switch flag which is only
152 // reset after we have executed the context switch.
153 int interrupt;
155 // Total words allocated by this cap since rts start
156 // See [Note allocation accounting] in Storage.c
157 W_ total_allocated;
159#if defined(THREADED_RTS)
160 // Worker Tasks waiting in the wings. Singly-linked.
161 Task *spare_workers;
162 uint32_t n_spare_workers; // count of above
164 // This lock protects:
165 // running_task
166 // returning_tasks_{hd,tl}
167 // wakeup_queue
168 // inbox
169 Mutex lock;
171 // Tasks waiting to return from a foreign call, or waiting to make
172 // a new call-in using this Capability (NULL if empty).
173 // NB. this field needs to be modified by tasks other than the
174 // running_task, so it requires cap->lock to modify. A task can
175 // check whether it is NULL without taking the lock, however.
176 Task *returning_tasks_hd; // Singly-linked, with head/tail
177 Task *returning_tasks_tl;
179 // Messages, or END_TSO_QUEUE.
180 // Locks required: cap->lock
181 Message *inbox;
183 SparkPool *sparks;
185 // Stats on spark creation/conversion
186 SparkCounters spark_stats;
187#if !defined(mingw32_HOST_OS)
188 // IO manager for this cap
189 int io_manager_control_wr_fd;
190#endif
191#endif
193 // Per-capability STM-related data
194 StgTVarWatchQueue *free_tvar_watch_queues;
195 StgTRecChunk *free_trec_chunks;
196 StgTRecHeader *free_trec_headers;
197 uint32_t transaction_tokens;
198} // typedef Capability is defined in RtsAPI.h
199 // We never want a Capability to overlap a cache line with anything
200 // else, so round it up to a cache line size:
201#ifndef mingw32_HOST_OS
202 ATTRIBUTE_ALIGNED(64)
203#endif
204 ;
206HsBool myCapabilityHasOtherRunnableThreads() {
207 return rts_unsafeGetMyCapability()->run_queue_hd == END_TSO_QUEUE ? HS_BOOL_FALSE : HS_BOOL_TRUE;