93 lines
2.6 KiB
C
93 lines
2.6 KiB
C
/*
|
|
* Copyright (c) 2015, Charlie Curtsinger and Emery Berger,
|
|
* University of Massachusetts Amherst
|
|
* This file is part of the Coz project. See LICENSE.md file at the top-level
|
|
* directory of this distribution and at http://github.com/plasma-umass/coz.
|
|
*/
|
|
|
|
#if !defined(COZ_H)
|
|
#define COZ_H
|
|
|
|
#ifndef __USE_GNU
|
|
# define __USE_GNU
|
|
#endif
|
|
|
|
#ifndef _GNU_SOURCE
|
|
# define _GNU_SOURCE
|
|
#endif
|
|
|
|
#include <dlfcn.h>
|
|
#include <stdint.h>
|
|
#include <string.h> /* for memcpy hack below */
|
|
|
|
#if defined(__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define COZ_COUNTER_TYPE_THROUGHPUT 1
|
|
#define COZ_COUNTER_TYPE_BEGIN 2
|
|
#define COZ_COUNTER_TYPE_END 3
|
|
|
|
// Declare dlsym as a weak reference so libdl isn't required
|
|
void* dlsym(void* handle, const char* symbol) __attribute__((weak));
|
|
|
|
// Counter info struct, containing both a counter and backoff size
|
|
typedef struct {
|
|
size_t count; // The actual count
|
|
size_t backoff; // Used to batch updates to the shared counter. Currently unused.
|
|
} coz_counter_t;
|
|
|
|
// The type of the _coz_get_counter function
|
|
typedef coz_counter_t* (*coz_get_counter_t)(int, const char*);
|
|
|
|
// Locate and invoke _coz_get_counter
|
|
static coz_counter_t* _call_coz_get_counter(int type, const char* name) {
|
|
static unsigned char _initialized = 0;
|
|
static coz_get_counter_t fn; // The pointer to _coz_get_counter
|
|
|
|
if(!_initialized) {
|
|
if(dlsym) {
|
|
// Locate the _coz_get_counter method
|
|
void* p = dlsym(RTLD_DEFAULT, "_coz_get_counter");
|
|
|
|
// Use memcpy to avoid pedantic GCC complaint about storing function pointer in void*
|
|
memcpy(&fn, &p, sizeof(p));
|
|
}
|
|
|
|
_initialized = 1;
|
|
}
|
|
|
|
// Call the function, or return null if profiler is not found
|
|
if(fn) return fn(type, name);
|
|
else return 0;
|
|
}
|
|
|
|
// Macro to initialize and increment a counter
|
|
#define COZ_INCREMENT_COUNTER(type, name) \
|
|
if(1) { \
|
|
static unsigned char _initialized = 0; \
|
|
static coz_counter_t* _counter = 0; \
|
|
\
|
|
if(!_initialized) { \
|
|
_counter = _call_coz_get_counter(type, name); \
|
|
_initialized = 1; \
|
|
} \
|
|
if(_counter) { \
|
|
__atomic_add_fetch(&_counter->count, 1, __ATOMIC_RELAXED); \
|
|
} \
|
|
}
|
|
|
|
#define STR2(x) #x
|
|
#define STR(x) STR2(x)
|
|
|
|
#define COZ_PROGRESS_NAMED(name) COZ_INCREMENT_COUNTER(COZ_COUNTER_TYPE_THROUGHPUT, name)
|
|
|
|
#define COZ_PROGRESS COZ_INCREMENT_COUNTER(COZ_COUNTER_TYPE_THROUGHPUT, __FILE__ ":" STR(__LINE__))
|
|
#define COZ_BEGIN(name) COZ_INCREMENT_COUNTER(COZ_COUNTER_TYPE_BEGIN, name)
|
|
#define COZ_END(name) COZ_INCREMENT_COUNTER(COZ_COUNTER_TYPE_END, name)
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif
|
|
|
|
#endif |