795 lines
22 KiB
C
795 lines
22 KiB
C
#ifdef __TANDEM
|
||
#pragma columns 79
|
||
#pragma page "srgputl.c - T9050 - utility routines for Regroup Module"
|
||
#endif
|
||
|
||
/* @@@ START COPYRIGHT @@@
|
||
** Tandem Confidential: Need to Know only
|
||
** Copyright (c) 1995, Tandem Computers Incorporated
|
||
** Protected as an unpublished work.
|
||
** All Rights Reserved.
|
||
**
|
||
** The computer program listings, specifications, and documentation
|
||
** herein are the property of Tandem Computers Incorporated and shall
|
||
** not be reproduced, copied, disclosed, or used in whole or in part
|
||
** for any reason without the prior express written permission of
|
||
** Tandem Computers Incorporated.
|
||
**
|
||
** @@@ END COPYRIGHT @@@
|
||
**/
|
||
|
||
/*---------------------------------------------------------------------------
|
||
* This file (srgputl.c) contains the cluster_t data type implementation
|
||
* and the node pruning algorithm used by Regroup.
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif /* __cplusplus */
|
||
|
||
|
||
#include <wrgp.h>
|
||
|
||
/************************************************************************
|
||
* ClusterInit,
|
||
* ClusterUnion,
|
||
* ClusterIntersection,
|
||
* ClusterDifference,
|
||
* ClusterCompare,
|
||
* ClusterSubsetOf,
|
||
* ClusterComplement,
|
||
* ClusterMember,
|
||
* ClusterInsert,
|
||
* ClusterDelete,
|
||
* ClusterCopy,
|
||
* ClusterSwap,
|
||
* ClusterNumMembers
|
||
* =================
|
||
*
|
||
* Description:
|
||
*
|
||
* Functions that implement operations on the cluster_t type.
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* Operates on the byte array that is the cluster_t type.
|
||
*
|
||
************************************************************************/
|
||
_priv _resident void
|
||
ClusterInit(cluster_t c)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
c[i] = 0;
|
||
}
|
||
|
||
_priv _resident void
|
||
ClusterUnion(cluster_t dst, cluster_t src1, cluster_t src2)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
dst[i] = src1[i] | src2[i];
|
||
}
|
||
|
||
_priv _resident void
|
||
ClusterIntersection(cluster_t dst, cluster_t src1, cluster_t src2)
|
||
{
|
||
int i;
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
dst[i] = src1[i] & src2[i];
|
||
}
|
||
|
||
_priv _resident void
|
||
ClusterDifference(cluster_t dst, cluster_t src1, cluster_t src2)
|
||
{
|
||
int i;
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
dst[i] = src1[i] & (~src2[i]);
|
||
}
|
||
|
||
_priv _resident int ClusterCompare(cluster_t c1, cluster_t c2)
|
||
{
|
||
int identical, i;
|
||
|
||
identical = 1;
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
{
|
||
if (c1[i] != c2[i])
|
||
{
|
||
identical = 0;
|
||
break;
|
||
}
|
||
}
|
||
return(identical);
|
||
}
|
||
|
||
_priv _resident int ClusterSubsetOf(cluster_t big, cluster_t small)
|
||
/* Returns 1 if set small = set big or small is a subset of big. */
|
||
{
|
||
int subset, i;
|
||
|
||
subset = 1;
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
{
|
||
if ( (big[i] != small[i]) && ((big[i] ^ small[i]) & small[i]) )
|
||
{
|
||
subset = 0;
|
||
break;
|
||
}
|
||
}
|
||
return(subset);
|
||
}
|
||
|
||
_priv _resident void ClusterComplement(cluster_t dst, cluster_t src)
|
||
{
|
||
int i;
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
dst[i] = ~src[i];
|
||
}
|
||
|
||
_priv _resident int ClusterMember(cluster_t c, node_t i)
|
||
{
|
||
return((BYTE(c,i) >> (BYTEL-1-BIT(i))) & 1);
|
||
}
|
||
|
||
_priv _resident void ClusterInsert(cluster_t c, node_t i)
|
||
{
|
||
BYTE(c, i) |= (1 << (BYTEL-1-BIT(i)));
|
||
}
|
||
|
||
_priv _resident void ClusterDelete(cluster_t c, node_t i)
|
||
{
|
||
BYTE(c, i) &= ~(1 << (BYTEL-1-BIT(i)));
|
||
}
|
||
|
||
_priv _resident void ClusterCopy(cluster_t dst, cluster_t src)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
dst[i] = src[i];
|
||
}
|
||
|
||
_priv _resident void ClusterSwap(cluster_t c1, cluster_t c2)
|
||
{
|
||
int i;
|
||
unsigned char temp;
|
||
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
{
|
||
temp = c1[i];
|
||
c1[i] = c2[i];
|
||
c2[i] = temp;
|
||
}
|
||
}
|
||
|
||
_priv _resident int ClusterNumMembers(cluster_t c)
|
||
/* Returns the number of nodes in the cluster. */
|
||
{
|
||
int num_members = 0, i, j;
|
||
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
{
|
||
if (c[i])
|
||
{
|
||
for (j = 0; j < BYTEL; j++)
|
||
if (c[i] & (1 << j))
|
||
num_members++;
|
||
}
|
||
}
|
||
return(num_members);
|
||
}
|
||
|
||
/************************************************************************
|
||
* ClusterEmpty
|
||
* =================
|
||
*
|
||
* Description:
|
||
*
|
||
* Checks that a cluster has no members
|
||
*
|
||
* Parameters:
|
||
*
|
||
* cluster_t c
|
||
* cluster to be examined
|
||
*
|
||
* Returns:
|
||
*
|
||
* 0 - cluster contains at least one node
|
||
* 1 - cluster is empty
|
||
*
|
||
* Comment:
|
||
*
|
||
* The proper place for this function is in srgputl.c
|
||
*
|
||
************************************************************************/
|
||
int ClusterEmpty(cluster_t c)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < BYTES_IN_CLUSTER; i++)
|
||
{
|
||
if (c[i])
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* rgp_select_tiebreaker
|
||
* =====================
|
||
*
|
||
* Description:
|
||
*
|
||
* Simple algorithm to select the tie-breaker.
|
||
*
|
||
* Parameters:
|
||
*
|
||
* cluster_t cluster -
|
||
* cluster from which a tie-breaker is to be selected
|
||
*
|
||
* Returns:
|
||
*
|
||
* node_t - the node number of the selected tie-breaker
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* The tie-breaker is defined as the lowest numbered node in the
|
||
* cluster.
|
||
*
|
||
************************************************************************/
|
||
_priv _resident node_t
|
||
rgp_select_tiebreaker(cluster_t cluster)
|
||
{
|
||
node_t i;
|
||
|
||
for (i = 0; (i < (node_t) rgp->num_nodes) && !ClusterMember(cluster, i); i++);
|
||
|
||
/* If the cluster does not have any members, we have a problem! */
|
||
if (i >= (node_t) rgp->num_nodes)
|
||
RGP_ERROR(RGP_INTERNAL_ERROR);
|
||
|
||
return(i);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------------
|
||
* Node pruning algorithm used by Regroup.
|
||
*---------------------------------------------------------------------------
|
||
*/
|
||
|
||
/************************************************************************
|
||
* group_exists
|
||
* ============
|
||
*
|
||
* Description:
|
||
*
|
||
* Check if a specific group already exists or is a subset of a
|
||
* group that already exists.
|
||
*
|
||
* Parameters:
|
||
*
|
||
* cluster_t groups[] -
|
||
* array of groups to examine
|
||
*
|
||
* int numgroups -
|
||
* number of groups discovered so far
|
||
*
|
||
* cluster_t g -
|
||
* specific group to check
|
||
*
|
||
* Returns:
|
||
*
|
||
* int - 1 if the specified group exists in the array; 0 therwise.
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* Goes through the array and calls ClusterSubsetOf to check if the
|
||
* specified group g is a subset of the the array element.
|
||
*
|
||
************************************************************************/
|
||
#if !defined(NT)
|
||
_priv _resident static
|
||
int
|
||
#endif
|
||
group_exists(cluster_t groups[], int numgroups, cluster_t g)
|
||
{
|
||
int exists, i;
|
||
|
||
exists = 0;
|
||
for (i = 0; i < numgroups; i++)
|
||
{
|
||
if (ClusterSubsetOf(groups[i],g))
|
||
{
|
||
exists = 1;
|
||
break;
|
||
}
|
||
}
|
||
return(exists);
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* prune
|
||
* =====
|
||
*
|
||
* Description:
|
||
*
|
||
* Algorithm to find all fully connected groups based on # of
|
||
* disconnects in the matrix.
|
||
*
|
||
* Parameters:
|
||
*
|
||
* disconnect_array disconnects -
|
||
* input : array of disconnects
|
||
*
|
||
* int D -
|
||
* input : size of disconnects array
|
||
*
|
||
* cluster_t live_nodes -
|
||
* input : set of all live nodes
|
||
*
|
||
* cluster_t groups[] -
|
||
* output: array of fully-connected groups
|
||
*
|
||
* Returns:
|
||
*
|
||
* int - the number of groups made; 0 if no groups or other error
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* Start with one group that contains the set of live nodes.
|
||
* More groups will be generated as disconnects are examined.
|
||
*
|
||
* Process each disconnect in the disconnects array by applying
|
||
* the disconnect to the current set of fully-connected groups.
|
||
*
|
||
* The effect of a disconnect on a fully-conncted group depends on
|
||
* whether the end points of the disconnect are in the group or not.
|
||
*
|
||
* If the group contains neither or only one of the endpoints of
|
||
* the disconnect, the disconnect has no effect on the group.
|
||
*
|
||
* If both endpoints of the disconnect are in the group, then the
|
||
* group is split into two groups - the original group without
|
||
* endpoint 1 and the original group without endpoint 2.
|
||
* New groups so generated should be discarded if they already
|
||
* exist or are subsets of currently existing groups.
|
||
*
|
||
* After every disconnect is processed, we end up with the final
|
||
* set of fully-connected groups.
|
||
*
|
||
************************************************************************/
|
||
#if !defined(NT)
|
||
_priv _resident static
|
||
#endif
|
||
int
|
||
prune(
|
||
disconnect_array disconnects,
|
||
int D,
|
||
cluster_t live_nodes,
|
||
cluster_t groups[])
|
||
{
|
||
int numgroups = 1, i, j;
|
||
|
||
ClusterCopy(groups[0], live_nodes);
|
||
|
||
for (i = 0; i < D; i ++)
|
||
{
|
||
for (j = 0; j < numgroups; j++)
|
||
{
|
||
/* Split a group that has both ends of the disconnect. */
|
||
if (ClusterMember(groups[j],disconnects[i][0]) &&
|
||
ClusterMember(groups[j],disconnects[i][1]))
|
||
{
|
||
/* Correct current group in place.
|
||
* Add new group at the end of the array.
|
||
*/
|
||
numgroups++;
|
||
ClusterCopy(groups[numgroups-1], groups[j]);
|
||
ClusterDelete(groups[j], disconnects[i][0]);
|
||
ClusterDelete(groups[numgroups-1], disconnects[i][1]);
|
||
|
||
/* Check if the new groups already exist or are subgroups
|
||
* of existing groups.
|
||
*/
|
||
|
||
/* First, check the group added at the end of the array. */
|
||
if (group_exists(groups, numgroups-1, groups[numgroups-1]))
|
||
numgroups--;
|
||
|
||
/* Next, check the modified group at j.
|
||
* To simplify the checking, switch it with the last element
|
||
* of the array. If the group already exists, it should be
|
||
* removed. Since the group is now the last element of the
|
||
* array, removal requires only decrementing the array count.
|
||
*/
|
||
ClusterSwap(groups[j], groups[numgroups-1]);
|
||
if (group_exists(groups, numgroups-1, groups[numgroups-1]))
|
||
numgroups--;
|
||
j--; /* The j-th entry has been switched with the last entry;
|
||
it has to be examined again */
|
||
}
|
||
}
|
||
}
|
||
|
||
return(numgroups);
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* select_group_with_designated_node
|
||
* =================================
|
||
*
|
||
* Description:
|
||
*
|
||
* Function to pick an arbitrary fully connected group that
|
||
* includes a specified node.
|
||
*
|
||
* Parameters:
|
||
*
|
||
* connectivity_matrix_t c -
|
||
* input : cluster's connectivity info
|
||
*
|
||
* node_t selected_node -
|
||
* input : just find a fully-connected group that includes this node
|
||
*
|
||
* cluster_t *group -
|
||
* output: group that includes selected_node
|
||
*
|
||
* Returns:
|
||
*
|
||
* int - returns 1 if the specified node is alive and 0 if it is not
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* Start with a group that includes just the selected node.
|
||
* Then, examine nodes starting with node 0 and go up till the
|
||
* largest node number. If a node is alive, include it in the group
|
||
* if and only if it is connected to all current members of the
|
||
* group.
|
||
*
|
||
* When all nodes are examined, we get a fully-connected group that
|
||
* includes the selected node. This is only one of potentially many
|
||
* fully-connected groups and is not necessarily the largest
|
||
* solution.
|
||
*
|
||
* This order of examining nodes gives higher priority to lower
|
||
* numbered nodes.
|
||
*
|
||
************************************************************************/
|
||
#if !defined(NT)
|
||
_priv _resident static
|
||
#endif
|
||
int
|
||
select_group_with_designated_node(
|
||
connectivity_matrix_t c,
|
||
node_t selected_node,
|
||
cluster_t *group)
|
||
{
|
||
node_t i, j;
|
||
|
||
if (!node_considered_alive(selected_node))
|
||
return(0);
|
||
else
|
||
{
|
||
ClusterInit(*group);
|
||
ClusterInsert(*group, selected_node);
|
||
for (i = 0; i < (node_t) rgp->num_nodes; i++)
|
||
{
|
||
if ((i != selected_node) &&
|
||
node_considered_alive(i) &&
|
||
connected(i, selected_node)
|
||
)
|
||
{
|
||
/* Check if i is connected to all members of the group
|
||
* built so far.
|
||
*/
|
||
for (j = 0; j < i; j++)
|
||
{
|
||
if (ClusterMember(*group, j) && !connected(j, i))
|
||
break;
|
||
}
|
||
if (j == i) /* i is connected to all current members*/
|
||
ClusterInsert(*group, i);
|
||
}
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* MatrixInit
|
||
* ==========
|
||
*
|
||
* Description:
|
||
*
|
||
* Initialize the matrix c to show 0 connectivity.
|
||
*
|
||
* Parameters:
|
||
*
|
||
* connectivity_matrix_t c - matrix to be set to 0s.
|
||
*
|
||
* Returns:
|
||
*
|
||
* void - no return value
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* Calls ClusterInit to initialize the clusters in the matrix.
|
||
*
|
||
************************************************************************/
|
||
_priv _resident void
|
||
MatrixInit(connectivity_matrix_t c)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < (node_t) rgp->num_nodes; i++)
|
||
{
|
||
ClusterInit(c[i]);
|
||
}
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* MatrixSet
|
||
* =========
|
||
*
|
||
* Description:
|
||
*
|
||
* Set matrix[row,column] to 1.
|
||
*
|
||
* Parameters:
|
||
*
|
||
* connectivity_matrix_t c - matrix to be modified
|
||
*
|
||
* int row - row number
|
||
*
|
||
* int column - column number
|
||
*
|
||
* Returns:
|
||
*
|
||
* void - no return value
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* Calls ClusterInsert to set the appropriate bit (column) in the
|
||
* appropriate cluster (row) in the matrix.
|
||
*
|
||
************************************************************************/
|
||
_priv _resident void
|
||
MatrixSet(connectivity_matrix_t c, int row, int column)
|
||
{
|
||
ClusterInsert(c[row], (node_t) column);
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* MatrixOr
|
||
* ========
|
||
*
|
||
* Description:
|
||
*
|
||
* matrix t := t OR s
|
||
*
|
||
* Parameters:
|
||
*
|
||
* connectivity_matrix_t t - target matrix
|
||
*
|
||
* connectivity_matrix_t s - source matrix to be ORed into target
|
||
*
|
||
* Returns:
|
||
*
|
||
* void - no return value
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* Calls ClusterUnion to OR the appropriate clusters (rows) in the
|
||
* matrices.
|
||
*
|
||
************************************************************************/
|
||
_priv _resident void
|
||
MatrixOr(connectivity_matrix_t t, connectivity_matrix_t s)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < (node_t) rgp->num_nodes; i++)
|
||
ClusterUnion(t[i], s[i], t[i]);
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* connectivity_complete
|
||
* =====================
|
||
*
|
||
* Description:
|
||
*
|
||
* Boolean function that checks if a given connectivity matrix implies
|
||
* full connectivity (all nodes can talk to all others).
|
||
*
|
||
* Parameters:
|
||
*
|
||
* connectivity_matrix_t c - connectivity matrix of the cluster
|
||
*
|
||
* Returns:
|
||
*
|
||
* int - 0 if there are disconnects in the cluster; 1 if it has full
|
||
* connectivity.
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* Checks to see if there is any live node in the cluster that cannot
|
||
* communicate to another live node in the cluster. Node i is
|
||
* considered alive if c[i,i] is set. Nodes i and j are deemed to
|
||
* be able to communicate if c[i,j] and c[j,i] are both set.
|
||
*
|
||
************************************************************************/
|
||
_priv _resident int
|
||
connectivity_complete(connectivity_matrix_t c)
|
||
{
|
||
node_t i, j;
|
||
|
||
for (i = 0; i < (node_t) rgp->num_nodes; i++)
|
||
{
|
||
if (node_considered_alive(i))
|
||
{
|
||
for (j = 0; j < i; j++)
|
||
{
|
||
if (node_considered_alive(j) && !connected(i, j))
|
||
{
|
||
/* i and j are a pair of live nodes which are not
|
||
connected. Thus, there is at least one disconnect.
|
||
Return 0. */
|
||
return(0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* No disconnects found; return 1. */
|
||
return(1);
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* find_all_fully_connected_groups
|
||
* ===============================
|
||
*
|
||
* Description:
|
||
*
|
||
* Function to find all fully connected groups in a graph specified
|
||
* by a connectivity matrix. An optional "selected_node" can be
|
||
* used to simplify the search in case of too large a number of
|
||
* possibilities. In that case, a fully-connected group that
|
||
* includes selected_node is returned.
|
||
*
|
||
* Parameters:
|
||
*
|
||
* connectivity_matrix_t c -
|
||
* input : cluster's connectivity info
|
||
*
|
||
* node_t selected_node -
|
||
* input : if there are too many potential groups, just find one
|
||
* that includes this node; if all groups can be listed, ignore this.
|
||
*
|
||
* cluster_t groups[] -
|
||
* output: array of potential clusters
|
||
*
|
||
* Returns:
|
||
*
|
||
* int - the number of groups made; 0 if no groups or other error
|
||
*
|
||
* Algorithm:
|
||
*
|
||
* First the set of live nodes and the set of disconnects in the
|
||
* cluster are evaluated. Then, if the number of live nodes and
|
||
* disconnects indicates a potentially large number of
|
||
* possibilities, select_group_with_designated_node() is called to
|
||
* limit the search to a group including the specified node.
|
||
* Otherwise, prune() is called to get the list of all possible
|
||
* fully-connected groups.
|
||
*
|
||
************************************************************************/
|
||
_priv _resident int
|
||
find_all_fully_connected_groups(
|
||
connectivity_matrix_t c,
|
||
node_t selected_node,
|
||
cluster_t groups[])
|
||
{
|
||
disconnect_array disconnects;
|
||
cluster_t live_nodes;
|
||
int num_livenodes = 0, num_disconnects = 0;
|
||
node_t i, j;
|
||
|
||
ClusterInit(live_nodes);
|
||
for (i = 0; i < (node_t) rgp->num_nodes; i++)
|
||
{
|
||
if (node_considered_alive(i))
|
||
{
|
||
ClusterInsert(live_nodes, i);
|
||
num_livenodes++;
|
||
for (j = 0; j < i; j++)
|
||
{
|
||
if (node_considered_alive(j) && !connected(i, j))
|
||
{
|
||
/* i and j are a pair of live nodes which are not
|
||
connected. */
|
||
disconnects[num_disconnects][0] = i;
|
||
disconnects[num_disconnects][1] = j;
|
||
num_disconnects++;
|
||
}
|
||
}
|
||
if (too_many_groups(num_livenodes, num_disconnects))
|
||
{
|
||
RGP_TRACE( "RGP Too many dis",
|
||
num_livenodes, /* TRACE */
|
||
num_disconnects, /* TRACE */
|
||
0, 0 ); /* TRACE */
|
||
/* There may be too many choices to consider in reasonable
|
||
* time/space. Just return a fully-connected group that
|
||
* includes the selected node.
|
||
*/
|
||
return(select_group_with_designated_node(c,selected_node,groups));
|
||
}
|
||
}
|
||
}
|
||
|
||
if (num_livenodes == 0)
|
||
return(0);
|
||
else
|
||
return(prune(disconnects, num_disconnects, live_nodes, groups));
|
||
}
|
||
/*---------------------------------------------------------------------------*/
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif /* __cplusplus */
|
||
|
||
|
||
#if 0
|
||
|
||
History of changes to this file:
|
||
-------------------------------------------------------------------------
|
||
1995, December 13 F40:KSK0610 /*F40:KSK06102.2*/
|
||
|
||
This file is part of the portable Regroup Module used in the NonStop
|
||
Kernel (NSK) and Loosely Coupled UNIX (LCU) operating systems. There
|
||
are 10 files in the module - jrgp.h, jrgpos.h, wrgp.h, wrgpos.h,
|
||
srgpif.c, srgpos.c, srgpsm.c, srgputl.c, srgpcli.c and srgpsvr.c.
|
||
The last two are simulation files to test the Regroup Module on a
|
||
UNIX workstation in user mode with processes simulating processor nodes
|
||
and UDP datagrams used to send unacknowledged datagrams.
|
||
|
||
This file was first submitted for release into NSK on 12/13/95.
|
||
------------------------------------------------------------------------------
|
||
This change occurred on 19 Jan 1996 /*F40:MB06458.1*/
|
||
Changes for phase IV Sierra message system release. Includes: /*F40:MB06458.2*/
|
||
- Some cleanup of the code /*F40:MB06458.3*/
|
||
- Increment KCCB counters to count the number of setup messages and /*F40:MB06458.4*/
|
||
unsequenced messages sent. /*F40:MB06458.5*/
|
||
- Fixed some bugs /*F40:MB06458.6*/
|
||
- Disable interrupts before allocating broadcast sibs. /*F40:MB06458.7*/
|
||
- Change per-packet-timeout to 5ms /*F40:MB06458.8*/
|
||
- Make the regroup and powerfail broadcast use highest priority /*F40:MB06458.9*/
|
||
tnet services queue. /*F40:MB06458.10*/
|
||
- Call the millicode backdoor to get the processor status from SP /*F40:MB06458.11*/
|
||
- Fixed expand bug in msg_listen_ and msg_readctrl_ /*F40:MB06458.12*/
|
||
- Added enhancement to msngr_sendmsg_ so that clients do not need /*F40:MB06458.13*/
|
||
to be unstoppable before calling this routine. /*F40:MB06458.14*/
|
||
- Added new steps in the build file called /*F40:MB06458.15*/
|
||
MSGSYS_C - compiles all the message system C files /*F40:MB06458.16*/
|
||
MSDRIVER - compiles all the MSDriver files /*F40:MB06458.17*/
|
||
REGROUP - compiles all the regroup files /*F40:MB06458.18*/
|
||
- remove #pragma env libspace because we set it as a command line /*F40:MB06458.19*/
|
||
parameter. /*F40:MB06458.20*/
|
||
----------------------------------------------------------------------- /*F40:MB06458.21*/
|
||
|
||
#endif /* 0 - change descriptions */
|
||
|