OSDN Git Service

* auto-inc-dec.c: Fix pass description, remove apparent
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natThread.cc
1 // natThread.cc - Native part of Thread class.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006, 2007  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12
13 #include <stdlib.h>
14
15 #include <gcj/cni.h>
16 #include <jvm.h>
17 #include <java-threads.h>
18
19 #include <gnu/gcj/RawDataManaged.h>
20 #include <java/lang/Thread.h>
21 #include <java/lang/Thread$State.h>
22 #include <java/lang/Thread$UncaughtExceptionHandler.h>
23 #include <java/lang/ThreadGroup.h>
24 #include <java/lang/IllegalArgumentException.h>
25 #include <java/lang/IllegalThreadStateException.h>
26 #include <java/lang/InterruptedException.h>
27 #include <java/lang/NullPointerException.h>
28
29 #include <jni.h>
30
31 #ifdef INTERPRETER
32 #include <jvmti.h>
33 #include "jvmti-int.h"
34 #endif
35
36 #ifdef ENABLE_JVMPI
37 #include <jvmpi.h>
38 #endif
39
40 \f
41
42 static void finalize_native (jobject ptr);
43
44 // This is called from the constructor to initialize the native side
45 // of the Thread.
46 void
47 java::lang::Thread::initialize_native (void)
48 {
49   natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread));
50   
51   state = JV_NEW;
52   nt->alive_flag = THREAD_DEAD;
53
54   data = (gnu::gcj::RawDataManaged *) nt;
55   
56   // Register a finalizer to clean up the native thread resources.
57   _Jv_RegisterFinalizer (data, finalize_native);
58
59   _Jv_MutexInit (&nt->join_mutex);
60   _Jv_CondInit (&nt->join_cond);
61
62   nt->park_helper.init();
63
64   nt->thread = _Jv_ThreadInitData (this);
65   // FIXME: if JNI_ENV is set we will want to free it.  It is
66   // malloc()d.
67   nt->jni_env = NULL;
68 }
69
70 static void
71 finalize_native (jobject ptr)
72 {
73   natThread *nt = (natThread *) ptr;
74   _Jv_ThreadDestroyData (nt->thread);
75 #ifdef _Jv_HaveCondDestroy
76   _Jv_CondDestroy (&nt->join_cond);
77 #endif
78 #ifdef _Jv_HaveMutexDestroy
79   _Jv_MutexDestroy (&nt->join_mutex);
80 #endif
81   _Jv_FreeJNIEnv((JNIEnv*)nt->jni_env);
82   
83   nt->park_helper.destroy();
84 }
85
86 jint
87 java::lang::Thread::countStackFrames (void)
88 {
89   // NOTE: This is deprecated in JDK 1.2.
90
91   // Old applets still call this method.  Rather than throwing
92   // UnsupportedOperationException we simply fail silently.
93
94   return 0;
95 }
96
97 java::lang::Thread *
98 java::lang::Thread::currentThread (void)
99 {
100   return _Jv_ThreadCurrent ();
101 }
102
103 jboolean
104 java::lang::Thread::holdsLock (jobject obj)
105 {
106   if (!obj)
107     throw new NullPointerException;
108   return !_Jv_ObjectCheckMonitor (obj);
109 }
110
111 jboolean
112 java::lang::Thread::isAlive (void)
113 {
114   natThread *nt = (natThread *) data;
115   return nt->alive_flag != (obj_addr_t)THREAD_DEAD;
116 }
117
118 void
119 java::lang::Thread::interrupt (void)
120 {
121   checkAccess ();
122
123   natThread *nt = (natThread *) data;
124
125   // If a thread is in state ALIVE, we atomically set it to state
126   // SIGNALED and send it a signal.  Once we've sent it the signal, we
127   // set its state back to ALIVE.
128   if (compare_and_swap 
129       (&nt->alive_flag, Thread::THREAD_ALIVE, Thread::THREAD_SIGNALED))
130     {
131       _Jv_ThreadInterrupt (nt->thread);
132       compare_and_swap 
133         (&nt->alive_flag, THREAD_SIGNALED, Thread::THREAD_ALIVE);
134
135       // Even though we've interrupted this thread, it might still be
136       // parked.
137       nt->park_helper.unpark ();
138     }
139 }
140
141 void
142 java::lang::Thread::join (jlong millis, jint nanos)
143 {
144   if (millis < 0 || nanos < 0 || nanos > 999999)
145     throw new IllegalArgumentException;
146
147   Thread *current = currentThread ();
148
149   // Here `NT' is the native structure for the thread we are trying to join.
150   natThread *nt = (natThread *) data;
151
152   // Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
153   // the timeout to occur. 
154   _Jv_MutexLock (&nt->join_mutex);
155   if (! isAlive ())
156     {
157       _Jv_MutexUnlock (&nt->join_mutex);
158       return;
159     }
160   _Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
161   _Jv_MutexUnlock (&nt->join_mutex);
162
163   if (current->isInterrupted (true))
164     throw new InterruptedException;
165 }
166
167 void
168 java::lang::Thread::resume (void)
169 {
170   checkAccess ();
171
172   // Old applets still call this method.  Rather than throwing
173   // UnsupportedOperationException we simply fail silently.
174 }
175
176 void
177 java::lang::Thread::setPriority (jint newPriority)
178 {
179   checkAccess ();
180   if (newPriority < MIN_PRIORITY || newPriority > MAX_PRIORITY)
181     throw new IllegalArgumentException;
182
183   jint gmax = group->getMaxPriority();
184   if (newPriority > gmax)
185     newPriority = gmax;
186
187   priority = newPriority;
188   natThread *nt = (natThread *) data;
189   _Jv_ThreadSetPriority (nt->thread, priority);
190 }
191
192 void
193 java::lang::Thread::sleep (jlong millis, jint nanos)
194 {
195   if (millis < 0 || nanos < 0 || nanos > 999999)
196     throw new IllegalArgumentException;
197
198   if (millis == 0 && nanos == 0)
199     ++nanos;
200
201   Thread *current = currentThread ();
202
203   // We use a condition variable to implement sleeping so that an
204   // interrupt can wake us up. 
205   natThread *nt = (natThread *) current->data;
206   _Jv_MutexLock (&nt->join_mutex);
207   _Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
208   _Jv_MutexUnlock (&nt->join_mutex);
209
210   if (current->isInterrupted (true))
211     throw new InterruptedException;
212 }
213
214 void
215 java::lang::Thread::finish_ ()
216 {
217   __sync_synchronize();
218   natThread *nt = (natThread *) data;
219   
220   nt->park_helper.deactivate ();
221   group->removeThread (this);
222
223 #ifdef INTERPRETER
224   if (JVMTI_REQUESTED_EVENT (ThreadEnd))
225     _Jv_JVMTI_PostEvent (JVMTI_EVENT_THREAD_END, this, nt->jni_env);
226 #endif
227
228 #ifdef ENABLE_JVMPI  
229   if (_Jv_JVMPI_Notify_THREAD_END)
230     {
231       JVMPI_Event event;
232
233       event.event_type = JVMPI_EVENT_THREAD_END;
234       event.env_id = _Jv_GetCurrentJNIEnv ();
235
236       _Jv_DisableGC ();
237       (*_Jv_JVMPI_Notify_THREAD_END) (&event);
238       _Jv_EnableGC ();
239     }
240 #endif
241
242   // If a method cache was created, free it.
243   _Jv_FreeMethodCache();
244
245   // Clear out thread locals.
246   locals = NULL;
247
248   // Signal any threads that are waiting to join() us.
249   _Jv_MutexLock (&nt->join_mutex);
250
251   {
252     JvSynchronize sync (this);
253     nt->alive_flag = THREAD_DEAD;
254     state = JV_TERMINATED;
255   }
256
257   _Jv_CondNotifyAll (&nt->join_cond, &nt->join_mutex);
258   _Jv_MutexUnlock (&nt->join_mutex);  
259 }
260
261 // Run once at thread startup, either when thread is attached or when 
262 // _Jv_ThreadRun is called.
263 static void
264 _Jv_NotifyThreadStart (java::lang::Thread* thread)
265 {
266 #ifdef INTERPRETER
267   if (JVMTI_REQUESTED_EVENT (ThreadStart))
268     {
269       natThread *nt = reinterpret_cast<natThread *> (thread->data);
270       _Jv_JVMTI_PostEvent (JVMTI_EVENT_THREAD_START, thread, nt->jni_env);
271     }
272 #endif
273
274 #ifdef ENABLE_JVMPI
275       if (_Jv_JVMPI_Notify_THREAD_START)
276         {
277           JVMPI_Event event;
278           
279           jstring thread_name = thread->getName ();
280           jstring group_name = NULL, parent_name = NULL;
281           java::lang::ThreadGroup *group = thread->getThreadGroup ();
282
283           if (group)
284             {
285               group_name = group->getName ();
286               group = group->getParent ();
287               
288               if (group)
289                 parent_name = group->getName ();
290             }
291           
292           int thread_len = thread_name ? JvGetStringUTFLength (thread_name) : 0;
293           int group_len = group_name ? JvGetStringUTFLength (group_name) : 0;
294           int parent_len = parent_name ? JvGetStringUTFLength (parent_name) : 0;
295           
296           char thread_chars[thread_len + 1];
297           char group_chars[group_len + 1];
298           char parent_chars[parent_len + 1];
299           
300           if (thread_name)
301             JvGetStringUTFRegion (thread_name, 0, 
302                                   thread_name->length(), thread_chars);
303           if (group_name)
304             JvGetStringUTFRegion (group_name, 0, 
305                                   group_name->length(), group_chars);
306           if (parent_name)
307             JvGetStringUTFRegion (parent_name, 0, 
308                                   parent_name->length(), parent_chars);
309           
310           thread_chars[thread_len] = '\0';
311           group_chars[group_len] = '\0';
312           parent_chars[parent_len] = '\0';
313           
314           event.event_type = JVMPI_EVENT_THREAD_START;
315           event.env_id = NULL;
316           event.u.thread_start.thread_name = thread_chars;
317           event.u.thread_start.group_name = group_chars;
318           event.u.thread_start.parent_name = parent_chars;
319           event.u.thread_start.thread_id = (jobjectID) thread;
320           event.u.thread_start.thread_env_id = _Jv_GetCurrentJNIEnv ();
321           
322           _Jv_DisableGC ();
323           (*_Jv_JVMPI_Notify_THREAD_START) (&event);
324           _Jv_EnableGC ();
325         }
326 #endif
327 }
328
329 void
330 _Jv_ThreadRun (java::lang::Thread* thread)
331 {
332   try
333     {
334       _Jv_NotifyThreadStart (thread);
335       thread->run ();
336     }
337   catch (java::lang::Throwable *t)
338     {
339       // Uncaught exceptions are forwarded to the ThreadGroup.  If
340       // this results in an uncaught exception, that is ignored.
341       try
342         {
343           thread->getUncaughtExceptionHandler()->uncaughtException (thread, t);
344         }
345       catch (java::lang::Throwable *f)
346         {
347           // Nothing.
348         }
349     }
350
351   thread->finish_ ();
352 }
353
354 _Jv_Thread_t*
355 _Jv_ThreadGetData (java::lang::Thread* thread)
356 {
357   natThread* nt = (natThread*) thread->data;
358   return nt->thread;
359 }
360
361 void
362 java::lang::Thread::start (void)
363 {
364   JvSynchronize sync (this);
365
366   // Its illegal to re-start() a thread, even if its dead.
367   if (!startable_flag)
368     throw new IllegalThreadStateException;
369
370   natThread *nt = (natThread *) data;
371   nt->alive_flag = THREAD_ALIVE;
372   startable_flag = false;
373   state = JV_RUNNABLE;
374   _Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &_Jv_ThreadRun);
375 }
376
377 void
378 java::lang::Thread::stop (java::lang::Throwable *)
379 {
380   checkAccess ();
381
382   // Old applets still call this method.  Rather than throwing
383   // UnsupportedOperationException we simply fail silently.
384 }
385
386 void
387 java::lang::Thread::suspend (void)
388 {
389   checkAccess ();
390
391   // Old applets still call this method.  Rather than throwing
392   // UnsupportedOperationException we simply fail silently.
393 }
394
395 static int nextThreadNumber = 0;
396
397 jstring
398 java::lang::Thread::gen_name (void)
399 {
400   jint i;
401   jclass sync = &java::lang::Thread::class$;
402   {
403     JvSynchronize dummy(sync); 
404     i = ++nextThreadNumber;
405   }
406
407   // Use an array large enough for "-2147483648"; i.e. 11 chars, + "Thread-".
408   jchar buffer[7+11];
409   jchar *bufend = (jchar *) ((char *) buffer + sizeof(buffer));
410   i = _Jv_FormatInt (bufend, i);
411   jchar *ptr = bufend - i;
412   // Prepend "Thread-".
413   *--ptr = '-';
414   *--ptr = 'd';
415   *--ptr = 'a';
416   *--ptr = 'e';
417   *--ptr = 'r';
418   *--ptr = 'h';
419   *--ptr = 'T';
420   return JvNewString (ptr, bufend - ptr);
421 }
422
423 void
424 java::lang::Thread::yield (void)
425 {
426   _Jv_ThreadYield ();
427 }
428
429 ::java::lang::Thread$State *
430 java::lang::Thread::getState()
431 {
432   _Jv_InitClass(&::java::lang::Thread$State::class$);
433
434   switch (state)
435     {
436     case JV_BLOCKED:
437       return ::java::lang::Thread$State::BLOCKED;
438     case JV_NEW:
439       return ::java::lang::Thread$State::NEW;
440
441     case JV_RUNNABLE:
442       return ::java::lang::Thread$State::RUNNABLE;
443     case JV_TERMINATED:
444       return ::java::lang::Thread$State::TERMINATED;
445     case JV_TIMED_WAITING:
446       return ::java::lang::Thread$State::TIMED_WAITING;
447     case JV_WAITING:
448       return ::java::lang::Thread$State::WAITING;
449     }
450
451   // We don't really need a default, but this makes the compiler
452   // happy.
453   return ::java::lang::Thread$State::RUNNABLE;
454 }
455
456 JNIEnv *
457 _Jv_GetCurrentJNIEnv ()
458 {
459   java::lang::Thread *t = _Jv_ThreadCurrent ();
460   if (t == NULL)
461     return NULL;
462   return ((natThread *) t->data)->jni_env;
463 }
464
465 void
466 _Jv_SetCurrentJNIEnv (JNIEnv *env)
467 {
468   java::lang::Thread *t = _Jv_ThreadCurrent ();
469   JvAssert (t != NULL);
470   ((natThread *) t->data)->jni_env = env;
471 }
472
473 // Attach the current native thread to an existing (but unstarted) Thread 
474 // object. Does not register thread with the garbage collector.
475 // Returns -1 on failure, 0 upon success.
476 jint
477 _Jv_AttachCurrentThread(java::lang::Thread* thread)
478 {
479   JvSynchronize sync (thread);
480   if (thread == NULL || thread->startable_flag == false)
481     return -1;
482   thread->startable_flag = false;
483   natThread *nt = (natThread *) thread->data;
484   nt->alive_flag = ::java::lang::Thread::THREAD_ALIVE;
485   thread->state = JV_RUNNABLE;
486   _Jv_ThreadRegister (nt->thread);
487   return 0;
488 }
489
490 java::lang::Thread*
491 _Jv_AttachCurrentThread(jstring name, java::lang::ThreadGroup* group)
492 {
493   // Register thread with GC before attempting any allocations.
494   _Jv_GCAttachThread ();
495   java::lang::Thread *thread = _Jv_ThreadCurrent ();
496   if (thread != NULL)
497     return thread;
498   if (name == NULL)
499     name = java::lang::Thread::gen_name ();
500   thread = new java::lang::Thread (NULL, group, NULL, name, false);
501   _Jv_AttachCurrentThread (thread);
502   _Jv_NotifyThreadStart (thread);
503   return thread;
504 }
505
506 java::lang::Thread*
507 _Jv_AttachCurrentThreadAsDaemon(jstring name, java::lang::ThreadGroup* group)
508 {
509   java::lang::Thread *thread = _Jv_ThreadCurrent ();
510   if (thread != NULL)
511     return thread;
512   if (name == NULL)
513     name = java::lang::Thread::gen_name ();
514   thread = new java::lang::Thread (NULL, group, NULL, name, false);
515   thread->setDaemon (true);
516   _Jv_AttachCurrentThread (thread);
517   _Jv_NotifyThreadStart (thread);
518   return thread;
519 }
520
521 jint
522 _Jv_DetachCurrentThread (void)
523 {
524   java::lang::Thread *t = _Jv_ThreadCurrent ();
525   if (t == NULL)
526     return -1;
527
528   _Jv_ThreadUnRegister ();
529   _Jv_GCDetachThread ();
530   // Release the monitors.
531   t->finish_ ();
532
533   return 0;
534 }