/*
 *
 * 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: lammisc.c,v 6.12 1999/09/02 01:20:01 jsquyres Exp $
 *
 *	Function:	- miscellaneous functions
 */

#include <lam_config.h>

#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

#if LAM_NEED_SYS_SELECT_H
#include <sys/select.h>
#endif

#if HAVE_SCHED_H
#include <sched.h>
#endif

#include "mpi.h"
#include "mpisys.h"
#include "terror.h"


/*
 * prototypes for OS's that don't have them (cough cough AIX 4.1 cough cough)
 */
#if HAVE_YIELD && !LAM_USE_SELECT_YIELD
void yield(void);
#endif

/*
 *	lam_cubedim
 *
 *	Function:	- get dimension of inscribing hypercube
 *	Accepts:	- # processes
 *	Returns:	- dimension or -1
 */
int
lam_cubedim(nprocs)

int			nprocs;

{
	int		dim;
	unsigned	size;

	if (nprocs < 1) return(-1);

	for (dim = 0, size = 1; size < nprocs; ++dim, size <<= 1);

	return(dim);
}

/*
 *	lam_hibit
 *
 *	Function:	- get position of the highest bit set
 *	Accepts:	- process rank
 *			- hypercube dimension
 *	Returns:	- position or -1
 */
int
lam_hibit(rank, dim)

int			rank;
int			dim;

{
	unsigned	mask;

	if ((rank < 1) || (dim < 1)) return(-1);

	--dim;
	mask = 1 << dim;

	for (; dim >= 0; --dim, mask >>= 1) {
		if (rank & mask) break;
	}

	return(dim);
}

/*
 *	lam_emtpystat
 *
 *	Function:	- set status to empty
 *	Accepts:	- ptr status
 */
void
lam_emptystat(pstat)

MPI_Status		*pstat;

{
	pstat->MPI_SOURCE = MPI_ANY_SOURCE;
	pstat->MPI_TAG = MPI_ANY_TAG;
	pstat->MPI_ERROR = MPI_ERR_PENDING;
	pstat->st_length = 0;
}

/*
 *      lam_yield
 *
 *      Function:       - make best effort to yield the processor
 */
void
lam_yield()
{
#if HAVE_YIELD && !LAM_USE_SELECT_YIELD

	yield();

#elif HAVE_SCHED_YIELD && !LAM_USE_SELECT_YIELD

	sched_yield();

#else

        struct timeval  timeout;

        timeout.tv_sec = 0;
        timeout.tv_usec = 1;

        select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &timeout);
#endif
}

