blob: b07901971a8af2415f7ba9bdffcbd1a36feff7e8 [file] [log] [blame]
/*************************************************************************/
/* */
/* 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. */
/* */
/*************************************************************************/
#include "defs.h"
#include "memory.h"
#include "box.h"
#include "partition_grid.h"
#include "cost_zones.h"
#define NUM_DIRECTIONS 4
typedef enum { RIGHT, LEFT, UP, DOWN } direction;
static long Child_Sequence[NUM_DIRECTIONS][NUM_OFFSPRING] =
{
{ 0, 1, 2, 3 },
{ 2, 3, 0, 1 },
{ 0, 3, 2, 1 },
{ 2, 1, 0, 3 },
};
static long Direction_Sequence[NUM_DIRECTIONS][NUM_OFFSPRING] =
{
{ UP, RIGHT, RIGHT, DOWN },
{ DOWN, LEFT, LEFT, UP },
{ RIGHT, UP, UP, LEFT },
{ LEFT, DOWN, DOWN, RIGHT },
};
void ComputeSubTreeCosts(long my_id, box *b);
void CostZonesHelper(long my_id, box *b, long work, direction dir);
void
CostZones (long my_id)
{
PartitionIterate(my_id, ComputeSubTreeCosts, BOTTOM);
BARRIER(G_Memory->synch, Number_Of_Processors);
Local[my_id].Total_Work = Grid->subtree_cost;
Local[my_id].Min_Work = ((Local[my_id].Total_Work / Number_Of_Processors)
* my_id);
if (my_id == (Number_Of_Processors - 1))
Local[my_id].Max_Work = Local[my_id].Total_Work;
else
Local[my_id].Max_Work = (Local[my_id].Min_Work
+ (Local[my_id].Total_Work
/ Number_Of_Processors));
InitPartition(my_id);
CostZonesHelper(my_id, Grid, 0, RIGHT);
BARRIER(G_Memory->synch, Number_Of_Processors);
}
void
ComputeSubTreeCosts (long my_id, box *b)
{
box *pb;
if (b->type == PARENT) {
while (b->interaction_synch != b->num_children) {
}
}
b->interaction_synch = 0;
ComputeCostOfBox(b);
b->subtree_cost += b->cost;
pb = b->parent;
if (pb != NULL) {
ALOCK(G_Memory->lock_array, pb->exp_lock_index);
pb->subtree_cost += b->subtree_cost;
pb->interaction_synch += 1;
AULOCK(G_Memory->lock_array, pb->exp_lock_index);
}
}
void
CostZonesHelper (long my_id, box *b, long work, direction dir)
{
box *cb;
long i;
long *next_child;
long *child_dir;
if (b->type == CHILDLESS) {
if (work >= Local[my_id].Min_Work)
InsertBoxInPartition(my_id, b);
}
else {
next_child = Child_Sequence[dir];
child_dir = Direction_Sequence[dir];
for (i = 0; (i < NUM_OFFSPRING) && (work < Local[my_id].Max_Work);
i++) {
cb = b->children[next_child[i]];
if (cb != NULL) {
if ((work + cb->subtree_cost) >= Local[my_id].Min_Work)
CostZonesHelper(my_id, cb, work, child_dir[i]);
work += cb->subtree_cost;
}
if (i == 2) {
if ((work >= Local[my_id].Min_Work)
&& (work < Local[my_id].Max_Work))
InsertBoxInPartition(my_id, b);
work += b->cost;
}
}
}
}
#undef DOWN
#undef UP
#undef LEFT
#undef RIGHT
#undef NUM_DIRECTIONS