summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/lgc.c
diff options
context:
space:
mode:
authorWilliam Wilgus <me.theuser@yahoo.com>2019-07-12 05:23:52 -0500
committerWilliam Wilgus <me.theuser@yahoo.com>2019-07-28 15:17:48 +0200
commit45bd14b392622cb58e967a24e4652c510b3d43e4 (patch)
tree22bd2e5cafc2d82ecc4773f83de7f86515b4db43 /apps/plugins/lua/lgc.c
parent4beafe16fafc2e5c59734ef065a6f8d23766520d (diff)
downloadrockbox-45bd14b392622cb58e967a24e4652c510b3d43e4.tar.gz
rockbox-45bd14b392622cb58e967a24e4652c510b3d43e4.zip
Lua Add Emergency Garbage Collector
Derivative of work by RobertGabrielJakabosky http://lua-users.org/wiki/EmergencyGarbageCollector I've only implemented the not enough memory part and expanded this idea to adding a mechanism to signal the OOM condition of the plugin buffer which allows us to only grab the playback buffer after garbage collection fails (SO THE MUSIC KEEPS PLAYING AS LONG AS POSSIBLE) Change-Id: I684fb98b540ffc01f7ba324ab5b761ceb59b9f9b
Diffstat (limited to 'apps/plugins/lua/lgc.c')
-rw-r--r--apps/plugins/lua/lgc.c60
1 files changed, 49 insertions, 11 deletions
diff --git a/apps/plugins/lua/lgc.c b/apps/plugins/lua/lgc.c
index 98194c1771..17b64a103b 100644
--- a/apps/plugins/lua/lgc.c
+++ b/apps/plugins/lua/lgc.c
@@ -58,6 +58,9 @@
58 58
59#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) 59#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
60 60
61#ifndef yield
62 #define yield() {}
63#endif
61 64
62static void removeentry (Node *n) { 65static void removeentry (Node *n) {
63 lua_assert(ttisnil(gval(n))); 66 lua_assert(ttisnil(gval(n)));
@@ -232,8 +235,10 @@ static void traverseclosure (global_State *g, Closure *cl) {
232 int i; 235 int i;
233 lua_assert(cl->l.nupvalues == cl->l.p->nups); 236 lua_assert(cl->l.nupvalues == cl->l.p->nups);
234 markobject(g, cl->l.p); 237 markobject(g, cl->l.p);
235 for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ 238 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
236 markobject(g, cl->l.upvals[i]); 239 if(cl->l.upvals[i])
240 markobject(g, cl->l.upvals[i]);
241 }
237 } 242 }
238} 243}
239 244
@@ -258,6 +263,7 @@ static void traversestack (global_State *g, lua_State *l) {
258 CallInfo *ci; 263 CallInfo *ci;
259 markvalue(g, gt(l)); 264 markvalue(g, gt(l));
260 lim = l->top; 265 lim = l->top;
266 if(l->stack == NULL) return; /* no stack to traverse */
261 for (ci = l->base_ci; ci <= l->ci; ci++) { 267 for (ci = l->base_ci; ci <= l->ci; ci++) {
262 lua_assert(ci->top <= l->stack_last); 268 lua_assert(ci->top <= l->stack_last);
263 if (lim < ci->top) lim = ci->top; 269 if (lim < ci->top) lim = ci->top;
@@ -266,7 +272,8 @@ static void traversestack (global_State *g, lua_State *l) {
266 markvalue(g, o); 272 markvalue(g, o);
267 for (; o <= lim; o++) 273 for (; o <= lim; o++)
268 setnilvalue(o); 274 setnilvalue(o);
269 checkstacksizes(l, lim); 275 if (!isfixedstack(l)) /* if stack size is fixed, can't resize it. */
276 checkstacksizes(l, lim);
270} 277}
271 278
272 279
@@ -419,8 +426,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
419 else { /* must erase `curr' */ 426 else { /* must erase `curr' */
420 lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); 427 lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
421 *p = curr->gch.next; 428 *p = curr->gch.next;
422 if (curr == g->rootgc) /* is the first element of the list? */
423 g->rootgc = curr->gch.next; /* adjust first */
424 freeobj(L, curr); 429 freeobj(L, curr);
425 } 430 }
426 } 431 }
@@ -434,6 +439,8 @@ static void checkSizes (lua_State *L) {
434 if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && 439 if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
435 g->strt.size > MINSTRTABSIZE*2) 440 g->strt.size > MINSTRTABSIZE*2)
436 luaS_resize(L, g->strt.size/2); /* table is too big */ 441 luaS_resize(L, g->strt.size/2); /* table is too big */
442 /* it is not safe to re-size the buffer if it is in use. */
443 if (luaZ_bufflen(&g->buff) > 0) return;
437 /* check size of buffer */ 444 /* check size of buffer */
438 if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ 445 if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */
439 size_t newsize = luaZ_sizebuffer(&g->buff) / 2; 446 size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
@@ -552,6 +559,15 @@ static void atomic (lua_State *L) {
552 g->estimate = g->totalbytes - udsize; /* first estimate */ 559 g->estimate = g->totalbytes - udsize; /* first estimate */
553} 560}
554 561
562static void sweepstrstep (global_State *g, lua_State *L) {
563 lu_mem old = g->totalbytes;
564 sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
565 if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
566 g->gcstate = GCSsweep; /* end sweep-string phase */
567 lua_assert(old >= g->totalbytes);
568 g->estimate -= old - g->totalbytes;
569}
570
555 571
556static l_mem singlestep (lua_State *L) { 572static l_mem singlestep (lua_State *L) {
557 global_State *g = G(L); 573 global_State *g = G(L);
@@ -570,12 +586,7 @@ static l_mem singlestep (lua_State *L) {
570 } 586 }
571 } 587 }
572 case GCSsweepstring: { 588 case GCSsweepstring: {
573 lu_mem old = g->totalbytes; 589 sweepstrstep(g, L);
574 sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
575 if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
576 g->gcstate = GCSsweep; /* end sweep-string phase */
577 lua_assert(old >= g->totalbytes);
578 g->estimate -= old - g->totalbytes;
579 return GCSWEEPCOST; 590 return GCSWEEPCOST;
580 } 591 }
581 case GCSsweep: { 592 case GCSsweep: {
@@ -609,10 +620,14 @@ static l_mem singlestep (lua_State *L) {
609 620
610void luaC_step (lua_State *L) { 621void luaC_step (lua_State *L) {
611 global_State *g = G(L); 622 global_State *g = G(L);
623 if(is_block_gc(L)) return;
624 set_block_gc(L);
612 l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; 625 l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
613 if (lim == 0) 626 if (lim == 0)
614 lim = (MAX_LUMEM-1)/2; /* no limit */ 627 lim = (MAX_LUMEM-1)/2; /* no limit */
615 g->gcdept += g->totalbytes - g->GCthreshold; 628 g->gcdept += g->totalbytes - g->GCthreshold;
629 if (g->estimate > g->totalbytes)
630 g->estimate = g->totalbytes;
616 do { 631 do {
617 lim -= singlestep(L); 632 lim -= singlestep(L);
618 if (g->gcstate == GCSpause) 633 if (g->gcstate == GCSpause)
@@ -629,11 +644,23 @@ void luaC_step (lua_State *L) {
629 else { 644 else {
630 setthreshold(g); 645 setthreshold(g);
631 } 646 }
647 unset_block_gc(L);
632} 648}
633 649
634 650
651int luaC_sweepstrgc (lua_State *L) {
652 global_State *g = G(L);
653 if (g->gcstate == GCSsweepstring) {
654 sweepstrstep(g, L);
655 return (g->gcstate == GCSsweepstring) ? 1 : 0;
656 }
657 return 0;
658}
659
635void luaC_fullgc (lua_State *L) { 660void luaC_fullgc (lua_State *L) {
636 global_State *g = G(L); 661 global_State *g = G(L);
662 if(is_block_gc(L)) return;
663 set_block_gc(L);
637 if (g->gcstate <= GCSpropagate) { 664 if (g->gcstate <= GCSpropagate) {
638 /* reset sweep marks to sweep all elements (returning them to white) */ 665 /* reset sweep marks to sweep all elements (returning them to white) */
639 g->sweepstrgc = 0; 666 g->sweepstrgc = 0;
@@ -649,12 +676,15 @@ void luaC_fullgc (lua_State *L) {
649 while (g->gcstate != GCSfinalize) { 676 while (g->gcstate != GCSfinalize) {
650 lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); 677 lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
651 singlestep(L); 678 singlestep(L);
679 yield();
652 } 680 }
653 markroot(L); 681 markroot(L);
654 while (g->gcstate != GCSpause) { 682 while (g->gcstate != GCSpause) {
655 singlestep(L); 683 singlestep(L);
684 yield();
656 } 685 }
657 setthreshold(g); 686 setthreshold(g);
687 unset_block_gc(L);
658} 688}
659 689
660 690
@@ -682,6 +712,14 @@ void luaC_barrierback (lua_State *L, Table *t) {
682} 712}
683 713
684 714
715void luaC_marknew (lua_State *L, GCObject *o) {
716 global_State *g = G(L);
717 o->gch.marked = luaC_white(g);
718 if (g->gcstate == GCSpropagate)
719 reallymarkobject(g, o); /* mark new objects as gray during propagate state. */
720}
721
722
685void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { 723void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
686 global_State *g = G(L); 724 global_State *g = G(L);
687 o->gch.next = g->rootgc; 725 o->gch.next = g->rootgc;