1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
// 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;
cfg->num_tuning_params = num_tuning_params;
cfg->tuning_params = malloc(cfg->num_tuning_params * sizeof(int64_t));
memcpy(cfg->tuning_params, tuning_param_defaults,
cfg->num_tuning_params * sizeof(int64_t));
cfg->tuning_param_names = tuning_param_names;
cfg->tuning_param_vars = tuning_param_vars;
cfg->tuning_param_classes = tuning_param_classes;
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->tuning_params);
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;
set_tuning_params(ctx);
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
|