+int smpi_sample_2(int global, const char *file, int line)
+{
+ char *loc = sample_location(global, file, line);
+ local_data_t *data;
+
+ xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
+ data = xbt_dict_get(samples, loc);
+ XBT_DEBUG("sample2 %s",loc);
+ free(loc);
+
+ if (data->benching==1) {
+ // we need to run a new bench
+ XBT_DEBUG("benchmarking: count:%d iter:%d stderr:%f thres:%f; mean:%f",
+ data->count, data->iters, data->relstderr, data->threshold, data->mean);
+ smpi_bench_begin();
+ return 1;
+ } else {
+ // Enough data, no more bench (either we got enough data from previous visits to this benched nest, or we just ran one bench and need to bail out now that our job is done).
+ // Just sleep instead
+ XBT_DEBUG("No benchmark (either no need, or just ran one): count >= iter (%d >= %d) or stderr<thres (%f<=%f). apply the %fs delay instead",
+ data->count, data->iters, data->relstderr, data->threshold, data->mean);
+ smpi_execute(data->mean);
+
+ smpi_bench_begin(); // prepare to capture future, unrelated computations
+ return 0;
+ }
+}
+
+
+void smpi_sample_3(int global, const char *file, int line)
+{
+ char *loc = sample_location(global, file, line);
+ local_data_t *data;
+
+ xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
+ data = xbt_dict_get(samples, loc);
+ XBT_DEBUG("sample3 %s",loc);
+
+ if (data->benching==0) {
+ THROW_IMPOSSIBLE;
+ }
+
+ // ok, benchmarking this loop is over
+ xbt_os_timer_stop(smpi_process_timer());
+
+ // update the stats
+ double sample, n;
+ data->count++;
+ sample = xbt_os_timer_elapsed(smpi_process_timer());
+ data->sum += sample;
+ data->sum_pow2 += sample * sample;
+ n = (double)data->count;
+ data->mean = data->sum / n;
+ data->relstderr = sqrt((data->sum_pow2 / n - data->mean * data->mean) / n) / data->mean;
+ if (!sample_enough_benchs(data)) {
+ data->mean = sample; // Still in benching process; We want sample_2 to simulate the exact time of this loop occurrence before leaving, not the mean over the history
+ }
+ XBT_DEBUG("Average mean after %d steps is %f, relative standard error is %f (sample was %f)", data->count,
+ data->mean, data->relstderr, sample);
+
+ // That's enough for now, prevent sample_2 to run the same code over and over
+ data->benching = 0;
+}
+
+#ifndef WIN32
+void *smpi_shared_malloc(size_t size, const char *file, int line)
+{
+ char *loc = bprintf("%zu_%s_%d", (size_t)getpid(), file, line);
+ size_t len = strlen(loc);
+ size_t i;
+ int fd;
+ void* mem;
+ shared_data_t *data;
+
+ for(i = 0; i < len; i++) {
+ /* Make the 'loc' ID be a flat filename */
+ if(loc[i] == '/') {
+ loc[i] = '_';
+ }
+ }
+ if (!allocs) {
+ allocs = xbt_dict_new_homogeneous(free);
+ }
+ data = xbt_dict_get_or_null(allocs, loc);
+ if(!data) {
+ fd = shm_open(loc, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if(fd < 0) {
+ switch(errno) {
+ case EEXIST:
+ xbt_die("Please cleanup /dev/shm/%s", loc);
+ default:
+ xbt_die("An unhandled error occured while opening %s: %s", loc, strerror(errno));
+ }
+ }
+ data = xbt_new(shared_data_t, 1);
+ data->fd = fd;
+ data->count = 1;
+ data->loc = loc;
+ mem = shm_map(fd, size, data);
+ if(shm_unlink(loc) < 0) {
+ XBT_WARN("Could not early unlink %s: %s", loc, strerror(errno));
+ }
+ xbt_dict_set(allocs, loc, data, NULL);
+ XBT_DEBUG("Mapping %s at %p through %d", loc, mem, fd);
+ } else {
+ mem = shm_map(data->fd, size, data);
+ data->count++;
+ }
+ XBT_DEBUG("Malloc %zu in %p (metadata at %p)", size, mem, data);
+ return mem;
+}
+void smpi_shared_free(void *ptr)
+{
+ char loc[PTR_STRLEN];
+ shared_metadata_t* meta;
+ shared_data_t* data;
+
+ if (!allocs) {
+ XBT_WARN("Cannot free: nothing was allocated");
+ return;
+ }
+ if(!allocs_metadata) {
+ XBT_WARN("Cannot free: no metadata was allocated");
+ }
+ snprintf(loc, PTR_STRLEN, "%p", ptr);
+ meta = (shared_metadata_t*)xbt_dict_get_or_null(allocs_metadata, loc);
+ if (!meta) {
+ XBT_WARN("Cannot free: %p was not shared-allocated by SMPI", ptr);
+ return;
+ }
+ data = meta->data;
+ if(!data) {
+ XBT_WARN("Cannot free: something is broken in the metadata link");
+ return;
+ }
+ if(munmap(ptr, meta->size) < 0) {
+ XBT_WARN("Unmapping of fd %d failed: %s", data->fd, strerror(errno));
+ }
+ data->count--;
+ if (data->count <= 0) {
+ close(data->fd);
+ xbt_dict_remove(allocs, data->loc);
+ free(data->loc);
+ }
+}
+#endif
+
+int smpi_shared_known_call(const char* func, const char* input) {
+ char* loc = bprintf("%s:%s", func, input);
+ xbt_ex_t ex;
+ int known;
+
+ if(!calls) {
+ calls = xbt_dict_new_homogeneous(NULL);
+ }
+ TRY {
+ xbt_dict_get(calls, loc); /* Succeed or throw */
+ known = 1;
+ }
+ CATCH(ex) {
+ if(ex.category == not_found_error) {
+ known = 0;
+ xbt_ex_free(ex);
+ } else {
+ RETHROW;
+ }
+ }
+ free(loc);
+ return known;
+}
+
+void* smpi_shared_get_call(const char* func, const char* input) {
+ char* loc = bprintf("%s:%s", func, input);
+ void* data;
+
+ if(!calls) {
+ calls = xbt_dict_new_homogeneous(NULL);
+ }
+ data = xbt_dict_get(calls, loc);
+ free(loc);
+ return data;
+}
+
+void* smpi_shared_set_call(const char* func, const char* input, void* data) {
+ char* loc = bprintf("%s:%s", func, input);
+
+ if(!calls) {
+ calls = xbt_dict_new_homogeneous(NULL);
+ }
+ xbt_dict_set(calls, loc, data, NULL);
+ free(loc);
+ return data;