OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [java/] [lang/] [natThread.cc] - Blame information for rev 758

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 758 jeremybenn
// 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
 
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.