Sanchayan Maity
0f4b39775c
During the last commit of splash2 benchmark it seems before committing when we ran "make clean", it effectively undid what the patch at below link did http://www.capsl.udel.edu/splash/Download.html Fix this since without this it is not possible to build the arcane splash2 benchmark.
635 lines
18 KiB
C
635 lines
18 KiB
C
/*************************************************************************/
|
|
/* */
|
|
/* Copyright (c) 1994 Stanford University */
|
|
/* */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* Permission is given to use, copy, and modify this software for any */
|
|
/* non-commercial purpose as long as this copyright notice is not */
|
|
/* removed. All other uses, including redistribution in whole or in */
|
|
/* part, are forbidden without prior written permission. */
|
|
/* */
|
|
/* This software is provided with absolutely no warranty and no */
|
|
/* support. */
|
|
/* */
|
|
/*************************************************************************/
|
|
|
|
/************************************************************************
|
|
*
|
|
* Class methods for small simple objects.
|
|
*
|
|
*
|
|
*************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
|
|
EXTERN_ENV;
|
|
|
|
include(radiosity.h)
|
|
|
|
struct {
|
|
char pad1[PAGE_SIZE]; /* padding to avoid false-sharing
|
|
and allow page-placement */
|
|
long n_local_free_elemvertex ;
|
|
ElemVertex *local_free_elemvertex ;
|
|
long n_local_free_edge ;
|
|
Edge *local_free_edge ;
|
|
long lock_alloc_counter ;
|
|
char pad2[PAGE_SIZE]; /* padding to avoid false-sharing
|
|
and allow page-placement */
|
|
} sobj_struct[MAX_PROCESSORS];
|
|
|
|
|
|
/***************************************************************************
|
|
****************************************************************************
|
|
*
|
|
* Methods for Vertex object
|
|
*
|
|
****************************************************************************
|
|
****************************************************************************/
|
|
|
|
/***************************************************************************
|
|
*
|
|
* vector_length()
|
|
*
|
|
* Comute length of a vector represented by Vertex
|
|
* length = | v |
|
|
*
|
|
****************************************************************************/
|
|
|
|
float vector_length(Vertex *v)
|
|
{
|
|
double t0, t1, t2 ;
|
|
|
|
t0 = v->x * v->x ;
|
|
t1 = v->y * v->y ;
|
|
t2 = v->z * v->z ;
|
|
|
|
return( sqrt( t0 + t1 + t2 ) ) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* distance()
|
|
*
|
|
* Comute distance of two points.
|
|
* dist = | P1 - P2 |
|
|
*
|
|
****************************************************************************/
|
|
|
|
float distance(Vertex *p1, Vertex *p2)
|
|
{
|
|
Vertex v12 ;
|
|
|
|
v12.x = p2->x - p1->x ;
|
|
v12.y = p2->y - p1->y ;
|
|
v12.z = p2->z - p1->z ;
|
|
|
|
return( vector_length( &v12 ) ) ;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* normalize_vector()
|
|
*
|
|
* Normalize vector represented by Vertex
|
|
* v1 <- normalized( v2 )
|
|
*
|
|
****************************************************************************/
|
|
|
|
float normalize_vector(Vertex *v1, Vertex *v2)
|
|
{
|
|
float t0 ;
|
|
float length ;
|
|
|
|
length = vector_length( v2 ) ;
|
|
t0 = (float)1.0 / length ;
|
|
|
|
v1->x = v2->x * t0 ;
|
|
v1->y = v2->y * t0 ;
|
|
v1->z = v2->z * t0 ;
|
|
|
|
return( length ) ;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* inner_product()
|
|
*
|
|
* (v1.v2) <- inner_product( v1, v2 )
|
|
*
|
|
***************************************************************************/
|
|
|
|
float inner_product(Vertex *v1, Vertex *v2)
|
|
{
|
|
float ip ;
|
|
|
|
ip = v1->x * v2->x ;
|
|
ip += v1->y * v2->y ;
|
|
ip += v1->z * v2->z ;
|
|
|
|
return( ip ) ;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* cross_product()
|
|
*
|
|
* Vc = V1 X V2
|
|
*
|
|
***************************************************************************/
|
|
|
|
void cross_product(Vertex *vc, Vertex *v1, Vertex *v2)
|
|
{
|
|
vc->x = v1->y * v2->z - v1->z * v2->y ;
|
|
vc->y = v1->z * v2->x - v1->x * v2->z ;
|
|
vc->z = v1->x * v2->y - v1->y * v2->x ;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* plane_normal()
|
|
*
|
|
* Vc = (P2-P1) X (P3-P1) / |(P2-P1) X (P3-P1)|
|
|
*
|
|
***************************************************************************/
|
|
|
|
float plane_normal(Vertex *vc, Vertex *p1, Vertex *p2, Vertex *p3)
|
|
{
|
|
Vertex v1, v2 ;
|
|
|
|
/* Compute vectors */
|
|
v1.x = p2->x - p1->x ;
|
|
v1.y = p2->y - p1->y ;
|
|
v1.z = p2->z - p1->z ;
|
|
|
|
v2.x = p3->x - p1->x ;
|
|
v2.y = p3->y - p1->y ;
|
|
v2.z = p3->z - p1->z ;
|
|
|
|
/* Compute cross product and normalize */
|
|
cross_product( vc, &v1, &v2 ) ;
|
|
return( normalize_vector( vc, vc ) ) ;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* center_point()
|
|
*
|
|
* P = (P1 + P2 + P3) / 3
|
|
*
|
|
***************************************************************************/
|
|
|
|
void center_point(Vertex *p1, Vertex *p2, Vertex *p3, Vertex *pc)
|
|
{
|
|
/* Compute mid point of the element */
|
|
|
|
pc->x = (p1->x + p2->x + p3->x) * (float)(1.0/3.0) ;
|
|
pc->y = (p1->y + p2->y + p3->y) * (float)(1.0/3.0) ;
|
|
pc->z = (p1->z + p2->z + p3->z) * (float)(1.0/3.0) ;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* four_center_points()
|
|
*
|
|
* P = (P1 + P2 + P3) / 3
|
|
*
|
|
***************************************************************************/
|
|
|
|
void four_center_points(Vertex *p1, Vertex *p2, Vertex *p3, Vertex *pc, Vertex *pc1, Vertex *pc2, Vertex *pc3)
|
|
{
|
|
/* Compute mid point of the element */
|
|
pc->x = (p1->x + p2->x + p3->x) * (float)(1.0/3.0) ;
|
|
pc->y = (p1->y + p2->y + p3->y) * (float)(1.0/3.0) ;
|
|
pc->z = (p1->z + p2->z + p3->z) * (float)(1.0/3.0) ;
|
|
|
|
pc1->x = (p1->x * 4 + p2->x + p3->x) * (float)(1.0/6.0) ;
|
|
pc1->y = (p1->y * 4 + p2->y + p3->y) * (float)(1.0/6.0) ;
|
|
pc1->z = (p1->z * 4 + p2->z + p3->z) * (float)(1.0/6.0) ;
|
|
|
|
pc2->x = (p1->x + p2->x * 4 + p3->x) * (float)(1.0/6.0) ;
|
|
pc2->y = (p1->y + p2->y * 4 + p3->y) * (float)(1.0/6.0) ;
|
|
pc2->z = (p1->z + p2->z * 4 + p3->z) * (float)(1.0/6.0) ;
|
|
|
|
pc3->x = (p1->x + p2->x + p3->x * 4) * (float)(1.0/6.0) ;
|
|
pc3->y = (p1->y + p2->y + p3->y * 4) * (float)(1.0/6.0) ;
|
|
pc3->z = (p1->z + p2->z + p3->z * 4) * (float)(1.0/6.0) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* print_point()
|
|
*
|
|
* Print point information.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void print_point(Vertex *point)
|
|
{
|
|
printf( "\tP(%.2f, %.2f, %.2f)\n", point->x, point->y, point->z ) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
****************************************************************************
|
|
*
|
|
* Methods for Rgb object
|
|
*
|
|
****************************************************************************
|
|
****************************************************************************
|
|
****************************************************************************
|
|
*
|
|
* print_rgb()
|
|
*
|
|
* Print RGB information.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void print_rgb(Rgb *rgb)
|
|
{
|
|
printf( "\tRGB(%.2f, %.2f, %.2f)\n", rgb->r, rgb->g, rgb->b ) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
****************************************************************************
|
|
*
|
|
* Methods for ElementVertex
|
|
*
|
|
****************************************************************************
|
|
****************************************************************************/
|
|
/***************************************************************************
|
|
*
|
|
* create_elemvertex
|
|
*
|
|
* Given Vertex, create and return a new ElemVertex object.
|
|
*
|
|
****************************************************************************/
|
|
|
|
ElemVertex *create_elemvertex(Vertex *p, long process_id)
|
|
{
|
|
ElemVertex *ev_new ;
|
|
|
|
ev_new = get_elemvertex(process_id) ;
|
|
ev_new->p = *p ;
|
|
|
|
return( ev_new ) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* get_elemvertex
|
|
*
|
|
* Returns an ElementVertex object
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
ElemVertex *get_elemvertex(long process_id)
|
|
{
|
|
ElemVertex *ev ;
|
|
|
|
if( sobj_struct[process_id].n_local_free_elemvertex == 0 )
|
|
{
|
|
LOCK(global->free_elemvertex_lock);
|
|
if ( MAX_ELEMVERTICES - global->free_elemvertex
|
|
< N_ELEMVERTEX_ALLOCATE )
|
|
{
|
|
fprintf( stderr, "Fatal:Ran out of ElemVertex buffer\n" ) ;
|
|
UNLOCK(global->free_elemvertex_lock);
|
|
exit(1) ;
|
|
}
|
|
sobj_struct[process_id].n_local_free_elemvertex = N_ELEMVERTEX_ALLOCATE ;
|
|
sobj_struct[process_id].local_free_elemvertex
|
|
= &global->elemvertex_buf[ global->free_elemvertex ] ;
|
|
global->free_elemvertex += N_ELEMVERTEX_ALLOCATE ;
|
|
UNLOCK(global->free_elemvertex_lock);
|
|
}
|
|
|
|
ev = sobj_struct[process_id].local_free_elemvertex++ ;
|
|
sobj_struct[process_id].n_local_free_elemvertex-- ;
|
|
|
|
|
|
/* Initialize contents */
|
|
ev->col.r = 0.0 ;
|
|
ev->col.g = 0.0 ;
|
|
ev->col.b = 0.0 ;
|
|
ev->weight = 0.0 ;
|
|
|
|
return( ev ) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* init_elemvertex()
|
|
*
|
|
* Initialize ElemVertex buffer.
|
|
* This routine must be called in single process state.
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
void init_elemvertex(long process_id)
|
|
{
|
|
long ev_cnt ;
|
|
|
|
/* Initialize global free list */
|
|
LOCKINIT(global->free_elemvertex_lock);
|
|
global->free_elemvertex = 0 ;
|
|
|
|
/* Allocate locks */
|
|
for( ev_cnt = 0 ; ev_cnt < MAX_ELEMVERTICES ; ev_cnt++ )
|
|
global->elemvertex_buf[ ev_cnt ].ev_lock
|
|
= get_sharedlock( SHARED_LOCK_SEGANY, process_id ) ;
|
|
|
|
/* Initialize local free list */
|
|
sobj_struct[process_id].n_local_free_elemvertex = 0 ;
|
|
sobj_struct[process_id].local_free_elemvertex = 0 ;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
****************************************************************************
|
|
*
|
|
* Methods for Edge
|
|
*
|
|
****************************************************************************
|
|
****************************************************************************/
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* foreach_leaf_edge()
|
|
*
|
|
* For each leaf edges of the binary edge tree, apply the specified
|
|
* function. Edges are traversed from A to B (i.e., from Pa of the root
|
|
* to the Pb of the root) if 'reverse' is 0. Otherwise, it is traversed
|
|
* from B to A.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void foreach_leaf_edge(Edge *edge, long reverse, void (*func)(), long arg1, long arg2, long process_id)
|
|
{
|
|
Edge *first, *second ;
|
|
|
|
if( edge == 0 )
|
|
return ;
|
|
|
|
if( (edge->ea == 0) && (edge->eb == 0) )
|
|
func( edge, reverse, arg1, arg2, process_id ) ;
|
|
else
|
|
{
|
|
if( reverse )
|
|
{
|
|
first = edge->eb ;
|
|
second = edge->ea ;
|
|
}
|
|
else
|
|
{
|
|
first = edge->ea ;
|
|
second = edge->eb ;
|
|
}
|
|
if( first )
|
|
foreach_leaf_edge( first, reverse, func, arg1, arg2, process_id ) ;
|
|
if( second )
|
|
foreach_leaf_edge( second, reverse, func, arg1, arg2, process_id ) ;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* create_edge()
|
|
*
|
|
* Given two ElemVertices V1 and V2, create a new edge (V1,V2)
|
|
*
|
|
****************************************************************************/
|
|
|
|
Edge *create_edge(ElemVertex *v1, ElemVertex *v2, long process_id)
|
|
{
|
|
Edge *enew ;
|
|
|
|
enew = get_edge(process_id) ;
|
|
enew->pa = v1 ;
|
|
enew->pb = v2 ;
|
|
return( enew ) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* subdivide_edge()
|
|
*
|
|
* Create child edges. If they already exist, do nothing.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void subdivide_edge(Edge *e, float a_ratio, long process_id)
|
|
{
|
|
Edge *enew, *e_am ;
|
|
ElemVertex *ev_middle ;
|
|
float b_ratio ;
|
|
|
|
/* Lock the element before checking the value */
|
|
LOCK(e->edge_lock->lock);
|
|
|
|
/* Check if the element already has children */
|
|
if( ! _LEAF_EDGE(e) )
|
|
{
|
|
UNLOCK(e->edge_lock->lock);
|
|
return ;
|
|
}
|
|
|
|
/* Create the subdivision point */
|
|
b_ratio = (float)1.0 - a_ratio ;
|
|
ev_middle = get_elemvertex(process_id) ;
|
|
ev_middle->p.x = a_ratio * e->pa->p.x + b_ratio * e->pb->p.x ;
|
|
ev_middle->p.y = a_ratio * e->pa->p.y + b_ratio * e->pb->p.y ;
|
|
ev_middle->p.z = a_ratio * e->pa->p.z + b_ratio * e->pb->p.z ;
|
|
|
|
/* (1) Create edge(A-middle) */
|
|
enew = get_edge(process_id) ;
|
|
e_am = enew ;
|
|
enew->pa = e->pa ;
|
|
enew->pb = ev_middle ;
|
|
|
|
/* (2) Create edge(middle-B) */
|
|
enew = get_edge(process_id) ;
|
|
enew->pa = ev_middle ;
|
|
enew->pb = e->pb ;
|
|
e->eb = enew ;
|
|
|
|
/* Finally, set e->ea */
|
|
e->ea = e_am ;
|
|
|
|
/* Unlock the element */
|
|
UNLOCK(e->edge_lock->lock);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* get_edge
|
|
*
|
|
* Returns an Edge object
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
Edge *get_edge(long process_id)
|
|
{
|
|
Edge *edge ;
|
|
|
|
if( sobj_struct[process_id].n_local_free_edge == 0 )
|
|
{
|
|
LOCK(global->free_edge_lock);
|
|
if ( MAX_EDGES - global->free_edge < N_EDGE_ALLOCATE )
|
|
{
|
|
fprintf( stderr, "Fatal:Ran out of Edge buffer\n" ) ;
|
|
UNLOCK(global->free_edge_lock);
|
|
exit(1) ;
|
|
}
|
|
sobj_struct[process_id].n_local_free_edge = N_EDGE_ALLOCATE ;
|
|
sobj_struct[process_id].local_free_edge
|
|
= &global->edge_buf[ global->free_edge ] ;
|
|
global->free_edge += N_EDGE_ALLOCATE ;
|
|
UNLOCK(global->free_edge_lock);
|
|
}
|
|
|
|
edge = sobj_struct[process_id].local_free_edge++ ;
|
|
sobj_struct[process_id].n_local_free_edge-- ;
|
|
|
|
|
|
/* Initialize contents */
|
|
edge->pa = 0 ;
|
|
edge->pb = 0 ;
|
|
edge->ea = 0 ;
|
|
edge->eb = 0 ;
|
|
|
|
return( edge ) ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* init_edge()
|
|
*
|
|
* Initialize Edge buffer.
|
|
* This routine must be called in single process state.
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
void init_edge(long process_id)
|
|
{
|
|
long edge_cnt ;
|
|
|
|
/* Initialize global free list */
|
|
LOCKINIT(global->free_edge_lock);
|
|
global->free_edge = 0 ;
|
|
|
|
/* Allocate locks */
|
|
for( edge_cnt = 0 ; edge_cnt < MAX_EDGES ; edge_cnt++ )
|
|
global->edge_buf[ edge_cnt ].edge_lock
|
|
= get_sharedlock( SHARED_LOCK_SEG0, process_id ) ;
|
|
|
|
/* Initialize local free list */
|
|
sobj_struct[process_id].n_local_free_edge = 0 ;
|
|
sobj_struct[process_id].local_free_edge = 0 ;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
****************************************************************************
|
|
*
|
|
* Methods for Shared_Lock
|
|
*
|
|
* Some machines provide a limited number of lock variables due to hardware
|
|
* constraints etc. This package controls the sharing of this limited number
|
|
* of locks among objects.
|
|
*
|
|
****************************************************************************
|
|
****************************************************************************/
|
|
/***************************************************************************
|
|
*
|
|
* init_sharedlock()
|
|
*
|
|
* Initialize shared lock.
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
void init_sharedlock(long process_id)
|
|
{
|
|
long i ;
|
|
|
|
for( i = 0 ; i < MAX_SHARED_LOCK ; i++ )
|
|
{
|
|
LOCKINIT(global->sh_lock[i].lock);
|
|
}
|
|
|
|
sobj_struct[process_id].lock_alloc_counter = 0 ;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* get_sharedlock()
|
|
*
|
|
* Return a shared lock variable. If SHARED_LOCK_SEG[01] is specified,
|
|
* the lock is selected from the specified segment. If SHARED_LOCK_SEGANY
|
|
* is specified, the lock is picked up from arbitrary segment.
|
|
*
|
|
****************************************************************************/
|
|
|
|
Shared_Lock *get_sharedlock(long segment, long process_id)
|
|
{
|
|
Shared_Lock *pshl ;
|
|
long effective_lock_ctr ;
|
|
|
|
/* Compute effective lock allocation counter value */
|
|
switch( segment )
|
|
{
|
|
case SHARED_LOCK_SEG0:
|
|
effective_lock_ctr = sobj_struct[process_id].lock_alloc_counter % SHARED_LOCK_SEG_SIZE ;
|
|
break ;
|
|
case SHARED_LOCK_SEG1:
|
|
effective_lock_ctr = sobj_struct[process_id].lock_alloc_counter % SHARED_LOCK_SEG_SIZE
|
|
+ SHARED_LOCK_SEG_SIZE ;
|
|
break ;
|
|
default:
|
|
effective_lock_ctr = sobj_struct[process_id].lock_alloc_counter ;
|
|
}
|
|
|
|
|
|
/* Get pointer to the lock */
|
|
pshl = &global->sh_lock[ effective_lock_ctr ] ;
|
|
|
|
/* Update the lock counter */
|
|
sobj_struct[process_id].lock_alloc_counter++ ;
|
|
if( sobj_struct[process_id].lock_alloc_counter >= MAX_SHARED_LOCK )
|
|
sobj_struct[process_id].lock_alloc_counter = 0 ;
|
|
|
|
return( pshl ) ;
|
|
}
|
|
|