mirror of
https://github.com/corda/corda.git
synced 2025-06-18 07:08:15 +00:00
various threading bugfixes
This commit is contained in:
108
src/machine.cpp
108
src/machine.cpp
@ -32,27 +32,79 @@ join(Thread* t, Thread* o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
count(Thread* t, Thread* o)
|
||||||
|
{
|
||||||
|
unsigned c = 0;
|
||||||
|
|
||||||
|
if (t != o) ++ c;
|
||||||
|
|
||||||
|
for (Thread* p = t->peer; p; p = p->peer) {
|
||||||
|
c += count(p, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t->child) c += count(t->child, o);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread**
|
||||||
|
fill(Thread* t, Thread* o, Thread** array)
|
||||||
|
{
|
||||||
|
if (t != o) *(array++) = t;
|
||||||
|
|
||||||
|
for (Thread* p = t->peer; p; p = p->peer) {
|
||||||
|
array = fill(p, o, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t->child) array = fill(t->child, o, array);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dispose(Thread* t, Thread* o, bool remove)
|
dispose(Thread* t, Thread* o, bool remove)
|
||||||
{
|
{
|
||||||
if (remove) {
|
if (remove) {
|
||||||
|
// debug
|
||||||
|
expect(t, find(t->m->rootThread, o));
|
||||||
|
|
||||||
|
unsigned c = count(t->m->rootThread, o);
|
||||||
|
Thread* threads[c];
|
||||||
|
fill(t->m->rootThread, o, threads);
|
||||||
|
// end debug
|
||||||
|
|
||||||
if (o->parent) {
|
if (o->parent) {
|
||||||
if (o->child) {
|
Thread* previous;
|
||||||
o->parent->child = o->child;
|
for (Thread* p = o->parent->child; p;) {
|
||||||
if (o->peer) {
|
if (p == o) {
|
||||||
o->peer->peer = o->child->peer;
|
if (p == o->parent->child) {
|
||||||
o->child->peer = o->peer;
|
o->parent->child = p->peer;
|
||||||
|
} else {
|
||||||
|
previous->peer = p->peer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
previous = p;
|
||||||
|
p = p->peer;
|
||||||
}
|
}
|
||||||
} else if (o->peer) {
|
}
|
||||||
o->parent->child = o->peer;
|
|
||||||
} else {
|
for (Thread* p = o->child; p;) {
|
||||||
o->parent->child = 0;
|
Thread* next = p->peer;
|
||||||
|
p->peer = o->parent->child;
|
||||||
|
o->parent->child = p;
|
||||||
|
p->parent = o->parent;
|
||||||
|
p = next;
|
||||||
}
|
}
|
||||||
} else if (o->child) {
|
} else if (o->child) {
|
||||||
t->m->rootThread = o->child;
|
t->m->rootThread = o->child;
|
||||||
if (o->peer) {
|
|
||||||
o->peer->peer = o->child->peer;
|
for (Thread* p = o->peer; p;) {
|
||||||
o->child->peer = o->peer;
|
Thread* next = p->peer;
|
||||||
|
p->peer = t->m->rootThread;
|
||||||
|
t->m->rootThread = p;
|
||||||
|
p = next;
|
||||||
}
|
}
|
||||||
} else if (o->peer) {
|
} else if (o->peer) {
|
||||||
t->m->rootThread = o->peer;
|
t->m->rootThread = o->peer;
|
||||||
@ -60,7 +112,13 @@ dispose(Thread* t, Thread* o, bool remove)
|
|||||||
abort(t);
|
abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(t, not find(t->m->rootThread, o));
|
// debug
|
||||||
|
expect(t, not find(t->m->rootThread, o));
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < c; ++i) {
|
||||||
|
expect(t, find(t->m->rootThread, threads[i]));
|
||||||
|
}
|
||||||
|
// end debug
|
||||||
}
|
}
|
||||||
|
|
||||||
o->dispose();
|
o->dispose();
|
||||||
@ -1290,12 +1348,17 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
if (declaredVirtualCount == 0
|
if (declaredVirtualCount == 0
|
||||||
and (classFlags(t, class_) & ACC_INTERFACE) == 0)
|
and (classFlags(t, class_) & ACC_INTERFACE) == 0)
|
||||||
{
|
{
|
||||||
// inherit interface table and virtual table from superclass
|
// inherit virtual table from superclass
|
||||||
|
|
||||||
set(t, class_, ClassInterfaceTable,
|
|
||||||
classInterfaceTable(t, classSuper(t, class_)));
|
|
||||||
|
|
||||||
set(t, class_, ClassVirtualTable, superVirtualTable);
|
set(t, class_, ClassVirtualTable, superVirtualTable);
|
||||||
|
|
||||||
|
if (classInterfaceTable(t, classSuper(t, class_))
|
||||||
|
and arrayLength(t, classInterfaceTable(t, class_))
|
||||||
|
== arrayLength(t, classInterfaceTable(t, classSuper(t, class_))))
|
||||||
|
{
|
||||||
|
// inherit interface table from superclass
|
||||||
|
set(t, class_, ClassInterfaceTable,
|
||||||
|
classInterfaceTable(t, classSuper(t, class_)));
|
||||||
|
}
|
||||||
} else if (virtualCount) {
|
} else if (virtualCount) {
|
||||||
// generate class vtable
|
// generate class vtable
|
||||||
|
|
||||||
@ -1892,6 +1955,7 @@ Thread::init()
|
|||||||
#include "type-java-initializations.cpp"
|
#include "type-java-initializations.cpp"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
peer = parent->child;
|
||||||
parent->child = this;
|
parent->child = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2048,6 +2112,8 @@ enter(Thread* t, Thread::State s)
|
|||||||
case Thread::ExclusiveState: {
|
case Thread::ExclusiveState: {
|
||||||
assert(t, t->m->exclusive == t);
|
assert(t, t->m->exclusive == t);
|
||||||
t->m->exclusive = 0;
|
t->m->exclusive = 0;
|
||||||
|
|
||||||
|
t->m->stateLock->notifyAll(t->systemThread);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Thread::ActiveState: break;
|
case Thread::ActiveState: break;
|
||||||
@ -2632,7 +2698,7 @@ addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
|
|||||||
}
|
}
|
||||||
|
|
||||||
System::Monitor*
|
System::Monitor*
|
||||||
objectMonitor(Thread* t, object o)
|
objectMonitor(Thread* t, object o, bool createNew)
|
||||||
{
|
{
|
||||||
object p = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual);
|
object p = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual);
|
||||||
|
|
||||||
@ -2644,7 +2710,7 @@ objectMonitor(Thread* t, object o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<System::Monitor*>(pointerValue(t, p));
|
return static_cast<System::Monitor*>(pointerValue(t, p));
|
||||||
} else {
|
} else if (createNew) {
|
||||||
PROTECT(t, o);
|
PROTECT(t, o);
|
||||||
|
|
||||||
ENTER(t, Thread::ExclusiveState);
|
ENTER(t, Thread::ExclusiveState);
|
||||||
@ -2665,6 +2731,8 @@ objectMonitor(Thread* t, object o)
|
|||||||
addFinalizer(t, o, removeMonitor);
|
addFinalizer(t, o, removeMonitor);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1998,12 +1998,12 @@ void
|
|||||||
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));
|
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));
|
||||||
|
|
||||||
System::Monitor*
|
System::Monitor*
|
||||||
objectMonitor(Thread* t, object o);
|
objectMonitor(Thread* t, object o, bool createNew);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
acquire(Thread* t, object o)
|
acquire(Thread* t, object o)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, true);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p acquires %p for %x\n",
|
fprintf(stderr, "thread %p acquires %p for %x\n",
|
||||||
@ -2016,7 +2016,7 @@ acquire(Thread* t, object o)
|
|||||||
inline void
|
inline void
|
||||||
release(Thread* t, object o)
|
release(Thread* t, object o)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p releases %p for %x\n",
|
fprintf(stderr, "thread %p releases %p for %x\n",
|
||||||
@ -2029,14 +2029,14 @@ release(Thread* t, object o)
|
|||||||
inline void
|
inline void
|
||||||
wait(Thread* t, object o, int64_t milliseconds)
|
wait(Thread* t, object o, int64_t milliseconds)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p waits %"LLD" millis on %p for %x\n",
|
fprintf(stderr, "thread %p waits %"LLD" millis on %p for %x\n",
|
||||||
t, milliseconds, m, objectHash(t, o));
|
t, milliseconds, m, objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->owner() == t->systemThread) {
|
if (m and m->owner() == t->systemThread) {
|
||||||
ENTER(t, Thread::IdleState);
|
ENTER(t, Thread::IdleState);
|
||||||
|
|
||||||
bool interrupted = m->wait(t->systemThread, milliseconds);
|
bool interrupted = m->wait(t->systemThread, milliseconds);
|
||||||
@ -2058,14 +2058,14 @@ wait(Thread* t, object o, int64_t milliseconds)
|
|||||||
inline void
|
inline void
|
||||||
notify(Thread* t, object o)
|
notify(Thread* t, object o)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p notifies on %p for %x\n",
|
fprintf(stderr, "thread %p notifies on %p for %x\n",
|
||||||
t, m, objectHash(t, o));
|
t, m, objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->owner() == t->systemThread) {
|
if (m and m->owner() == t->systemThread) {
|
||||||
m->notify(t->systemThread);
|
m->notify(t->systemThread);
|
||||||
} else {
|
} else {
|
||||||
t->exception = makeIllegalMonitorStateException(t);
|
t->exception = makeIllegalMonitorStateException(t);
|
||||||
@ -2075,14 +2075,14 @@ notify(Thread* t, object o)
|
|||||||
inline void
|
inline void
|
||||||
notifyAll(Thread* t, object o)
|
notifyAll(Thread* t, object o)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p notifies all on %p for %x\n",
|
fprintf(stderr, "thread %p notifies all on %p for %x\n",
|
||||||
t, m, objectHash(t, o));
|
t, m, objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->owner() == t->systemThread) {
|
if (m and m->owner() == t->systemThread) {
|
||||||
m->notifyAll(t->systemThread);
|
m->notifyAll(t->systemThread);
|
||||||
} else {
|
} else {
|
||||||
t->exception = makeIllegalMonitorStateException(t);
|
t->exception = makeIllegalMonitorStateException(t);
|
||||||
|
@ -80,7 +80,7 @@ class MySystem: public System {
|
|||||||
|
|
||||||
virtual void join() {
|
virtual void join() {
|
||||||
int rv UNUSED = pthread_join(thread, 0);
|
int rv UNUSED = pthread_join(thread, 0);
|
||||||
assert(s, rv == 0);
|
expect(s, rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
@ -150,21 +150,32 @@ class MySystem: public System {
|
|||||||
void append(Thread* t) {
|
void append(Thread* t) {
|
||||||
if (last) {
|
if (last) {
|
||||||
last->next = t;
|
last->next = t;
|
||||||
|
last = t;
|
||||||
} else {
|
} else {
|
||||||
first = last = t;
|
first = last = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(Thread* t) {
|
void remove(Thread* t) {
|
||||||
for (Thread** p = &first; *p;) {
|
Thread* previous;
|
||||||
if (t == *p) {
|
for (Thread* current = first; current;) {
|
||||||
*p = t->next;
|
if (t == current) {
|
||||||
if (last == t) {
|
if (current == first) {
|
||||||
last = 0;
|
first = t->next;
|
||||||
|
} else {
|
||||||
|
previous->next = t->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current == last) {
|
||||||
|
last = previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->next = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
p = &((*p)->next);
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,10 +205,10 @@ class MySystem: public System {
|
|||||||
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
|
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
|
||||||
int rv UNUSED = pthread_cond_timedwait
|
int rv UNUSED = pthread_cond_timedwait
|
||||||
(&(t->condition), &(t->mutex), &ts);
|
(&(t->condition), &(t->mutex), &ts);
|
||||||
assert(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR);
|
expect(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR);
|
||||||
} else {
|
} else {
|
||||||
int rv UNUSED = pthread_cond_wait(&(t->condition), &(t->mutex));
|
int rv UNUSED = pthread_cond_wait(&(t->condition), &(t->mutex));
|
||||||
assert(s, rv == 0 or rv == EINTR);
|
expect(s, rv == 0 or rv == EINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
@ -227,7 +238,7 @@ class MySystem: public System {
|
|||||||
|
|
||||||
t->flags |= Notified;
|
t->flags |= Notified;
|
||||||
int rv UNUSED = pthread_cond_signal(&(t->condition));
|
int rv UNUSED = pthread_cond_signal(&(t->condition));
|
||||||
assert(s, rv == 0);
|
expect(s, rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void notify(System::Thread* context) {
|
virtual void notify(System::Thread* context) {
|
||||||
@ -266,7 +277,7 @@ class MySystem: public System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
assert(s, owner_ == 0);
|
expect(s, owner_ == 0);
|
||||||
pthread_mutex_destroy(&mutex);
|
pthread_mutex_destroy(&mutex);
|
||||||
s->free(this);
|
s->free(this);
|
||||||
}
|
}
|
||||||
@ -283,7 +294,7 @@ class MySystem: public System {
|
|||||||
public:
|
public:
|
||||||
Local(System* s): s(s) {
|
Local(System* s): s(s) {
|
||||||
int r UNUSED = pthread_key_create(&key, 0);
|
int r UNUSED = pthread_key_create(&key, 0);
|
||||||
assert(s, r == 0);
|
expect(s, r == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* get() {
|
virtual void* get() {
|
||||||
@ -292,12 +303,12 @@ class MySystem: public System {
|
|||||||
|
|
||||||
virtual void set(void* p) {
|
virtual void set(void* p) {
|
||||||
int r UNUSED = pthread_setspecific(key, p);
|
int r UNUSED = pthread_setspecific(key, p);
|
||||||
assert(s, r == 0);
|
expect(s, r == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
int r UNUSED = pthread_key_delete(key);
|
int r UNUSED = pthread_key_delete(key);
|
||||||
assert(s, r == 0);
|
expect(s, r == 0);
|
||||||
|
|
||||||
s->free(this);
|
s->free(this);
|
||||||
}
|
}
|
||||||
@ -395,7 +406,7 @@ class MySystem: public System {
|
|||||||
sa.sa_handler = handleSignal;
|
sa.sa_handler = handleSignal;
|
||||||
|
|
||||||
int rv UNUSED = sigaction(InterruptSignal, &sa, 0);
|
int rv UNUSED = sigaction(InterruptSignal, &sa, 0);
|
||||||
assert(this, rv == 0);
|
expect(this, rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool success(Status s) {
|
virtual bool success(Status s) {
|
||||||
@ -455,7 +466,7 @@ class MySystem: public System {
|
|||||||
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r);
|
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r);
|
||||||
r->attach(t);
|
r->attach(t);
|
||||||
int rv UNUSED = pthread_create(&(t->thread), 0, run, r);
|
int rv UNUSED = pthread_create(&(t->thread), 0, run, r);
|
||||||
assert(this, rv == 0);
|
expect(this, rv == 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,21 +151,32 @@ class MySystem: public System {
|
|||||||
void append(Thread* t) {
|
void append(Thread* t) {
|
||||||
if (last) {
|
if (last) {
|
||||||
last->next = t;
|
last->next = t;
|
||||||
|
last = t;
|
||||||
} else {
|
} else {
|
||||||
first = last = t;
|
first = last = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(Thread* t) {
|
void remove(Thread* t) {
|
||||||
for (Thread** p = &first; *p;) {
|
Thread* previous;
|
||||||
if (t == *p) {
|
for (Thread* current = first; current;) {
|
||||||
*p = t->next;
|
if (t == current) {
|
||||||
if (last == t) {
|
if (current == first) {
|
||||||
last = 0;
|
first = t->next;
|
||||||
|
} else {
|
||||||
|
previous->next = t->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current == last) {
|
||||||
|
last = previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->next = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
p = &((*p)->next);
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user