// posix-threads.cc - interface between libjava and POSIX threads.
-/* Copyright (C) 1998, 1999 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
// If we're using the Boehm GC, then we need to override some of the
// thread primitives. This is fairly gross.
#ifdef HAVE_BOEHM_GC
-extern "C"
-{
-#include <gcconfig.h>
#include <gc.h>
-};
#endif /* HAVE_BOEHM_GC */
#include <stdlib.h>
_Jv_Thread_t *current = _Jv_ThreadCurrentData ();
java::lang::Thread *current_obj = _Jv_ThreadCurrent ();
+ pthread_mutex_lock (¤t->wait_mutex);
+
+ // Now that we hold the wait mutex, check if this thread has been
+ // interrupted already.
+ if (current_obj->interrupt_flag)
+ {
+ pthread_mutex_unlock (¤t->wait_mutex);
+ return _JV_INTERRUPTED;
+ }
+
// Add this thread to the cv's wait set.
current->next = NULL;
}
}
- pthread_mutex_lock (¤t->wait_mutex);
-
- // Now that we hold the wait mutex, check if this thread has been
- // interrupted already.
- if (current_obj->interrupt_flag)
- {
- pthread_mutex_unlock (¤t->wait_mutex);
- return _JV_INTERRUPTED;
- }
-
// Record the current lock depth, so it can be restored when we re-aquire it.
int count = mu->count;
else
r = pthread_cond_timedwait (¤t->wait_cond, ¤t->wait_mutex,
&ts);
-
+
// In older glibc's (prior to 2.1.3), the cond_wait functions may
// spuriously wake up on a signal. Catch that here.
if (r != EINTR)
done_sleeping = true;
}
- // Check for an interrupt *before* unlocking the wait mutex.
+ // Check for an interrupt *before* releasing the wait mutex.
jboolean interrupted = current_obj->interrupt_flag;
pthread_mutex_unlock (¤t->wait_mutex);
sigaction (INTR, &act, NULL);
}
-void
-_Jv_ThreadInitData (_Jv_Thread_t **data, java::lang::Thread *obj)
+_Jv_Thread_t *
+_Jv_ThreadInitData (java::lang::Thread *obj)
{
- _Jv_Thread_t *info = new _Jv_Thread_t;
- info->flags = 0;
- info->thread_obj = obj;
+ _Jv_Thread_t *data = (_Jv_Thread_t *) _Jv_Malloc (sizeof (_Jv_Thread_t));
+ data->flags = 0;
+ data->thread_obj = obj;
- pthread_mutex_init (&info->wait_mutex, NULL);
- pthread_cond_init (&info->wait_cond, NULL);
+ pthread_mutex_init (&data->wait_mutex, NULL);
+ pthread_cond_init (&data->wait_cond, NULL);
- // FIXME register a finalizer for INFO here.
- // FIXME also must mark INFO somehow.
+ return data;
+}
- *data = info;
+void
+_Jv_ThreadDestroyData (_Jv_Thread_t *data)
+{
+ pthread_mutex_destroy (&data->wait_mutex);
+ pthread_cond_destroy (&data->wait_cond);
+ _Jv_Free ((void *)data);
}
void
}
}
+void
+_Jv_ThreadRegister (_Jv_Thread_t *data)
+{
+ pthread_setspecific (_Jv_ThreadKey, data->thread_obj);
+ pthread_setspecific (_Jv_ThreadDataKey, data);
+
+ // glibc 2.1.3 doesn't set the value of `thread' until after start_routine
+ // is called. Since it may need to be accessed from the new thread, work
+ // around the potential race here by explicitly setting it again.
+ data->thread = pthread_self ();
+
+# ifdef SLOW_PTHREAD_SELF
+ // Clear all self cache slots that might be needed by this thread.
+ int dummy;
+ int low_index = SC_INDEX(&dummy) + SC_CLEAR_MIN;
+ int high_index = SC_INDEX(&dummy) + SC_CLEAR_MAX;
+ for (int i = low_index; i <= high_index; ++i)
+ {
+ int current_index = i;
+ if (current_index < 0)
+ current_index += SELF_CACHE_SIZE;
+ if (current_index >= SELF_CACHE_SIZE)
+ current_index -= SELF_CACHE_SIZE;
+ _Jv_self_cache[current_index].high_sp_bits = BAD_HIGH_SP_VALUE;
+ }
+# endif
+}
+
+void
+_Jv_ThreadUnRegister ()
+{
+ pthread_setspecific (_Jv_ThreadKey, NULL);
+ pthread_setspecific (_Jv_ThreadDataKey, NULL);
+}
+
// This function is called when a thread is started. We don't arrange
// to call the `run' method directly, because this function must
// return a value.
{
struct starter *info = (struct starter *) x;
- pthread_setspecific (_Jv_ThreadKey, info->data->thread_obj);
- pthread_setspecific (_Jv_ThreadDataKey, info->data);
-
- // glibc 2.1.3 doesn't set the value of `thread' until after start_routine
- // is called. Since it may need to be accessed from the new thread, work
- // around the potential race here by explicitly setting it again.
- info->data->thread = pthread_self ();
+ _Jv_ThreadRegister (info->data);
info->method (info->data->thread_obj);
-
+
if (! (info->data->flags & FLAG_DAEMON))
{
pthread_mutex_lock (&daemon_mutex);
pthread_cond_signal (&daemon_cond);
pthread_mutex_unlock (&daemon_mutex);
}
-
-#ifndef LINUX_THREADS
- // Clean up. These calls do nothing on Linux.
- pthread_mutex_destroy (&info->data->wait_mutex);
- pthread_cond_destroy (&info->data->wait_cond);
-#endif /* ! LINUX_THREADS */
return NULL;
}
pthread_attr_init (&attr);
pthread_attr_setschedparam (&attr, ¶m);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
- // FIXME: handle marking the info object for GC.
info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter));
info->method = meth;
info->data = data;
if (r)
{
const char* msg = "Cannot create additional threads";
- JvThrow (new java::lang::OutOfMemoryError (JvNewStringUTF (msg)));
+ throw new java::lang::OutOfMemoryError (JvNewStringUTF (msg));
}
}
pthread_cond_wait (&daemon_cond, &daemon_mutex);
pthread_mutex_unlock (&daemon_mutex);
}
+
+#if defined(SLOW_PTHREAD_SELF)
+
+// Support for pthread_self() lookup cache.
+
+volatile self_cache_entry _Jv_self_cache[SELF_CACHE_SIZE];
+
+
+_Jv_ThreadId_t
+_Jv_ThreadSelf_out_of_line(volatile self_cache_entry *sce, size_t high_sp_bits)
+{
+ pthread_t self = pthread_self();
+ // The ordering between the following writes matters.
+ // On Alpha, we probably need a memory barrier in the middle.
+ sce -> high_sp_bits = high_sp_bits;
+ sce -> self = self;
+ return self;
+}
+
+#endif /* SLOW_PTHREAD_SELF */