#include <sys/types.h>
#include <sys/mman.h> /* for mprotect */
#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
#include "thread.h"
#include "locks.h"
thread* threadQtail[MAX_THREAD_PRIO + 1];
thread* liveThreads = NULL;
-thread* alarmList;
+thread* sleepThreads = NULL;
int blockInts;
bool needReschedule;
/* Setup default thread stack size - this can be overwritten if required */
int threadStackSize = THREADSTACKSIZE;
+/* Pointer to the stack of the last killed thread. The free is delayed. */
+void *stack_to_be_freed = 0;
+
static thread* startDaemon(void* func, char* nm, int stackSize);
/*
result;
unsigned long pageBegin;
- CONTEXT(tid).stackMem = malloc(size + 2 * pageSize);
+ assert(stack_to_be_freed == 0);
+
+ CONTEXT(tid).stackMem = malloc(size + 4 * pageSize);
assert(CONTEXT(tid).stackMem != 0);
CONTEXT(tid).stackEnd = CONTEXT(tid).stackMem + size + 2 * pageSize;
}
/*
- * Free the stack for a thread
+ * Mark the stack for a thread to be freed. We cannot free the stack
+ * immediately because it is still in use!
*/
void
freeThreadStack (thread *tid)
pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
pageBegin = pageBegin - pageBegin % pageSize;
-
+
result = mprotect((void*)pageBegin, pageSize,
PROT_READ | PROT_WRITE | PROT_EXEC);
assert(result == 0);
- free(CONTEXT(tid).stackMem);
+ assert(stack_to_be_freed == 0);
+
+ stack_to_be_freed = CONTEXT(tid).stackMem;
}
CONTEXT(tid).stackMem = 0;
CONTEXT(tid).stackBase = 0;
thread *the_main_thread;
int i;
+ signal(SIGPIPE, SIG_IGN);
+
initLocks();
for (i = 0; i < MAXTHREADS; ++i) {
}
/* Allocate a thread to be the main thread */
- liveThreads = the_main_thread = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+ liveThreads = the_main_thread = (thread*)builtin_new(loader_load(utf_new_char("java/lang/Thread")));
assert(the_main_thread != 0);
/* heap_addreference((void **) &liveThreads); */
the_main_thread->PrivateInfo = 1;
CONTEXT(the_main_thread).free = false;
- the_main_thread->name = javastring_new(unicode_new_char("main"));
+ the_main_thread->name = javastring_new(utf_new_char("main"));
the_main_thread->priority = NORM_THREAD_PRIO;
CONTEXT(the_main_thread).priority = (u1)the_main_thread->priority;
CONTEXT(the_main_thread).exceptionptr = 0;
the_main_thread->daemon = 0;
the_main_thread->stillborn = 0;
the_main_thread->target = 0;
- the_main_thread->interruptRequested = 0;
- the_main_thread->group =
- (threadGroup*)builtin_new(loader_load(unicode_new_char("java/lang/ThreadGroup")));
- /* we should call the constructor */
+
+ the_main_thread->contextClassLoader = 0;
+ the_main_thread->inheritedAccessControlContext = 0;
+ the_main_thread->values = 0;
+
+ /* Allocate and init ThreadGroup */
+ the_main_thread->group = (threadGroup*)native_new_and_init(loader_load(utf_new_char("java/lang/ThreadGroup")));
assert(the_main_thread->group != 0);
talive++;
/* Load exception classes */
- class_java_lang_ThreadDeath = loader_load(unicode_new_char("java/lang/ThreadDeath"));
+ class_java_lang_ThreadDeath = loader_load(utf_new_char("java/lang/ThreadDeath"));
DBG( fprintf(stderr, "finishing initThreads\n"); );
if (i == MAXTHREADS)
panic("Too many threads");
+ assert(tid->priority >= MIN_THREAD_PRIO && tid->priority <= MAX_THREAD_PRIO);
+
tid->PrivateInfo = i + 1;
CONTEXT(tid).free = false;
CONTEXT(tid).thread = tid;
DBG( printf("startDaemon %s\n", nm); );
- tid = (thread*)builtin_new(loader_load(unicode_new_char("java/lang/Thread")));
+ tid = (thread*)builtin_new(loader_load(utf_new_char("java/lang/Thread")));
assert(tid != 0);
for (i = 0; i < MAXTHREADS; ++i)
tid->daemon = 1;
tid->stillborn = 0;
tid->target = 0;
- tid->interruptRequested = 0;
tid->group = 0;
/* Construct the initial restore point. */
/* Find the run()V method and call it */
method = class_findmethod(currentThread->header.vftbl->class,
- unicode_new_char("run"), unicode_new_char("()V"));
+ utf_new_char("run"), utf_new_char("()V"));
if (method == 0)
panic("Cannot find method \'void run ()\'");
asm_calljavamethod(method, currentThread, NULL, NULL, NULL);
* (which is set by suspendThread(.))
*/
void
-resumeThread(thread* tid)
+resumeThread (thread* tid)
{
if ((CONTEXT(tid).flags & THREAD_FLAGS_USER_SUSPEND) != 0)
{
/* If we only have daemons left, then everyone is dead. */
if (talive == tdaemon) {
/* atexit functions get called to clean things up */
+ intsRestore();
exit(0);
}
{
thread** ntid;
+ assert(prio >= MIN_THREAD_PRIO && prio <= MAX_THREAD_PRIO);
+
if (tid->PrivateInfo == 0) {
tid->priority = prio;
return;
intsRestore();
}
+/*
+ * Get the current time in milliseconds since 1970-01-01.
+ */
+s8
+currentTime (void)
+{
+ struct timeval tv;
+ s8 time;
+
+ gettimeofday(&tv, 0);
+
+ time = tv.tv_sec;
+ time *= 1000;
+ time += tv.tv_usec / 1000;
+
+ return time;
+}
+
+/*
+ * Put a thread to sleep.
+ */
+void
+sleepThread (s8 time)
+{
+ thread** tidp;
+
+ /* Sleep for no time */
+ if (time <= 0) {
+ return;
+ }
+
+ intsDisable();
+
+ /* Get absolute time */
+ CONTEXT(currentThread).time = time + currentTime();
+
+ /* Find place in alarm list */
+ for (tidp = &sleepThreads; (*tidp) != 0; tidp = &(*tidp)->next)
+ {
+ if (CONTEXT(*tidp).time > CONTEXT(currentThread).time)
+ break;
+ }
+
+ /* Suspend thread on it */
+ suspendOnQThread(currentThread, tidp);
+
+ intsRestore();
+}
+
/*
* Is this thread alive?
*/
exceptionptr = CONTEXT(currentThread).exceptionptr;
+ if (stack_to_be_freed != 0)
+ {
+ free(stack_to_be_freed);
+ stack_to_be_freed = 0;
+ }
+
/* Alarm signal may be blocked - if so
* unblock it.
*/