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.