summaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-10-25 17:05:28 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-10-25 17:05:28 -0300
commit96e15b8501e5d8fc40c475cbac573f910ab5853b (patch)
tree2c8efededa6849704f0db3075d0cbe0efaa40b2d /lgc.c
parent0fd91b1b087b478fffa36f96bc0f608d86627a4b (diff)
downloadlua-96e15b8501e5d8fc40c475cbac573f910ab5853b.tar.gz
lua-96e15b8501e5d8fc40c475cbac573f910ab5853b.tar.bz2
lua-96e15b8501e5d8fc40c475cbac573f910ab5853b.zip
threads now are real Lua objects, subject to garbage collection
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c89
1 files changed, 48 insertions, 41 deletions
diff --git a/lgc.c b/lgc.c
index b7fc4c79..efa35cad 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.152 2002/10/08 18:46:08 roberto Exp roberto $ 2** $Id: lgc.c,v 1.153 2002/10/22 17:58:14 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -99,6 +99,32 @@ static void markclosure (GCState *st, Closure *cl) {
99} 99}
100 100
101 101
102static void checkstacksizes (lua_State *L, StkId max) {
103 int used = L->ci - L->base_ci; /* number of `ci' in use */
104 if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
105 luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
106 used = max - L->stack; /* part of stack in use */
107 if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
108 luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
109}
110
111
112static void markstack (GCState *st, lua_State *L1) {
113 StkId o, lim;
114 CallInfo *ci;
115 markobject(st, gt(L1));
116 for (o=L1->stack; o<L1->top; o++)
117 markobject(st, o);
118 lim = o;
119 for (ci = L1->base_ci; ci <= L1->ci; ci++) {
120 lua_assert(ci->top <= L1->stack_last);
121 if (lim < ci->top) lim = ci->top;
122 }
123 for (; o<=lim; o++) setnilvalue(o);
124 checkstacksizes(L1, lim);
125}
126
127
102static void reallymarkobject (GCState *st, GCObject *o) { 128static void reallymarkobject (GCState *st, GCObject *o) {
103 setbit(o->gch.marked, 0); /* mark object */ 129 setbit(o->gch.marked, 0); /* mark object */
104 switch (o->gch.tt) { 130 switch (o->gch.tt) {
@@ -115,46 +141,11 @@ static void reallymarkobject (GCState *st, GCObject *o) {
115 st->tmark = &o->h; 141 st->tmark = &o->h;
116 break; 142 break;
117 } 143 }
118 } 144 case LUA_TTHREAD: {
119} 145 markstack(st, &o->th);
120 146 break;
121
122static void checkstacksizes (lua_State *L, StkId max) {
123 int used = L->ci - L->base_ci; /* number of `ci' in use */
124 if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
125 luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
126 used = max - L->stack; /* part of stack in use */
127 if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
128 luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
129}
130
131
132static void traversestacks (GCState *st) {
133 lua_State *L1 = st->L;
134 do { /* for each thread */
135 StkId o, lim;
136 CallInfo *ci;
137 if (ttisnil(gt(L1))) { /* incomplete state? */
138 lua_assert(L1 != st->L);
139 L1 = L1->next;
140 luaE_closethread(st->L, L1->previous); /* collect it */
141 continue;
142 }
143 markobject(st, gt(L1));
144 for (o=L1->stack; o<L1->top; o++)
145 markobject(st, o);
146 lim = o;
147 for (ci = L1->base_ci; ci <= L1->ci; ci++) {
148 lua_assert(ci->top <= L1->stack_last);
149 if (lim < ci->top) lim = ci->top;
150 } 147 }
151 for (; o<=lim; o++) setnilvalue(o); 148 }
152 checkstacksizes(L1, lim);
153 lua_assert(L1->previous->next == L1 && L1->next->previous == L1);
154 L1 = L1->next;
155 } while (L1 != st->L);
156 markobject(st, defaultmeta(L1));
157 markobject(st, registry(L1));
158} 149}
159 150
160 151
@@ -292,6 +283,11 @@ static void freeobj (lua_State *L, GCObject *o) {
292 case LUA_TFUNCTION: luaF_freeclosure(L, &o->cl); break; 283 case LUA_TFUNCTION: luaF_freeclosure(L, &o->cl); break;
293 case LUA_TUPVAL: luaM_freelem(L, &o->uv); break; 284 case LUA_TUPVAL: luaM_freelem(L, &o->uv); break;
294 case LUA_TTABLE: luaH_free(L, &o->h); break; 285 case LUA_TTABLE: luaH_free(L, &o->h); break;
286 case LUA_TTHREAD: {
287 lua_assert(&o->th != L && &o->th != G(L)->mainthread);
288 luaE_freethread(L, &o->th);
289 break;
290 }
295 case LUA_TSTRING: { 291 case LUA_TSTRING: {
296 luaM_free(L, o, sizestring((&o->ts)->tsv.len)); 292 luaM_free(L, o, sizestring((&o->ts)->tsv.len));
297 break; 293 break;
@@ -389,13 +385,24 @@ void luaC_sweep (lua_State *L, int all) {
389} 385}
390 386
391 387
388/* mark root set */
389static void markroot (GCState *st) {
390 lua_State *L = st->L;
391 markobject(st, defaultmeta(L));
392 markobject(st, registry(L));
393 markstack(st, G(L)->mainthread);
394 if (L != G(L)->mainthread) /* another thread is running? */
395 reallymarkobject(st, cast(GCObject *, L)); /* cannot collect it */
396}
397
398
392static void mark (lua_State *L) { 399static void mark (lua_State *L) {
393 GCState st; 400 GCState st;
394 Table *toclear; 401 Table *toclear;
395 st.L = L; 402 st.L = L;
396 st.tmark = NULL; 403 st.tmark = NULL;
397 st.toclear = NULL; 404 st.toclear = NULL;
398 traversestacks(&st); /* mark all stacks */ 405 markroot(&st);
399 propagatemarks(&st); /* mark all reachable objects */ 406 propagatemarks(&st); /* mark all reachable objects */
400 toclear = st.toclear; /* weak tables; to be cleared */ 407 toclear = st.toclear; /* weak tables; to be cleared */
401 st.toclear = NULL; 408 st.toclear = NULL;