/*
 *
 * Copyright 1998-1999, University of Notre Dame.
 * Authors: Jeffrey M. Squyres, Kinis L. Meyer with M. D. McNally 
 *          and Andrew Lumsdaine
 *
 * This file is part of the Notre Dame LAM implementation of MPI.
 *
 * You should have received a copy of the License Agreement for the
 * Notre Dame LAM implementation of MPI along with the software; see
 * the file LICENSE.  If not, contact Office of Research, University
 * of Notre Dame, Notre Dame, IN 46556.
 *
 * Permission to modify the code and to distribute modified code is
 * granted, provided the text of this NOTICE is retained, a notice that
 * the code was modified is included with the above COPYRIGHT NOTICE and
 * with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE
 * file is distributed with the modified code.
 *
 * LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.
 * By way of example, but not limitation, Licensor MAKES NO
 * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
 * PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS
 * OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS
 * OR OTHER RIGHTS.  
 *
 * Additional copyrights may follow.
 *
 *	Ohio Trollius
 *	Copyright 1996 The Ohio State University
 *	RBD
 *
 *	$Id: lamprocs.c,v 6.6 1999/07/28 20:14:18 kmeyer1 Exp $
 *
 *	Function:	- manage MPI processes information
 */

#include <all_list.h>
#include <app_mgmt.h>
#include <mpi.h>
#include <mpisys.h>
#include <rpisys.h>
#include <typical.h>

/*
 * static variables
 */
static LIST		*plist = 0;		/* list of processes */
static struct _proc	*curproc = 0;		/* current process iterator */

/*
 *	lam_proccmp
 *
 *	Function:	- compare two process entries
 *	Accepts:	- ptr 2 process entries
 *	Returns:	- -1/0/+1 comparison
 */
int
lam_proccmp(p1, p2)

struct _proc		*p1, *p2;

{
	return(LAM_FULL_GPSCMP(&(p1->p_gps), &(p2->p_gps)));
}

/*
 *	lam_procadd
 *
 *	Function:	- add process to the list if not already present
 *	Accepts:	- process GPS
 *	Returns:	- process or NULL
 */
struct _proc *
lam_procadd(gps)

struct _gps		*gps;

{
	struct _proc	pelem;			/* process element */
	struct _proc	*p;			/* favourite pointer */
/*
 * Initialize the list if necessary.
 */
	if (plist == 0) {
		plist = al_init(sizeof(struct _proc), lam_proccmp);
		if (plist == 0) return(0);
	}
/*
 * Check if the process is in the list.
 */
	LAM_ZERO_ME(pelem);
	pelem.p_gps = *gps;
	p = al_find(plist, &pelem);

	if (p) {
		return(p);
	}
/*
 * The process is not present so initialize and insert it.  The reference count
 * will be incremented upon addition to a group.
 */
	pelem.p_mode = 0;
	pelem.p_ger_nsnd = 0;
	pelem.p_refcount = 0;
	
	return(al_insert(plist, &pelem));
}

/*
 *	lam_procfree
 *
 *	Function:	- free a process
 *	Accepts:	- process
 *	Returns:	- 0 or LAMERROR
 */
int
lam_procfree(p)

struct _proc		*p;

{
	if (RPI_SPLIT(_rpi_lamd_finalize, _rpi_c2c_finalize, (p))) {
		return(LAMERROR);
	}

	return(lam_procrm(p));
}

/*
 *	lam_procfind
 *
 *	Function:	- locate process in the list
 *	Accepts:	- process GPS
 *	Returns:	- process or NULL
 */
struct _proc *
lam_procfind(gps)

struct _gps		*gps;

{
	struct _proc	pelem;			/* process element */
	struct _proc	*p = 0;

	if (plist) {
		pelem.p_gps = *gps;
		p = (struct _proc *) al_find(plist, &pelem);
	}

	return(p);
}

/*
 *	lam_procrm
 *
 *	Function:	- remove a process from the list
 *	Accepts:	- ptr to process
 *	Returns:	- 0 or LAMERROR
 */
int
lam_procrm(proc)

struct _proc		*proc;

{
	return((plist) ? al_delete(plist, proc) : LAMERROR);
}

/*
 *	lam_topproc
 *
 *	Function:	- reset process list iterator and get top element
 *	Returns:	- top process in list
 */
struct _proc *
lam_topproc()

{
	curproc = (plist) ? al_top(plist) : 0;
	return(curproc);
}

/*
 *	lam_nextproc
 *
 *	Function:	- get next process in list
 *			- this should NOT be called if processes have been
 *			  removed from the list since
 *			  the last call to this function or lam_topproc
 *	Returns:	- next process in list or 0
 */
struct _proc *
lam_nextproc()

{
	if (curproc) curproc = al_next(plist, curproc);

	return(curproc);
}

/*
 *	lam_nprocs
 *
 *	Function:	- size of process list
 *	Returns:	- number of processes in process list
 */
int
lam_nprocs()

{
	return ((plist) ? al_count(plist) : 0);
}

/*
 *	lam_nukeprocs
 *
 *	Function:	- delete the process list
 */
void
lam_nukeprocs()

{
	LIST		*tmp;

	tmp = plist;
/*
 * The process list is set to null and we free the temporary to avoid a
 * nasty recursion when a signal occurs in al_free().  
 */
	plist = 0;
	curproc = 0;

	if (tmp) {
		(void) al_free(tmp);
	}
}
