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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [java/] [lang/] [natThread.cc] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
// natThread.cc - Native part of Thread class.
2
 
3
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006  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/ThreadGroup.h>
22
#include <java/lang/IllegalArgumentException.h>
23
#include <java/lang/UnsupportedOperationException.h>
24
#include <java/lang/IllegalThreadStateException.h>
25
#include <java/lang/InterruptedException.h>
26
#include <java/lang/NullPointerException.h>
27
 
28
#include <jni.h>
29
 
30
#ifdef ENABLE_JVMPI
31
#include <jvmpi.h>
32
#endif
33
 
34
 
35
 
36
// This structure is used to represent all the data the native side
37
// needs.  An object of this type is assigned to the `data' member of
38
// the Thread class.
39
struct natThread
40
{
41
  // These are used to interrupt sleep and join calls.  We can share a
42
  // condition variable here since it only ever gets notified when the thread
43
  // exits.
44
  _Jv_Mutex_t join_mutex;
45
  _Jv_ConditionVariable_t join_cond;
46
 
47
  // This is private data for the thread system layer.
48
  _Jv_Thread_t *thread;
49
 
50
  // Each thread has its own JNI object.
51
  JNIEnv *jni_env;
52
};
53
 
54
static void finalize_native (jobject ptr);
55
 
56
// This is called from the constructor to initialize the native side
57
// of the Thread.
58
void
59
java::lang::Thread::initialize_native (void)
60
{
61
  natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread));
62
 
63
  data = (gnu::gcj::RawDataManaged *) nt;
64
 
65
  // Register a finalizer to clean up the native thread resources.
66
  _Jv_RegisterFinalizer (data, finalize_native);
67
 
68
  _Jv_MutexInit (&nt->join_mutex);
69
  _Jv_CondInit (&nt->join_cond);
70
  nt->thread = _Jv_ThreadInitData (this);
71
  // FIXME: if JNI_ENV is set we will want to free it.  It is
72
  // malloc()d.
73
  nt->jni_env = NULL;
74
}
75
 
76
static void
77
finalize_native (jobject ptr)
78
{
79
  natThread *nt = (natThread *) ptr;
80
  _Jv_ThreadDestroyData (nt->thread);
81
#ifdef _Jv_HaveCondDestroy
82
  _Jv_CondDestroy (&nt->join_cond);
83
#endif
84
#ifdef _Jv_HaveMutexDestroy
85
  _Jv_MutexDestroy (&nt->join_mutex);
86
#endif
87
  _Jv_FreeJNIEnv(nt->jni_env);
88
}
89
 
90
jint
91
java::lang::Thread::countStackFrames (void)
92
{
93
  // NOTE: This is deprecated in JDK 1.2.
94
  throw new UnsupportedOperationException
95
    (JvNewStringLatin1 ("Thread.countStackFrames unimplemented"));
96
  return 0;
97
}
98
 
99
java::lang::Thread *
100
java::lang::Thread::currentThread (void)
101
{
102
  return _Jv_ThreadCurrent ();
103
}
104
 
105
jboolean
106
java::lang::Thread::holdsLock (jobject obj)
107
{
108
  if (!obj)
109
    throw new NullPointerException;
110
  return !_Jv_ObjectCheckMonitor (obj);
111
}
112
 
113
void
114
java::lang::Thread::interrupt (void)
115
{
116
  checkAccess ();
117
  natThread *nt = (natThread *) data;
118
  JvSynchronize sync (this);
119
  if (alive_flag)
120
    _Jv_ThreadInterrupt (nt->thread);
121
}
122
 
123
void
124
java::lang::Thread::join (jlong millis, jint nanos)
125
{
126
  if (millis < 0 || nanos < 0 || nanos > 999999)
127
    throw new IllegalArgumentException;
128
 
129
  Thread *current = currentThread ();
130
 
131
  // Here `NT' is the native structure for the thread we are trying to join.
132
  natThread *nt = (natThread *) data;
133
 
134
  // Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
135
  // the timeout to occur. 
136
  _Jv_MutexLock (&nt->join_mutex);
137
  if (! isAlive ())
138
    {
139
      _Jv_MutexUnlock (&nt->join_mutex);
140
      return;
141
    }
142
  _Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
143
  _Jv_MutexUnlock (&nt->join_mutex);
144
 
145
  if (current->isInterrupted (true))
146
    throw new InterruptedException;
147
}
148
 
149
void
150
java::lang::Thread::resume (void)
151
{
152
  checkAccess ();
153
  throw new UnsupportedOperationException
154
    (JvNewStringLatin1 ("Thread.resume unimplemented"));
155
}
156
 
157
void
158
java::lang::Thread::setPriority (jint newPriority)
159
{
160
  checkAccess ();
161
  if (newPriority < MIN_PRIORITY || newPriority > MAX_PRIORITY)
162
    throw new IllegalArgumentException;
163
 
164
  jint gmax = group->getMaxPriority();
165
  if (newPriority > gmax)
166
    newPriority = gmax;
167
 
168
  priority = newPriority;
169
  natThread *nt = (natThread *) data;
170
  _Jv_ThreadSetPriority (nt->thread, priority);
171
}
172
 
173
void
174
java::lang::Thread::sleep (jlong millis, jint nanos)
175
{
176
  if (millis < 0 || nanos < 0 || nanos > 999999)
177
    throw new IllegalArgumentException;
178
 
179
  if (millis == 0 && nanos == 0)
180
    ++nanos;
181
 
182
  Thread *current = currentThread ();
183
 
184
  // We use a condition variable to implement sleeping so that an
185
  // interrupt can wake us up. 
186
  natThread *nt = (natThread *) current->data;
187
  _Jv_MutexLock (&nt->join_mutex);
188
  _Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
189
  _Jv_MutexUnlock (&nt->join_mutex);
190
 
191
  if (current->isInterrupted (true))
192
    throw new InterruptedException;
193
}
194
 
195
void
196
java::lang::Thread::finish_ ()
197
{
198
  natThread *nt = (natThread *) data;
199
 
200
  group->removeThread (this);
201
 
202
#ifdef ENABLE_JVMPI  
203
  if (_Jv_JVMPI_Notify_THREAD_END)
204
    {
205
      JVMPI_Event event;
206
 
207
      event.event_type = JVMPI_EVENT_THREAD_END;
208
      event.env_id = _Jv_GetCurrentJNIEnv ();
209
 
210
      _Jv_DisableGC ();
211
      (*_Jv_JVMPI_Notify_THREAD_END) (&event);
212
      _Jv_EnableGC ();
213
    }
214
#endif
215
 
216
  // If a method cache was created, free it.
217
  _Jv_FreeMethodCache();
218
 
219
  // Signal any threads that are waiting to join() us.
220
  _Jv_MutexLock (&nt->join_mutex);
221
 
222
  {
223
    JvSynchronize sync (this);
224
    alive_flag = false;
225
  }
226
 
227
  _Jv_CondNotifyAll (&nt->join_cond, &nt->join_mutex);
228
  _Jv_MutexUnlock (&nt->join_mutex);
229
}
230
 
231
// Run once at thread startup, either when thread is attached or when 
232
// _Jv_ThreadRun is called.
233
static void
234
_Jv_NotifyThreadStart (java::lang::Thread* thread)
235
{
236
#ifdef ENABLE_JVMPI
237
      if (_Jv_JVMPI_Notify_THREAD_START)
238
        {
239
          JVMPI_Event event;
240
 
241
          jstring thread_name = thread->getName ();
242
          jstring group_name = NULL, parent_name = NULL;
243
          java::lang::ThreadGroup *group = thread->getThreadGroup ();
244
 
245
          if (group)
246
            {
247
              group_name = group->getName ();
248
              group = group->getParent ();
249
 
250
              if (group)
251
                parent_name = group->getName ();
252
            }
253
 
254
          int thread_len = thread_name ? JvGetStringUTFLength (thread_name) : 0;
255
          int group_len = group_name ? JvGetStringUTFLength (group_name) : 0;
256
          int parent_len = parent_name ? JvGetStringUTFLength (parent_name) : 0;
257
 
258
          char thread_chars[thread_len + 1];
259
          char group_chars[group_len + 1];
260
          char parent_chars[parent_len + 1];
261
 
262
          if (thread_name)
263
            JvGetStringUTFRegion (thread_name, 0,
264
                                  thread_name->length(), thread_chars);
265
          if (group_name)
266
            JvGetStringUTFRegion (group_name, 0,
267
                                  group_name->length(), group_chars);
268
          if (parent_name)
269
            JvGetStringUTFRegion (parent_name, 0,
270
                                  parent_name->length(), parent_chars);
271
 
272
          thread_chars[thread_len] = '\0';
273
          group_chars[group_len] = '\0';
274
          parent_chars[parent_len] = '\0';
275
 
276
          event.event_type = JVMPI_EVENT_THREAD_START;
277
          event.env_id = NULL;
278
          event.u.thread_start.thread_name = thread_chars;
279
          event.u.thread_start.group_name = group_chars;
280
          event.u.thread_start.parent_name = parent_chars;
281
          event.u.thread_start.thread_id = (jobjectID) thread;
282
          event.u.thread_start.thread_env_id = _Jv_GetCurrentJNIEnv ();
283
 
284
          _Jv_DisableGC ();
285
          (*_Jv_JVMPI_Notify_THREAD_START) (&event);
286
          _Jv_EnableGC ();
287
        }
288
#endif
289
}
290
 
291
void
292
_Jv_ThreadRun (java::lang::Thread* thread)
293
{
294
  try
295
    {
296
      _Jv_NotifyThreadStart (thread);
297
      thread->run ();
298
    }
299
  catch (java::lang::Throwable *t)
300
    {
301
      // Uncaught exceptions are forwarded to the ThreadGroup.  If
302
      // this results in an uncaught exception, that is ignored.
303
      try
304
        {
305
          thread->group->uncaughtException (thread, t);
306
        }
307
      catch (java::lang::Throwable *f)
308
        {
309
          // Nothing.
310
        }
311
    }
312
 
313
  thread->finish_ ();
314
}
315
 
316
void
317
java::lang::Thread::start (void)
318
{
319
  JvSynchronize sync (this);
320
 
321
  // Its illegal to re-start() a thread, even if its dead.
322
  if (!startable_flag)
323
    throw new IllegalThreadStateException;
324
 
325
  alive_flag = true;
326
  startable_flag = false;
327
  natThread *nt = (natThread *) data;
328
  _Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &_Jv_ThreadRun);
329
}
330
 
331
void
332
java::lang::Thread::stop (java::lang::Throwable *)
333
{
334
  checkAccess ();
335
  throw new UnsupportedOperationException
336
    (JvNewStringLatin1 ("Thread.stop unimplemented"));
337
}
338
 
339
void
340
java::lang::Thread::suspend (void)
341
{
342
  checkAccess ();
343
  throw new UnsupportedOperationException
344
    (JvNewStringLatin1 ("Thread.suspend unimplemented"));
345
}
346
 
347
static int nextThreadNumber = 0;
348
 
349
jstring
350
java::lang::Thread::gen_name (void)
351
{
352
  jint i;
353
  jclass sync = &java::lang::Thread::class$;
354
  {
355
    JvSynchronize dummy(sync);
356
    i = ++nextThreadNumber;
357
  }
358
 
359
  // Use an array large enough for "-2147483648"; i.e. 11 chars, + "Thread-".
360
  jchar buffer[7+11];
361
  jchar *bufend = (jchar *) ((char *) buffer + sizeof(buffer));
362
  i = _Jv_FormatInt (bufend, i);
363
  jchar *ptr = bufend - i;
364
  // Prepend "Thread-".
365
  *--ptr = '-';
366
  *--ptr = 'd';
367
  *--ptr = 'a';
368
  *--ptr = 'e';
369
  *--ptr = 'r';
370
  *--ptr = 'h';
371
  *--ptr = 'T';
372
  return JvNewString (ptr, bufend - ptr);
373
}
374
 
375
void
376
java::lang::Thread::yield (void)
377
{
378
  _Jv_ThreadYield ();
379
}
380
 
381
JNIEnv *
382
_Jv_GetCurrentJNIEnv ()
383
{
384
  java::lang::Thread *t = _Jv_ThreadCurrent ();
385
  if (t == NULL)
386
    return NULL;
387
  return ((natThread *) t->data)->jni_env;
388
}
389
 
390
void
391
_Jv_SetCurrentJNIEnv (JNIEnv *env)
392
{
393
  java::lang::Thread *t = _Jv_ThreadCurrent ();
394
  JvAssert (t != NULL);
395
  ((natThread *) t->data)->jni_env = env;
396
}
397
 
398
// Attach the current native thread to an existing (but unstarted) Thread 
399
// object. Returns -1 on failure, 0 upon success.
400
jint
401
_Jv_AttachCurrentThread(java::lang::Thread* thread)
402
{
403
  JvSynchronize sync (thread);
404
  if (thread == NULL || thread->startable_flag == false)
405
    return -1;
406
  thread->startable_flag = false;
407
  thread->alive_flag = true;
408
  natThread *nt = (natThread *) thread->data;
409
  _Jv_ThreadRegister (nt->thread);
410
  return 0;
411
}
412
 
413
java::lang::Thread*
414
_Jv_AttachCurrentThread(jstring name, java::lang::ThreadGroup* group)
415
{
416
  java::lang::Thread *thread = _Jv_ThreadCurrent ();
417
  if (thread != NULL)
418
    return thread;
419
  if (name == NULL)
420
    name = java::lang::Thread::gen_name ();
421
  thread = new java::lang::Thread (NULL, group, NULL, name);
422
  _Jv_AttachCurrentThread (thread);
423
  _Jv_NotifyThreadStart (thread);
424
  return thread;
425
}
426
 
427
java::lang::Thread*
428
_Jv_AttachCurrentThreadAsDaemon(jstring name, java::lang::ThreadGroup* group)
429
{
430
  java::lang::Thread *thread = _Jv_ThreadCurrent ();
431
  if (thread != NULL)
432
    return thread;
433
  if (name == NULL)
434
    name = java::lang::Thread::gen_name ();
435
  thread = new java::lang::Thread (NULL, group, NULL, name);
436
  thread->setDaemon (true);
437
  _Jv_AttachCurrentThread (thread);
438
  _Jv_NotifyThreadStart (thread);
439
  return thread;
440
}
441
 
442
jint
443
_Jv_DetachCurrentThread (void)
444
{
445
  java::lang::Thread *t = _Jv_ThreadCurrent ();
446
  if (t == NULL)
447
    return -1;
448
 
449
  _Jv_ThreadUnRegister ();
450
  // Release the monitors.
451
  t->finish_ ();
452
 
453
  return 0;
454
}

powered by: WebSVN 2.1.0

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