+++ /dev/null
-## Process this file with automake to produce Makefile.in
-
-# $Id: Makefile.am 1255 2004-06-30 20:56:08Z twisti $
-
-
-noinst_LIBRARIES = @LIBTHREAD@
-EXTRA_LIBRARIES = libthreads.a
-
-libthreads_a_SOURCES = \
- locks.c \
- locks.h \
- thread.c \
- thread.h \
- nativethread.c \
- nativethread.h \
- threadio.c \
- threadio.h
-
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/jit/@ARCH_DIR@
-
-
-## Local variables:
-## mode: Makefile
-## indent-tabs-mode: t
-## c-basic-offset: 4
-## tab-width: 8
-## compile-command: "automake --add-missing"
-## End:
+++ /dev/null
-/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * locks.c
- * Manage locking system
- * This include the mutex's and cv's.
- *
- * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
- */
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdio.h>
-
-#include "thread.h"
-#include "locks.h"
-#include "builtin.h"
-#include "exceptions.h"
-
-#include "tables.h"
-#include "native.h"
-#include "loader.h"
-#include "toolbox/memory.h"
-
-
-#if !defined(NATIVE_THREADS)
-
-extern thread* currentThread;
-
-mutexHashEntry *mutexHashTable;
-int mutexHashTableSize;
-long mutexHashMask;
-
-mutexHashEntry *mutexOverflowTable;
-int mutexOverflowTableSize;
-mutexHashEntry *firstFreeOverflowEntry = 0;
-
-conditionHashEntry *conditionHashTable;
-int conditionHashTableSize;
-long conditionHashMask;
-
-/*
- * Init the tables.
- */
-void
-initLocks (void)
-{
- int i;
-
- mutexHashTableSize = MUTEX_HASH_TABLE_SIZE;
- mutexHashTable = MNEW(mutexHashEntry, mutexHashTableSize);
- mutexHashMask = (mutexHashTableSize - 1) << 3;
-
- for (i = 0; i < mutexHashTableSize; ++i)
- {
- mutexHashTable[i].object = 0;
- mutexHashTable[i].mutex.holder = 0;
- mutexHashTable[i].mutex.count = 0;
- mutexHashTable[i].mutex.muxWaiters = 0;
- mutexHashTable[i].conditionCount = 0;
- mutexHashTable[i].next = 0;
- }
-
- mutexOverflowTableSize = MUTEX_OVERFLOW_TABLE_SIZE;
- mutexOverflowTable = MNEW(mutexHashEntry, mutexOverflowTableSize);
-
- firstFreeOverflowEntry = &mutexOverflowTable[0];
-
- for (i = 0; i < mutexOverflowTableSize; ++i)
- {
- mutexOverflowTable[i].object = 0;
- mutexOverflowTable[i].mutex.holder = 0;
- mutexOverflowTable[i].mutex.count = 0;
- mutexOverflowTable[i].mutex.muxWaiters = 0;
- mutexOverflowTable[i].conditionCount = 0;
- mutexOverflowTable[i].next = &mutexOverflowTable[i + 1];
- }
- mutexOverflowTable[i - 1].next = 0;
-
- conditionHashTableSize = CONDITION_HASH_TABLE_SIZE;
- conditionHashTable = MNEW(conditionHashEntry, conditionHashTableSize);
- conditionHashMask = (conditionHashTableSize - 1) << 3;
-
- for (i = 0; i < conditionHashTableSize; ++i)
- {
- conditionHashTable[i].object = 0;
- conditionHashTable[i].condition.cvWaiters = 0;
- conditionHashTable[i].condition.mux = 0;
- }
-}
-
-
-/*
- * Reorders part of the condition hash table. Must be called after an entry has been deleted.
- */
-void
-reorderConditionHashTable (int begin)
-{
- while (conditionHashTable[begin].object != 0)
- {
- int hashValue = CONDITION_HASH_VALUE(conditionHashTable[begin].object);
-
- if (hashValue != begin)
- {
- while (conditionHashTable[hashValue].object != 0)
- {
- hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
- if (hashValue == begin)
- break;
- }
- if (hashValue != begin)
- {
- conditionHashTable[hashValue] = conditionHashTable[begin];
- conditionHashTable[begin].object = 0;
- conditionHashTable[begin].condition.cvWaiters = 0;
- conditionHashTable[begin].condition.mux = 0;
- }
- }
-
- begin = CONDITION_HASH_SUCCESSOR(begin);
- }
-}
-
-/*
- * Looks up an entry in the condition hash table.
- */
-iCv*
-conditionForObject (java_objectheader *object)
-{
- int hashValue;
-
- intsDisable();
-
- hashValue = CONDITION_HASH_VALUE(object);
- while (conditionHashTable[hashValue].object != object
- && conditionHashTable[hashValue].object != 0)
- hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
-
- if (conditionHashTable[hashValue].object == 0)
- {
- intsRestore();
- return 0;
- }
-
- intsRestore();
- return &conditionHashTable[hashValue].condition;
-}
-
-/*
- * Adds a new entry in the condition hash table and returns a pointer to the condition
- */
-iCv*
-addConditionForObject (java_objectheader *object)
-{
- int hashValue;
-
- intsDisable();
-
- hashValue = CONDITION_HASH_VALUE(object);
- while (conditionHashTable[hashValue].object != 0)
- hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
-
- conditionHashTable[hashValue].object = object;
-
- intsRestore();
-
- return &conditionHashTable[hashValue].condition;
-}
-
-/*
- * Removes an entry from the condition hash table.
- */
-void
-removeConditionForObject (java_objectheader *object)
-{
- int hashValue;
-
- intsDisable();
-
- hashValue = CONDITION_HASH_VALUE(object);
- while (conditionHashTable[hashValue].object != object)
- hashValue = CONDITION_HASH_SUCCESSOR(hashValue);
-
- conditionHashTable[hashValue].object = 0;
- conditionHashTable[hashValue].condition.cvWaiters = 0;
- conditionHashTable[hashValue].condition.mux = 0;
-
- reorderConditionHashTable(CONDITION_HASH_SUCCESSOR(hashValue));
-
- intsRestore();
-}
-
-/*
- * Returns the mutex entry for the specified object and increments its conditionCount.
- */
-mutexHashEntry*
-conditionLockedMutexForObject (java_objectheader *object)
-{
- int hashValue;
- mutexHashEntry *entry;
-
- assert(object != 0);
-
- intsDisable();
-
- hashValue = MUTEX_HASH_VALUE(object);
- entry = &mutexHashTable[hashValue];
-
- if (entry->object != 0)
- {
- if (entry->mutex.count == 0 && entry->conditionCount == 0)
- {
- entry->object = 0;
- entry->mutex.holder = 0;
- entry->mutex.count = 0;
- entry->mutex.muxWaiters = 0;
- }
- else
- {
- while (entry->next != 0 && entry->object != object)
- entry = entry->next;
-
- if (entry->object != object)
- {
- entry->next = firstFreeOverflowEntry;
- firstFreeOverflowEntry = firstFreeOverflowEntry->next;
-
- entry = entry->next;
- entry->object = 0;
- entry->next = 0;
- assert(entry->conditionCount == 0);
- }
- }
- }
-
- if (entry->object == 0)
- entry->object = object;
-
- ++entry->conditionCount;
-
- intsRestore();
-
- return entry;
-}
-
-/*
- * Wait for the condition of an object to be signalled
- */
-void
-wait_cond_for_object (java_objectheader *obj, s8 time, s4 par3)
-{
- iCv *condition;
- mutexHashEntry *mutexEntry;
-
- intsDisable();
-
- mutexEntry = conditionLockedMutexForObject(obj);
-
- condition = conditionForObject(obj);
- if (condition == 0)
- condition = addConditionForObject(obj);
-
- DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
-
- internal_wait_cond(&mutexEntry->mutex, condition, time);
-
- if (condition->cvWaiters == 0 && condition->mux == 0)
- removeConditionForObject(obj);
- --mutexEntry->conditionCount;
-
- intsRestore();
-}
-
-/*
- * Signal the condition of an object
- */
-void
-signal_cond_for_object (java_objectheader *obj)
-{
- iCv *condition;
-
- intsDisable();
-
- condition = conditionForObject(obj);
- if (condition == 0)
- condition = addConditionForObject(obj);
-
- DBG( fprintf(stderr, "condition of %p is %p\n", obj, condition); );
-
- internal_signal_cond(condition);
-
- if (condition->cvWaiters == 0 && condition->mux == 0)
- removeConditionForObject(obj);
-
- intsRestore();
-}
-
-/*
- * Broadcast the condition of an object.
- */
-void
-broadcast_cond_for_object (java_objectheader *obj)
-{
- intsDisable();
- internal_broadcast_cond_for_object(obj);
- intsRestore();
-}
-
-/*
- * Internal: Broadcast the condition of an object.
- */
-void
-internal_broadcast_cond_for_object (java_objectheader *obj)
-{
- iCv *condition;
-
- condition = conditionForObject(obj);
- if (condition == 0)
- condition = addConditionForObject(obj);
-
- internal_broadcast_cond(condition);
-
- if (condition->cvWaiters == 0 && condition->mux == 0)
- removeConditionForObject(obj);
-}
-
-/*
- * Lock a mutex.
- */
-void
-lock_mutex (iMux *mux)
-{
- intsDisable();
- internal_lock_mutex(mux);
- intsRestore();
-}
-
-/*
- * Lock the mutex for an object.
- */
-void
-lock_mutex_for_object (java_objectheader *obj)
-{
- intsDisable();
- internal_lock_mutex_for_object(obj);
- intsRestore();
-}
-
-/*
- * Unlock a mutex.
- */
-void
-unlock_mutex (iMux *mux)
-{
- intsDisable();
- internal_unlock_mutex(mux);
- intsRestore();
-}
-
-/*
- * Unlock the mutex for an object.
- */
-void
-unlock_mutex_for_object (java_objectheader *obj)
-{
- intsDisable();
- internal_unlock_mutex_for_object(obj);
- intsRestore();
-}
-
-/*
- * Wait on a condition variable.
- */
-void
-wait_cond (iMux *mux, iCv *cond, s8 timeout)
-{
- intsDisable();
- internal_wait_cond(mux, cond, timeout);
- intsRestore();
-}
-
-/*
- * Signal a condition variable.
- */
-void
-signal_cond (iCv *cond)
-{
- intsDisable();
- internal_signal_cond(cond);
- intsRestore();
-}
-
-/*
- * Broadcast a condition variable.
- */
-void
-broadcast_cond (iCv *cond)
-{
- intsDisable();
- internal_broadcast_cond(cond);
- intsRestore();
-}
-
-/*
- * Internal: Lock a mutex.
- */
-void
-internal_lock_mutex(iMux* mux)
-{
- assert(blockInts > 0);
-
- if (mux->holder == 0)
- {
- mux->holder = currentThread;
- mux->count = 1;
- DBG( fprintf(stderr, "set holder of %p to %p\n", mux, mux->holder); )
- }
- else if (mux->holder == currentThread)
- {
- mux->count++;
- }
- else
- {
- while (mux->holder != 0)
- {
- suspendOnQThread(currentThread, &mux->muxWaiters);
- }
- mux->holder = currentThread;
- mux->count = 1;
- }
-}
-
-/*
- * Internal: Release a mutex.
- */
-void
-internal_unlock_mutex(iMux* mux)
-{
- thread* tid;
-
- assert(blockInts > 0);
-
- assert(mux->holder == currentThread);
-
- mux->count--;
- if (mux->count == 0)
- {
- mux->holder = 0;
- if (mux->muxWaiters != 0)
- {
- tid = mux->muxWaiters;
- mux->muxWaiters = tid->vmThread->next;
- iresumeThread(tid);
- }
- }
-}
-
-/*
- * Internal: Wait on a conditional variable.
- * (timeout currently ignored)
- */
-void
-internal_wait_cond(iMux* mux, iCv* cv, s8 timeout)
-{
- int count;
- thread* tid;
-
- DBG( fprintf(stderr, "waiting on %p\n", cv); );
-
- if (mux->holder != currentThread) {
- *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException);
- }
-
- assert(blockInts > 0);
-
- count = mux->count;
- mux->holder = 0;
- mux->count = 0;
- cv->mux = mux;
-
- /* If there's anyone waiting here, wake them up */
- if (mux->muxWaiters != 0) {
- tid = mux->muxWaiters;
- mux->muxWaiters = tid->vmThread->next;
- iresumeThread(tid);
- }
-
- /* Suspend, and keep suspended until I re-get the lock */
- suspendOnQThread(currentThread, &cv->cvWaiters);
- while (mux->holder != 0) {
- DBG( fprintf(stderr, "woke up\n"); );
- suspendOnQThread(currentThread, &mux->muxWaiters);
- }
-
- mux->holder = currentThread;
- mux->count = count;
-}
-
-/*
- * Internal: Wake one thread on a conditional variable.
- */
-void
-internal_signal_cond (iCv* cv)
-{
- thread* tid;
-
- DBG( fprintf(stderr, "signalling on %p\n", cv); );
-
- /* If 'mux' isn't set then we've never waited on this object. */
- if (cv->mux == 0) {
- return;
- }
-
- if (cv->mux->holder != currentThread) {
- *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException);
- }
-
- assert(blockInts > 0);
-
- /* Remove one thread from cv list */
- if (cv->cvWaiters != 0) {
- DBG( fprintf(stderr, "releasing a waiter\n"); );
-
- tid = cv->cvWaiters;
- cv->cvWaiters = tid->vmThread->next;
-
- /* Place it on mux list */
- tid->vmThread->next = cv->mux->muxWaiters;
- cv->mux->muxWaiters = tid;
- }
-}
-
-/*
- * Internal: Wake all threads on a conditional variable.
- */
-void
-internal_broadcast_cond (iCv* cv)
-{
- thread** tidp;
-
- /* If 'mux' isn't set then we've never waited on this object. */
- if (cv->mux == 0) {
- return;
- }
-
- if (cv->mux->holder != currentThread) {
- *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException);
- }
-
- assert(blockInts > 0);
-
- /* Find the end of the cv list */
- if (cv->cvWaiters) {
- for (tidp = &cv->cvWaiters; *tidp != 0; tidp = &(*tidp)->vmThread->next)
- ;
-
- /* Place entire cv list on mux list */
- (*tidp) = cv->mux->muxWaiters;
- cv->mux->muxWaiters = cv->cvWaiters;
- cv->cvWaiters = 0;
- }
-}
-
-#endif
+++ /dev/null
-/*
- * locks.h
- * Manage locking system
- * This include the mutex's and cv's.
- *
- * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
- */
-
-#ifndef __locks_h
-#define __locks_h
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-
-#include "global.h"
-
-#define WAITFOREVER -1
-
-struct _thread;
-
-typedef struct _iMux {
- struct _thread *holder;
- int count;
- struct _thread *muxWaiters;
-} iMux;
-
-typedef struct _iCv {
- struct _thread* cvWaiters;
- struct _iMux* mux;
-} iCv;
-
-#define MAX_MUTEXES 256
-
-typedef struct _mutexHashEntry
-{
- java_objectheader *object;
- iMux mutex;
- struct _mutexHashEntry *next;
- int conditionCount;
-} mutexHashEntry;
-
-#define MUTEX_HASH_TRASH_BITS 3
-#define MUTEX_HASH_SIGN_BITS 10
-
-#define MUTEX_HASH_TABLE_SIZE 1024
-#define MUTEX_OVERFLOW_TABLE_SIZE 1024
-/*
-#define MAX_MUTEX_HASH_TABLE_SIZE 65536
-*/
-
-/*
-#define MUTEX_USE_THRESHOLD 1024
-*/
-
-extern long mutexHashMask;
-extern int mutexHashTableSize;
-extern mutexHashEntry *mutexHashTable;
-
-extern mutexHashEntry *mutexOverflowTable;
-extern int mutexOverflowTableSize;
-extern mutexHashEntry *firstFreeOverflowEntry;
-
-#define MUTEX_HASH_MASK ((MUTEX_HASH_TABLE_SIZE - 1) << 3)
-
-#if 0
-#define MUTEX_HASH_VALUE(a) ((((long)(a)) & MUTEX_HASH_MASK) >> MUTEX_HASH_TRASH_BITS)
-#else
-#define MUTEX_HASH_VALUE(a) (( (((long)(a)) ^ ((long)(a) >> MUTEX_HASH_SIGN_BITS)) & mutexHashMask) >> MUTEX_HASH_TRASH_BITS)
-#endif
-#define MUTEX_HASH_SUCCESSOR(h) (((h) + 7) & (mutexHashTableSize - 1))
-
-typedef struct _conditionHashEntry
-{
- java_objectheader *object;
- iCv condition;
-} conditionHashEntry;
-
-#define CONDITION_HASH_TABLE_SIZE 1024
-
-#define CONDITION_HASH_VALUE(a) ((((long)(a)) & conditionHashMask) >> 3)
-#define CONDITION_HASH_SUCCESSOR(h) (((h) + 7) & (conditionHashTableSize - 1))
-
-typedef struct
-{
- bool free;
- java_objectheader *object;
- iMux mutex;
- iCv condition;
-} object_mutex;
-
-extern void initLocks (void);
-
-mutexHashEntry* conditionLockedMutexForObject (java_objectheader *object);
-
-void reorderConditionHashTable (int begin);
-iCv* conditionForObject (java_objectheader *object);
-iCv* addConditionForObject (java_objectheader *object);
-void removeConditionForObject (java_objectheader *object);
-
-/*
- * use these functions only outside critical sections (intsEnable/intsRestore).
- */
-
-void signal_cond_for_object (java_objectheader *obj);
-void broadcast_cond_for_object (java_objectheader *obj);
-void wait_cond_for_object (java_objectheader *obj, s8 time, s4);
-void lock_mutex_for_object (java_objectheader *obj);
-void unlock_mutex_for_object (java_objectheader *obj);
-
-void lock_mutex (iMux*);
-void unlock_mutex (iMux*);
-void wait_cond (iMux*, iCv*, s8);
-void signal_cond (iCv*);
-void broadcast_cond (iCv*);
-
-/*
- * use these internal functions only in critical sections. blockInts must be exactly
- * 1.
- */
-void internal_lock_mutex (iMux*);
-void internal_unlock_mutex (iMux*);
-void internal_wait_cond (iMux*, iCv*, s8);
-void internal_signal_cond (iCv*);
-void internal_broadcast_cond (iCv*);
-
-void internal_lock_mutex_for_object (java_objectheader *obj);
-void internal_unlock_mutex_for_object (java_objectheader *obj);
-void internal_broadcast_cond_for_object (java_objectheader *obj);
-
-#endif /* USE_THREADS */
-
-#endif /* __locks_h */
+++ /dev/null
-#include "global.h"
-
-#if defined(NATIVE_THREADS)
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <time.h>
-#include <errno.h>
-
-#include "config.h"
-#include "thread.h"
-#include "codegen.h"
-#include "locks.h"
-#include "tables.h"
-#include "native.h"
-#include "loader.h"
-#include "builtin.h"
-#include "asmpart.h"
-#include "exceptions.h"
-#include "toolbox/logging.h"
-#include "toolbox/memory.h"
-#include "toolbox/avl.h"
-#include "mm/boehm.h"
-
-#include "nat/java_lang_Object.h"
-#include "nat/java_lang_Throwable.h"
-#include "nat/java_lang_Thread.h"
-#include "nat/java_lang_ThreadGroup.h"
-#include "nat/java_lang_VMThread.h"
-
-#include <pthread.h>
-#include <semaphore.h>
-
-#if !defined(__DARWIN__)
-#if defined(__LINUX__)
-#define GC_LINUX_THREADS
-#elif defined(__MIPS__)
-#define GC_IRIX_THREADS
-#endif
-#include "../mm/boehm-gc/include/gc.h"
-#endif
-
-#ifdef MUTEXSIM
-
-/* We need this for older MacOSX (10.1.x) */
-
-typedef struct {
- pthread_mutex_t mutex;
- pthread_t owner;
- int count;
-} pthread_mutex_rec_t;
-
-static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
-{
- pthread_mutex_init(&m->mutex, NULL);
- m->count = 0;
-}
-
-static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
-{
- pthread_mutex_destroy(&m->mutex);
-}
-
-static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
-{
- for (;;)
- if (!m->count)
- {
- pthread_mutex_lock(&m->mutex);
- m->owner = pthread_self();
- m->count++;
- break;
- } else {
- if (m->owner != pthread_self())
- pthread_mutex_lock(&m->mutex);
- else
- {
- m->count++;
- break;
- }
- }
-}
-
-static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
-{
- if (!--m->count)
- pthread_mutex_unlock(&m->mutex);
-}
-
-#else /* MUTEXSIM */
-
-#define pthread_mutex_lock_rec pthread_mutex_lock
-#define pthread_mutex_unlock_rec pthread_mutex_unlock
-#define pthread_mutex_rec_t pthread_mutex_t
-
-#endif /* MUTEXSIM */
-
-static void setPriority(pthread_t tid, int priority)
-{
- struct sched_param schedp;
- int policy;
-
- pthread_getschedparam(tid, &policy, &schedp);
- schedp.sched_priority = priority;
- pthread_setschedparam(tid, policy, &schedp);
-}
-
-#include "machine-instr.h"
-
-static struct avl_table *criticaltree;
-static threadobject *mainthreadobj;
-
-#ifndef HAVE___THREAD
-pthread_key_t tkey_threadinfo;
-#else
-__thread threadobject *threadobj;
-#endif
-
-static pthread_mutex_rec_t compiler_mutex;
-static pthread_mutex_rec_t tablelock;
-
-void compiler_lock()
-{
- pthread_mutex_lock_rec(&compiler_mutex);
-}
-
-void compiler_unlock()
-{
- pthread_mutex_unlock_rec(&compiler_mutex);
-}
-
-void tables_lock()
-{
- pthread_mutex_lock_rec(&tablelock);
-}
-
-void tables_unlock()
-{
- pthread_mutex_unlock_rec(&tablelock);
-}
-
-static int criticalcompare(const void *pa, const void *pb, void *param)
-{
- const threadcritnode *na = pa;
- const threadcritnode *nb = pb;
-
- if (na->mcodebegin < nb->mcodebegin)
- return -1;
- if (na->mcodebegin > nb->mcodebegin)
- return 1;
- return 0;
-}
-
-static const threadcritnode *findcritical(u1 *mcodeptr)
-{
- struct avl_node *n = criticaltree->avl_root;
- const threadcritnode *m = NULL;
- if (!n)
- return NULL;
- for (;;)
- {
- const threadcritnode *d = n->avl_data;
- if (mcodeptr == d->mcodebegin)
- return d;
- if (mcodeptr < d->mcodebegin) {
- if (n->avl_link[0])
- n = n->avl_link[0];
- else
- return m;
- } else {
- if (n->avl_link[1]) {
- m = n->avl_data;
- n = n->avl_link[1];
- } else
- return n->avl_data;
- }
- }
-}
-
-void thread_registercritical(threadcritnode *n)
-{
- avl_insert(criticaltree, n);
-}
-
-u1 *thread_checkcritical(u1 *mcodeptr)
-{
- const threadcritnode *n = findcritical(mcodeptr);
- return (n && mcodeptr < n->mcodeend && mcodeptr > n->mcodebegin) ? n->mcoderestart : NULL;
-}
-
-static void thread_addstaticcritical()
-{
- threadcritnode *n = &asm_criticalsections;
-
- while (n->mcodebegin)
- thread_registercritical(n++);
-}
-
-static pthread_mutex_t threadlistlock;
-
-static pthread_mutex_t stopworldlock;
-volatile int stopworldwhere;
-
-static sem_t suspend_ack;
-#if defined(__MIPS__)
-static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
-#endif
-
-/*
- * where - 1 from within GC
- 2 class numbering
- */
-void lock_stopworld(int where)
-{
- pthread_mutex_lock(&stopworldlock);
- stopworldwhere = where;
-}
-
-void unlock_stopworld()
-{
- stopworldwhere = 0;
- pthread_mutex_unlock(&stopworldlock);
-}
-
-#if !defined(__DARWIN__)
-/* Caller must hold threadlistlock */
-static int cast_sendsignals(int sig, int count)
-{
- /* Count threads */
- threadobject *tobj = mainthreadobj;
- nativethread *infoself = THREADINFO;
-
- if (count == 0)
- do {
- count++;
- tobj = tobj->info.next;
- } while (tobj != mainthreadobj);
-
- do {
- nativethread *info = &tobj->info;
- if (info != infoself)
- pthread_kill(info->tid, sig);
- tobj = tobj->info.next;
- } while (tobj != mainthreadobj);
-
- return count-1;
-}
-
-#else
-
-static void cast_darwinstop()
-{
- threadobject *tobj = mainthreadobj;
- nativethread *infoself = THREADINFO;
-
- do {
- nativethread *info = &tobj->info;
- if (info != infoself)
- {
- thread_state_flavor_t flavor = PPC_THREAD_STATE;
- mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
- ppc_thread_state_t thread_state;
- mach_port_t thread = info->mach_thread;
- kern_return_t r;
-
- r = thread_suspend(thread);
- if (r != KERN_SUCCESS)
- panic("thread_suspend failed");
-
- r = thread_get_state(thread, flavor,
- (natural_t*)&thread_state, &thread_state_count);
- if (r != KERN_SUCCESS)
- panic("thread_get_state failed");
-
- thread_restartcriticalsection(&thread_state);
-
- r = thread_set_state(thread, flavor,
- (natural_t*)&thread_state, thread_state_count);
- if (r != KERN_SUCCESS)
- panic("thread_set_state failed");
- }
- tobj = tobj->info.next;
- } while (tobj != mainthreadobj);
-}
-
-static void cast_darwinresume()
-{
- threadobject *tobj = mainthreadobj;
- nativethread *infoself = THREADINFO;
-
- do {
- nativethread *info = &tobj->info;
- if (info != infoself)
- {
- mach_port_t thread = info->mach_thread;
- kern_return_t r;
-
- r = thread_resume(thread);
- if (r != KERN_SUCCESS)
- panic("thread_resume failed");
- }
- tobj = tobj->info.next;
- } while (tobj != mainthreadobj);
-}
-
-#endif
-
-#if defined(__MIPS__)
-static void cast_irixresume()
-{
- pthread_mutex_lock(&suspend_ack_lock);
- pthread_cond_broadcast(&suspend_cond);
- pthread_mutex_unlock(&suspend_ack_lock);
-}
-#endif
-
-void cast_stopworld()
-{
- int count, i;
- lock_stopworld(2);
- pthread_mutex_lock(&threadlistlock);
-#if defined(__DARWIN__)
- cast_darwinstop();
-#else
- count = cast_sendsignals(GC_signum1(), 0);
- for (i=0; i<count; i++)
- sem_wait(&suspend_ack);
-#endif
- pthread_mutex_unlock(&threadlistlock);
-}
-
-void cast_startworld()
-{
- pthread_mutex_lock(&threadlistlock);
-#if defined(__DARWIN__)
- cast_darwinresume();
-#elif defined(__MIPS__)
- cast_irixresume();
-#else
- cast_sendsignals(GC_signum2(), -1);
-#endif
- pthread_mutex_unlock(&threadlistlock);
- unlock_stopworld();
-}
-
-#if !defined(__DARWIN__)
-static void sigsuspend_handler(ucontext_t *ctx)
-{
- int sig;
- sigset_t sigs;
-
- thread_restartcriticalsection(ctx);
-
- /* Do as Boehm does. On IRIX a condition variable is used for wake-up
- (not POSIX async-safe). */
-#if defined(__IRIX__)
- pthread_mutex_lock(&suspend_ack_lock);
- sem_post(&suspend_ack);
- pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
- pthread_mutex_unlock(&suspend_ack_lock);
-#else
- sem_post(&suspend_ack);
-
- sig = GC_signum2();
- sigfillset(&sigs);
- sigdelset(&sigs, sig);
- sigsuspend(&sigs);
-#endif
-}
-
-int cacao_suspendhandler(ucontext_t *ctx)
-{
- if (stopworldwhere != 2)
- return 0;
-
- sigsuspend_handler(ctx);
- return 1;
-}
-#endif
-
-static void setthreadobject(threadobject *thread)
-{
-#if !defined(HAVE___THREAD)
- pthread_setspecific(tkey_threadinfo, thread);
-#else
- threadobj = thread;
-#endif
-}
-
-static monitorLockRecord *dummyLR;
-
-static void initPools();
-
-/*
- * Initialize threads.
- */
-void
-initThreadsEarly()
-{
-#ifndef MUTEXSIM
- pthread_mutexattr_t mutexattr;
- pthread_mutexattr_init(&mutexattr);
- pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&compiler_mutex, &mutexattr);
- pthread_mutex_init(&tablelock, &mutexattr);
- pthread_mutexattr_destroy(&mutexattr);
-#else
- pthread_mutex_init_rec(&compiler_mutex);
- pthread_mutex_init_rec(&tablelock);
-#endif
-
- pthread_mutex_init(&threadlistlock, NULL);
- pthread_mutex_init(&stopworldlock, NULL);
-
- /* Allocate something so the garbage collector's signal handlers are */
- /* installed. */
- heap_allocate(1, false, NULL);
-
- mainthreadobj = NEW(threadobject);
- memset(mainthreadobj, 0, sizeof(threadobject));
- mainthreadobj->info.tid = pthread_self();
-#if !defined(HAVE___THREAD)
- pthread_key_create(&tkey_threadinfo, NULL);
-#endif
- setthreadobject(mainthreadobj);
- initPools();
-
- criticaltree = avl_create(criticalcompare, NULL, NULL);
- thread_addstaticcritical();
- sem_init(&suspend_ack, 0, 0);
-
- /* Every newly created object's monitorPtr points here so we save a check
- * against NULL */
- dummyLR = mem_alloc(sizeof(monitorLockRecord));
- dummyLR->o = NULL;
- dummyLR->ownerThread = NULL;
- dummyLR->waiting = false;
-}
-
-static pthread_attr_t threadattr;
-
-static void freeLockRecordPools(lockRecordPool *);
-
-void
-initThreads(u1 *stackbottom)
-{
- classinfo *threadclass;
- classinfo *threadgroupclass;
- java_lang_String *threadname;
- java_lang_Thread *mainthread;
- java_lang_ThreadGroup *threadgroup;
- threadobject *tempthread = mainthreadobj;
- methodinfo *method;
-
- threadclass = class_new(utf_new_char("java/lang/VMThread"));
- class_load(threadclass);
- class_link(threadclass);
-
- if (!threadclass)
- throw_exception_exit();
-
- freeLockRecordPools(mainthreadobj->ee.lrpool);
- /* This is kinda tricky, we grow the java.lang.Thread object so we can keep
- * the execution environment there. No Thread object must have been created
- * at an earlier time */
- threadclass->instancesize = sizeof(threadobject);
-
- /* Create a VMThread */
- mainthreadobj = (threadobject *) builtin_new(threadclass);
-
- if (!mainthreadobj)
- throw_exception_exit();
-
- FREE(tempthread, threadobject);
- initThread(&mainthreadobj->o);
-
- setthreadobject(mainthreadobj);
-
- initLocks();
- mainthreadobj->info.next = mainthreadobj;
- mainthreadobj->info.prev = mainthreadobj;
-
- threadname = javastring_new(utf_new_char("main"));
-
- /* Allocate and init ThreadGroup */
- threadgroupclass = class_new(utf_new_char("java/lang/ThreadGroup"));
- threadgroup =
- (java_lang_ThreadGroup *) native_new_and_init(threadgroupclass);
-
- if (!threadgroup)
- throw_exception_exit();
-
- /* Create a Thread */
- threadclass = class_new(utf_new_char("java/lang/Thread"));
- mainthread = (java_lang_Thread*) builtin_new(threadclass);
- mainthreadobj->o.thread = mainthread;
-
- if (!mainthread)
- throw_exception_exit();
-
- /* Call Thread constructor */
- method = class_resolveclassmethod(threadclass,
- utf_new_char("<init>"),
- utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
- threadclass,
- true);
-
- if (!method)
- throw_exception_exit();
-
- asm_calljavafunction(method, mainthread, mainthreadobj, threadname, (void*) 5);
- if (*exceptionptr)
- throw_exception_exit();
-
- mainthread->group = threadgroup;
- /* XXX This is a hack because the fourth argument was omitted */
- mainthread->daemon = false;
-
- /* Add mainthread to ThreadGroup */
- method = class_resolveclassmethod(threadgroupclass,
- utf_new_char("addThread"),
- utf_new_char("(Ljava/lang/Thread;)V"),
- threadgroupclass,
- true);
-
- if (!method)
- throw_exception_exit();
-
- asm_calljavafunction(method, threadgroup, mainthread, NULL, NULL);
- if (*exceptionptr)
- throw_exception_exit();
-
- setPriority(pthread_self(), 5);
-
- pthread_attr_init(&threadattr);
- pthread_attr_setdetachstate(&threadattr, PTHREAD_CREATE_DETACHED);
-}
-
-void initThread(java_lang_VMThread *t)
-{
- threadobject *thread = (threadobject*) t;
- nativethread *info = &thread->info;
- info->tid = pthread_self();
- /* TODO destroy all those things */
- pthread_mutex_init(&info->joinMutex, NULL);
- pthread_cond_init(&info->joinCond, NULL);
-
- pthread_mutex_init(&thread->waitLock, NULL);
- pthread_cond_init(&thread->waitCond, NULL);
- thread->interrupted = false;
- thread->signaled = false;
- thread->isSleeping = false;
-}
-
-static void initThreadLocks(threadobject *);
-
-typedef struct {
- threadobject *thread;
- sem_t *psem;
-} startupinfo;
-
-static void *threadstartup(void *t)
-{
- startupinfo *startup = t;
- threadobject *thread = startup->thread;
- sem_t *psem = startup->psem;
- nativethread *info = &thread->info;
- threadobject *tnext;
- methodinfo *method;
-
- t = NULL;
-#if defined(__DARWIN__)
- info->mach_thread = mach_thread_self();
-#endif
- setthreadobject(thread);
-
- pthread_mutex_lock(&threadlistlock);
- info->prev = mainthreadobj;
- info->next = tnext = mainthreadobj->info.next;
- mainthreadobj->info.next = thread;
- tnext->info.prev = thread;
- pthread_mutex_unlock(&threadlistlock);
-
- initThreadLocks(thread);
-
- startup = NULL;
- sem_post(psem);
-
- setPriority(info->tid, thread->o.thread->priority);
- sched_yield();
-
- /* Find the run()V method and call it */
- method = class_resolveclassmethod(thread->o.header.vftbl->class,
- utf_new_char("run"),
- utf_new_char("()V"),
- thread->o.header.vftbl->class,
- true);
-
- /* if method != NULL, we had not exception */
- if (method) {
- asm_calljavafunction(method, thread, NULL, NULL, NULL);
-
- } else {
- throw_exception();
- }
-
- /* Allow lock record pools to be used by other threads. They cannot be
- * deleted so we'd better not waste them. */
- freeLockRecordPools(thread->ee.lrpool);
-
- pthread_mutex_lock(&threadlistlock);
- info->next->info.prev = info->prev;
- info->prev->info.next = info->next;
- pthread_mutex_unlock(&threadlistlock);
-
- pthread_mutex_lock(&info->joinMutex);
- info->tid = 0;
- pthread_mutex_unlock(&info->joinMutex);
- pthread_cond_broadcast(&info->joinCond);
-
- return NULL;
-}
-
-void startThread(thread *t)
-{
- nativethread *info = &((threadobject*) t->vmThread)->info;
- sem_t sem;
- startupinfo startup;
-
- startup.thread = (threadobject*) t->vmThread;
- startup.psem = &sem;
-
- sem_init(&sem, 0, 0);
-
- if (pthread_create(&info->tid, &threadattr, threadstartup, &startup))
- panic("pthread_create failed");
-
- /* Wait here until the thread has entered itself into the thread list */
- sem_wait(&sem);
- sem_destroy(&sem);
-}
-
-/* At the end of the program, we wait for all running non-daemon threads to die
- */
-
-static threadobject *findNonDaemon(threadobject *thread)
-{
- while (thread != mainthreadobj) {
- if (!thread->o.thread->daemon)
- return thread;
- thread = thread->info.prev;
- }
-
- return NULL;
-}
-
-void joinAllThreads()
-{
- threadobject *thread;
- pthread_mutex_lock(&threadlistlock);
- while ((thread = findNonDaemon(mainthreadobj->info.prev)) != NULL) {
- nativethread *info = &thread->info;
- pthread_mutex_lock(&info->joinMutex);
- pthread_mutex_unlock(&threadlistlock);
- while (info->tid)
- pthread_cond_wait(&info->joinCond, &info->joinMutex);
- pthread_mutex_unlock(&info->joinMutex);
- pthread_mutex_lock(&threadlistlock);
- }
- pthread_mutex_unlock(&threadlistlock);
-}
-
-static void initLockRecord(monitorLockRecord *r, threadobject *t)
-{
- r->lockCount = 1;
- r->ownerThread = t;
- r->queuers = 0;
- r->o = NULL;
- r->waiter = NULL;
- r->incharge = (monitorLockRecord *) &dummyLR;
- r->waiting = false;
- sem_init(&r->queueSem, 0, 0);
- pthread_mutex_init(&r->resolveLock, NULL);
- pthread_cond_init(&r->resolveWait, NULL);
-}
-
-/* No lock record must ever be destroyed because there may still be references
- * to it.
-
-static void destroyLockRecord(monitorLockRecord *r)
-{
- sem_destroy(&r->queueSem);
- pthread_mutex_destroy(&r->resolveLock);
- pthread_cond_destroy(&r->resolveWait);
-}
-*/
-
-void initLocks()
-{
- initThreadLocks(mainthreadobj);
-}
-
-static void initThreadLocks(threadobject *thread)
-{
- thread->ee.firstLR = NULL;
- thread->ee.lrpool = NULL;
- thread->ee.numlr = 0;
-}
-
-static lockRecordPool *allocNewLockRecordPool(threadobject *thread, int size)
-{
- lockRecordPool *p = mem_alloc(sizeof(lockRecordPoolHeader) + sizeof(monitorLockRecord) * size);
- int i;
-
- p->header.size = size;
- for (i=0; i<size; i++) {
- initLockRecord(&p->lr[i], thread);
- p->lr[i].nextFree = &p->lr[i+1];
- }
- p->lr[i-1].nextFree = NULL;
- return p;
-}
-
-#define INITIALLOCKRECORDS 8
-
-static pthread_mutex_t pool_lock;
-static lockRecordPool *global_pool;
-
-static void initPools()
-{
- pthread_mutex_init(&pool_lock, NULL);
-}
-
-static lockRecordPool *allocLockRecordPool(threadobject *t, int size)
-{
- pthread_mutex_lock(&pool_lock);
- if (global_pool) {
- int i;
- lockRecordPool *pool = global_pool;
- global_pool = pool->header.next;
- pthread_mutex_unlock(&pool_lock);
-
- for (i=0; i < pool->header.size; i++)
- pool->lr[i].ownerThread = t;
-
- return pool;
- }
- pthread_mutex_unlock(&pool_lock);
-
- return allocNewLockRecordPool(t, size);
-}
-
-static void freeLockRecordPools(lockRecordPool *pool)
-{
- lockRecordPoolHeader *last;
- pthread_mutex_lock(&pool_lock);
- last = &pool->header;
- while (last->next)
- last = &last->next->header;
- last->next = global_pool;
- global_pool = pool;
- pthread_mutex_unlock(&pool_lock);
-}
-
-static monitorLockRecord *allocLockRecordSimple(threadobject *t)
-{
- monitorLockRecord *r = t->ee.firstLR;
-
- if (!r) {
- int poolsize = t->ee.numlr ? t->ee.numlr * 2 : INITIALLOCKRECORDS;
- lockRecordPool *pool = allocLockRecordPool(t, poolsize);
- pool->header.next = t->ee.lrpool;
- t->ee.lrpool = pool;
- r = &pool->lr[0];
- t->ee.numlr += pool->header.size;
- }
-
- t->ee.firstLR = r->nextFree;
- return r;
-}
-
-static inline void recycleLockRecord(threadobject *t, monitorLockRecord *r)
-{
- r->nextFree = t->ee.firstLR;
- t->ee.firstLR = r;
-}
-
-void initObjectLock(java_objectheader *o)
-{
- o->monitorPtr = dummyLR;
-}
-
-static void queueOnLockRecord(monitorLockRecord *lr, java_objectheader *o)
-{
- atomic_add(&lr->queuers, 1);
- MEMORY_BARRIER_AFTER_ATOMIC();
- while (lr->o == o)
- sem_wait(&lr->queueSem);
- atomic_add(&lr->queuers, -1);
-}
-
-static void freeLockRecord(monitorLockRecord *lr)
-{
- int q;
- lr->o = NULL;
- MEMORY_BARRIER();
- q = lr->queuers;
- while (q--)
- sem_post(&lr->queueSem);
-}
-
-static inline void handleWaiter(monitorLockRecord *mlr, monitorLockRecord *lr)
-{
- if (lr->waiting)
- mlr->waiter = lr;
-}
-
-monitorLockRecord *monitorEnter(threadobject *t, java_objectheader *o)
-{
- for (;;) {
- monitorLockRecord *lr = o->monitorPtr;
- if (lr->o != o) {
- monitorLockRecord *nlr, *mlr = allocLockRecordSimple(t);
- mlr->o = o;
- if (mlr == lr) {
- MEMORY_BARRIER();
- nlr = o->monitorPtr;
- if (nlr == lr) {
- handleWaiter(mlr, lr);
- return mlr;
- }
- } else {
- if (lr->ownerThread != t)
- mlr->incharge = lr;
- MEMORY_BARRIER_BEFORE_ATOMIC();
- nlr = (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) mlr);
- }
- if (nlr == lr) {
- if (mlr == lr || lr->o != o) {
- handleWaiter(mlr, lr);
- return mlr;
- }
- while (lr->o == o)
- queueOnLockRecord(lr, o);
- handleWaiter(mlr, lr);
- return mlr;
- }
- freeLockRecord(mlr);
- recycleLockRecord(t, mlr);
- queueOnLockRecord(nlr, o);
- } else {
- if (lr->ownerThread == t) {
- lr->lockCount++;
- return lr;
- }
- queueOnLockRecord(lr, o);
- }
- }
-}
-
-static void wakeWaiters(monitorLockRecord *lr)
-{
- do {
- int q = lr->queuers;
- while (q--)
- sem_post(&lr->queueSem);
- lr = lr->waiter;
- } while (lr);
-}
-
-#define GRAB_LR(lr,t) \
- if (lr->ownerThread != t) { \
- lr = lr->incharge; \
- }
-
-#define CHECK_MONITORSTATE(lr,t,mo,a) \
- if (lr->o != mo || lr->ownerThread != t) { \
- *exceptionptr = new_exception(string_java_lang_IllegalMonitorStateException); \
- a; \
- }
-
-bool monitorExit(threadobject *t, java_objectheader *o)
-{
- monitorLockRecord *lr = o->monitorPtr;
- GRAB_LR(lr, t);
- CHECK_MONITORSTATE(lr, t, o, return false);
- if (lr->lockCount > 1) {
- lr->lockCount--;
- return true;
- }
- if (lr->waiter) {
- monitorLockRecord *wlr = lr->waiter;
- if (o->monitorPtr != lr ||
- (void*) compare_and_swap((long*) &o->monitorPtr, (long) lr, (long) wlr) != lr)
- {
- monitorLockRecord *nlr = o->monitorPtr;
- nlr->waiter = wlr;
- STORE_ORDER_BARRIER();
- } else
- wakeWaiters(wlr);
- lr->waiter = NULL;
- }
- freeLockRecord(lr);
- recycleLockRecord(t, lr);
- return true;
-}
-
-static void removeFromWaiters(monitorLockRecord *lr, monitorLockRecord *wlr)
-{
- do {
- if (lr->waiter == wlr) {
- lr->waiter = wlr->waiter;
- break;
- }
- lr = lr->waiter;
- } while (lr);
-}
-
-static inline bool timespec_less(const struct timespec *tv1, const struct timespec *tv2)
-{
- return tv1->tv_sec < tv2->tv_sec || (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
-}
-
-static bool timeIsEarlier(const struct timespec *tv)
-{
- struct timeval tvnow;
- struct timespec tsnow;
- gettimeofday(&tvnow, NULL);
- tsnow.tv_sec = tvnow.tv_sec;
- tsnow.tv_nsec = tvnow.tv_usec * 1000;
- return timespec_less(&tsnow, tv);
-}
-
-bool waitWithTimeout(threadobject *t, monitorLockRecord *lr, struct timespec *wakeupTime)
-{
- bool wasinterrupted;
-
- pthread_mutex_lock(&t->waitLock);
- t->isSleeping = true;
- if (wakeupTime->tv_sec || wakeupTime->tv_nsec)
- while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
- pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
- else
- while (!t->interrupted && !t->signaled)
- pthread_cond_wait(&t->waitCond, &t->waitLock);
- wasinterrupted = t->interrupted;
- t->interrupted = false;
- t->signaled = false;
- t->isSleeping = false;
- pthread_mutex_unlock(&t->waitLock);
- return wasinterrupted;
-}
-
-static void calcAbsoluteTime(struct timespec *tm, s8 millis, s4 nanos)
-{
- if (millis || nanos) {
- struct timeval tv;
- long nsec;
- gettimeofday(&tv, NULL);
- tv.tv_sec += millis / 1000;
- millis %= 1000;
- nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
- tm->tv_sec = tv.tv_sec + nsec / 1000000000;
- tm->tv_nsec = nsec % 1000000000;
- } else {
- tm->tv_sec = 0;
- tm->tv_nsec = 0;
- }
-}
-
-void monitorWait(threadobject *t, java_objectheader *o, s8 millis, s4 nanos)
-{
- bool wasinterrupted;
- struct timespec wakeupTime;
- monitorLockRecord *mlr, *lr = o->monitorPtr;
- GRAB_LR(lr, t);
- CHECK_MONITORSTATE(lr, t, o, return);
-
- calcAbsoluteTime(&wakeupTime, millis, nanos);
-
- if (lr->waiter)
- wakeWaiters(lr->waiter);
- lr->waiting = true;
- STORE_ORDER_BARRIER();
- freeLockRecord(lr);
- wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
- mlr = monitorEnter(t, o);
- removeFromWaiters(mlr, lr);
- mlr->lockCount = lr->lockCount;
- lr->lockCount = 1;
- lr->waiting = false;
- lr->waiter = NULL;
- recycleLockRecord(t, lr);
-
- if (wasinterrupted)
- *exceptionptr = new_exception(string_java_lang_InterruptedException);
-}
-
-static void notifyOneOrAll(threadobject *t, java_objectheader *o, bool one)
-{
- monitorLockRecord *lr = o->monitorPtr;
- GRAB_LR(lr, t);
- CHECK_MONITORSTATE(lr, t, o, return);
- do {
- threadobject *wthread;
- monitorLockRecord *wlr = lr->waiter;
- if (!wlr)
- break;
- wthread = wlr->ownerThread;
- pthread_mutex_lock(&wthread->waitLock);
- if (wthread->isSleeping)
- pthread_cond_signal(&wthread->waitCond);
- wthread->signaled = true;
- pthread_mutex_unlock(&wthread->waitLock);
- lr = wlr;
- } while (!one);
-}
-
-bool threadHoldsLock(threadobject *t, java_objectheader *o)
-{
- monitorLockRecord *lr = o->monitorPtr;
- GRAB_LR(lr, t);
- return lr->o == o && lr->ownerThread == t;
-}
-
-void interruptThread(java_lang_VMThread *thread)
-{
- threadobject *t = (threadobject*) thread;
-
- t->interrupted = true;
- pthread_mutex_lock(&t->waitLock);
- if (t->isSleeping)
- pthread_cond_signal(&t->waitCond);
- pthread_mutex_unlock(&t->waitLock);
-}
-
-bool interruptedThread()
-{
- threadobject *t = (threadobject*) THREADOBJECT;
- bool intr = t->interrupted;
- t->interrupted = false;
- return intr;
-}
-
-bool isInterruptedThread(java_lang_VMThread *thread)
-{
- threadobject *t = (threadobject*) thread;
- return t->interrupted;
-}
-
-void sleepThread(s8 millis, s4 nanos)
-{
- bool wasinterrupted;
- threadobject *t = (threadobject*) THREADOBJECT;
- monitorLockRecord *lr;
- struct timespec wakeupTime;
- calcAbsoluteTime(&wakeupTime, millis, nanos);
-
- lr = allocLockRecordSimple(t);
- wasinterrupted = waitWithTimeout(t, lr, &wakeupTime);
- recycleLockRecord(t, lr);
-
- if (wasinterrupted)
- *exceptionptr = new_exception(string_java_lang_InterruptedException);
-}
-
-void yieldThread()
-{
- sched_yield();
-}
-
-void setPriorityThread(thread *t, s4 priority)
-{
- nativethread *info = &((threadobject*) t->vmThread)->info;
- setPriority(info->tid, priority);
-}
-
-void wait_cond_for_object(java_objectheader *o, s8 time, s4 nanos)
-{
- threadobject *t = (threadobject*) THREADOBJECT;
- monitorWait(t, o, time, nanos);
-}
-
-void signal_cond_for_object(java_objectheader *o)
-{
- threadobject *t = (threadobject*) THREADOBJECT;
- notifyOneOrAll(t, o, true);
-}
-
-void broadcast_cond_for_object(java_objectheader *o)
-{
- threadobject *t = (threadobject*) THREADOBJECT;
- notifyOneOrAll(t, o, false);
-}
-
-#endif
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-#ifndef _NATIVETHREAD_H
-#define _NATIVETHREAD_H
-
-#include <semaphore.h>
-
-#include "jni.h"
-#include "nat/java_lang_Object.h" /* required by java/lang/VMThread */
-#include "nat/java_lang_Thread.h"
-#include "nat/java_lang_VMThread.h"
-#include "toolbox/memory.h"
-
-#if defined(__DARWIN__)
-#include <mach/mach.h>
-
-/* We need to emulate recursive mutexes. */
-#define MUTEXSIM
-#endif
-
-struct _threadobject;
-
-
-typedef struct monitorLockRecord monitorLockRecord;
-
-struct monitorLockRecord {
- struct _threadobject *ownerThread;
- java_objectheader *o;
- int lockCount;
- monitorLockRecord *nextFree;
- int queuers;
- monitorLockRecord *waiter;
- monitorLockRecord *incharge;
- bool waiting;
- sem_t queueSem;
- pthread_mutex_t resolveLock;
- pthread_cond_t resolveWait;
-};
-
-
-struct _lockRecordPool;
-
-typedef struct {
- struct _lockRecordPool *next;
- int size;
-} lockRecordPoolHeader;
-
-typedef struct _lockRecordPool {
- lockRecordPoolHeader header;
- monitorLockRecord lr[1];
-} lockRecordPool;
-
-/* Monitor lock implementation */
-typedef struct {
- monitorLockRecord *firstLR;
- lockRecordPool *lrpool;
- int numlr;
-} ExecEnvironment;
-
-typedef struct {
- struct _threadobject *next, *prev;
- java_objectheader *_exceptionptr;
- methodinfo *_threadrootmethod;
- void *_stackframeinfo;
- pthread_t tid;
-#if defined(__DARWIN__)
- mach_port_t mach_thread;
-#endif
- pthread_mutex_t joinMutex;
- pthread_cond_t joinCond;
-} nativethread;
-
-typedef java_lang_Thread thread;
-
-
-/* threadobject ****************************************************************
-
- TODO
-
-*******************************************************************************/
-
-typedef struct _threadobject {
- java_lang_VMThread o;
- nativethread info;
- ExecEnvironment ee;
-
- pthread_mutex_t waitLock;
- pthread_cond_t waitCond;
- bool interrupted;
- bool signaled;
- bool isSleeping;
-
- dumpinfo dumpinfo; /* dump memory info structure */
-} threadobject;
-
-
-monitorLockRecord *monitorEnter(threadobject *, java_objectheader *);
-bool monitorExit(threadobject *, java_objectheader *);
-
-bool threadHoldsLock(threadobject *t, java_objectheader *o);
-void signal_cond_for_object (java_objectheader *obj);
-void broadcast_cond_for_object (java_objectheader *obj);
-void wait_cond_for_object (java_objectheader *obj, s8 time, s4 nanos);
-
-void initThreadsEarly();
-void initThreads(u1 *stackbottom);
-void initObjectLock(java_objectheader *);
-void initLocks();
-void initThread(java_lang_VMThread *);
-void startThread(thread *t);
-void joinAllThreads();
-
-void sleepThread(s8 millis, s4 nanos);
-void yieldThread();
-
-void setPriorityThread(thread *t, s4 priority);
-
-void interruptThread(java_lang_VMThread *);
-bool interruptedThread();
-bool isInterruptedThread(java_lang_VMThread *);
-
-#if !defined(HAVE___THREAD)
-extern pthread_key_t tkey_threadinfo;
-#define THREADOBJECT ((java_lang_VMThread*) pthread_getspecific(tkey_threadinfo))
-#define THREADINFO (&((threadobject*) pthread_getspecific(tkey_threadinfo))->info)
-#else
-extern __thread threadobject *threadobj;
-#define THREADOBJECT ((java_lang_VMThread*) threadobj)
-#define THREADINFO (&threadobj->info)
-#endif
-
-#include "builtin.h"
-
-/* This must not be changed, it is used in asm_criticalsections */
-typedef struct {
- u1 *mcodebegin, *mcodeend, *mcoderestart;
-} threadcritnode;
-
-void thread_registercritical(threadcritnode *);
-u1 *thread_checkcritical(u1*);
-
-extern volatile int stopworldwhere;
-
-void cast_stopworld();
-void cast_startworld();
-
-#endif /* _NATIVETHREAD_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* ------------------------ thread.c -------------------------- */
-
-/*
- * Handle alarm.
- * This routine uses a different meaning of "blockInts". Formerly, it was just
- * "don't reschedule if you don't have to". Now it is "don't do ANY
- * rescheduling actions due to an expired timer". An alternative would be to
- * block SIGALARM during critical sections (by means of sigprocmask). But
- * this would be required quite often (for every outmost intsDisable(),
- * intsRestore()) and therefore would be much more expensive than just
- * setting an int flag which - sometimes - might cause an additional
- * setitimer call.
- */
-static
-void
-alarmException(int sig)
-{
- thread* tid;
- int64 time;
-
- /* Re-enable signal - necessary for SysV */
- signal(sig, (SIG_T)alarmException);
-
- /*
- * If ints are blocked, this might indicate an inconsistent state of
- * one of the thread queues (either alarmList or threadQhead/tail).
- * We better don't touch one of them in this case and come back later.
- */
- if (blockInts > 0) {
- MALARM(50);
- return;
- }
-
- intsDisable();
-
- /* Wake all the threads which need waking */
- time = currentTime();
- while (alarmList != 0 && alarmList->PrivateInfo->time <= time) {
- tid = alarmList;
- alarmList = alarmList->next;
- iresumeThread(tid);
- }
-
- /* Restart alarm */
- if (alarmList != 0) {
- MALARM(alarmList->PrivateInfo->time - time);
- }
-
- /*
- * The next bit is rather tricky. If we don't reschedule then things
- * are fine, we exit this handler and everything continues correctly.
- * On the otherhand, if we do reschedule, we will schedule the new
- * thread with alarms blocked which is wrong. However, we cannot
- * unblock them here incase we have just set an alarm which goes
- * off before the reschedule takes place (and we enter this routine
- * recusively which isn't good). So, we set a flag indicating alarms
- * are blocked, and allow the rescheduler to unblock the alarm signal
- * after the context switch has been made. At this point it's safe.
- */
- alarmBlocked = true;
- intsRestore();
- alarmBlocked = false;
-}
-
-/*
- * How many stack frames have I invoked?
- */
-long
-framesThread(thread* tid)
-{
- long count;
- THREADFRAMES(tid, count);
- return (count);
-}
+++ /dev/null
-/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * thread.c
- * Thread support.
- *
- * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
- */
-
-#include "global.h"
-
-#if !defined(NATIVE_THREADS)
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/mman.h> /* for mprotect */
-#include <unistd.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <time.h>
-#include <errno.h>
-
-#include "config.h"
-#include "exceptions.h"
-#include "thread.h"
-#include "locks.h"
-#include "tables.h"
-#include "native.h"
-#include "loader.h"
-#include "builtin.h"
-#include "asmpart.h"
-#include "options.h"
-#include "toolbox/logging.h"
-#include "toolbox/memory.h"
-#include "toolbox/avl.h"
-
-static classinfo *class_java_lang_ThreadDeath;
-
-thread* currentThread = NULL;
-thread* mainThread;
-thread* threadQhead[MAX_THREAD_PRIO + 1];
-thread* threadQtail[MAX_THREAD_PRIO + 1];
-
-thread* liveThreads = NULL;
-thread* sleepThreads = NULL;
-
-int blockInts;
-bool needReschedule;
-
-vmthread *contexts[MAXTHREADS];
-
-/* Number of threads alive, also counting daemons */
-static int talive;
-
-/* Number of daemon threads alive */
-static int tdaemon;
-
-static void firstStartThread(void);
-
-void reschedule(void);
-
-/* 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);
-
-
-
-java_objectheader *init_vmthread(void *thr)
-{
- methodinfo *m;
- java_objectheader *o;
- classinfo *c=class_new(utf_new_char("java/lang/VMThread"));
-
- if (!c)
- return *exceptionptr;
-
- o = builtin_new(c); /* create object */
-
- if (!o)
- return NULL;
-
- /* find initializer */
-
- m = class_findmethod(c,
- utf_new_char("<init>"),
- utf_new_char("(Ljava/lang/Thread;)V"));
-
- if (!m) { /* initializer not found */
- if (verbose) {
- char logtext[MAXLOGTEXT];
- sprintf(logtext, "Warning: class has no instance-initializer: ");
- utf_sprint_classname(logtext + strlen(logtext), c->name);
- log_text(logtext);
- }
- return o;
- }
-
- /* call initializer */
-
- asm_calljavafunction(m, o, thr, NULL, NULL);
- return o;
-}
-
-
-
-
-/*
- * Allocate the stack for a thread
- */
-void
-allocThreadStack (thread *tid, int size)
-{
- int pageSize = getpagesize();
- unsigned long pageBegin;
-
- assert(stack_to_be_freed == 0);
-
- CONTEXT(tid).stackMem = GCNEW(u1, size + 4 * pageSize);
- assert(CONTEXT(tid).stackMem != 0);
- CONTEXT(tid).stackEnd = CONTEXT(tid).stackMem + size + 2 * pageSize;
-
- pageBegin = (unsigned long)(CONTEXT(tid).stackMem) + pageSize - 1;
- pageBegin = pageBegin - pageBegin % pageSize;
-
- CONTEXT(tid).stackBase = (u1*)pageBegin + pageSize;
-}
-
-/*
- * Mark the stack for a thread to be freed. We cannot free the stack
- * immediately because it is still in use!
- */
-void
-freeThreadStack (vmthread *vmtid)
-{
- if (!(vmtid->flags & THREAD_FLAGS_NOSTACKALLOC))
- {
- int pageSize = getpagesize();
- unsigned long pageBegin;
-
- pageBegin = (unsigned long)(vmtid->stackMem) + pageSize - 1;
- pageBegin = pageBegin - pageBegin % pageSize;
-
- assert(stack_to_be_freed == 0);
-
- stack_to_be_freed = vmtid->stackMem;
- }
- vmtid->stackMem = 0;
- vmtid->stackBase = 0;
- vmtid->stackEnd = 0;
-}
-
-/*
- * Initialize threads.
- */
-void
-initThreads(u1 *stackbottom)
-{
- thread *the_main_thread;
- int i;
- char mainname[] = "main";
- /*int len = strlen(mainname);*/
-
- signal(SIGPIPE, SIG_IGN);
-
- initLocks();
-
- for (i = 0; i < MAXTHREADS; ++i) {
- contexts[i]=0;
- }
-
- /* Allocate a thread to be the main thread */
- liveThreads = the_main_thread =
- (thread *) builtin_new(class_new(utf_new_char("java/lang/Thread")));
- the_main_thread->vmThread=init_vmthread(the_main_thread);
- assert(the_main_thread != 0);
-
-/* the_main_thread->PrivateInfo = 1;
- CONTEXT(the_main_thread).free = false;*/
-
-#if 0
- {
- /* stefan */
- methodinfo *m;
- m = class_fetchmethod(
- class_java_lang_String,
- utf_new_char ("toCharArray"),
- utf_new_char ("()[C")
- );
-printf("DEADCODE LIVES ?????????\n");fflush(stdout);
- the_main_thread->name = asm_calljavafunction (m, javastring_new(utf_new_char("main")), 0, 0, 0);
- }
-#endif
- the_main_thread->name=javastring_new(utf_new_char(mainname));
-/* the_main_thread->name = builtin_newarray_char(len);
- { u2 *d = the_main_thread->name->data;
- for (i=0; i<len; i++)
- d[i] = mainname[i];
- }*/
-
- the_main_thread->priority = NORM_THREAD_PRIO;
- CONTEXT(the_main_thread).priority = (u1)the_main_thread->priority;
- CONTEXT(the_main_thread).texceptionptr = 0;
- the_main_thread->vmThread->next = 0;
- CONTEXT(the_main_thread).status = THREAD_SUSPENDED;
- CONTEXT(the_main_thread).stackBase = CONTEXT(the_main_thread).stackEnd = stackbottom;
- THREADINFO(&CONTEXT(the_main_thread));
-
- DBG( printf("main thread %p base %p end %p\n",
- the_main_thread,
- CONTEXT(the_main_thread).stackBase,
- CONTEXT(the_main_thread).stackEnd); );
-
- CONTEXT(the_main_thread).flags = THREAD_FLAGS_NOSTACKALLOC;
- CONTEXT(the_main_thread).nextlive = 0;
- /*CONTEXT(the_main_thread).thread = the_main_thread;*/
- /*the_main_thread->single_step = 0;*/
- the_main_thread->daemon = 0;
- /*the_main_thread->stillborn = 0;*/
- /*the_main_thread->target = 0;*/
-
- 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(class_load(class_new(utf_new_char("java/lang/ThreadGroup"))));
- assert(the_main_thread->group != 0);
-
- talive++;
-
- /* Load exception classes */
-/* loader_load_sysclass(&class_java_lang_ThreadDeath, */
-/* utf_new_char("java/lang/ThreadDeath")); */
- class_java_lang_ThreadDeath =
- class_load(class_new(utf_new_char("java/lang/ThreadDeath")));
-
- DBG( fprintf(stderr, "finishing initThreads\n"); );
-
- mainThread = currentThread = the_main_thread;
- contexts[0]=mainThread->vmThread;
- /* Add thread into runQ */
- iresumeThread(mainThread);
-
- assert(blockInts == 0);
-}
-
-/*
- * Start a new thread running.
- */
-void
-startThread (thread* tid)
-{
- int i;
-
- /* Allocate a stack context */
- for (i = 0; i < MAXTHREADS; ++i)
- if (contexts[i]==0)
- break;
-
- if (i == MAXTHREADS)
- panic("Too many threads");
-
- assert(tid->priority >= MIN_THREAD_PRIO && tid->priority <= MAX_THREAD_PRIO);
- contexts[i]=tid->vmThread;
-/* tid->PrivateInfo = i + 1;
- CONTEXT(tid).free = false;*/
- if (tid->vmThread==0) {
- panic("vmThread field not set");
-/* tid->vmThread=init_vmthread(tid);*/
- }
-
-/* CONTEXT(tid).thread = tid;*/
- CONTEXT(tid).nextlive = liveThreads;
- liveThreads = tid;
- allocThreadStack(tid, threadStackSize);
- CONTEXT(tid).usedStackTop = CONTEXT(tid).stackBase;
- CONTEXT(tid).flags = THREAD_FLAGS_GENERAL;
- CONTEXT(tid).status = THREAD_SUSPENDED;
- CONTEXT(tid).priority = (u1)tid->priority;
- CONTEXT(tid).texceptionptr = 0;
-
- /* Construct the initial restore point. */
- THREADINIT((&CONTEXT(tid)), firstStartThread);
-
- DBG( printf("new thread %p base %p end %p\n",
- tid, CONTEXT(tid).stackBase,
- CONTEXT(tid).stackEnd); );
-
- talive++;
- if (tid->daemon)
- tdaemon++;
-
- /* Add thread into runQ */
- iresumeThread(tid);
-}
-
-
-/*
- * Start a daemon thread.
- */
-static thread *startDaemon(void* func, char* nm, int stackSize)
-{
- thread* tid;
- int i;
-
- DBG( printf("startDaemon %s\n", nm); );
-
- tid = (thread *) builtin_new(class_new(utf_new_char("java/lang/Thread")));
- assert(tid != 0);
-
-/* for (i = 0; i < MAXTHREADS; ++i)
- if (contexts[i]==0)
- break;
- if (i == MAXTHREADS)
- panic("Too many threads");*/
-
-/* tid->PrivateInfo = i + 1;
- CONTEXT(tid).free = false;*/
- tid->name = 0; /* for the moment */
- tid->priority = MAX_THREAD_PRIO;
- CONTEXT(tid).priority = (u1)tid->priority;
- tid->vmThread->next = 0;
- CONTEXT(tid).status = THREAD_SUSPENDED;
-
- allocThreadStack(tid, stackSize);
- /*tid->single_step = 0;*/
- tid->daemon = 1;
- /*tid->stillborn = 0;*/
- /*tid->target = 0;*/
- tid->group = 0;
-
- /* Construct the initial restore point. */
- THREADINIT((&CONTEXT(tid)), func);
-
- talive++;
- tdaemon++;
-
- return tid;
-}
-
-/*
- * All threads start here.
- */
-static void
-firstStartThread(void)
-{
- methodinfo *method;
-
- DBG( printf("firstStartThread %p\n", currentThread); );
-
- if (stack_to_be_freed != 0) {
- stack_to_be_freed = 0;
- }
-
- /* Every thread starts with the interrupts off */
- intsRestore();
- assert(blockInts == 0);
-
- /* Find the run()V method and call it */
- method = class_findmethod(currentThread->vmThread->header.vftbl->class,
- utf_new_char("run"), utf_new_char("()V"));
- if (method == 0)
- panic("Cannot find method \'void run ()\'");
-
- asm_calljavafunction(method, currentThread->vmThread, NULL, NULL, NULL);
-
- if (*exceptionptr) {
- utf_display((*exceptionptr)->vftbl->class->name);
- printf("\n");
- }
-
- killThread(0);
- assert("Thread returned from killThread" == 0);
-}
-
-/*
- * Resume a thread running.
- * This routine has to be called only from locations which ensure
- * run / block queue consistency. There is no check for illegal resume
- * conditions (like explicitly resuming an IO blocked thread). There also
- * is no update of any blocking queue. Both has to be done by the caller
- */
-void
-iresumeThread(thread* tid)
-{
- vmthread *vmctid;
- DBG( printf("resumeThread %p\n", tid); );
-
- intsDisable();
- if (tid->vmThread==0) {
- intsRestore();
- return;
- }
-
- if (currentThread->vmThread==0) {
- long i1;
- for (i1=0;i1<MAXTHREADS;i1++) {
- if (!contexts[i1]) continue;
- if (contexts[i1]->thread==currentThread) {
- vmctid=contexts[i1];
- break;
- }
- }
- if (i1==MAXTHREADS) vmctid=0; /*panic("Thread not found in iresumeThread");*/
-
- } else {
- vmctid=currentThread->vmThread;
- }
-
- if (CONTEXT(tid).status != THREAD_RUNNING)
- {
- CONTEXT(tid).status = THREAD_RUNNING;
-
- DBG( fprintf(stderr, "prio is %d\n", CONTEXT(tid).priority); );
-
- /* Place thread on the end of its queue */
- if (threadQhead[CONTEXT(tid).priority] == 0) {
- threadQhead[CONTEXT(tid).priority] = tid;
- threadQtail[CONTEXT(tid).priority] = tid;
-
- if ((vmctid==0) || (CONTEXT(tid).priority
- > vmctid->priority) )
- needReschedule = true;
- }
- else
- {
- threadQtail[CONTEXT(tid).priority]->vmThread->next = tid;
- threadQtail[CONTEXT(tid).priority] = tid;
- }
- tid->vmThread->next = 0;
- }
- SDBG( else { printf("Re-resuming %p\n", tid); } );
-
- intsRestore();
-}
-
-/*
- * Yield process to another thread of equal priority.
- */
-void
-yieldThread()
-{
- intsDisable();
-
- if (threadQhead[CONTEXT(currentThread).priority]
- != threadQtail[CONTEXT(currentThread).priority])
- {
- /* Get the next thread and move me to the end */
- threadQhead[CONTEXT(currentThread).priority] = currentThread->vmThread->next;
- threadQtail[CONTEXT(currentThread).priority]->vmThread->next = currentThread;
- threadQtail[CONTEXT(currentThread).priority] = currentThread;
- currentThread->vmThread->next = 0;
- needReschedule = true;
- }
-
- intsRestore();
-}
-
-/*
- * Explicit request by user to resume a thread
- * The definition says that it is just legal to call this after a preceeding
- * suspend (which got through). If the thread was blocked for some other
- * reason (either sleep or IO or a muxSem), we simply can't do it
- * We use a new thread flag THREAD_FLAGS_USER_SUSPEND for this purpose
- * (which is set by suspendThread(.))
- */
-void
-resumeThread (thread* tid)
-{
- if ((CONTEXT(tid).flags & THREAD_FLAGS_USER_SUSPEND) != 0)
- {
- intsDisable();
- CONTEXT(tid).flags &= ~THREAD_FLAGS_USER_SUSPEND;
- iresumeThread(tid);
- intsRestore();
- }
-}
-
-/*
- * Suspend a thread.
- * This is an explicit user request to suspend the thread - the counterpart
- * for resumeThreadRequest(.). It is JUST called by the java method
- * Thread.suspend()
- * What makes it distinct is the fact that the suspended thread is not contained
- * in any block queue. Without a special flag (indicating the user suspend), we
- * can't check s suspended thread for this condition afterwards (which is
- * required by resumeThreadRequest()). The new thread flag
- * THREAD_FLAGS_USER_SUSPEND is used for this purpose.
- */
-void
-suspendThread(thread* tid)
-{
- thread** ntid;
-
- intsDisable();
-
- if (CONTEXT(tid).status != THREAD_SUSPENDED)
- {
- CONTEXT(tid).status = THREAD_SUSPENDED;
-
- /*
- * This is used to indicate the explicit suspend condition
- * required by resumeThreadRequest()
- */
- CONTEXT(tid).flags |= THREAD_FLAGS_USER_SUSPEND;
-
- for (ntid = &threadQhead[CONTEXT(tid).priority];
- *ntid != 0;
- ntid = &(*ntid)->vmThread->next)
- {
- if (*ntid == tid)
- {
- *ntid = tid->vmThread->next;
- tid->vmThread->next = 0;
- if (tid == currentThread)
- {
- reschedule();
- }
- break;
- }
- }
- }
- SDBG( else { printf("Re-suspending %p\n", tid); } );
-
- intsRestore();
-}
-
-/*
- * Suspend a thread on a queue.
- */
-void
-suspendOnQThread(thread* tid, thread** queue)
-{
- thread** ntid;
-
- DBG( printf("suspendOnQThread %p %p\n", tid, queue); );
-
- assert(blockInts > 0);
-
- if (CONTEXT(tid).status != THREAD_SUSPENDED)
- {
- CONTEXT(tid).status = THREAD_SUSPENDED;
-
- for (ntid = &threadQhead[CONTEXT(tid).priority];
- *ntid != 0;
- ntid = &(*ntid)->vmThread->next)
- {
- if (*ntid == tid)
- {
- *ntid = tid->vmThread->next;
- /* Insert onto head of lock wait Q */
- tid->vmThread->next = *queue;
- *queue = tid;
- if (tid == currentThread)
- {
- DBG( fprintf(stderr, "suspending %p (cur=%p) with prio %d\n",
- tid, currentThread, CONTEXT(tid).priority); );
- reschedule();
- }
- break;
- }
- }
- }
- SDBG( else { printf("Re-suspending %p on %p\n", tid, *queue); } );
-}
-
-/*
- * Kill thread.
- */
-void
-killThread(thread* tid)
-{
- vmthread *context;
- thread** ntid;
-
- intsDisable();
-
- /* A null tid means the current thread */
- if (tid == 0)
- {
- tid = currentThread;
- }
-
- if (tid->vmThread==0) {
- long i1;
- for (i1=0;i1<MAXTHREADS;i1++) {
- if (!contexts[i1]) continue;
- if (contexts[i1]->thread==tid) {
- context=contexts[i1];
- break;
- }
- }
- if (i1==MAXTHREADS) panic("Thread not found in killThread");
-
- } else context=tid->vmThread;
-
- DBG( printf("killThread %p\n", tid); );
-
- if (context->status != THREAD_DEAD)
- {
- /* Get thread off runq (if it needs it) */
- if (context->status == THREAD_RUNNING)
- {
- for (ntid = &threadQhead[context->priority];
- *ntid != 0;
- ntid = &(*ntid)->vmThread->next)
- {
- if (*ntid == tid)
- {
- *ntid = context->next;
- break;
- }
- }
- }
-
- context->status = THREAD_DEAD;
- talive--;
- if (tid->daemon) {
- tdaemon--;
- }
-
- /* If we only have daemons left, then everyone is dead. */
- if (talive == tdaemon) {
- /* atexit functions get called to clean things up */
- intsRestore();
- exit(0);
- }
-
- /* Notify on the object just in case anyone is waiting */
- internal_lock_mutex_for_object(&tid->header);
- internal_broadcast_cond_for_object(&tid->header);
- internal_unlock_mutex_for_object(&tid->header);
-
- /* Remove thread from live list to it can be garbaged */
- for (ntid = &liveThreads;
- *ntid != 0;
- ntid = &(CONTEXT((*ntid)).nextlive))
- {
- if (tid == (*ntid))
- {
- (*ntid) = context->nextlive;
- break;
- }
- }
-
-
- /* Free stack */
- freeThreadStack(context);
-
- /* free context */
- if (tid != mainThread)
- {
- long i;
- for (i=0;i<MAXTHREADS;i++) {
- if (!contexts[i]) continue;
- if (contexts[i]==context) {
- contexts[i]=0;
- break;
- }
- }
- }
-/* if (tid != mainThread) {
- CONTEXT(tid).free = true;
- CONTEXT(tid).thread = NULL;
- }*/
-
- /* Run something else */
- needReschedule = true;
- }
- for (ntid = &sleepThreads;
- *ntid != 0;
- ntid = &(CONTEXT((*ntid)).next))
- {
- if (tid == (*ntid))
- {
- (*ntid) = context->next;
- break;
- }
- }
-
- intsRestore();
-}
-
-/*
- * Change thread priority.
- */
-void
-setPriorityThread(thread* tid, int prio)
-{
- thread** ntid;
-
- assert(prio >= MIN_THREAD_PRIO && prio <= MAX_THREAD_PRIO);
-
-#warning fixme ??
-/* if (tid->PrivateInfo == 0) {
- tid->priority = prio;
- return;
- }*/
-
- if (CONTEXT(tid).status == THREAD_SUSPENDED) {
- CONTEXT(tid).priority = (u8)prio;
- return;
- }
-
- intsDisable();
-
- /* Remove from current thread list */
- for (ntid = &threadQhead[CONTEXT(tid).priority]; *ntid != 0; ntid = &(*ntid)->vmThread->next) {
- if (*ntid == tid) {
- *ntid = tid->vmThread->next;
- break;
- }
- }
-
- /* Insert onto a new one */
- tid->priority = prio;
- CONTEXT(tid).priority = (u8)tid->priority;
- if (threadQhead[prio] == 0) {
- threadQhead[prio] = tid;
- threadQtail[prio] = tid;
- if (prio > CONTEXT(currentThread).priority) {
- needReschedule = true;
- }
- }
- else {
- threadQtail[prio]->vmThread->next = tid;
- threadQtail[prio] = tid;
- }
- tid->vmThread->next = 0;
-
- 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, s4 nanos)
-{
- 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)->vmThread->next))
- {
- if (CONTEXT((*tidp)).time > CONTEXT(currentThread).time)
- break;
- }
-
- /* Suspend thread on it */
- suspendOnQThread(currentThread, tidp);
-
- intsRestore();
-}
-
-/*
- * Is this thread alive?
- */
-bool
-aliveThread(thread* tid)
-{
- if (tid!=mainThread && CONTEXT(tid).status != THREAD_DEAD)
- return (true);
- else
- return (false);
-}
-
-/*
- * Reschedule the thread.
- * Called whenever a change in the running thread is required.
- */
-void
-reschedule(void)
-{
- int i;
- thread* lastThread;
- int b;
- /* sigset_t nsig; */
-
- /* A reschedule in a non-blocked context is half way to hell */
- assert(blockInts > 0);
- b = blockInts;
-
- /* Check events - we may release a high priority thread */
- /* Just check IO, no need for a reschedule call by checkEvents() */
- needReschedule = false;
- checkEvents(false);
-
- for (;;)
- {
- for (i = MAX_THREAD_PRIO; i >= MIN_THREAD_PRIO; i--)
- {
- if (threadQhead[i] != 0)
- {
- DBG( fprintf(stderr, "found thread %p in head %d\n", threadQhead[i], i); );
-
- if (threadQhead[i] != currentThread)
- {
- /* USEDSTACKTOP((CONTEXT(currentThread).usedStackTop)); */
-
- lastThread = currentThread;
- currentThread = threadQhead[i];
-
- CONTEXT(currentThread).texceptionptr = *exceptionptr;
-
- DBG( fprintf(stderr, "thread switch from: %p to: %p\n", lastThread, currentThread); );
- {
- THREADSWITCH((&CONTEXT(currentThread)),
- (&CONTEXT(lastThread)));
- }
- blockInts = b;
-
- *exceptionptr = CONTEXT(currentThread).texceptionptr;
-
- if (stack_to_be_freed != 0) {
- stack_to_be_freed = 0;
- }
-
- /* Alarm signal may be blocked - if so
- * unblock it.
- */
- /*
- if (alarmBlocked == true) {
- alarmBlocked = false;
- sigemptyset(&nsig);
- sigaddset(&nsig, SIGALRM);
- sigprocmask(SIG_UNBLOCK, &nsig, 0);
- }
- */
-
- /* I might be dying */
- if ((CONTEXT(lastThread).flags & THREAD_FLAGS_KILLED)
- != 0)
- {
- CONTEXT(lastThread).flags &= ~THREAD_FLAGS_KILLED;
- *exceptionptr = native_new_and_init(class_java_lang_ThreadDeath);
- }
- }
- /* Now we kill the schedule and turn ints
- back on */
- needReschedule = false;
- return;
- }
- }
- /* Nothing to run - wait for external event */
- DBG( fprintf(stderr, "nothing more to do\n"); );
- checkEvents(true);
- }
-}
-
-void lock_stopworld(int dummy)
-{
-}
-
-void unlock_stopworld()
-{
-}
-
-void cacao_suspendhandler(void *ctx)
-{
-}
-
-#endif
-
+++ /dev/null
-/* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * thread.h
- * Thread support.
- *
- * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
- */
-
-#ifndef _THREAD_H
-#define _THREAD_H
-
-#include "config.h"
-
-typedef struct {
- int super_baseval, super_diffval, sub_baseval;
-} castinfo;
-
-#ifdef USE_THREADS
-
-#include "global.h"
-
-#define THREADCLASS "java/lang/Thread"
-#define THREADGROUPCLASS "java/lang/ThreadGroup"
-#define THREADDEATHCLASS "java/lang/ThreadDeath"
-
-#define MIN_THREAD_PRIO 1
-#define NORM_THREAD_PRIO 5
-#define MAX_THREAD_PRIO 10
-
-#define THREAD_SUSPENDED 0
-#define THREAD_RUNNING 1
-#define THREAD_DEAD 2
-#define THREAD_KILL 3
-
-#define THREAD_FLAGS_GENERAL 0
-#define THREAD_FLAGS_NOSTACKALLOC 1
-#define THREAD_FLAGS_USER_SUSPEND 2 /* Flag explicit suspend() call */
-#define THREAD_FLAGS_KILLED 4
-
-#if !defined(NATIVE_THREADS)
-
-#define MAXTHREADS 256 /* schani */
-
-#if 1
-#define DBG(s)
-#define SDBG(s)
-#else
-#define DBG(s) s
-#define SDBG(s) s
-#endif
-
-struct _thread;
-
-#if 0
-typedef struct _ctx
-{
- struct _thread *thread;
- bool free;
- u1 status;
- u1 priority;
- u1* restorePoint;
- u1* stackMem; /* includes guard page */
- u1* stackBase;
- u1* stackEnd;
- u1* usedStackTop;
- s8 time;
- java_objectheader *texceptionptr;
- struct _thread *nextlive;
- u1 flags;
-} ctx;
-#endif
-
-/*
-struct _stringClass;
-struct _object;
-*/
-
-/* This structure mirrors java.lang.ThreadGroup.h */
-
-typedef struct _threadGroup {
- java_objectheader header;
- struct _threadGroup* parent;
- struct java_objectheader* name;
- struct java_objectheader* threads;
- struct java_objectheader* groups;
- s4 daemon_flag;
- s4 maxpri;
-} threadGroup;
-
-
-
-/* This structure mirrors java.lang.VMThread.h */
-typedef struct vmthread {
- java_objectheader header;
- struct _thread* thread;
- s4 running;
- s4 status;
- s4 priority;
- void* restorePoint;
- void* stackMem;
- void* stackBase;
- void* stackEnd;
- void* usedStackTop;
- s8 time;
- java_objectheader *texceptionptr;
- struct _thread* nextlive;
- struct _thread* next;
- s4 flags;
-} vmthread;
-
-/* This structure mirrors java.lang.Thread.h */
-typedef struct _thread {
- java_objectheader header;
- vmthread* vmThread;
- threadGroup* group;
- struct java_lang_Runnable* runnable;
- struct java_lang_String* name;
- s4 daemon;
- s4 priority;
- s8 stacksize;
- struct java_lang_Throwable* stillborn;
- struct java_lang_ClassLoader* contextClassLoader;
-} thread;
-
-void initThreads (u1 *stackbottom);
-void clear_thread_flags (void);
-void startThread (thread*);
-void resumeThread (thread*);
-void iresumeThread (thread*);
-void suspendThread (thread*);
-void suspendOnQThread (thread*, thread**);
-void yieldThread (void);
-void killThread (thread*);
-void setPriorityThread (thread*, int);
-
-s8 currentTime (void);
-void sleepThread(s8 millis, s4 nanos);
-bool aliveThread (thread*);
-long framesThread (thread*);
-
-void reschedule (void);
-
-void checkEvents (bool block);
-
-extern int blockInts;
-extern bool needReschedule;
-extern thread *currentThread;
-extern thread *mainThread;
-/*extern ctx contexts[];*/
-extern int threadStackSize;
-
-extern thread *liveThreads;
-extern thread *sleepThreads;
-
-extern thread *threadQhead[MAX_THREAD_PRIO + 1];
-
-
-/*#define CONTEXT(_t) (contexts[(_t)->PrivateInfo - 1])*/
-#define CONTEXT(_t) (*(_t->vmThread))
-
-#define intsDisable() blockInts++
-
-#define intsRestore() if (blockInts == 1 && needReschedule) { \
- reschedule(); \
- } \
- blockInts--
-
-
-/* access macros */
-
-#define THREADSTACKSIZE (32 * 1024)
-
-#define THREADSWITCH(to, from) \
- do { \
- void *from1; \
- void *from2; \
- asm_perform_threadswitch((from?&(from)->restorePoint:&from1),\
- &(to)->restorePoint, (from?&(from)->usedStackTop:&from2)); \
- } while (0)
-
-
-#define THREADINIT(to, func) \
- do { \
- (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), \
- (to)->stackEnd); \
- } while (0)
-
-
-#define THREADINFO(e) \
- do { \
- (e)->restorePoint = 0; \
- (e)->flags = THREAD_FLAGS_NOSTACKALLOC; \
- } while(0)
-
-
-/* function prototypes */
-void asm_perform_threadswitch(u1 **from, u1 **to, u1 **stackTop);
-u1* asm_initialize_thread_stack(void *func, u1 *stack);
-
-#else /* NATIVE_THREADS */
-#include "nativethread.h"
-#endif
-
-#else
-
-#define intsDisable()
-#define intsRestore()
-
-#endif /* USE_THREADS */
-
-#endif /* _THREAD_H */
-
+++ /dev/null
-/*
- * threadCalls.c
- * Support for threaded ops which may block (read, write, connect, etc.).
- *
- * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * Written by Tim Wilkinson <tim@tjwassoc.demon.co.uk>, 1996.
- */
-
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <assert.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "config.h"
-#include "threads/thread.h"
-
-#if !defined(NATIVE_THREADS)
-
-#define TH_READ 0
-#define TH_WRITE 1
-#define TH_ACCEPT TH_READ
-#define TH_CONNECT TH_WRITE
-
-static int maxFd;
-static fd_set readsPending;
-static fd_set writesPending;
-static thread* readQ[FD_SETSIZE];
-static thread* writeQ[FD_SETSIZE];
-
-void blockOnFile(int, int);
-void waitOnEvents(void);
-
-extern thread* currentThread;
-
-/* These are undefined because we do not yet support async I/O */
-#undef F_SETOWN
-#undef FIOSETOWN
-#undef O_ASYNC
-#undef FIOASYNC
-
-/*
- * Create a threaded file descriptor.
- */
-int
-threadedFileDescriptor(int fd)
-{
-#if !defined(BLOCKING_CALLS)
- int r;
-#if defined(HAVE_IOCTL) && defined(FIOASYNC)
- int on = 1;
-#endif
- int pid;
-
- /* Make non-blocking */
-#if defined(HAVE_FCNTL) && defined(O_NONBLOCK)
- r = fcntl(fd, F_GETFL, 0);
- r = fcntl(fd, F_SETFL, r|O_NONBLOCK);
-#elif defined(HAVE_IOCTL) && defined(FIONBIO)
- r = ioctl(fd, FIONBIO, &on);
-#else
- r = 0;
-#endif
- if (r < 0)
- {
- return (r);
- }
-
- /* Allow socket to signal this process when new data is available */
- pid = getpid();
-#if defined(HAVE_FCNTL) && defined(F_SETOWN)
- r = fcntl(fd, F_SETOWN, pid);
-#elif defined(HAVE_IOCTL) && defined(FIOSETOWN)
- r = ioctl(fd, FIOSETOWN, &pid);
-#else
- r = 0;
-#endif
- if (r < 0)
- {
- return (r);
- }
-
-#if defined(HAVE_FCNTL) && defined(O_ASYNC)
- r = fcntl(fd, F_GETFL, 0);
- r = fcntl(fd, F_SETFL, r|O_ASYNC);
-#elif defined(HAVE_IOCTL) && defined(FIOASYNC)
- r = ioctl(fd, FIOASYNC, &on);
-#else
- r = 0;
-#endif
- if (r < 0)
- {
- return (r);
- }
-#endif
- return (fd);
-}
-
-void clear_thread_flags(void)
-{
-#if !defined(BLOCKING_CALLS)
-#if defined(HAVE_FCNTL) && defined(O_NONBLOCK)
- int fl, fd;
-
- fd = fileno(stdin);
- fl = fcntl(fd, F_GETFL, 0);
- fl = fcntl(fd, F_SETFL, fl & (~O_NONBLOCK));
-
- fd = fileno(stdout);
- fl = fcntl(fd, F_GETFL, 0);
- fl = fcntl(fd, F_SETFL, fl & (~O_NONBLOCK));
-
- fd = fileno(stderr);
- fl = fcntl(fd, F_GETFL, 0);
- fl = fcntl(fd, F_SETFL, fl & (~O_NONBLOCK));
-
-#elif defined(HAVE_IOCTL) && defined(FIONBIO)
- int fl, fd;
-
- fl = 0;
- fd = fileno(stdin);
- (void) ioctl(fd, FIONBIO, &fl);
-
- fd = fileno(stdout);
- (void) ioctl(fd, FIONBIO, &fl);
-
- fd = fileno(stderr);
- (void) ioctl(fd, FIONBIO, &fl);
-#endif
-#endif
-
- fflush(stdout);
- fflush(stderr);
-}
-
-
-/*
- * Threaded create socket.
- */
-int
-threadedSocket(int af, int type, int proto)
-{
- int fd;
-
- fd = socket(af, type, proto);
- return (threadedFileDescriptor(fd));
-}
-
-/*
- * Threaded file open.
- */
-int
-threadedOpen(char* path, int flags, int mode)
-{
- int fd;
-
- fd = open(path, flags, mode);
- return (threadedFileDescriptor(fd));
-}
-
-/*
- * Threaded socket connect.
- */
-int
-threadedConnect(int fd, struct sockaddr* addr, int len)
-{
- int r;
-
- r = connect(fd, addr, len);
-#if !defined(BLOCKING_CALLS)
- if ((r < 0)
- && (errno == EINPROGRESS || errno == EALREADY
- || errno == EWOULDBLOCK)) {
- blockOnFile(fd, TH_CONNECT);
- r = 0; /* Assume it's okay when we get released */
- }
-#endif
-
- return (r);
-}
-
-/*
- * Threaded socket accept.
- */
-int
-threadedAccept(int fd, struct sockaddr* addr, int* len)
-{
- int r;
-
- for (;;)
- {
-#if defined(BLOCKING_CALLS)
- blockOnFile(fd, TH_ACCEPT);
-#endif
- r = accept(fd, addr, (int*)len);
- if (r >= 0
- || !(errno == EINPROGRESS || errno == EALREADY
- || errno == EWOULDBLOCK))
- {
- break;
- }
-#if !defined(BLOCKING_CALLS)
- blockOnFile(fd, TH_ACCEPT);
-#endif
- }
- return (threadedFileDescriptor(r));
-}
-
-/*
- * Read but only if we can.
- */
-int
-threadedRead(int fd, char* buf, int len)
-{
- int r;
-
- DBG( printf("threadedRead\n"); )
-
-#if defined(BLOCKING_CALLS)
- blockOnFile(fd, TH_READ);
-#endif
- for (;;)
- {
- r = read(fd, buf, len);
- if (r < 0
- && (errno == EAGAIN || errno == EWOULDBLOCK
- || errno == EINTR))
- {
- blockOnFile(fd, TH_READ);
- continue;
- }
- return (r);
- }
-}
-
-/*
- * Write but only if we can.
- */
-int
-threadedWrite(int fd, char* buf, int len)
-{
- int r;
- char* ptr;
-
- ptr = buf;
- r = 1;
-
- DBG( printf("threadedWrite %dbytes\n",len); )
-
- while (len > 0 && r > 0)
- {
-#if defined(BLOCKING_CALLS)
- blockOnFile(fd, TH_WRITE);
-#endif
- r = write(fd, ptr, len);
- if (r < 0
- && (errno == EAGAIN || errno == EWOULDBLOCK
- || errno == EINTR))
- {
-#if !defined(BLOCKING_CALLS)
- blockOnFile(fd, TH_WRITE);
-#endif
- r = 1;
- }
- else
- {
- ptr += r;
- len -= r;
- }
- }
- return (ptr - buf);
-}
-
-/*
- * Receive, but only if we can.
- */
-int
-threadedRecvfrom (int fd, void *buf, size_t len, int flags, struct sockaddr *addr, int *addrlen)
-{
- int r;
-
- DBG( printf("threadedRecvfrom\n"); )
-
-#if defined(BLOCKING_CALLS)
- blockOnFile(fd, TH_READ);
-#endif
- for (;;)
- {
- r = recvfrom(fd, buf, len, flags, addr, addrlen);
- if (r < 0
- && (errno == EAGAIN || errno == EWOULDBLOCK
- || errno == EINTR))
- {
- blockOnFile(fd, TH_READ);
- continue;
- }
- return (r);
- }
-}
-
-/*
- * Send, but only if we can.
- */
-int
-threadedSendto (int fd, void *buf, size_t len, int flags, struct sockaddr *addr, int addrlen)
-{
- int r;
-
- DBG( printf("threadedSendto\n"); )
-
-#if defined(BLOCKING_CALLS)
- blockOnFile(fd, TH_WRITE);
-#endif
- for (;;)
- {
- r = sendto(fd, buf, len, flags, addr, addrlen);
- if (r < 0
- && (errno == EAGAIN || errno == EWOULDBLOCK
- || errno == EINTR))
- {
- blockOnFile(fd, TH_WRITE);
- continue;
- }
- return (r);
- }
-}
-
-/*
- * An attempt to access a file would block, so suspend the thread until
- * it will happen.
- */
-void
-blockOnFile(int fd, int op)
-{
-DBG( printf("blockOnFile()\n"); )
-
- intsDisable();
-
- if (fd > maxFd)
- {
- maxFd = fd;
- }
-
- if (op == TH_READ)
- {
- FD_SET(fd, &readsPending);
- suspendOnQThread(currentThread, &readQ[fd]);
- FD_CLR(fd, &readsPending);
- }
- else
- {
- FD_SET(fd, &writesPending);
- suspendOnQThread(currentThread, &writeQ[fd]);
- FD_CLR(fd, &writesPending);
- }
-
- intsRestore();
-}
-
-/*
- * Check if some file descriptor or other event to become ready.
- * Block if required (but make sure we can still take timer interrupts).
- */
-void
-checkEvents(bool block)
-{
- int r;
- fd_set rd;
- fd_set wr;
- thread* tid;
- thread* ntid;
- int i;
- s8 time = -1;
- struct timeval tv;
- struct timeval *timeout;
-
- assert(blockInts > 0);
-
- DBG( printf("checkEvents block:%d\n", block); )
-
- if (sleepThreads != 0)
- {
- time = currentTime();
- while (sleepThreads != 0 && time >= CONTEXT(sleepThreads).time)
- {
- tid = sleepThreads;
- sleepThreads = sleepThreads->vmThread->next;
- tid->vmThread->next = 0;
-
- iresumeThread(tid);
- }
- }
-
- if (block)
- {
- if (sleepThreads != 0)
- {
- s8 wait_time = CONTEXT(sleepThreads).time - time;
-
- tv.tv_sec = wait_time / 1000;
- tv.tv_usec = (wait_time % 1000) * 1000;
- timeout = &tv;
- }
- else
- timeout = 0;
- }
- else
- {
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- timeout = &tv;
- }
-
-#if defined(FD_COPY)
- FD_COPY(&readsPending, &rd);
- FD_COPY(&writesPending, &wr);
-#else
- memcpy(&rd, &readsPending, sizeof(rd));
- memcpy(&wr, &writesPending, sizeof(wr));
-#endif
-
- r = select(maxFd+1, &rd, &wr, 0, timeout);
-
- /* We must be holding off interrupts before we start playing with
- * the read and write queues. This should be already done but a
- * quick check never hurt anyone.
- */
- assert(blockInts > 0);
-
- DBG( printf("Select returns %d\n", r); )
-
- /* Some threads may have finished sleeping.
- */
- if (block && sleepThreads != 0)
- {
- time = currentTime();
- while (sleepThreads != 0 && time >= CONTEXT(sleepThreads).time)
- {
- tid = sleepThreads;
- sleepThreads = sleepThreads->vmThread->next;
- tid->vmThread->next = 0;
-
- iresumeThread(tid);
- }
- }
-
- for (i = 0; r > 0 && i <= maxFd; i++)
- {
- if (readQ[i] != 0 && FD_ISSET(i, &rd))
- {
- for (tid = readQ[i]; tid != 0; tid = ntid)
- {
- ntid = tid->vmThread->next;
- iresumeThread(tid);
- }
- readQ[i] = 0;
- r--;
- }
- if (writeQ[i] != 0 && FD_ISSET(i, &wr))
- {
- for (tid = writeQ[i]; tid != 0; tid = ntid)
- {
- ntid = tid->vmThread->next;
- iresumeThread(tid);
- }
- writeQ[i] = 0;
- r--;
- }
- }
-}
-
-#endif
+++ /dev/null
-/* -*- c -*- */
-
-#ifndef __threadio_h_
-#define __threadio_h_
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include "global.h"
-
-#ifdef USE_THREADS
-int threadedFileDescriptor(int fd);
-int threadedSocket(int af, int type, int proto);
-int threadedOpen(char* path, int flags, int mode);
-int threadedConnect(int fd, struct sockaddr* addr, int len);
-int threadedAccept(int fd, struct sockaddr* addr, int* len);
-int threadedRead(int fd, char* buf, int len);
-int threadedWrite(int fd, char* buf, int len);
-int threadedRecvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, int *addrlen);
-int threadedSendto(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, int addrlen);
-#else
-#define threadedFileDescriptor(fd)
-#define threadedRead(fd,buf,len) read(fd,buf,len)
-#define threadedWrite(fd,buf,len) write(fd,buf,len)
-#define threadedSocket(af,type,proto) socket(af,type,proto)
-#define threadedAccept(fd,addr,len) accept(fd,addr,len)
-#define threadedRecvfrom(fd,buf,len,flags,addr,addrlen) recvfrom(fd,buf,len,flags,addr,addrlen)
-#define threadedSendto(fd,buf,len,flags,addr,addrlen) sendto(fd,buf,len,flags,addr,addrlen)
-#define threadedConnect(fd,addr,len) connect(fd,addr,len)
-#endif
-
-
-#endif