funnyvm/src/thread.h

234 lines
7.8 KiB
C

/*
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
* Robert Lougher <rob@jamvm.org.uk>.
*
* This file is part of JamVM.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef CREATING
#include <pthread.h>
#include <setjmp.h>
#include <stdlib.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
/* Thread states */
#define JVMTI_THREAD_STATE_ALIVE 0x001
#define JVMTI_THREAD_STATE_TERMINATED 0x002
#define JVMTI_THREAD_STATE_RUNNABLE 0x004
#define JVMTI_THREAD_STATE_WAITING_INDEFINITELY 0x010
#define JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT 0x020
#define JVMTI_THREAD_STATE_SLEEPING 0x040
#define JVMTI_THREAD_STATE_WAITING 0x080
#define JVMTI_THREAD_STATE_IN_OBJECT_WAIT 0x100
#define JVMTI_THREAD_STATE_PARKED 0x200
#define JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER 0x400
#define CREATING 0x0
#define RUNNING (JVMTI_THREAD_STATE_ALIVE \
|JVMTI_THREAD_STATE_RUNNABLE)
#define WAITING (JVMTI_THREAD_STATE_ALIVE \
|JVMTI_THREAD_STATE_WAITING \
|JVMTI_THREAD_STATE_WAITING_INDEFINITELY)
#define TIMED_WAITING (JVMTI_THREAD_STATE_ALIVE \
|JVMTI_THREAD_STATE_WAITING \
|JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT)
#define OBJECT_WAIT (JVMTI_THREAD_STATE_IN_OBJECT_WAIT|WAITING)
#define OBJECT_TIMED_WAIT (JVMTI_THREAD_STATE_IN_OBJECT_WAIT|TIMED_WAITING)
#define SLEEPING (JVMTI_THREAD_STATE_SLEEPING|TIMED_WAITING)
#define PARKED (JVMTI_THREAD_STATE_PARKED|WAITING)
#define TIMED_PARKED (JVMTI_THREAD_STATE_PARKED|TIMED_WAITING)
#define BLOCKED JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
#define TERMINATED JVMTI_THREAD_STATE_TERMINATED
/* thread priorities */
#define MIN_PRIORITY 1
#define NORM_PRIORITY 5
#define MAX_PRIORITY 10
/* Suspend states */
#define SUSP_NONE 0
#define SUSP_BLOCKING 1
#define SUSP_CRITICAL 2
#define SUSP_SUSPENDED 3
/* Park states */
#define PARK_BLOCKED 0
#define PARK_RUNNING 1
#define PARK_PERMIT 2
typedef struct thread Thread;
typedef struct monitor {
pthread_mutex_t lock;
Thread *owner;
Object *obj;
int count;
int in_wait;
uintptr_t entering;
int wait_count;
Thread *wait_set;
struct monitor *next;
} Monitor;
struct thread {
int id;
pthread_t tid;
ExecEnv *ee;
void *stack_top;
void *stack_base;
Monitor *wait_mon;
Monitor *blocked_mon;
Thread *wait_prev;
Thread *wait_next;
pthread_cond_t wait_cv;
pthread_cond_t park_cv;
pthread_mutex_t park_lock;
long long blocked_count;
long long waited_count;
Thread *prev, *next;
unsigned int wait_id;
unsigned int notify_id;
char suspend;
char park_state;
char interrupted;
char interrupting;
char suspend_state;
CLASSLIB_THREAD_EXTRA_FIELDS
};
extern Thread *threadSelf();
extern long long javaThreadId(Thread *thread);
extern Thread *jThread2Thread(Object *jThread);
extern long long jThread2ThreadId(Object *jthread);
extern void *getStackTop(Thread *thread);
extern void *getStackBase(Thread *thread);
extern int getThreadsCount();
extern int getPeakThreadsCount();
extern void resetPeakThreadsCount();
extern long long getTotalStartedThreadsCount();
extern void threadInterrupt(Thread *thread);
extern void threadSleep(Thread *thread, long long ms, int ns);
extern void threadYield(Thread *thread);
extern int threadIsAlive(Thread *thread);
extern int threadInterrupted(Thread *thread);
extern int threadIsInterrupted(Thread *thread);
extern int systemIdle(Thread *self);
extern void threadPark(Thread *thread, int absolute, long long time);
extern void threadUnpark(Thread *thread);
extern void suspendAllThreads(Thread *thread);
extern void resumeAllThreads(Thread *thread);
extern void createVMThread(char *name, void (*start)(Thread*));
extern void disableSuspend0(Thread *thread, void *stack_top);
extern void enableSuspend(Thread *thread);
extern void fastEnableSuspend(Thread *thread);
extern Thread *attachJNIThread(char *name, char is_daemon, Object *group);
extern void detachJNIThread(Thread *thread);
extern char *getThreadStateString(Thread *thread);
extern Thread *findThreadById(long long id);
extern Thread *findRunningThreadByTid(int tid);
extern void suspendThread(Thread *thread);
extern void resumeThread(Thread *thread);
extern Object *runningThreadStackTrace(Thread *thread, int max_depth,
int *in_native);
extern Object *runningThreadObjects();
extern void printThreadsDump(Thread *self);
#define disableSuspend(thread) \
{ \
sigjmp_buf *env; \
env = alloca(sizeof(sigjmp_buf)); \
sigsetjmp(*env, FALSE); \
disableSuspend0(thread, (void*)env); \
}
#define fastDisableSuspend(thread) \
{ \
thread->suspend_state = SUSP_CRITICAL; \
MBARRIER(); \
}
typedef struct {
pthread_mutex_t lock;
pthread_cond_t cv;
} VMWaitLock;
typedef pthread_mutex_t VMLock;
#define initVMLock(lock) pthread_mutex_init(&lock, NULL)
#define initVMWaitLock(wait_lock) { \
pthread_mutex_init(&wait_lock.lock, NULL); \
pthread_cond_init(&wait_lock.cv, NULL); \
}
#define lockVMLock(lock, self) { \
classlibSetThreadState(self, BLOCKED); \
pthread_mutex_lock(&lock); \
classlibSetThreadState(self, RUNNING); \
}
#define tryLockVMLock(lock, self) \
(pthread_mutex_trylock(&lock) == 0)
#define unlockVMLock(lock, self) if(self) pthread_mutex_unlock(&lock)
#define lockVMWaitLock(wait_lock, self) lockVMLock(wait_lock.lock, self)
#define unlockVMWaitLock(wait_lock, self) unlockVMLock(wait_lock.lock, self)
#define waitVMWaitLock(wait_lock, self) { \
classlibSetThreadState(self, WAITING); \
pthread_cond_wait(&wait_lock.cv, &wait_lock.lock); \
classlibSetThreadState(self, RUNNING); \
}
#define timedWaitVMWaitLock(wait_lock, self, ms) { \
struct timeval tv; \
struct timespec ts; \
gettimeofday(&tv, 0); \
ts.tv_sec = tv.tv_sec + ms/1000; \
ts.tv_nsec = (tv.tv_usec + ((ms%1000)*1000))*1000; \
if(ts.tv_nsec > 999999999L) { \
ts.tv_sec++; \
ts.tv_nsec -= 1000000000L; \
} \
classlibSetThreadState(self, TIMED_WAITING); \
pthread_cond_timedwait(&wait_lock.cv, &wait_lock.lock, &ts); \
classlibSetThreadState(self, RUNNING); \
}
#define notifyVMWaitLock(wait_lock, self) pthread_cond_signal(&wait_lock.cv)
#define notifyAllVMWaitLock(wait_lock, self) pthread_cond_broadcast(&wait_lock.cv)
#endif