blob: f5937b89c7b6b97618e457d203670f5e766e2e8d [file] [log] [blame]
/* global_state.h -*-C++-*-
*
*************************************************************************
*
* Copyright (C) 2009-2016, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* *********************************************************************
*
* PLEASE NOTE: This file is a downstream copy of a file mainitained in
* a repository at cilkplus.org. Changes made to this file that are not
* submitted through the contribution process detailed at
* http://www.cilkplus.org/submit-cilk-contribution will be lost the next
* time that a new version is released. Changes only submitted to the
* GNU compiler collection or posted to the git repository at
* https://bitbucket.org/intelcilkruntime/intel-cilk-runtime.git are
* not tracked.
*
* We welcome your contributions to this open source project. Thank you
* for your assistance in helping us improve Cilk Plus.
**************************************************************************/
/**
* @file global_state.h
*
* @brief The global_state_t structure contains most of the global context
* maintained by the Intel Cilk runtime.
*/
#ifndef INCLUDED_GLOBAL_STATE_DOT_H
#define INCLUDED_GLOBAL_STATE_DOT_H
#include <cilk/common.h>
#include "frame_malloc.h"
#include "stats.h"
#include "bug.h"
#include "cilk_fiber.h"
__CILKRTS_BEGIN_EXTERN_C
/**
* Non-null place-holder for a stack handle that has no meaningful value.
*/
#define PLACEHOLDER_FIBER ((cilk_fiber *) -2)
/**
* States for record_or_replay
*/
enum record_replay_t {
RECORD_REPLAY_NONE,
RECORD_LOG,
REPLAY_LOG
};
/**
* @brief Global state structure version.
*
* Since the global state is exposed for debugger access, we need a version
* number to let it know that the version of the structure is what it expects
* to see. If any of the fields marked as (fixed) below are changed, the
* version number needs to be bumped.
*/
#define GLOBAL_STATE_VERSION 0
/**
* @brief The global state is a structure that is shared by all workers in
* Cilk.
*
* Make the structure ready for use by calling
* cilkg_init_global_state() and then cilkg_publish_global_state().
*
* The same global lock should be held while both of these methods are
* called. These methods are split because it is useful to execute
* other runtime initialization code in between.
*
* After cilkg_publish_global_state() has completed, Cilk runtime
* methods may call cilkg_get_global_state() to look at the published
* value without holding the global lock.
*
* Finally, clean up the global state by calling
* cilkg_deinit_global_state(). This method should be called only
* after all calls to cilkg_get_global_state() have completed, and
* while holding the global lock.
*
* Before initialization and after deinitialization, the fields in the
* global state have unspecified values, except for a few special
* fields labeled "USER SETTING", which can be read and written before
* initialization and after deinitialization.
*/
struct global_state_t { /* COMMON_PORTABLE */
/* Fields described as "(fixed)" should not be changed after
* initialization.
*/
/*************************************************************************
* Note that debugger integration must reach into the
* global state! The debugger integration is depending on the
* offsets of the addr_size, system_workers, total_workers,
* stealing_disabled, sysdep, and workers. If these offsets change, the
* debugger integration library will need to be changed to match!!!
*************************************************************************/
uint16_t addr_size; ///< Number of bytes for an address, used by debugger (fixed)
uint16_t version; ///< Version of this structure (fixed)
int system_workers; ///< Number of system workers (fixed)
/**
* @brief USER SETTING: Maximum number of user workers that can be
* bound to cilk workers.
*
* 0 unless set by user. Call cilkg_calc_max_user_workers to get
* the value.
*/
int max_user_workers;
int total_workers; ///< Total number of worker threads allocated (fixed)
int workers_running; ///< True when system workers have beens started */
/// Set by debugger to disable stealing (fixed)
int stealing_disabled;
/// System-dependent part of the global state
struct global_sysdep_state *sysdep;
/// Array of worker structures.
__cilkrts_worker **workers;
/******* END OF DEBUGGER-INTEGRATION FIELDS ***************/
/// Number of frames in each worker's lazy task queue
__STDNS size_t ltqsize;
/**
* @brief USER SETTING: Force all possible reductions.
*
* TRUE if running a p-tool that requires reducers to call the reduce()
* method even if no actual stealing occurs.
*
* When set to TRUE, runtime will simulate steals, forcing calls to the
* the reduce() methods of reducers.
*
*/
int force_reduce;
/// USER SETTING: Per-worker fiber pool size
int fiber_pool_size;
/// USER SETTING: Global fiber pool size
int global_fiber_pool_size;
/**
* @brief TRUE when workers should exit scheduling loop so we can
* shut down the runtime and free the global state.
*
* @note @c work_done will be checked *FREQUENTLY* in the scheduling loop
* by idle workers. We need to ensure that it's not in a cache line which
* may be invalidated by other cores. The surrounding fields are either
* constant after initialization or not used until shutdown (stats) so we
* should be OK.
*/
volatile int work_done;
int under_ptool; ///< True when running under a serial PIN tool
statistics stats; ///< Statistics on use of runtime
/**
* @brief USER SETTING: Maximum number of stacks the runtime will
* allocate (apart from those created by the OS when worker
* threads are created).
*
* If max_stacks == 0,there is no pre-defined maximum.
*/
unsigned max_stacks;
/// Size of each stack
size_t stack_size;
/// Global cache for per-worker memory
struct __cilkrts_frame_cache frame_malloc;
/// Global fiber pool
cilk_fiber_pool fiber_pool;
/**
* @brief Track whether the runtime has failed to allocate a
* stack.
*
* Setting this flag prevents multiple warnings from being
* issued.
*/
int failure_to_allocate_stack;
/**
* @brief USER SETTING: indicate record or replay log.
* Set to NULL if not used in this run.
*/
char *record_replay_file_name;
/**
* @brief Record/replay state.
* Valid states are:
* RECORD_REPLAY_NONE - Not recording or replaying a log
* RECORD_LOG - Recording a log for replay later
* REPLAY_LOG - Replay a log recorded earlier
*/
enum record_replay_t record_or_replay;
/**
* @brief Buffer to force max_steal_failures to appear on a
* different cache line from the previous member variables.
*
* This padding is needed because max_steal_failures is read
* constantly and other modified values in the global state will
* cause thrashing.
*/
char cache_buf[64];
/**
* @brief Maximum number of times a thread should fail to steal
* before checking if Cilk is shutting down.
*/
unsigned int max_steal_failures;
/// Pointer to scheduler entry point
void (*scheduler)(__cilkrts_worker *w);
/**
* @brief Buffer to force P and Q to appear on a different cache
* line from the previous member variables.
*/
char cache_buf_2[64];
int P; ///< USER SETTING: number of system workers + 1 (fixed)
int Q; ///< Number of user threads currently bound to workers
};
/**
* @brief Initialize the global state object. This method must both
* complete before referencing any fields in the global state, except
* those specified as "user-settable values".
*/
global_state_t* cilkg_init_global_state();
/**
* @brief Publish the global state object, so that
* cilkg_is_published can return true.
*
* @param g - the global state created by cilkg_init_global_state() to
* publish.
*
* After the global state object has been published, a thread should
* not modify this state unless it has exclusive access (i.e., holds
* the global lock).
*/
void cilkg_publish_global_state(global_state_t* g);
/**
* @brief Return true if the global state has been fully initialized
* and published, and has not been deinitialized.
*/
int cilkg_is_published(void);
/**
* @brief De-initializes the global state object. Must be called to free
* resources when the global state is no longer needed.
*/
void cilkg_deinit_global_state(void);
/**
* @brief Returns the global state object. Result is valid only if the
* global state has been published (see cilkg_publish_global_state()).
*/
static inline
global_state_t* cilkg_get_global_state(void)
{
// "private" extern declaration:
extern global_state_t *cilkg_singleton_ptr;
__CILKRTS_ASSERT(cilkg_singleton_ptr); // Debug only
return cilkg_singleton_ptr;
}
/**
* @brief Implementation of __cilkrts_set_params.
*
* Set user controllable parameters
* @param param - string specifying parameter to be set
* @param value - string specifying new value
* @returns One of: CILKG_SET_PARAM_SUCCESS ( = 0),
* CILKG_SET_PARAM_UNIMP, CILKG_SET_PARAM_XRANGE,
* CILKG_SET_PARAM_INVALID, or CILKG_SET_PARAM_LATE.
*
* @attention The wide character version __cilkrts_set_param_w() is available
* only on Windows.
*
* Allowable parameter names:
*
* - "nworkers" - number of processors that should run Cilk code.
* The value is a string of digits to be parsed by strtol.
*
* - "force reduce" - test reducer callbacks by allocating new views
* for every spawn within which a reducer is accessed. This can
* significantly reduce performance. The value is "1" or "true"
* to enable, "0" or "false" to disable.
* @warning Enabling "force reduce" when running with more than a single
* worker is currently broken.
*
* - "max user workers" - (Not publicly documented) Sets the number of slots
* allocated for user worker threads
*
* - "local stacks" - (Not publicly documented) Number of stacks we'll hold in
* the per-worker stack cache. Range 1 .. 42. See
* cilkg_init_global_state for details.
*
* - "shared stacks" - (Not publicly documented) Maximum number of stacks
* we'll hold in the global stack cache. Maximum value is 42. See
* __cilkrts_make_global_state for details
*
* - "nstacks" - (Not publicly documented at this time, though it may be
* exposed in the future) Sets the maximum number of stacks permitted at one
* time. If the runtime reaches this maximum, it will cease to allocate
* stacks and the app will lose parallelism. 0 means unlimited. Default is
* unlimited. Minimum is twice the number of worker threads, though that
* cannot be tested at this time.
*/
int cilkg_set_param(const char* param, const char* value);
#ifdef _WIN32
/**
* @brief Implementation of __cilkrts_set_params for Unicode characters on
* Windows. See the documentation on @ref cilkg_set_param for more details.
*
* Set user controllable parameters
* @param param - string specifying parameter to be set
* @param value - string specifying new value
* @returns One of: CILKG_SET_PARAM_SUCCESS ( = 0),
* CILKG_SET_PARAM_UNIMP, CILKG_SET_PARAM_XRANGE,
* CILKG_SET_PARAM_INVALID, or CILKG_SET_PARAM_LATE.
*/
int cilkg_set_param_w(const wchar_t* param, const wchar_t* value);
#endif
/**
* @brief implementation of __cilkrts_get_nworkers()
*/
static inline
int cilkg_get_nworkers(void)
{
// "private" extern declaration
extern global_state_t* cilkg_get_user_settable_values(void);
return cilkg_get_user_settable_values()->P;
}
/**
* @brief implementation of __cilkrts_get_total_workers()
*/
static inline
int cilkg_get_total_workers(void)
{
// "private" extern declaration
extern int cilkg_calc_total_workers(void);
// This number can fluctate until initialization so we
// compute it from scratch
return cilkg_calc_total_workers();
}
/**
* @brief implementation of __cilkrts_get_force_reduce()
*/
static inline
int cilkg_get_force_reduce(void)
{
// "private" extern declaration
extern global_state_t* cilkg_get_user_settable_values(void);
return cilkg_get_user_settable_values()->force_reduce;
}
/**
* @brief implementation of __cilkrts_get_stack_size()
*/
static inline
size_t cilkg_get_stack_size(void)
{
// "private" extern declaration
extern global_state_t* cilkg_get_user_settable_values(void);
return cilkg_get_user_settable_values()->stack_size;
}
/**
* @brief Run the scheduler function stored in the global_state
*
* Look up the scheduler function in global_state and run it. Report a fatal
* error if an exception escapes the scheduler function.
*
* @param w - Worker structure to associate with the current thread.
*
* @attention The scheduler field of the global state must be set before this
* function is called.
*/
void __cilkrts_run_scheduler_with_exceptions(__cilkrts_worker *w);
__CILKRTS_END_EXTERN_C
#endif // ! defined(INCLUDED_GLOBAL_STATE_DOT_H)