copy-paste

This commit is contained in:
rusefillc 2021-04-16 00:20:44 -04:00
parent b3c688e516
commit 4191c25b32
3 changed files with 485 additions and 0 deletions

67
src/hash.c Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2003, 2004, 2005, 2006, 2007
* 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.
*/
#include <string.h>
#include <stdlib.h>
#include "jam.h"
#include "hash.h"
#include "class.h"
#include "classlib.h"
void lockHashTable0(HashTable *table, Thread *self) {
if(!tryLockVMLock(table->lock, self)) {
disableSuspend(self);
lockVMLock(table->lock, self);
enableSuspend(self);
}
fastDisableSuspend(self);
}
void unlockHashTable0(HashTable *table, Thread *self) {
fastEnableSuspend(self);
unlockVMLock(table->lock, self);
}
void resizeHash(HashTable *table, int new_size) {
HashEntry *new_table = gcMemMalloc(sizeof(HashEntry)*new_size);
int i;
memset(new_table, 0, sizeof(HashEntry)*new_size);
for(i = table->hash_size-1; i >= 0; i--) {
void *ptr = table->hash_table[i].data;
if(ptr != NULL) {
int hash = table->hash_table[i].hash;
int new_index = hash & (new_size - 1);
while(new_table[new_index].data != NULL)
new_index = (new_index+1) & (new_size - 1);
new_table[new_index].hash = hash;
new_table[new_index].data = ptr;
}
}
gcMemFree(table->hash_table);
table->hash_table = new_table;
table->hash_size = new_size;
}

185
src/hash.h Normal file
View File

@ -0,0 +1,185 @@
/*
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 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.
*/
#include "thread.h"
typedef struct hash_entry {
void *data;
int hash;
} HashEntry;
typedef struct hash_table {
HashEntry *hash_table;
int hash_size;
int hash_count;
VMLock lock;
} HashTable;
extern void resizeHash(HashTable *table, int new_size);
extern void lockHashTable0(HashTable *table, Thread *self);
extern void unlockHashTable0(HashTable *table, Thread *self);
#define initHashTable(table, initial_size, create_lock) \
{ \
table.hash_table = gcMemMalloc(sizeof(HashEntry)*initial_size); \
memset(table.hash_table, 0, sizeof(HashEntry)*initial_size); \
table.hash_size = initial_size; \
table.hash_count = 0; \
if(create_lock) \
initVMLock(table.lock); \
}
#define lockHashTable(table) \
lockHashTable0(&table, threadSelf());
#define unlockHashTable(table) \
unlockHashTable0(&table, threadSelf());
#define hashTableCount(table) \
table.hash_count
#define findHashEntry(table, ptr, ptr2, add_if_absent, scavenge, \
locked) \
{ \
int hash = HASH(ptr); \
int i; \
\
Thread *self; \
if(locked) { \
self = threadSelf(); \
lockHashTable0(&table, self); \
} \
\
i = hash & (table.hash_size - 1); \
\
for(;;) { \
ptr2 = table.hash_table[i].data; \
if((ptr2 == NULL) || \
(COMPARE(ptr, ptr2, hash, table.hash_table[i].hash))) \
break; \
\
i = (i+1) & (table.hash_size - 1); \
} \
\
if(ptr2) { \
ptr2 = FOUND(ptr, ptr2); \
} else \
if(add_if_absent) { \
table.hash_table[i].hash = hash; \
ptr2 = table.hash_table[i].data = PREPARE(ptr); \
\
if(ptr2) { \
table.hash_count++; \
if((table.hash_count * 4) > (table.hash_size * 3)) { \
int new_size; \
if(scavenge) { \
HashEntry *entry = table.hash_table; \
int cnt = table.hash_count; \
for(; cnt; entry++) { \
void *data = entry->data; \
if(data) { \
if(SCAVENGE(data)) { \
entry->data = NULL; \
table.hash_count--; \
} \
cnt--; \
} \
} \
if((table.hash_count * 3) > \
(table.hash_size * 2)) \
new_size = table.hash_size*2; \
else \
new_size = table.hash_size; \
} else \
new_size = table.hash_size*2; \
\
resizeHash(&table, new_size); \
} \
} \
} \
\
if(locked) \
unlockHashTable0(&table, self); \
}
#define deleteHashEntry(table, ptr, locked) \
{ \
int hash = HASH(ptr); \
void *ptr2; \
int i; \
\
Thread *self; \
if(locked) { \
self = threadSelf(); \
lockHashTable0(&table, self); \
} \
\
i = hash & (table.hash_size - 1); \
\
for(;;) { \
ptr2 = table.hash_table[i].data; \
if((ptr2 == NULL) || \
(COMPARE(ptr, ptr2, hash, table.hash_table[i].hash))) \
break; \
\
i = (i+1) & (table.hash_size - 1); \
} \
\
if(ptr2) \
table.hash_table[i].data = DELETED; \
\
if(locked) \
unlockHashTable0(&table, self); \
}
#define hashIterate(table) \
{ \
HashEntry *_entry = table.hash_table; \
int _cnt = table.hash_count; \
\
while(_cnt) { \
void *_data = _entry++->data; \
if(_data) { \
ITERATE(_data); \
_cnt--; \
} \
} \
}
#define hashIterateP(table) \
{ \
HashEntry *entry = table.hash_table; \
int cnt = table.hash_count; \
\
while(cnt) { \
void **data_pntr = &entry++->data; \
if(*data_pntr) { \
ITERATE(data_pntr); \
cnt--; \
} \
} \
}
#define freeHashTable(table) \
gcMemFree(table.hash_table)
#define gcFreeHashTable(table) \
freeHashTable(table)

233
src/thread.h Normal file
View File

@ -0,0 +1,233 @@
/*
* 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