
/*
 *           PVM 3.2:  Parallel Virtual Machine System 3.2
 *               University of Tennessee, Knoxville TN.
 *           Oak Ridge National Laboratory, Oak Ridge TN.
 *                   Emory University, Atlanta GA.
 *      Authors:  A. L. Beguelin, J. J. Dongarra, G. A. Geist,
 *    W. C. Jiang, R. J. Manchek, B. K. Moore, and V. S. Sunderam
 *                   (C) 1992 All Rights Reserved
 *
 *                              NOTICE
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted
 * provided that the above copyright notice appear in all copies and
 * that both the copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * Neither the Institutions (Emory University, Oak Ridge National
 * Laboratory, and University of Tennessee) nor the Authors make any
 * representations about the suitability of this software for any
 * purpose.  This software is provided ``as is'' without express or
 * implied warranty.
 *
 * PVM 3.2 was funded in part by the U.S. Department of Energy, the
 * National Science Foundation and the State of Tennessee.
 */

/*
 *	pvmfrag.c
 *
 *	Frag buffer util.
 *
$Log: pvmfrag.c,v $
 * Revision 1.1  1993/08/30  23:26:51  manchek
 * Initial revision
 *
 */

#include "protoglarp.h"
#include "pvmalloc.h"
#include "pvmfrag.h"
#include "listmac.h"
#include "pvmdabuf.h"


extern void pvmbailout();


/***************
 **  Private  **
 **           **
 ***************/

static char rcsid[] = "$Id: pvmfrag.c,v 1.1 1993/08/30 23:26:51 manchek Exp $";


/**********************
 **  Frag Functions  **
 **                  **
 **********************/

/*	fr_new()
*
*	Create a new frag with 1 reference, not in a list.
*	If len is nonzero, len bytes are allocated as data space.
*	Else, the frag has no data (is a master or will get data later).
*/

struct frag *
fr_new(len)
	int len;	/* (max) buffer size or 0 */
{
	struct frag *fp;

	if (!(fp = TALLOC(1, struct frag, "frag")))
		goto oops;

	if (len) {	/* slave frag */
		fp->fr_link = fp->fr_rlink = 0;
		if (!(fp->fr_dat = fp->fr_buf = da_new(len))) {
			PVM_FREE(fp);
			goto oops;
		}
		fp->fr_max = len;

	} else {	/* master */
		fp->fr_link = fp->fr_rlink = fp;
		fp->fr_dat = fp->fr_buf = 0;
		fp->fr_max = 0;
	}
	fp->fr_len = 0;
	fp->fr_ref = 1;
	return fp;

oops:
	pvmlogerror("fr_new() can't get memory\n");
	pvmbailout(0);
	return (struct frag*)0;
}


/*	fr_unref()
*
*	Reduce frag refcount by 1.  If result is < 1:
*		If the frag is a master, unref all its slave frags
*		Else, unref its data.
*		Then, free the frag.
*/

void
fr_unref(fp)
	struct frag *fp;		/* master frag */
{
	if (--fp->fr_ref < 1) {
		struct frag *fp2, *fp3;

		if (fp->fr_buf) {		/* slave frag */
			da_unref(fp->fr_buf);

		} else {				/* master frag */

	/* unref all frags in chain */
			for (fp2 = fp->fr_link; fp2 != fp; fp2 = fp3) {
				fp3 = fp2->fr_link;
				LISTDELETE(fp2, fr_link, fr_rlink);
				fr_unref(fp2);
			}
		}
		PVM_FREE(fp);
	}
}


