#include "../threads/thread.h" /* schani */
#include "../threads/locks.h"
+#include "../sysdep/threads.h"
if ( isbitclear(startbits, blocknum) ) return;
if ( isbitset(markbits, blocknum) ) return;
+ /* fprintf(stderr, "mark: marking object at 0x%lx\n", obj); */
setbit (markbits, blocknum);
if ( isbitclear(referencebits, blocknum) ) return;
******************************************************************************/
-static void markstack () /* schani */
+static void markstack ()
{
void *dummy;
- void **top_of_stack = &dummy;
#ifdef USE_THREADS
- thread *aThread;
-
- for (aThread = liveThreads; aThread != 0; aThread = CONTEXT(aThread).nextlive) {
- mark((heapblock*)aThread);
- if (aThread == currentThread) {
- if (top_of_stack > (void**)CONTEXT(aThread).stackEnd)
- markreferences ((void**)CONTEXT(aThread).stackEnd, top_of_stack);
- else
- markreferences (top_of_stack, (void**)CONTEXT(aThread).stackEnd);
- }
- else {
+ thread *aThread;
+
+ if (currentThread == NULL) {
+ void **top_of_stack = &dummy;
+
+ if (top_of_stack > bottom_of_stack)
+ markreferences(bottom_of_stack, top_of_stack);
+ else
+ markreferences(top_of_stack, bottom_of_stack);
+ }
+ else {
+ for (aThread = liveThreads; aThread != 0;
+ aThread = CONTEXT(aThread).nextlive) {
+ mark((heapblock*)aThread);
if (CONTEXT(aThread).usedStackTop > CONTEXT(aThread).stackEnd)
- markreferences ((void**)CONTEXT(aThread).stackEnd,
- (void**)CONTEXT(aThread).usedStackTop + 16);
+ markreferences((void**)CONTEXT(aThread).stackEnd,
+ (void**)CONTEXT(aThread).usedStackTop);
else
- markreferences ((void**)CONTEXT(aThread).usedStackTop - 16,
- (void**)CONTEXT(aThread).stackEnd);
- }
- }
+ markreferences((void**)CONTEXT(aThread).usedStackTop,
+ (void**)CONTEXT(aThread).stackEnd);
+ }
- markreferences((void**)&threadQhead[0], (void**)&threadQhead[MAX_THREAD_PRIO]);
+ markreferences((void**)&threadQhead[0],
+ (void**)&threadQhead[MAX_THREAD_PRIO]);
+ }
#else
- if (top_of_stack > bottom_of_stack)
- markreferences(bottom_of_stack, top_of_stack);
- else
- markreferences(top_of_stack, bottom_of_stack);
+ void **top_of_stack = &dummy;
+
+ /* fprintf(stderr, "marking stack\n"); */
+
+ if (top_of_stack > bottom_of_stack)
+ markreferences(bottom_of_stack, top_of_stack);
+ else
+ markreferences(top_of_stack, bottom_of_stack);
#endif
}
-
/**************** Funktion: searchlivefinalizees *****************************
geht die Liste aller Objekte durch, die noch finalisiert werden m"ussen
/* Alle vom Stack referenzierten Objekte markieren */
asm_dumpregistersandcall (markstack);
+ /* fprintf(stderr, "marking references\n"); */
/* Alle von globalen Variablen erreichbaren Objekte markieren */
p = chain_first (allglobalreferences);
while (p) {
/* Ende des freien Bereiches suchen */
freeend = findnextsetbit (markbits, topofheap, freestart+1);
+#if 0
+ if (freeend==topofheap) {
+ topofheap = freestart;
+ heapfreemem += (freeend-freestart);
+ goto freememfinished;
+ } else {
+ fprintf(stderr, "%lx -- %lx\n", heap + freestart, heap + freeend);
+#endif
+
/* Freien Bereich in Freispeicherliste einh"angen */
- memlist_addrange (freestart, freeend-freestart);
+ memlist_addrange (freestart, freeend-freestart);
/* Menge des freien Speichers mitnotieren */
- heapfreemem += (freeend-freestart);
+ heapfreemem += (freeend-freestart);
+#if 0
}
+#endif
+ }
freememfinished:
/************************* Function: gc_init **********************************
- Initializes the garbage collection thread mechanism.
+ Initializes anything that must be initialized to call the gc on the right
+ stack.
******************************************************************************/
-#ifdef USE_THREADS
-iMux gcStartMutex;
-iMux gcThreadMutex;
-iCv gcConditionStart;
-iCv gcConditionDone;
-
-void
-gc_init (void)
-{
- gcStartMutex.holder = 0;
- gcStartMutex.count = 0;
- gcStartMutex.muxWaiters = 0;
-
- gcThreadMutex.holder = 0;
- gcThreadMutex.count = 0;
- gcThreadMutex.muxWaiters = 0;
-
- gcConditionStart.cvWaiters = 0;
- gcConditionStart.mux = 0;
-
- gcConditionDone.cvWaiters = 0;
- gcConditionDone.mux = 0;
-}
-#else
void
gc_init (void)
{
}
-#endif
-/************************* Function: gc_thread ********************************
+/************************** Function: gc_call ********************************
- In an endless loop waits for a condition to be posted, then
- garbage collects the heap.
+ Calls the garbage collector. The garbage collector should always be called
+ using this function since it ensures that enough stack space is available.
******************************************************************************/
-#ifdef USE_THREADS
-void
-gc_thread (void)
-{
- intsRestore(); /* all threads start with interrupts disabled */
-
- assert(blockInts == 0);
-
- lock_mutex(&gcThreadMutex);
-
- for (;;)
- {
- wait_cond(&gcThreadMutex, &gcConditionStart, 0);
-
- intsDisable();
- heap_docollect();
- intsRestore();
-
- signal_cond(&gcConditionDone);
- }
-}
-#endif
-
void
gc_call (void)
{
#ifdef USE_THREADS
- lock_mutex(&gcThreadMutex);
+ u1 dummy;
- signal_cond(&gcConditionStart);
- wait_cond(&gcThreadMutex, &gcConditionDone, 0);
+ assert(blockInts == 0);
- unlock_mutex(&gcThreadMutex);
+ intsDisable();
+ if (currentThread == NULL || currentThread == mainThread) {
+ CONTEXT(mainThread).usedStackTop = &dummy;
+ heap_docollect();
+ }
+ else
+ asm_switchstackandcall(CONTEXT(mainThread).usedStackTop, heap_docollect,
+ (void**)&(CONTEXT(currentThread).usedStackTop));
+ intsRestore();
#else
- heap_docollect();
+ heap_docollect();
#endif
}
void heap_close ()
{
+ while (livefinalizees) {
+ finalizernode *n = livefinalizees->next;
+ asm_calljavamethod (livefinalizees->finalizer,
+ heap+livefinalizees->objstart,
+ NULL,NULL,NULL);
+ FREE (livefinalizees, finalizernode);
+ livefinalizees = n;
+ }
+
#ifndef TRACECALLARGS
- MFREE (heap, heapblock, heapsize); */
+ MFREE (heap, heapblock, heapsize);
#endif
MFREE (startbits, bitfieldtype, heapsize/BITFIELDBITS);
MFREE (markbits, bitfieldtype, heapsize/BITFIELDBITS);
MFREE (referencebits, bitfieldtype, heapsize/BITFIELDBITS);
- chain_free (allglobalreferences);
-
- while (livefinalizees) {
- finalizernode *n = livefinalizees->next;
- FREE (livefinalizees, finalizernode);
- livefinalizees = n;
- }
+ if (allglobalreferences != NULL)
+ chain_free (allglobalreferences);
}
u4 freestart,freelength;
u4 length = ALIGN(bytelength, BLOCKSIZE) / BLOCKSIZE;
+ /* fprintf(stderr, "heap_allocate: 0x%lx (%ld) requested, 0x%lx (%ld) aligned\n", bytelength, bytelength, length * BLOCKSIZE, length * BLOCKSIZE); */
+
+ /* heap_docollect(); */
+
intsDisable(); /* schani */
memlist_getsuitable (&freestart, &freelength, length);
+onemoretry:
if (!freelength) {
- if ( (topofheap+length > collectthreashold) || (topofheap+length > heapsize) ) {
+ if ((topofheap+length > collectthreashold) ||
+ (topofheap+length > heapsize)) {
+
intsRestore();
gc_call();
intsDisable();
-
+
memlist_getsuitable (&freestart, &freelength, length);
- if (freelength)
- goto have_block; /* phil */
- }
+ if (freelength) goto onemoretry;
+ }
if (topofheap+length > heapsize) {
sprintf (logtext, "Heap-Allocation failed for %d bytes",
- (int) bytelength);
+ (int) bytelength);
dolog();
intsRestore(); /* schani */
return NULL;
- }
+ }
freestart = topofheap;
freelength = length;
setbit (startbits, topofheap);
topofheap += length;
- }
-
- have_block:
- if (freelength>length) {
- setbit (startbits, freestart+length);
- memlist_addrange (freestart+length, freelength-length);
- }
+ }
+ else {
+ if (freelength>length) {
+ setbit (startbits, freestart+length);
+ memlist_addrange (freestart+length, freelength-length);
+ }
+ }
- if (references)
- setbit (referencebits, freestart);
-
- setbit (startbits, freestart); /* phil */
+ if (references) setbit (referencebits, freestart);
heapfillgrade += length;
n -> objstart = freestart;
n -> finalizer = finalizer;
livefinalizees = n;
- }
+ }
intsRestore(); /* schani */
if (runverbose) {
sprintf (logtext, "new returns: %lx", (long) (heap + freestart));
dolog ();
- }
+ }
return (void*) (heap + freestart);
}