futhark-0.25.35: rts/c/context.h
// Start of context.h
// Internal functions.
static void set_error(struct futhark_context* ctx, char *error) {
lock_lock(&ctx->error_lock);
if (ctx->error == NULL) {
ctx->error = error;
} else {
free(error);
}
lock_unlock(&ctx->error_lock);
}
// XXX: should be static, but used in ispc_util.h
void lexical_realloc_error(struct futhark_context* ctx, size_t new_size) {
set_error(ctx,
msgprintf("Failed to allocate memory.\nAttempted allocation: %12lld bytes\n",
(long long) new_size));
}
static int lexical_realloc(struct futhark_context *ctx,
unsigned char **ptr,
int64_t *old_size,
int64_t new_size) {
unsigned char *new = realloc(*ptr, (size_t)new_size);
if (new == NULL) {
lexical_realloc_error(ctx, new_size);
return FUTHARK_OUT_OF_MEMORY;
} else {
*ptr = new;
*old_size = new_size;
return FUTHARK_SUCCESS;
}
}
static void free_all_in_free_list(struct futhark_context* ctx) {
fl_mem mem;
free_list_pack(&ctx->free_list);
while (free_list_first(&ctx->free_list, (fl_mem*)&mem) == 0) {
free((void*)mem);
}
}
static int is_small_alloc(size_t size) {
return size < 1024*1024;
}
static void host_alloc(struct futhark_context* ctx,
size_t size, const char* tag, size_t* size_out, void** mem_out) {
if (is_small_alloc(size) || free_list_find(&ctx->free_list, size, tag, size_out, (fl_mem*)mem_out) != 0) {
*size_out = size;
*mem_out = malloc(size);
}
}
static void host_free(struct futhark_context* ctx,
size_t size, const char* tag, void* mem) {
// Small allocations are handled by malloc()s own free list. The
// threshold here is kind of arbitrary, but seems to work OK.
// Larger allocations are mmap()ed/munmapped() every time, which is
// very slow, and Futhark programs tend to use a few very large
// allocations.
if (is_small_alloc(size)) {
free(mem);
} else {
free_list_insert(&ctx->free_list, size, (fl_mem)mem, tag);
}
}
static void add_event(struct futhark_context* ctx,
const char* name,
const char* provenance,
struct kvs *kvs,
void* data,
event_report_fn f) {
if (provenance == NULL) {
provenance = "unknown";
}
if (ctx->logging) {
fprintf(ctx->log, "Event: %s\n at: %s\n", name, provenance);
if (kvs) {
kvs_log(kvs, " ", ctx->log);
}
}
add_event_to_list(&ctx->event_list, name, provenance, kvs, data, f);
}
char *futhark_context_get_error(struct futhark_context *ctx) {
char *error = ctx->error;
ctx->error = NULL;
return error;
}
void futhark_context_config_set_debugging(struct futhark_context_config *cfg, int flag) {
cfg->profiling = cfg->logging = cfg->debugging = flag;
}
void futhark_context_config_set_profiling(struct futhark_context_config *cfg, int flag) {
cfg->profiling = flag;
}
void futhark_context_config_set_logging(struct futhark_context_config *cfg, int flag) {
cfg->logging = flag;
}
void futhark_context_config_set_cache_file(struct futhark_context_config *cfg, const char *f) {
cfg->cache_fname = strdup(f);
}
int futhark_get_tuning_param_count(void) {
return NUM_TUNING_PARAMS;
}
const char *futhark_get_tuning_param_name(int i) {
return tuning_param_names[i];
}
const char *futhark_get_tuning_param_class(int i) {
return tuning_param_classes[i];
}
void futhark_context_set_logging_file(struct futhark_context *ctx, FILE *f){
ctx->log = f;
}
void futhark_context_pause_profiling(struct futhark_context *ctx) {
ctx->profiling_paused = 1;
}
void futhark_context_unpause_profiling(struct futhark_context *ctx) {
ctx->profiling_paused = 0;
}
struct futhark_context_config* futhark_context_config_new(void) {
struct futhark_context_config* cfg = malloc(sizeof(struct futhark_context_config));
if (cfg == NULL) {
return NULL;
}
cfg->in_use = 0;
cfg->debugging = 0;
cfg->profiling = 0;
cfg->logging = 0;
cfg->cache_fname = NULL;
for (int i = 0; i < NUM_TUNING_PARAMS; i++) {
cfg->tuning_params[i].set = false;
cfg->tuning_params[i].val = tuning_param_defaults[i];
cfg->tuning_params[i].name = tuning_param_names[i];
cfg->tuning_params[i].var = tuning_param_vars[i];
cfg->tuning_params[i].class = tuning_param_classes[i];
}
backend_context_config_setup(cfg);
return cfg;
}
void futhark_context_config_free(struct futhark_context_config* cfg) {
assert(!cfg->in_use);
backend_context_config_teardown(cfg);
free(cfg->cache_fname);
free(cfg);
}
struct futhark_context* futhark_context_new(struct futhark_context_config* cfg) {
struct futhark_context* ctx = malloc(sizeof(struct futhark_context));
if (ctx == NULL) {
return NULL;
}
assert(!cfg->in_use);
ctx->cfg = cfg;
ctx->cfg->in_use = 1;
ctx->program_initialised = false;
create_lock(&ctx->error_lock);
create_lock(&ctx->lock);
free_list_init(&ctx->free_list);
event_list_init(&ctx->event_list);
ctx->peak_mem_usage_default = 0;
ctx->cur_mem_usage_default = 0;
ctx->constants = malloc(sizeof(struct constants));
ctx->debugging = cfg->debugging;
ctx->logging = cfg->logging;
ctx->detail_memory = cfg->logging;
ctx->profiling = cfg->profiling;
ctx->profiling_paused = 0;
ctx->error = NULL;
ctx->log = stderr;
if (backend_context_setup(ctx) == 0) {
setup_program(ctx);
init_constants(ctx);
ctx->program_initialised = true;
(void)futhark_context_clear_caches(ctx);
(void)futhark_context_sync(ctx);
}
return ctx;
}
void futhark_context_free(struct futhark_context* ctx) {
if (ctx->program_initialised) {
free_constants(ctx);
teardown_program(ctx);
}
backend_context_teardown(ctx);
free_all_in_free_list(ctx);
free_list_destroy(&ctx->free_list);
event_list_free(&ctx->event_list);
free(ctx->constants);
free(ctx->error);
free_lock(&ctx->lock);
free_lock(&ctx->error_lock);
ctx->cfg->in_use = 0;
free(ctx);
}
// End of context.h