Mark as release
[official-gcc.git] / libjava / java / lang / natThread.cc
blobfacce30fa2e259a177e065ee594180e8a3da05ae
1 // natThread.cc - Native part of Thread class.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 #include <config.h>
13 #include <stdlib.h>
15 #include <gcj/cni.h>
16 #include <jvm.h>
17 #include <java-threads.h>
19 #include <gnu/gcj/RawDataManaged.h>
20 #include <java/lang/Thread.h>
21 #include <java/lang/ThreadGroup.h>
22 #include <java/lang/IllegalArgumentException.h>
23 #include <java/lang/IllegalThreadStateException.h>
24 #include <java/lang/InterruptedException.h>
25 #include <java/lang/NullPointerException.h>
27 #include <jni.h>
29 #ifdef ENABLE_JVMPI
30 #include <jvmpi.h>
31 #endif
35 // This structure is used to represent all the data the native side
36 // needs. An object of this type is assigned to the `data' member of
37 // the Thread class.
38 struct natThread
40 // These are used to interrupt sleep and join calls. We can share a
41 // condition variable here since it only ever gets notified when the thread
42 // exits.
43 _Jv_Mutex_t join_mutex;
44 _Jv_ConditionVariable_t join_cond;
46 // This is private data for the thread system layer.
47 _Jv_Thread_t *thread;
49 // Each thread has its own JNI object.
50 JNIEnv *jni_env;
53 static void finalize_native (jobject ptr);
55 // This is called from the constructor to initialize the native side
56 // of the Thread.
57 void
58 java::lang::Thread::initialize_native (void)
60 natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread));
62 data = (gnu::gcj::RawDataManaged *) nt;
64 // Register a finalizer to clean up the native thread resources.
65 _Jv_RegisterFinalizer (data, finalize_native);
67 _Jv_MutexInit (&nt->join_mutex);
68 _Jv_CondInit (&nt->join_cond);
69 nt->thread = _Jv_ThreadInitData (this);
70 // FIXME: if JNI_ENV is set we will want to free it. It is
71 // malloc()d.
72 nt->jni_env = NULL;
75 static void
76 finalize_native (jobject ptr)
78 natThread *nt = (natThread *) ptr;
79 _Jv_ThreadDestroyData (nt->thread);
80 #ifdef _Jv_HaveCondDestroy
81 _Jv_CondDestroy (&nt->join_cond);
82 #endif
83 #ifdef _Jv_HaveMutexDestroy
84 _Jv_MutexDestroy (&nt->join_mutex);
85 #endif
86 _Jv_FreeJNIEnv(nt->jni_env);
89 jint
90 java::lang::Thread::countStackFrames (void)
92 // NOTE: This is deprecated in JDK 1.2.
94 // Old applets still call this method. Rather than throwing
95 // UnsupportedOperationException we simply fail silently.
97 return 0;
100 java::lang::Thread *
101 java::lang::Thread::currentThread (void)
103 return _Jv_ThreadCurrent ();
106 jboolean
107 java::lang::Thread::holdsLock (jobject obj)
109 if (!obj)
110 throw new NullPointerException;
111 return !_Jv_ObjectCheckMonitor (obj);
114 void
115 java::lang::Thread::interrupt (void)
117 checkAccess ();
118 natThread *nt = (natThread *) data;
119 JvSynchronize sync (this);
120 if (alive_flag)
121 _Jv_ThreadInterrupt (nt->thread);
124 void
125 java::lang::Thread::join (jlong millis, jint nanos)
127 if (millis < 0 || nanos < 0 || nanos > 999999)
128 throw new IllegalArgumentException;
130 Thread *current = currentThread ();
132 // Here `NT' is the native structure for the thread we are trying to join.
133 natThread *nt = (natThread *) data;
135 // Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
136 // the timeout to occur.
137 _Jv_MutexLock (&nt->join_mutex);
138 if (! isAlive ())
140 _Jv_MutexUnlock (&nt->join_mutex);
141 return;
143 _Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
144 _Jv_MutexUnlock (&nt->join_mutex);
146 if (current->isInterrupted (true))
147 throw new InterruptedException;
150 void
151 java::lang::Thread::resume (void)
153 checkAccess ();
155 // Old applets still call this method. Rather than throwing
156 // UnsupportedOperationException we simply fail silently.
159 void
160 java::lang::Thread::setPriority (jint newPriority)
162 checkAccess ();
163 if (newPriority < MIN_PRIORITY || newPriority > MAX_PRIORITY)
164 throw new IllegalArgumentException;
166 jint gmax = group->getMaxPriority();
167 if (newPriority > gmax)
168 newPriority = gmax;
170 priority = newPriority;
171 natThread *nt = (natThread *) data;
172 _Jv_ThreadSetPriority (nt->thread, priority);
175 void
176 java::lang::Thread::sleep (jlong millis, jint nanos)
178 if (millis < 0 || nanos < 0 || nanos > 999999)
179 throw new IllegalArgumentException;
181 if (millis == 0 && nanos == 0)
182 ++nanos;
184 Thread *current = currentThread ();
186 // We use a condition variable to implement sleeping so that an
187 // interrupt can wake us up.
188 natThread *nt = (natThread *) current->data;
189 _Jv_MutexLock (&nt->join_mutex);
190 _Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
191 _Jv_MutexUnlock (&nt->join_mutex);
193 if (current->isInterrupted (true))
194 throw new InterruptedException;
197 void
198 java::lang::Thread::finish_ ()
200 natThread *nt = (natThread *) data;
202 group->removeThread (this);
204 #ifdef ENABLE_JVMPI
205 if (_Jv_JVMPI_Notify_THREAD_END)
207 JVMPI_Event event;
209 event.event_type = JVMPI_EVENT_THREAD_END;
210 event.env_id = _Jv_GetCurrentJNIEnv ();
212 _Jv_DisableGC ();
213 (*_Jv_JVMPI_Notify_THREAD_END) (&event);
214 _Jv_EnableGC ();
216 #endif
218 // If a method cache was created, free it.
219 _Jv_FreeMethodCache();
221 // Clear out thread locals.
222 locals = NULL;
224 // Signal any threads that are waiting to join() us.
225 _Jv_MutexLock (&nt->join_mutex);
228 JvSynchronize sync (this);
229 alive_flag = false;
232 _Jv_CondNotifyAll (&nt->join_cond, &nt->join_mutex);
233 _Jv_MutexUnlock (&nt->join_mutex);
236 // Run once at thread startup, either when thread is attached or when
237 // _Jv_ThreadRun is called.
238 static void
239 _Jv_NotifyThreadStart (java::lang::Thread* thread)
241 #ifdef ENABLE_JVMPI
242 if (_Jv_JVMPI_Notify_THREAD_START)
244 JVMPI_Event event;
246 jstring thread_name = thread->getName ();
247 jstring group_name = NULL, parent_name = NULL;
248 java::lang::ThreadGroup *group = thread->getThreadGroup ();
250 if (group)
252 group_name = group->getName ();
253 group = group->getParent ();
255 if (group)
256 parent_name = group->getName ();
259 int thread_len = thread_name ? JvGetStringUTFLength (thread_name) : 0;
260 int group_len = group_name ? JvGetStringUTFLength (group_name) : 0;
261 int parent_len = parent_name ? JvGetStringUTFLength (parent_name) : 0;
263 char thread_chars[thread_len + 1];
264 char group_chars[group_len + 1];
265 char parent_chars[parent_len + 1];
267 if (thread_name)
268 JvGetStringUTFRegion (thread_name, 0,
269 thread_name->length(), thread_chars);
270 if (group_name)
271 JvGetStringUTFRegion (group_name, 0,
272 group_name->length(), group_chars);
273 if (parent_name)
274 JvGetStringUTFRegion (parent_name, 0,
275 parent_name->length(), parent_chars);
277 thread_chars[thread_len] = '\0';
278 group_chars[group_len] = '\0';
279 parent_chars[parent_len] = '\0';
281 event.event_type = JVMPI_EVENT_THREAD_START;
282 event.env_id = NULL;
283 event.u.thread_start.thread_name = thread_chars;
284 event.u.thread_start.group_name = group_chars;
285 event.u.thread_start.parent_name = parent_chars;
286 event.u.thread_start.thread_id = (jobjectID) thread;
287 event.u.thread_start.thread_env_id = _Jv_GetCurrentJNIEnv ();
289 _Jv_DisableGC ();
290 (*_Jv_JVMPI_Notify_THREAD_START) (&event);
291 _Jv_EnableGC ();
293 #endif
296 void
297 _Jv_ThreadRun (java::lang::Thread* thread)
301 _Jv_NotifyThreadStart (thread);
302 thread->run ();
304 catch (java::lang::Throwable *t)
306 // Uncaught exceptions are forwarded to the ThreadGroup. If
307 // this results in an uncaught exception, that is ignored.
310 thread->group->uncaughtException (thread, t);
312 catch (java::lang::Throwable *f)
314 // Nothing.
318 thread->finish_ ();
321 _Jv_Thread_t*
322 _Jv_ThreadGetData (java::lang::Thread* thread)
324 natThread* nt = (natThread*) thread->data;
325 return nt->thread;
328 void
329 java::lang::Thread::start (void)
331 JvSynchronize sync (this);
333 // Its illegal to re-start() a thread, even if its dead.
334 if (!startable_flag)
335 throw new IllegalThreadStateException;
337 alive_flag = true;
338 startable_flag = false;
339 natThread *nt = (natThread *) data;
340 _Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &_Jv_ThreadRun);
343 void
344 java::lang::Thread::stop (java::lang::Throwable *)
346 checkAccess ();
348 // Old applets still call this method. Rather than throwing
349 // UnsupportedOperationException we simply fail silently.
352 void
353 java::lang::Thread::suspend (void)
355 checkAccess ();
357 // Old applets still call this method. Rather than throwing
358 // UnsupportedOperationException we simply fail silently.
361 static int nextThreadNumber = 0;
363 jstring
364 java::lang::Thread::gen_name (void)
366 jint i;
367 jclass sync = &java::lang::Thread::class$;
369 JvSynchronize dummy(sync);
370 i = ++nextThreadNumber;
373 // Use an array large enough for "-2147483648"; i.e. 11 chars, + "Thread-".
374 jchar buffer[7+11];
375 jchar *bufend = (jchar *) ((char *) buffer + sizeof(buffer));
376 i = _Jv_FormatInt (bufend, i);
377 jchar *ptr = bufend - i;
378 // Prepend "Thread-".
379 *--ptr = '-';
380 *--ptr = 'd';
381 *--ptr = 'a';
382 *--ptr = 'e';
383 *--ptr = 'r';
384 *--ptr = 'h';
385 *--ptr = 'T';
386 return JvNewString (ptr, bufend - ptr);
389 void
390 java::lang::Thread::yield (void)
392 _Jv_ThreadYield ();
395 JNIEnv *
396 _Jv_GetCurrentJNIEnv ()
398 java::lang::Thread *t = _Jv_ThreadCurrent ();
399 if (t == NULL)
400 return NULL;
401 return ((natThread *) t->data)->jni_env;
404 void
405 _Jv_SetCurrentJNIEnv (JNIEnv *env)
407 java::lang::Thread *t = _Jv_ThreadCurrent ();
408 JvAssert (t != NULL);
409 ((natThread *) t->data)->jni_env = env;
412 // Attach the current native thread to an existing (but unstarted) Thread
413 // object. Does not register thread with the garbage collector.
414 // Returns -1 on failure, 0 upon success.
415 jint
416 _Jv_AttachCurrentThread(java::lang::Thread* thread)
418 JvSynchronize sync (thread);
419 if (thread == NULL || thread->startable_flag == false)
420 return -1;
421 thread->startable_flag = false;
422 thread->alive_flag = true;
423 natThread *nt = (natThread *) thread->data;
424 _Jv_ThreadRegister (nt->thread);
425 return 0;
428 java::lang::Thread*
429 _Jv_AttachCurrentThread(jstring name, java::lang::ThreadGroup* group)
431 // Register thread with GC before attempting any allocations.
432 _Jv_GCAttachThread ();
433 java::lang::Thread *thread = _Jv_ThreadCurrent ();
434 if (thread != NULL)
435 return thread;
436 if (name == NULL)
437 name = java::lang::Thread::gen_name ();
438 thread = new java::lang::Thread (NULL, group, NULL, name);
439 _Jv_AttachCurrentThread (thread);
440 _Jv_NotifyThreadStart (thread);
441 return thread;
444 java::lang::Thread*
445 _Jv_AttachCurrentThreadAsDaemon(jstring name, java::lang::ThreadGroup* group)
447 java::lang::Thread *thread = _Jv_ThreadCurrent ();
448 if (thread != NULL)
449 return thread;
450 if (name == NULL)
451 name = java::lang::Thread::gen_name ();
452 thread = new java::lang::Thread (NULL, group, NULL, name);
453 thread->setDaemon (true);
454 _Jv_AttachCurrentThread (thread);
455 _Jv_NotifyThreadStart (thread);
456 return thread;
459 jint
460 _Jv_DetachCurrentThread (void)
462 java::lang::Thread *t = _Jv_ThreadCurrent ();
463 if (t == NULL)
464 return -1;
466 _Jv_ThreadUnRegister ();
467 _Jv_GCDetachThread ();
468 // Release the monitors.
469 t->finish_ ();
471 return 0;