@@ -0,0 +1,209 @@
3+// The InCall structure represents either a single in-call from C to
4+// Haskell, or a worker thread.
5+typedef 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
17+ SchedulerStatus rstat; // return status
18+ StgClosure ** ret; // return value
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;
34+typedef 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.
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
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;
66+ struct InCall_ *spare_incalls;
68+ rtsBool worker; // == rtsTrue if this is a worker Task
69+ rtsBool stopped; // this task has stopped or exited Haskell
71+ // So that we can detect when a finalizer illegally calls back into Haskell
72+ rtsBool running_finalizers;
74+ // Links tasks on the returning_tasks queue of a Capability, and
78+ // Links tasks on the all_tasks list; need ACQUIRE_LOCK(&all_tasks_mutex)
79+ struct Task_ *all_next;
80+ struct Task_ *all_prev;
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).
91+ nat 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.
99+ // true if this Capability is running Haskell code, used for
100+ // catching unsafe call-ins.
103+ // Has there been any activity on this Capability since the last GC?
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
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
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.
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.
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.
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.
155+ // Total words allocated by this cap since rts start
156+ // See [Note allocation accounting] in Storage.c
159+#if defined(THREADED_RTS)
160+ // Worker Tasks waiting in the wings. Singly-linked.
161+ Task *spare_workers;
162+ nat n_spare_workers; // count of above
164+ // This lock protects:
166+ // returning_tasks_{hd,tl}
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
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;
193+ // Per-capability STM-related data
194+ StgTVarWatchQueue *free_tvar_watch_queues;
195+ StgInvariantCheckQueue *free_invariant_check_queues;
196+ StgTRecChunk *free_trec_chunks;
197+ StgTRecHeader *free_trec_headers;
198+ nat transaction_tokens;
199+} // typedef Capability is defined in RtsAPI.h
200+ // We never want a Capability to overlap a cache line with anything
201+ // else, so round it up to a cache line size:
202+#ifndef mingw32_HOST_OS
203+ ATTRIBUTE_ALIGNED(64)
207+HsBool myCapabilityHasOtherRunnableThreads() {
208+ return rts_unsafeGetMyCapability()->run_queue_hd == END_TSO_QUEUE ? HS_BOOL_FALSE : HS_BOOL_TRUE;