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.