1 /** 2 * \file 3 * Worker threads for parallel and concurrent GC. 4 * 5 * Copyright 2011 Xamarin Inc (http://www.xamarin.com) 6 * Copyright (C) 2012 Xamarin Inc 7 * 8 * Licensed under the MIT license. See LICENSE file in the project root for full license information. 9 */ 10 11 #ifndef __MONO_SGEN_WORKER_H__ 12 #define __MONO_SGEN_WORKER_H__ 13 14 #include "mono/sgen/sgen-thread-pool.h" 15 16 typedef struct _WorkerData WorkerData; 17 typedef struct _WorkerContext WorkerContext; 18 19 typedef gint32 State; 20 21 typedef void (*SgenWorkersFinishCallback) (void); 22 typedef void (*SgenWorkerCallback) (WorkerData *data); 23 24 struct _WorkerData { 25 gint32 state; 26 SgenGrayQueue private_gray_queue; /* only read/written by worker thread */ 27 /* 28 * Workers allocate major objects only from here. It has same structure as the 29 * global one. This is normally accessed from the worker_block_free_list_key. 30 * We hold it here so we can clear free lists from all threads before sweep 31 * starts. 32 */ 33 gpointer free_block_lists; 34 WorkerContext *context; 35 36 /* Work time distribution. Measured in ticks. */ 37 gint64 major_scan_time, los_scan_time, total_time; 38 /* 39 * When changing the state of the worker from not working to work enqueued 40 * we set the timestamp so we can compute for how long the worker did actual 41 * work during the phase 42 */ 43 gint64 last_start; 44 }; 45 46 struct _WorkerContext { 47 int workers_num; 48 int active_workers_num; 49 volatile gboolean started; 50 volatile gboolean forced_stop; 51 WorkerData *workers_data; 52 53 /* 54 * When using multiple workers, we need to have the last worker 55 * enqueue the preclean jobs (if there are any). This lock ensures 56 * that when the last worker takes it, all the other workers have 57 * gracefully finished, so it can restart them. 58 */ 59 mono_mutex_t finished_lock; 60 volatile gboolean workers_finished; 61 int worker_awakenings; 62 63 SgenSectionGrayQueue workers_distribute_gray_queue; 64 65 SgenObjectOperations * volatile idle_func_object_ops; 66 SgenObjectOperations *idle_func_object_ops_par, *idle_func_object_ops_nopar; 67 68 /* 69 * finished_callback is called only when the workers finish work normally (when they 70 * are not forced to finish). The callback is used to enqueue preclean jobs. 71 */ 72 volatile SgenWorkersFinishCallback finish_callback; 73 74 int generation; 75 int thread_pool_context; 76 }; 77 78 void sgen_workers_create_context (int generation, int num_workers); 79 void sgen_workers_stop_all_workers (int generation); 80 void sgen_workers_set_num_active_workers (int generation, int num_workers); 81 void sgen_workers_start_all_workers (int generation, SgenObjectOperations *object_ops_nopar, SgenObjectOperations *object_ops_par, SgenWorkersFinishCallback finish_job); 82 void sgen_workers_enqueue_job (int generation, SgenThreadPoolJob *job, gboolean enqueue); 83 void sgen_workers_join (int generation); 84 gboolean sgen_workers_have_idle_work (int generation); 85 gboolean sgen_workers_all_done (void); 86 void sgen_workers_assert_gray_queue_is_empty (int generation); 87 void sgen_workers_take_from_queue (int generation, SgenGrayQueue *queue); 88 SgenObjectOperations* sgen_workers_get_idle_func_object_ops (WorkerData *worker); 89 int sgen_workers_get_job_split_count (int generation); 90 void sgen_workers_foreach (int generation, SgenWorkerCallback callback); 91 gboolean sgen_workers_is_worker_thread (MonoNativeThreadId id); 92 93 #endif 94