ftp.nice.ch/pub/next/unix/developer/pcn.2.0.s.tar.gz#/src/runtime/procs.c

This is procs.c in view mode; [Download] [Up]

/*
 * PCN Abstract Machine Emulator
 * Authors:     Steve Tuecke and Ian Foster
 *              Argonne National Laboratory
 *
 * Please see the DISCLAIMER file in the top level directory of the
 * distribution regarding the provisions under which this software
 * is distributed.
 *
 * procs.c - Process record handling utilities
 */

#include "pcn.h"

typedef struct pr_free_list_struct
{
    proc_record_t *	head;
    int_t		n_args;
} pr_free_list_t;

static pr_free_list_t pr_free_list_table[] =
{
    {(proc_record_t *) NULL, 8},
    {(proc_record_t *) NULL, 16},
    {(proc_record_t *) NULL, 24},
    {(proc_record_t *) NULL, 32},
    {(proc_record_t *) NULL, 64},
    {(proc_record_t *) NULL, 128},
    {(proc_record_t *) NULL, 255},
    {(proc_record_t *) NULL, -1}
};
static pr_free_list_t *pr_indirection_table[256];

static value_note_t *vn_free_list;
    
static cell_t *alloc_page();


/*
 * alloc_page()
 *
 * Allocate 1 page (where the page has HEAP_PAGE_SIZE cells)
 * and return a pointer to the beginning of it.
 *
 * This allocation can be done in one of two ways:
 *   1) malloc() the space for the pages.
 *	This is practical on machines that have with virtual memory.
 *   2) Allocate space from the top of the heap for the pages.
 *	If there is not enough free space at the top of the heap for
 *	the page then we need to garbage collect enough space.
 *	This is practical on machines that do not have with
 *	virtual memory, because it allows you to run in a
 *	non-expanding space.
 *
 * GC_ALERT: This procedure may induce garbage collection
 *
 * Return:	Pointer to first cell of the n_pages contiguous pages
 */
static cell_t *alloc_page()
{
    cell_t *new_page;
    
#ifdef NO_VIRTUAL_MEMORY

    TryGCWithSize(PCN_PAGE_SIZE);
    _p_heap_cancel_top -= PCN_PAGE_SIZE;
    CalcHeapTops();
    new_page = _p_heap_cancel_top;
    
#else  /* NO_VIRTUAL_MEMORY */    

    if ((new_page = (cell_t *) malloc (PCN_PAGE_SIZE * CELL_SIZE))
	== (cell_t *) NULL)
    {
	_p_malloc_error();
    }

#endif /* NO_VIRTUAL_MEMORY */    
    
    return (new_page);
} /* alloc_page() */


/*
 * _p_init_proc_record_pool()
 *
 * Initialize the process record and value note pools.  This means
 * setting up the indirection table for the proc_records.
 */
void _p_init_proc_record_pool()
{
    int_t flt_index;
    int_t it_index = 0;

    for (flt_index = 0;
	 pr_free_list_table[flt_index].n_args >= 0;
	 flt_index++)
    {
	for ( ; it_index <= pr_free_list_table[flt_index].n_args; it_index++)
	{
	    /*
	     * Set the entries in the indirection_table up to n_args to
	     * point to this pr_free_list_table entry.
	     */
	    pr_indirection_table[it_index] = &(pr_free_list_table[flt_index]);
	}
    }

    vn_free_list = (value_note_t *) NULL;
} /* _p_init_proc_record_pool() */


/*
 * _p_alloc_proc_record()
 *
 * Allocate a process record with 'n_args' arguments.
 *
 * GC_ALERT: This procedure may induce garbage collection
 *
 * Return:	a pointer to the newly allocated proc_record.
 */
proc_record_t *_p_alloc_proc_record(n_args)
int_t n_args;
{
    pr_free_list_t *free_list_entry;
    proc_record_t *proc_record, *pr, *tmp_pr;
    int_t pr_n_args, pr_size, n_entries;

    /*
     * pr_indirection_table[n_args] yields a pointer to a particular
     * pr_free_list_table entry, that contains proc_records
     * with >= n_args arguments.
     */
    free_list_entry = pr_indirection_table[n_args];

    /*
     * If there is a proc_record available on the free list for
     * this proc_record size, use it.
     */
    if ((proc_record = free_list_entry->head) != (proc_record_t *) NULL)
    {
#ifdef DEBUG
	if (proc_record->header.tag != PROC_RECORD_TAG)
	{
	    _p_fatal_error("Internal Error: _p_alloc_proc_record(): Corrupt proc_record -- illegal tag");
	}
#endif	
	free_list_entry->head = proc_record->next;
	return (proc_record);
    }

    /*
     * If we reach this, the free list for this proc_record size is
     * empty.  So we need to allocate a new page, break it into
     * some number of proc_records, and put them on the free list.
     */
    proc_record = pr = (proc_record_t *) alloc_page();
    pr_n_args = free_list_entry->n_args;
    pr_size = ProcRecordSize(pr_n_args);
    for (n_entries = (PCN_PAGE_SIZE / pr_size) - 1; n_entries > 0; n_entries--)
    {
	pr->header.tag = PROC_RECORD_TAG;
	pr->header.mark = 0;
	pr->header.size = pr_n_args;
	tmp_pr = pr->next = (proc_record_t *) (((cell_t *) pr) + pr_size);
	pr = tmp_pr;
    }
    pr->header.tag = PROC_RECORD_TAG;
    pr->header.mark = 0;
    pr->header.size = pr_n_args;
    pr->next = (proc_record_t *) NULL;
    
    free_list_entry->head = proc_record->next;

    return (proc_record);

} /* _p_alloc_proc_record() */


/*
 * _p_free_proc_record()
 *
 * Free a process record by putting it back on the appropriate free list.
 */
void _p_free_proc_record(proc_record)
proc_record_t *proc_record;
{
    int_t size;
    pr_free_list_t *free_list_entry;

#ifdef DEBUG
    if (proc_record->header.tag != PROC_RECORD_TAG)
    {
	_p_fatal_error("Internal Error: _p_free_proc_record(): Corrupt proc_record -- illegal tag");
    }
#endif
    
    size = proc_record->header.size;

#ifdef DEBUG
    if (size < 0 || size > NUM_A_REGS)
    {
	_p_fatal_error("Internal Error: _p_free_proc_record(): Corrupt proc_record -- illegal size");
    }
#endif

    free_list_entry = pr_indirection_table[size];
    proc_record->next = free_list_entry->head;
    free_list_entry->head = proc_record;
} /* _p_free_proc_record() */


/*
 * _p_alloc_value_note()
 *
 * Allocate a value note, and fill it in the the passed 'location' and
 * 'node' values.
 *
 * GC_ALERT: This procedure may induce garbage collection
 */
value_note_t *_p_alloc_value_note(location, node)
u_int_t location;
u_int_t node;
{
    value_note_t *value_note, *vn, *tmp_vn;
    int_t n_entries;

    if (vn_free_list != (value_note_t *) NULL)
    {
	/*
	 * If there is a value_note available on the free list, use it.
	 */
	value_note = vn_free_list;
	vn_free_list = vn_free_list->next;
#ifdef DEBUG
	if (value_note->header.tag != VALUE_NOTE_TAG)
	{
	    _p_fatal_error("Internal Error: _p_alloc_value_note(): Corrupt value_note -- illegal tag");
	}
#endif	
    }
    else
    {
	/*
	 * The value note free list is empty.
	 * So we need to allocate a new page, break it into
	 * some number of value_notes, and put them on the free list.
	 */
	value_note = vn = (value_note_t *) alloc_page();
	for (n_entries = (PCN_PAGE_SIZE / ValueNoteSize) - 1;
	     n_entries > 0;
	     n_entries--)
	{
	    vn->header.tag = VALUE_NOTE_TAG;
	    vn->header.mark = 0;
	    vn->header.size = 0;
	    tmp_vn = vn->next = vn + 1;
	    vn = tmp_vn;
	}
	vn->header.tag = VALUE_NOTE_TAG;
	vn->header.mark = 0;
	vn->header.size = 0;
	vn->next = (value_note_t *) NULL;
	vn_free_list = value_note->next;
    }

    value_note->node = node;
    value_note->location = location;
    
    return (value_note);
} /* _p_alloc_value_note() */


/*
 * _p_free_value_note()
 *
 * Free the passed value note.
 */
void _p_free_value_note(value_note)
value_note_t *value_note;
{
#ifdef DEBUG
    if (value_note->header.tag != VALUE_NOTE_TAG)
    {
	_p_fatal_error("Internal Error: _p_free_value_note(): Corrupt value_note -- illegal tag");
    }
#endif	
    value_note->next = vn_free_list;
    vn_free_list = value_note;
} /* _p_free_value_note() */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.