X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fsgen%2Fsgen-workers.h;h=e3147f051af78a87304ce3ffb150f0daeb7f2b74;hb=787faec0048b660f3aede97b5400bef23ba88007;hp=780d2eb6df921ed6a096879c4876eef75f8adbaf;hpb=56ad8f4e5dfb8198e4671f631a3103b1e8b83dd3;p=mono.git diff --git a/mono/sgen/sgen-workers.h b/mono/sgen/sgen-workers.h index 780d2eb6df9..e3147f051af 100644 --- a/mono/sgen/sgen-workers.h +++ b/mono/sgen/sgen-workers.h @@ -1,5 +1,6 @@ -/* - * sgen-workers.c: Worker threads for parallel and concurrent GC. +/** + * \file + * Worker threads for parallel and concurrent GC. * * Copyright 2011 Xamarin Inc (http://www.xamarin.com) * Copyright (C) 2012 Xamarin Inc @@ -13,23 +14,80 @@ #include "mono/sgen/sgen-thread-pool.h" typedef struct _WorkerData WorkerData; +typedef struct _WorkerContext WorkerContext; + +typedef gint32 State; + +typedef void (*SgenWorkersFinishCallback) (void); +typedef void (*SgenWorkerCallback) (WorkerData *data); + struct _WorkerData { + gint32 state; SgenGrayQueue private_gray_queue; /* only read/written by worker thread */ + /* + * 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; }; -void sgen_workers_init (int num_workers); -void sgen_workers_stop_all_workers (void); -void sgen_workers_start_all_workers (SgenObjectOperations *object_ops, SgenThreadPoolJob *finish_job); -void sgen_workers_ensure_awake (void); -void sgen_workers_init_distribute_gray_queue (void); -void sgen_workers_enqueue_job (SgenThreadPoolJob *job, gboolean enqueue); -void sgen_workers_wait_for_jobs_finished (void); -void sgen_workers_distribute_gray_queue_sections (void); -void sgen_workers_reset_data (void); -void sgen_workers_join (void); -gboolean sgen_workers_have_idle_work (void); +void sgen_workers_create_context (int generation, int num_workers); +void sgen_workers_stop_all_workers (int generation); +void sgen_workers_set_num_active_workers (int generation, int num_workers); +void sgen_workers_start_all_workers (int generation, SgenObjectOperations *object_ops_nopar, SgenObjectOperations *object_ops_par, SgenWorkersFinishCallback finish_job); +void sgen_workers_enqueue_job (int generation, SgenThreadPoolJob *job, gboolean enqueue); +void sgen_workers_join (int generation); +gboolean sgen_workers_have_idle_work (int generation); gboolean sgen_workers_all_done (void); -gboolean sgen_workers_are_working (void); -SgenSectionGrayQueue* sgen_workers_get_distribute_section_gray_queue (void); +void sgen_workers_assert_gray_queue_is_empty (int generation); +void sgen_workers_take_from_queue (int generation, SgenGrayQueue *queue); +SgenObjectOperations* sgen_workers_get_idle_func_object_ops (WorkerData *worker); +int sgen_workers_get_job_split_count (int generation); +void sgen_workers_foreach (int generation, SgenWorkerCallback callback); +gboolean sgen_workers_is_worker_thread (MonoNativeThreadId id); #endif