Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: ireclaim.c,v 1.7 2003/09/03 03:22:59 giles Exp $ */
18
/* Interpreter's interface to garbage collector */
19
#include "ghost.h"
20
#include "ierrors.h"
21
#include "gsstruct.h"
22
#include "iastate.h"
23
#include "icontext.h"
24
#include "interp.h"
25
#include "isave.h"		/* for isstate.h */
26
#include "isstate.h"		/* for mem->saved->state */
27
#include "dstack.h"		/* for dsbot, dsp, dict_set_top */
28
#include "estack.h"		/* for esbot, esp */
29
#include "ostack.h"		/* for osbot, osp */
30
#include "opdef.h"		/* for defining init procedure */
31
#include "store.h"		/* for make_array */
32
 
33
/* Import preparation and cleanup routines. */
34
extern void ialloc_gc_prepare(gs_ref_memory_t *);
35
 
36
/* Forward references */
37
private void gs_vmreclaim(gs_dual_memory_t *, bool);
38
 
39
/* Initialize the GC hook in the allocator. */
40
private int ireclaim(gs_dual_memory_t *, int);
41
private int
42
ireclaim_init(i_ctx_t *i_ctx_p)
43
{
44
    gs_imemory.reclaim = ireclaim;
45
    return 0;
46
}
47
 
48
/* GC hook called when the allocator signals a GC is needed (space = -1), */
49
/* or for vmreclaim (space = the space to collect). */
50
private int
51
ireclaim(gs_dual_memory_t * dmem, int space)
52
{
53
    bool global;
54
    gs_ref_memory_t *mem;
55
 
56
    if (space < 0) {
57
	/* Determine which allocator exceeded the limit. */
58
	int i;
59
 
60
	mem = dmem->space_global;	/* just in case */
61
	for (i = 0; i < countof(dmem->spaces_indexed); ++i) {
62
	    mem = dmem->spaces_indexed[i];
63
	    if (mem == 0)
64
		continue;
65
	    if (mem->gc_status.requested > 0 ||
66
		((gs_ref_memory_t *)mem->stable_memory)->gc_status.requested > 0
67
		)
68
		break;
69
	}
70
    } else {
71
	mem = dmem->spaces_indexed[space >> r_space_shift];
72
    }
73
    if_debug3('0', "[0]GC called, space=%d, requestor=%d, requested=%ld\n",
74
	      space, mem->space, (long)mem->gc_status.requested);
75
    global = mem->space != avm_local;
76
    /* Since dmem may move, reset the request now. */
77
    ialloc_reset_requested(dmem);
78
    gs_vmreclaim(dmem, global);
79
    ialloc_set_limit(mem);
80
    if (space < 0) {
81
	gs_memory_status_t stats;
82
	ulong allocated;
83
 
84
	/* If the ammount still allocated after the GC is complete */
85
	/* exceeds the max_vm setting, then return a VMerror       */
86
	gs_memory_status((gs_memory_t *) mem, &stats);
87
	allocated = stats.allocated;
88
	if (mem->stable_memory != (gs_memory_t *)mem) {
89
	    gs_memory_status(mem->stable_memory, &stats);
90
	    allocated += stats.allocated;
91
	}
92
	if (allocated >= mem->gc_status.max_vm) {
93
	    /* We can't satisfy this request within max_vm. */
94
	    return_error(e_VMerror);
95
	}
96
    }
97
    return 0;
98
}
99
 
100
/* Interpreter entry to garbage collector. */
101
private void
102
gs_vmreclaim(gs_dual_memory_t *dmem, bool global)
103
{
104
    /* HACK: we know the gs_dual_memory_t is embedded in a context state. */
105
    i_ctx_t *i_ctx_p =
106
	(i_ctx_t *)((char *)dmem - offset_of(i_ctx_t, memory));
107
    gs_ref_memory_t *lmem = dmem->space_local;
108
    int code = context_state_store(i_ctx_p);
109
    gs_ref_memory_t *memories[5];
110
    gs_ref_memory_t *mem;
111
    int nmem, i;
112
 
113
    memories[0] = dmem->space_system;
114
    memories[1] = mem = dmem->space_global;
115
    nmem = 2;
116
    if (lmem != dmem->space_global)
117
	memories[nmem++] = lmem;
118
    for (i = nmem; --i >= 0;) {
119
	mem = memories[i];
120
	if (mem->stable_memory != (gs_memory_t *)mem)
121
	    memories[nmem++] = (gs_ref_memory_t *)mem->stable_memory;
122
    }
123
 
124
    /****** ABORT IF code < 0 ******/
125
    for (i = nmem; --i >= 0; )
126
	alloc_close_chunk(memories[i]);
127
 
128
    /* Prune the file list so it won't retain potentially collectible */
129
    /* files. */
130
 
131
    for (i = (global ? i_vm_system : i_vm_local);
132
	 i < countof(dmem->spaces_indexed);
133
	 ++i
134
	 ) {
135
	gs_ref_memory_t *mem = dmem->spaces_indexed[i];
136
 
137
	if (mem == 0 || (i > 0 && mem == dmem->spaces_indexed[i - 1]))
138
	    continue;
139
	if (mem->stable_memory != (gs_memory_t *)mem)
140
	    ialloc_gc_prepare((gs_ref_memory_t *)mem->stable_memory);
141
	for (;; mem = &mem->saved->state) {
142
	    ialloc_gc_prepare(mem);
143
	    if (mem->saved == 0)
144
		break;
145
	}
146
    }
147
 
148
    /* Do the actual collection. */
149
 
150
    {
151
	void *ctxp = i_ctx_p;
152
	gs_gc_root_t context_root;
153
 
154
	gs_register_struct_root((gs_memory_t *)lmem, &context_root,
155
				&ctxp, "i_ctx_p root");
156
	GS_RECLAIM(&dmem->spaces, global);
157
	gs_unregister_root((gs_memory_t *)lmem, &context_root, "i_ctx_p root");
158
	i_ctx_p = ctxp;
159
	dmem = &i_ctx_p->memory;
160
    }
161
 
162
    /* Update caches not handled by context_state_load. */
163
 
164
    *systemdict = *ref_stack_index(&d_stack, ref_stack_count(&d_stack) - 1);
165
 
166
    /* Reload the context state. */
167
 
168
    code = context_state_load(i_ctx_p);
169
    /****** ABORT IF code < 0 ******/
170
 
171
    /* Update the cached value pointers in names. */
172
 
173
    dicts_gc_cleanup();
174
 
175
    /* Reopen the active chunks. */
176
 
177
    for (i = 0; i < nmem; ++i)
178
	alloc_open_chunk(memories[i]);
179
}
180
 
181
/* ------ Initialization procedure ------ */
182
 
183
const op_def ireclaim_l2_op_defs[] =
184
{
185
    op_def_end(ireclaim_init)
186
};