+ /*
+ * Workers allocate major objects only from here. It has same structure as the
+ * global one. This is normally accessed from the worker_block_free_list_key.
+ * We hold it here so we can clear free lists from all threads before sweep
+ * starts.
+ */
+ gpointer free_block_lists;
+ WorkerContext *context;
+
+ /* Work time distribution. Measured in ticks. */
+ gint64 major_scan_time, los_scan_time, total_time;
+ /*
+ * When changing the state of the worker from not working to work enqueued
+ * we set the timestamp so we can compute for how long the worker did actual
+ * work during the phase
+ */
+ gint64 last_start;
+};
+
+struct _WorkerContext {
+ int workers_num;
+ int active_workers_num;
+ volatile gboolean started;
+ volatile gboolean forced_stop;
+ WorkerData *workers_data;
+
+ /*
+ * When using multiple workers, we need to have the last worker
+ * enqueue the preclean jobs (if there are any). This lock ensures
+ * that when the last worker takes it, all the other workers have
+ * gracefully finished, so it can restart them.
+ */
+ mono_mutex_t finished_lock;
+ volatile gboolean workers_finished;
+ int worker_awakenings;
+
+ SgenSectionGrayQueue workers_distribute_gray_queue;
+
+ SgenObjectOperations * volatile idle_func_object_ops;
+ SgenObjectOperations *idle_func_object_ops_par, *idle_func_object_ops_nopar;
+
+ /*
+ * finished_callback is called only when the workers finish work normally (when they
+ * are not forced to finish). The callback is used to enqueue preclean jobs.
+ */
+ volatile SgenWorkersFinishCallback finish_callback;
+
+ int generation;
+ int thread_pool_context;