mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-08-08 15:19:50 +00:00
initial commit. This is icculus version 5542b94cae02a6333845854bbbd1abe0a259f1a4
This commit is contained in:
commit
3096eaf5e2
2519 changed files with 816064 additions and 0 deletions
166
ExternalLibs/iprof/prof_gather.c
Normal file
166
ExternalLibs/iprof/prof_gather.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "prof.h"
|
||||
#include "prof_internal.h"
|
||||
|
||||
Prof_Define(_global);
|
||||
|
||||
Prof_Zone_Stack Prof_dummy ; // impossible parent
|
||||
Prof_Zone_Stack Prof_dummy2 ;
|
||||
Prof_Zone_Stack *Prof_stack = &Prof_dummy2;
|
||||
|
||||
int Prof_num_zones;
|
||||
Prof_Zone *Prof_zones[];
|
||||
|
||||
#define MAX_HASH_SIZE 65536 // not unlimited, to catch unbalanced BEGIN/END_PROF
|
||||
#define INIT_HASH_SIZE 256 // balance resource usage and avoid initial growth
|
||||
|
||||
static Prof_Zone_Stack *init_hash[] = { &Prof_dummy };
|
||||
static Prof_Zone_Stack **zone_hash = init_hash;
|
||||
static int zone_hash_count = 1;
|
||||
static int zone_hash_max = 1;
|
||||
static int zone_hash_mask = 0;
|
||||
|
||||
static int hash(Prof_Zone *z, Prof_Zone_Stack *s)
|
||||
{
|
||||
int n = (int) z + (int) s;
|
||||
return n + (n >> 8);
|
||||
}
|
||||
|
||||
static void insert_node(Prof_Zone_Stack *q)
|
||||
{
|
||||
int h = hash(q->zone, q->parent);
|
||||
int x = h & zone_hash_mask;
|
||||
int s = ((h << 4) + (h >> 4)) | 1;
|
||||
|
||||
while (zone_hash[x] != &Prof_dummy)
|
||||
x = (x + s) & zone_hash_mask;
|
||||
|
||||
zone_hash[x] = q;
|
||||
|
||||
++zone_hash_count;
|
||||
}
|
||||
|
||||
static void init_zone(Prof_Zone *zone)
|
||||
{
|
||||
Prof_zones[Prof_num_zones++] = zone;
|
||||
|
||||
zone->initialized = 1;
|
||||
}
|
||||
|
||||
static int count_recursion_depth(Prof_Zone_Stack *stack, Prof_Zone *zone)
|
||||
{
|
||||
int n=0;
|
||||
while (stack) {
|
||||
if (stack->zone == zone)
|
||||
++n;
|
||||
stack = stack->parent;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static Prof_Zone_Stack *createStackNode(Prof_Zone *zone, Prof_Zone_Stack *parent)
|
||||
{
|
||||
// create a new node
|
||||
Prof_Zone_Stack *z = (Prof_Zone_Stack *) malloc(sizeof(*z));
|
||||
z->zone = zone;
|
||||
z->parent = parent;
|
||||
z->total_entry_count = 0;
|
||||
z->total_hier_ticks = 0;
|
||||
z->total_self_ticks = 0;
|
||||
z->t_self_start = 0;
|
||||
z->highlevel = NULL;
|
||||
z->recursion_depth = count_recursion_depth(parent, zone);
|
||||
return z;
|
||||
}
|
||||
|
||||
static void init_zone_hash(int size)
|
||||
{
|
||||
int i;
|
||||
assert(size <= MAX_HASH_SIZE);
|
||||
zone_hash_max = size;
|
||||
zone_hash_count = 0;
|
||||
zone_hash = (Prof_Zone_Stack **) malloc(sizeof(*zone_hash) * zone_hash_max);
|
||||
zone_hash_mask = size-1;
|
||||
for (i=0; i < zone_hash_max; ++i)
|
||||
zone_hash[i] = &Prof_dummy;
|
||||
}
|
||||
|
||||
static void Prof_init_lowlevel(void);
|
||||
|
||||
// this code is structured to minimize computation
|
||||
// assuming there's a hit in the very first slot
|
||||
Prof_extern_C Prof_Zone_Stack *Prof_StackAppend(Prof_Zone *zone)
|
||||
{
|
||||
int h = hash(zone, Prof_stack), s;
|
||||
int x = h & zone_hash_mask;
|
||||
Prof_Zone_Stack *z = zone_hash[x];
|
||||
if (z->parent == Prof_stack && z->zone == zone) return z;
|
||||
if (z != &Prof_dummy) {
|
||||
|
||||
// compute a secondary hash function; force it to be odd
|
||||
// so it's relatively prime to the power-of-two table size
|
||||
s = ((h << 4) + (h >> 4)) | 1;
|
||||
for(;;) {
|
||||
x = (x + s) & zone_hash_mask;
|
||||
z = zone_hash[x];
|
||||
if (z->parent == Prof_stack && z->zone == zone) return z;
|
||||
if (z == &Prof_dummy) break;
|
||||
}
|
||||
// loop is guaranteed to terminate because the hash table is never full
|
||||
}
|
||||
|
||||
// now's as good a time as any to initialize this zone
|
||||
if (!zone->initialized) {
|
||||
if (zone_hash_max == 1) {
|
||||
Prof_init_lowlevel();
|
||||
// the above is reentrant since it initializes _global
|
||||
// so now invariants are broken, so start over
|
||||
return Prof_StackAppend(zone);
|
||||
}
|
||||
init_zone(zone);
|
||||
}
|
||||
|
||||
// check if we need to grow the table
|
||||
// we keep it at most 1/2 full to be very fast
|
||||
if (zone_hash_count*2 > zone_hash_max) {
|
||||
Prof_Zone_Stack **old_hash = zone_hash, *z;
|
||||
int i,n = zone_hash_max;
|
||||
|
||||
init_zone_hash(zone_hash_max*2);
|
||||
|
||||
for (i=0; i < n; ++i)
|
||||
if (old_hash[i] != &Prof_dummy)
|
||||
insert_node(old_hash[i]);
|
||||
|
||||
z = createStackNode(zone, Prof_stack);
|
||||
insert_node(z);
|
||||
return z;
|
||||
}
|
||||
|
||||
// insert new entry in hash table
|
||||
++zone_hash_count;
|
||||
return zone_hash[x] = createStackNode(zone, Prof_stack);
|
||||
}
|
||||
|
||||
void Prof_traverse(void (*func)(Prof_Zone_Stack *z))
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < zone_hash_max; ++i)
|
||||
if (zone_hash[i] != &Prof_dummy)
|
||||
func(zone_hash[i]);
|
||||
}
|
||||
|
||||
static void Prof_init_lowlevel(void)
|
||||
{
|
||||
init_zone_hash(INIT_HASH_SIZE);
|
||||
|
||||
Prof_init_highlevel();
|
||||
|
||||
// intentionally unbalanced, this wraps everything else
|
||||
{
|
||||
Prof_Region(_global)
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue