summaryrefslogtreecommitdiffstats
path: root/libdimension/profile.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2014-08-19 17:10:03 -0400
committerTavian Barnes <tavianator@tavianator.com>2015-10-25 11:03:56 -0400
commit7b09710392d35fb55b52031d447a542d99fc6b4b (patch)
tree270eb927ee8c52ceeb99926ebf4843704775a610 /libdimension/profile.c
parent200c86b91ea7063d35be3bffc11c5da53c054653 (diff)
downloaddimension-7b09710392d35fb55b52031d447a542d99fc6b4b.tar.xz
Modularize the libdimension codebase.
Diffstat (limited to 'libdimension/profile.c')
-rw-r--r--libdimension/profile.c167
1 files changed, 0 insertions, 167 deletions
diff --git a/libdimension/profile.c b/libdimension/profile.c
deleted file mode 100644
index 164e002..0000000
--- a/libdimension/profile.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*************************************************************************
- * Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> *
- * *
- * This file is part of The Dimension Library. *
- * *
- * The Dimension Library is free software; you can redistribute it and/ *
- * or modify it under the terms of the GNU Lesser General Public License *
- * as published by the Free Software Foundation; either version 3 of the *
- * License, or (at your option) any later version. *
- * *
- * The Dimension Library is distributed in the hope that it will be *
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty *
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
- * Lesser General Public License for more details. *
- * *
- * You should have received a copy of the GNU Lesser General Public *
- * License along with this program. If not, see *
- * <http://www.gnu.org/licenses/>. *
- *************************************************************************/
-
-/**
- * @file
- * Branch profile accounting.
- */
-
-#include "dimension-internal.h"
-#include <pthread.h>
-#include <stdio.h>
-#include <inttypes.h>
-
-/// Information on one predicted branch.
-typedef struct {
- char *location;
- uint64_t predicted, branches;
-} dmnsn_branch;
-
-/// Count of mispredicted branches.
-static dmnsn_dictionary *dmnsn_profile = NULL;
-/// Mutex which protects \c dmnsn_profile.
-static pthread_mutex_t dmnsn_profile_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/// Thread-local count of mispredicted branches.
-static pthread_key_t dmnsn_thread_profile;
-/// Initialize the thread-specific pointer exactly once.
-static pthread_once_t dmnsn_thread_profile_once = PTHREAD_ONCE_INIT;
-
-/// Add thread-specific profile data to the global counts.
-static void
-dmnsn_profile_globalize(void *ptr)
-{
- dmnsn_branch *branch = ptr;
- dmnsn_branch *global = dmnsn_dictionary_at(dmnsn_profile, branch->location);
- if (global) {
- global->predicted += branch->predicted;
- global->branches += branch->branches;
- dmnsn_free(branch->location);
- } else {
- dmnsn_dictionary_insert(dmnsn_profile, branch->location, branch);
- }
-}
-
-/// Destructor function for thread-specific profile data.
-static void
-dmnsn_delete_thread_profile(void *ptr)
-{
- dmnsn_dictionary *thread_profile = ptr;
-
- dmnsn_lock_mutex(&dmnsn_profile_mutex);
- dmnsn_dictionary_apply(thread_profile, dmnsn_profile_globalize);
- dmnsn_unlock_mutex(&dmnsn_profile_mutex);
-
- dmnsn_delete_dictionary(thread_profile);
-}
-
-/// Initialize the thread-specific pointer.
-static void
-dmnsn_initialize_thread_profile(void)
-{
- dmnsn_key_create(&dmnsn_thread_profile, dmnsn_delete_thread_profile);
-
- dmnsn_lock_mutex(&dmnsn_profile_mutex);
- dmnsn_profile = dmnsn_new_dictionary(sizeof(dmnsn_branch));
- dmnsn_unlock_mutex(&dmnsn_profile_mutex);
-}
-
-/// Get the thread-specific profile data.
-static dmnsn_dictionary *
-dmnsn_get_thread_profile(void)
-{
- dmnsn_once(&dmnsn_thread_profile_once, dmnsn_initialize_thread_profile);
- return pthread_getspecific(dmnsn_thread_profile);
-}
-
-/// Set the thread-specific profile data.
-static void
-dmnsn_set_thread_profile(dmnsn_dictionary *thread_profile)
-{
- dmnsn_setspecific(dmnsn_thread_profile, thread_profile);
-}
-
-bool
-dmnsn_expect(bool result, bool expected, const char *func, const char *file,
- unsigned int line)
-{
- int size = snprintf(NULL, 0, "%s:%s:%u", file, func, line) + 1;
- if (size < 1) {
- dmnsn_error("sprintf() failed.");
- }
-
- char key[size];
- if (snprintf(key, size, "%s:%s:%u", file, func, line) < 0) {
- dmnsn_error("sprintf() failed.");
- }
-
- dmnsn_dictionary *thread_profile = dmnsn_get_thread_profile();
- if (!thread_profile) {
- thread_profile = dmnsn_new_dictionary(sizeof(dmnsn_branch));
- dmnsn_set_thread_profile(thread_profile);
- }
-
- dmnsn_branch *branch = dmnsn_dictionary_at(thread_profile, key);
- if (branch) {
- ++branch->branches;
- if (result == expected) {
- ++branch->predicted;
- }
- } else {
- dmnsn_branch new_branch = {
- .location = dmnsn_strdup(key),
- .predicted = (result == expected) ? 1 : 0,
- .branches = 1
- };
- dmnsn_dictionary_insert(thread_profile, key, &new_branch);
- }
-
- return result;
-}
-
-static void
-dmnsn_print_bad_prediction(void *ptr)
-{
- dmnsn_branch *branch = ptr;
- double rate = ((double)branch->predicted)/branch->branches;
- if (rate < 0.75 || branch->branches < 100000) {
- fprintf(stderr,
- "Bad branch prediction: %s: %" PRIu64 "/%" PRIu64 " (%g%%)\n",
- branch->location, branch->predicted, branch->branches, 100.0*rate);
- }
-
- dmnsn_free(branch->location);
-}
-
-DMNSN_DESTRUCTOR static void
-dmnsn_print_bad_predictions(void)
-{
- dmnsn_dictionary *thread_profile = dmnsn_get_thread_profile();
- if (thread_profile) {
- dmnsn_delete_thread_profile(thread_profile);
- dmnsn_set_thread_profile(NULL);
- }
-
- dmnsn_lock_mutex(&dmnsn_profile_mutex);
- dmnsn_dictionary_apply(dmnsn_profile, dmnsn_print_bad_prediction);
- dmnsn_delete_dictionary(dmnsn_profile);
- dmnsn_profile = NULL;
- dmnsn_unlock_mutex(&dmnsn_profile_mutex);
-}