/**
|
* \file
|
* Worker threads for parallel and concurrent GC.
|
*
|
* Copyright 2011 Xamarin Inc (http://www.xamarin.com)
|
* Copyright (C) 2012 Xamarin Inc
|
*
|
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
*/
|
|
#ifndef __MONO_SGEN_WORKER_H__
|
#define __MONO_SGEN_WORKER_H__
|
|
#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_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);
|
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
|