source: branches/GNU/src/gcc/libjava/java/lang/natObject.cc@ 3

Last change on this file since 3 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 40.8 KB
Line 
1// natObject.cc - Implementation of the Object class.
2
3/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11#include <config.h>
12
13#include <string.h>
14
15#pragma implementation "Object.h"
16
17#include <gcj/cni.h>
18#include <jvm.h>
19#include <java/lang/Object.h>
20#include <java-threads.h>
21#include <java-signal.h>
22#include <java/lang/CloneNotSupportedException.h>
23#include <java/lang/IllegalArgumentException.h>
24#include <java/lang/IllegalMonitorStateException.h>
25#include <java/lang/InterruptedException.h>
26#include <java/lang/NullPointerException.h>
27#include <java/lang/Class.h>
28#include <java/lang/Cloneable.h>
29#include <java/lang/Thread.h>
30
31#ifdef LOCK_DEBUG
32# include <stdio.h>
33#endif
34
35
36
37
38// This is used to represent synchronization information.
39struct _Jv_SyncInfo
40{
41#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
42 // We only need to keep track of initialization state if we can
43 // possibly finalize this object.
44 bool init;
45#endif
46 _Jv_ConditionVariable_t condition;
47 _Jv_Mutex_t mutex;
48};
49
50
51
52
53jclass
54java::lang::Object::getClass (void)
55{
56 _Jv_VTable **dt = (_Jv_VTable **) this;
57 return (*dt)->clas;
58}
59
60jint
61java::lang::Object::hashCode (void)
62{
63 return _Jv_HashCode (this);
64}
65
66jobject
67java::lang::Object::clone (void)
68{
69 jclass klass = getClass ();
70 jobject r;
71 jint size;
72
73 // We also clone arrays here. If we put the array code into
74 // __JArray, then we'd have to figure out a way to find the array
75 // vtbl when creating a new array class. This is easier, if uglier.
76 if (klass->isArray())
77 {
78 __JArray *array = (__JArray *) this;
79 jclass comp = getClass()->getComponentType();
80 jint eltsize;
81 if (comp->isPrimitive())
82 {
83 r = _Jv_NewPrimArray (comp, array->length);
84 eltsize = comp->size();
85 }
86 else
87 {
88 r = _Jv_NewObjectArray (array->length, comp, NULL);
89 eltsize = sizeof (jobject);
90 }
91 // We can't use sizeof on __JArray because we must account for
92 // alignment of the element type.
93 size = (_Jv_GetArrayElementFromElementType (array, comp) - (char *) array
94 + array->length * eltsize);
95 }
96 else
97 {
98 if (! java::lang::Cloneable::class$.isAssignableFrom(klass))
99 throw new CloneNotSupportedException;
100
101 size = klass->size();
102 r = JvAllocObject (klass, size);
103 }
104
105 memcpy ((void *) r, (void *) this, size);
106 return r;
107}
108
109void
110_Jv_FinalizeObject (jobject obj)
111{
112 // Ignore exceptions. From section 12.6 of the Java Language Spec.
113 try
114 {
115 obj->finalize ();
116 }
117 catch (java::lang::Throwable *t)
118 {
119 // Ignore.
120 }
121}
122
123
124//
125// Synchronization code.
126//
127
128#ifndef JV_HASH_SYNCHRONIZATION
129// This global is used to make sure that only one thread sets an
130// object's `sync_info' field.
131static _Jv_Mutex_t sync_mutex;
132
133// This macro is used to see if synchronization initialization is
134// needed.
135#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
136# define INIT_NEEDED(Obj) (! (Obj)->sync_info \
137 || ! ((_Jv_SyncInfo *) ((Obj)->sync_info))->init)
138#else
139# define INIT_NEEDED(Obj) (! (Obj)->sync_info)
140#endif
141
142#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
143// If we have to run a destructor for a sync_info member, then this
144// function is registered as a finalizer for the sync_info.
145static void
146finalize_sync_info (jobject obj)
147{
148 _Jv_SyncInfo *si = (_Jv_SyncInfo *) obj;
149#if defined (_Jv_HaveCondDestroy)
150 _Jv_CondDestroy (&si->condition);
151#endif
152#if defined (_Jv_HaveMutexDestroy)
153 _Jv_MutexDestroy (&si->mutex);
154#endif
155 si->init = false;
156}
157#endif
158
159// This is called to initialize the sync_info element of an object.
160void
161java::lang::Object::sync_init (void)
162{
163 _Jv_MutexLock (&sync_mutex);
164 // Check again to see if initialization is needed now that we have
165 // the lock.
166 if (INIT_NEEDED (this))
167 {
168 // We assume there are no pointers in the sync_info
169 // representation.
170 _Jv_SyncInfo *si;
171 // We always create a new sync_info, even if there is already
172 // one available. Any given object can only be finalized once.
173 // If we get here and sync_info is not null, then it has already
174 // been finalized. So if we just reinitialize the old one,
175 // we'll never be able to (re-)destroy the mutex and/or
176 // condition variable.
177 si = (_Jv_SyncInfo *) _Jv_AllocBytes (sizeof (_Jv_SyncInfo));
178 _Jv_MutexInit (&si->mutex);
179 _Jv_CondInit (&si->condition);
180#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
181 // Register a finalizer.
182 si->init = true;
183 _Jv_RegisterFinalizer (si, finalize_sync_info);
184#endif
185 sync_info = (jobject) si;
186 }
187 _Jv_MutexUnlock (&sync_mutex);
188}
189
190void
191java::lang::Object::notify (void)
192{
193 if (__builtin_expect (INIT_NEEDED (this), false))
194 sync_init ();
195 _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
196 if (__builtin_expect (_Jv_CondNotify (&si->condition, &si->mutex), false))
197 throw new IllegalMonitorStateException(JvNewStringLatin1
198 ("current thread not owner"));
199}
200
201void
202java::lang::Object::notifyAll (void)
203{
204 if (__builtin_expect (INIT_NEEDED (this), false))
205 sync_init ();
206 _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
207 if (__builtin_expect (_Jv_CondNotifyAll (&si->condition, &si->mutex), false))
208 throw new IllegalMonitorStateException(JvNewStringLatin1
209 ("current thread not owner"));
210}
211
212void
213java::lang::Object::wait (jlong timeout, jint nanos)
214{
215 if (__builtin_expect (INIT_NEEDED (this), false))
216 sync_init ();
217 if (__builtin_expect (timeout < 0 || nanos < 0 || nanos > 999999, false))
218 throw new IllegalArgumentException;
219 _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
220 switch (_Jv_CondWait (&si->condition, &si->mutex, timeout, nanos))
221 {
222 case _JV_NOT_OWNER:
223 throw new IllegalMonitorStateException (JvNewStringLatin1
224 ("current thread not owner"));
225 case _JV_INTERRUPTED:
226 if (Thread::interrupted ())
227 throw new InterruptedException;
228 }
229}
230
231//
232// Some runtime code.
233//
234
235// This function is called at system startup to initialize the
236// `sync_mutex'.
237void
238_Jv_InitializeSyncMutex (void)
239{
240 _Jv_MutexInit (&sync_mutex);
241}
242
243void
244_Jv_MonitorEnter (jobject obj)
245{
246#ifndef HANDLE_SEGV
247 if (__builtin_expect (! obj, false))
248 throw new java::lang::NullPointerException;
249#endif
250 if (__builtin_expect (INIT_NEEDED (obj), false))
251 obj->sync_init ();
252 _Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
253 _Jv_MutexLock (&si->mutex);
254 // FIXME: In the Windows case, this can return a nonzero error code.
255 // We should turn that into some exception ...
256}
257
258void
259_Jv_MonitorExit (jobject obj)
260{
261 JvAssert (obj);
262 JvAssert (! INIT_NEEDED (obj));
263 _Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
264 if (__builtin_expect (_Jv_MutexUnlock (&si->mutex), false))
265 throw new java::lang::IllegalMonitorStateException;
266}
267
268#else /* JV_HASH_SYNCHRONIZATION */
269
270// FIXME: We shouldn't be calling GC_register_finalizer directly.
271#ifndef HAVE_BOEHM_GC
272# error Hash synchronization currently requires boehm-gc
273// That's actually a bit of a lie: It should also work with the null GC,
274// probably even better than the alternative.
275// To really support alternate GCs here, we would need to widen the
276// interface to finalization, since we sometimes have to register a
277// second finalizer for an object that already has one.
278// We might also want to move the GC interface to a .h file, since
279// the number of procedure call levels involved in some of these
280// operations is already ridiculous, and would become worse if we
281// went through the proper intermediaries.
282#else
283# include "gc.h"
284#endif
285
286// What follows currenly assumes a Linux-like platform.
287// Some of it specifically assumes X86 or IA64 Linux, though that
288// should be easily fixable.
289
290// A Java monitor implemention based on a table of locks.
291// Each entry in the table describes
292// locks held for objects that hash to that location.
293// This started out as a reimplementation of the technique used in SGIs JVM,
294// for which we obtained permission from SGI.
295// But in fact, this ended up quite different, though some ideas are
296// still shared with the original.
297// It was also influenced by some of the published IBM work,
298// though it also differs in many ways from that.
299// We could speed this up if we had a way to atomically update
300// an entire cache entry, i.e. 2 contiguous words of memory.
301// That would usually be the case with a 32 bit ABI on a 64 bit processor.
302// But we don't currently go out of our way to target those.
303// I don't know how to do much better with a N bit ABI on a processor
304// that can atomically update only N bits at a time.
305// Author: Hans-J. Boehm ([email protected], [email protected])
306
307#include <assert.h>
308#include <limits.h>
309#include <unistd.h> // for usleep, sysconf.
310#include <sched.h> // for sched_yield.
311#include <gcj/javaprims.h>
312#include <sysdep/locks.h>
313
314// Try to determine whether we are on a multiprocessor, i.e. whether
315// spinning may be profitable.
316// This should really use a suitable autoconf macro.
317// False is the conservative answer, though the right one is much better.
318static bool
319is_mp()
320{
321#ifdef _SC_NPROCESSORS_ONLN
322 long nprocs = sysconf(_SC_NPROCESSORS_ONLN);
323 return (nprocs > 1);
324#else
325 return false;
326#endif
327}
328
329// A call to keep_live(p) forces p to be accessible to the GC
330// at this point.
331inline static void
332keep_live(obj_addr_t p)
333{
334 __asm__ __volatile__("" : : "rm"(p) : "memory");
335}
336
337// Each hash table entry holds a single preallocated "lightweight" lock.
338// In addition, it holds a chain of "heavyweight" locks. Lightweight
339// locks do not support Object.wait(), and are converted to heavyweight
340// status in response to contention. Unlike the SGI scheme, both
341// ligtweight and heavyweight locks in one hash entry can be simultaneously
342// in use. (The SGI scheme requires that we be able to acquire a heavyweight
343// lock on behalf of another thread, and can thus convert a lock we don't
344// hold to heavyweight status. Here we don't insist on that, and thus
345// let the original holder of the lighweight lock keep it.)
346
347struct heavy_lock {
348 void * reserved_for_gc;
349 struct heavy_lock *next; // Hash chain link.
350 // Traced by GC.
351 void * old_client_data; // The only other field traced by GC.
352 GC_finalization_proc old_finalization_proc;
353 obj_addr_t address; // Object to which this lock corresponds.
354 // Should not be traced by GC.
355 // Cleared as heavy_lock is destroyed.
356 // Together with the rest of the hevy lock
357 // chain, this is protected by the lock
358 // bit in the hash table entry to which
359 // the chain is attached.
360 _Jv_SyncInfo si;
361 // The remaining fields save prior finalization info for
362 // the object, which we needed to replace in order to arrange
363 // for cleanup of the lock structure.
364};
365
366#ifdef LOCK_DEBUG
367void
368print_hl_list(heavy_lock *hl)
369{
370 heavy_lock *p = hl;
371 for (; 0 != p; p = p->next)
372 fprintf (stderr, "(hl = %p, addr = %p)", p, (void *)(p -> address));
373}
374#endif /* LOCK_DEBUG */
375
376#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
377// If we have to run a destructor for a sync_info member, then this
378// function could be registered as a finalizer for the sync_info.
379// In fact, we now only invoke it explicitly.
380static inline void
381heavy_lock_finalization_proc (heavy_lock *hl)
382{
383#if defined (_Jv_HaveCondDestroy)
384 _Jv_CondDestroy (&hl->si.condition);
385#endif
386#if defined (_Jv_HaveMutexDestroy)
387 _Jv_MutexDestroy (&hl->si.mutex);
388#endif
389 hl->si.init = false;
390}
391#endif /* defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy) */
392
393// We convert the lock back to lightweight status when
394// we exit, so that a single contention episode doesn't doom the lock
395// forever. But we also need to make sure that lock structures for dead
396// objects are eventually reclaimed. We do that in a an additional
397// finalizer on the underlying object.
398// Note that if the corresponding object is dead, it is safe to drop
399// the heavy_lock structure from its list. It is not necessarily
400// safe to deallocate it, since the unlock code could still be running.
401
402struct hash_entry {
403 volatile obj_addr_t address; // Address of object for which lightweight
404 // k is held.
405 // We assume the 3 low order bits are zero.
406 // With the Boehm collector and bitmap
407 // allocation, objects of size 4 bytes are
408 // broken anyway. Thus this is primarily
409 // a constraint on statically allocated
410 // objects used for synchronization.
411 // This allows us to use the low order
412 // bits as follows:
413# define LOCKED 1 // This hash entry is locked, and its
414 // state may be invalid.
415 // The lock protects both the hash_entry
416 // itself (except for the light_count
417 // and light_thr_id fields, which
418 // are protected by the lightweight
419 // lock itself), and any heavy_monitor
420 // structures attached to it.
421# define HEAVY 2 // There may be heavyweight locks
422 // associated with this cache entry.
423 // The lightweight entry is still valid,
424 // if the leading bits of the address
425 // field are nonzero.
426 // Set if heavy_count is > 0 .
427 // Stored redundantly so a single
428 // compare-and-swap works in the easy case.
429# define REQUEST_CONVERSION 4 // The lightweight lock is held. But
430 // one or more other threads have tried
431 // to acquire the lock, and hence request
432 // conversion to heavyweight status.
433# define FLAGS (LOCKED | HEAVY | REQUEST_CONVERSION)
434 volatile _Jv_ThreadId_t light_thr_id;
435 // Thr_id of holder of lightweight lock.
436 // Only updated by lightweight lock holder.
437 // Must be recognizably invalid if the
438 // lightweight lock is not held.
439# define INVALID_THREAD_ID 0 // Works for Linux?
440 // If zero doesn't work, we have to
441 // initialize lock table.
442 volatile unsigned short light_count;
443 // Number of times the lightweight lock
444 // is held minus one. Zero if lightweight
445 // lock is not held.
446 unsigned short heavy_count; // Total number of times heavyweight locks
447 // associated with this hash entry are held
448 // or waiting to be acquired.
449 // Threads in wait() are included eventhough
450 // they have temporarily released the lock.
451 struct heavy_lock * heavy_locks;
452 // Chain of heavy locks. Protected
453 // by lockbit for he. Locks may
454 // remain allocated here even if HEAVY
455 // is not set and heavy_count is 0.
456 // If a lightweight and heavyweight lock
457 // correspond to the same address, the
458 // lightweight lock is the right one.
459};
460
461#ifndef JV_SYNC_TABLE_SZ
462# define JV_SYNC_TABLE_SZ 2048
463#endif
464
465hash_entry light_locks[JV_SYNC_TABLE_SZ];
466
467#define JV_SYNC_HASH(p) (((long)p ^ ((long)p >> 10)) % JV_SYNC_TABLE_SZ)
468
469// Note that the light_locks table is scanned conservatively by the
470// collector. It is essential the the heavy_locks field is scanned.
471// Currently the address field may or may not cause the associated object
472// to be retained, depending on whether flag bits are set.
473// This means that we can conceivable get an unexpected deadlock if
474// 1) Object at address A is locked.
475// 2) The client drops A without unlocking it.
476// 3) Flag bits in the address entry are set, so the collector reclaims
477// the object at A.
478// 4) A is reallocated, and an attempt is made to lock the result.
479// This could be fixed by scanning light_locks in a more customized
480// manner that ignores the flag bits. But it can only happen with hand
481// generated semi-illegal .class files, and then it doesn't present a
482// security hole.
483
484#ifdef LOCK_DEBUG
485 void print_he(hash_entry *he)
486 {
487 fprintf(stderr, "lock hash entry = %p, index = %d, address = 0x%lx\n"
488 "\tlight_thr_id = 0x%lx, light_count = %d, "
489 "heavy_count = %d\n\theavy_locks:", he,
490 he - light_locks, he -> address, he -> light_thr_id,
491 he -> light_count, he -> heavy_count);
492 print_hl_list(he -> heavy_locks);
493 fprintf(stderr, "\n");
494 }
495#endif /* LOCK_DEBUG */
496
497static bool mp = false; // Known multiprocesssor.
498
499// Wait for roughly 2^n units, touching as little memory as possible.
500static void
501spin(unsigned n)
502{
503 const unsigned MP_SPINS = 10;
504 const unsigned YIELDS = 4;
505 const unsigned SPINS_PER_UNIT = 30;
506 const unsigned MIN_SLEEP_USECS = 2001; // Shorter times spin under Linux.
507 const unsigned MAX_SLEEP_USECS = 200000;
508 static unsigned spin_limit = 0;
509 static unsigned yield_limit = YIELDS;
510 static bool spin_initialized = false;
511
512 if (!spin_initialized)
513 {
514 mp = is_mp();
515 if (mp)
516 {
517 spin_limit = MP_SPINS;
518 yield_limit = MP_SPINS + YIELDS;
519 }
520 spin_initialized = true;
521 }
522 if (n < spin_limit)
523 {
524 unsigned i = SPINS_PER_UNIT << n;
525 for (; i > 0; --i)
526 __asm__ __volatile__("");
527 }
528 else if (n < yield_limit)
529 {
530 sched_yield();
531 }
532 else
533 {
534 unsigned duration = MIN_SLEEP_USECS << (n - yield_limit);
535 if (n >= 15 + yield_limit || duration > MAX_SLEEP_USECS)
536 duration = MAX_SLEEP_USECS;
537 usleep(duration);
538 }
539}
540
541// Wait for a hash entry to become unlocked.
542static void
543wait_unlocked (hash_entry *he)
544{
545 unsigned i = 0;
546 while (he -> address & LOCKED)
547 spin (i++);
548}
549
550// Return the heavy lock for addr if it was already allocated.
551// The client passes in the appropriate hash_entry.
552// We hold the lock for he.
553static inline heavy_lock *
554find_heavy (obj_addr_t addr, hash_entry *he)
555{
556 heavy_lock *hl = he -> heavy_locks;
557 while (hl != 0 && hl -> address != addr) hl = hl -> next;
558 return hl;
559}
560
561// Unlink the heavy lock for the given address from its hash table chain.
562// Dies miserably and conspicuously if it's not there, since that should
563// be impossible.
564static inline void
565unlink_heavy (obj_addr_t addr, hash_entry *he)
566{
567 heavy_lock **currentp = &(he -> heavy_locks);
568 while ((*currentp) -> address != addr)
569 currentp = &((*currentp) -> next);
570 *currentp = (*currentp) -> next;
571}
572
573// Finalization procedure for objects that have associated heavy-weight
574// locks. This may replace the real finalization procedure.
575static void
576heavy_lock_obj_finalization_proc (void *obj, void *cd)
577{
578 heavy_lock *hl = (heavy_lock *)cd;
579 obj_addr_t addr = (obj_addr_t)obj;
580 hash_entry *he = light_locks + JV_SYNC_HASH(addr);
581 obj_addr_t he_address = (he -> address & ~LOCKED);
582
583 // Acquire lock bit immediately. It's possible that the hl was already
584 // destroyed while we were waiting for the finalizer to run. If it
585 // was, the address field was set to zero. The address filed access is
586 // protected by the lock bit to ensure that we do this exactly once.
587 // The lock bit also protects updates to the objects finalizer.
588 while (!compare_and_swap(&(he -> address), he_address, he_address|LOCKED ))
589 {
590 // Hash table entry is currently locked. We can't safely
591 // touch the list of heavy locks.
592 wait_unlocked(he);
593 he_address = (he -> address & ~LOCKED);
594 }
595 if (0 == hl -> address)
596 {
597 // remove_all_heavy destroyed hl, and took care of the real finalizer.
598 release_set(&(he -> address), he_address);
599 return;
600 }
601 assert(hl -> address == addr);
602 GC_finalization_proc old_finalization_proc = hl -> old_finalization_proc;
603 if (old_finalization_proc != 0)
604 {
605 // We still need to run a real finalizer. In an idealized
606 // world, in which people write thread-safe finalizers, that is
607 // likely to require synchronization. Thus we reregister
608 // ourselves as the only finalizer, and simply run the real one.
609 // Thus we don't clean up the lock yet, but we're likely to do so
610 // on the next GC cycle.
611 // It's OK if remove_all_heavy actually destroys the heavy lock,
612 // since we've updated old_finalization_proc, and thus the user's
613 // finalizer won't be rerun.
614 void * old_client_data = hl -> old_client_data;
615 hl -> old_finalization_proc = 0;
616 hl -> old_client_data = 0;
617# ifdef HAVE_BOEHM_GC
618 GC_REGISTER_FINALIZER_NO_ORDER(obj, heavy_lock_obj_finalization_proc, cd, 0, 0);
619# endif
620 release_set(&(he -> address), he_address);
621 old_finalization_proc(obj, old_client_data);
622 }
623 else
624 {
625 // The object is really dead, although it's conceivable that
626 // some thread may still be in the process of releasing the
627 // heavy lock. Unlink it and, if necessary, register a finalizer
628 // to destroy sync_info.
629 unlink_heavy(addr, he);
630 hl -> address = 0; // Don't destroy it again.
631 release_set(&(he -> address), he_address);
632# if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
633 // Make sure lock is not held and then destroy condvar and mutex.
634 _Jv_MutexLock(&(hl->si.mutex));
635 _Jv_MutexUnlock(&(hl->si.mutex));
636 heavy_lock_finalization_proc (hl);
637# endif
638 }
639}
640
641// We hold the lock on he, and heavy_count is 0.
642// Release the lock by replacing the address with new_address_val.
643// Remove all heavy locks on the list. Note that the only possible way
644// in which a lock may still be in use is if it's in the process of
645// being unlocked.
646static void
647remove_all_heavy (hash_entry *he, obj_addr_t new_address_val)
648{
649 assert(he -> heavy_count == 0);
650 assert(he -> address & LOCKED);
651 heavy_lock *hl = he -> heavy_locks;
652 he -> heavy_locks = 0;
653 // We would really like to release the lock bit here. Unfortunately, that
654 // Creates a race between or finalizer removal, and the potential
655 // reinstallation of a new finalizer as a new heavy lock is created.
656 // This may need to be revisited.
657 for(; 0 != hl; hl = hl->next)
658 {
659 obj_addr_t obj = hl -> address;
660 assert(0 != obj); // If this was previously finalized, it should no
661 // longer appear on our list.
662 hl -> address = 0; // Finalization proc might still see it after we
663 // finish.
664 GC_finalization_proc old_finalization_proc = hl -> old_finalization_proc;
665 void * old_client_data = hl -> old_client_data;
666# ifdef HAVE_BOEHM_GC
667 // Remove our finalization procedure.
668 // Reregister the clients if applicable.
669 GC_REGISTER_FINALIZER_NO_ORDER((GC_PTR)obj, old_finalization_proc,
670 old_client_data, 0, 0);
671 // Note that our old finalization procedure may have been
672 // previously determined to be runnable, and may still run.
673 // FIXME - direct dependency on boehm GC.
674# endif
675# if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
676 // Wait for a possible lock holder to finish unlocking it.
677 // This is only an issue if we have to explicitly destroy the mutex
678 // or possibly if we have to destroy a condition variable that is
679 // still being notified.
680 _Jv_MutexLock(&(hl->si.mutex));
681 _Jv_MutexUnlock(&(hl->si.mutex));
682 heavy_lock_finalization_proc (hl);
683# endif
684 }
685 release_set(&(he -> address), new_address_val);
686}
687
688// We hold the lock on he and heavy_count is 0.
689// We release it by replacing the address field with new_address_val.
690// Remove all heavy locks on the list if the list is sufficiently long.
691// This is called periodically to avoid very long lists of heavy locks.
692// This seems to otherwise become an issue with SPECjbb, for example.
693static inline void
694maybe_remove_all_heavy (hash_entry *he, obj_addr_t new_address_val)
695{
696 static const int max_len = 5;
697 heavy_lock *hl = he -> heavy_locks;
698
699 for (int i = 0; i < max_len; ++i)
700 {
701 if (0 == hl)
702 {
703 release_set(&(he -> address), new_address_val);
704 return;
705 }
706 hl = hl -> next;
707 }
708 remove_all_heavy(he, new_address_val);
709}
710
711// Allocate a new heavy lock for addr, returning its address.
712// Assumes we already have the hash_entry locked, and there
713// is currently no lightweight or allocated lock for addr.
714// We register a finalizer for addr, which is responsible for
715// removing the heavy lock when addr goes away, in addition
716// to the responsibilities of any prior finalizer.
717// This unfortunately holds the lock bit for the hash entry while it
718// allocates two objects (on for the finalizer).
719// It would be nice to avoid that somehow ...
720static heavy_lock *
721alloc_heavy(obj_addr_t addr, hash_entry *he)
722{
723 heavy_lock * hl = (heavy_lock *) _Jv_AllocTraceTwo(sizeof (heavy_lock));
724
725 hl -> address = addr;
726 _Jv_MutexInit (&(hl -> si.mutex));
727 _Jv_CondInit (&(hl -> si.condition));
728# if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
729 hl->si.init = true; // needed ?
730# endif
731 hl -> next = he -> heavy_locks;
732 he -> heavy_locks = hl;
733 // FIXME: The only call that cheats and goes directly to the GC interface.
734# ifdef HAVE_BOEHM_GC
735 GC_REGISTER_FINALIZER_NO_ORDER(
736 (void *)addr, heavy_lock_obj_finalization_proc,
737 hl, &hl->old_finalization_proc,
738 &hl->old_client_data);
739# endif /* HAVE_BOEHM_GC */
740 return hl;
741}
742
743// Return the heavy lock for addr, allocating if necessary.
744// Assumes we have the cache entry locked, and there is no lightweight
745// lock for addr.
746static heavy_lock *
747get_heavy(obj_addr_t addr, hash_entry *he)
748{
749 heavy_lock *hl = find_heavy(addr, he);
750 if (0 == hl)
751 hl = alloc_heavy(addr, he);
752 return hl;
753}
754
755void
756_Jv_MonitorEnter (jobject obj)
757{
758 obj_addr_t addr = (obj_addr_t)obj;
759 obj_addr_t address;
760 unsigned hash = JV_SYNC_HASH(addr);
761 hash_entry * he = light_locks + hash;
762 _Jv_ThreadId_t self = _Jv_ThreadSelf();
763 unsigned count;
764 const unsigned N_SPINS = 18;
765
766 // We need to somehow check that addr is not NULL on the fast path.
767 // A very predictable
768 // branch on a register value is probably cheaper than dereferencing addr.
769 // We could also permanently lock the NULL entry in the hash table.
770 // But it's not clear that's cheaper either.
771 if (__builtin_expect(!addr, false))
772 throw new java::lang::NullPointerException;
773
774 assert(!(addr & FLAGS));
775retry:
776 if (__builtin_expect(compare_and_swap(&(he -> address),
777 0, addr),true))
778 {
779 assert(he -> light_thr_id == INVALID_THREAD_ID);
780 assert(he -> light_count == 0);
781 he -> light_thr_id = self;
782 // Count fields are set correctly. Heavy_count was also zero,
783 // but can change asynchronously.
784 // This path is hopefully both fast and the most common.
785 return;
786 }
787 address = he -> address;
788 if ((address & ~(HEAVY | REQUEST_CONVERSION)) == addr)
789 {
790 if (he -> light_thr_id == self)
791 {
792 // We hold the lightweight lock, and it's for the right
793 // address.
794 count = he -> light_count;
795 if (count == USHRT_MAX)
796 {
797 // I think most JVMs don't check for this.
798 // But I'm not convinced I couldn't turn this into a security
799 // hole, even with a 32 bit counter.
800 throw new java::lang::IllegalMonitorStateException(
801 JvNewStringLatin1("maximum monitor nesting level exceeded"));
802 }
803 he -> light_count = count + 1;
804 return;
805 }
806 else
807 {
808 // Lightweight lock is held, but by somone else.
809 // Spin a few times. This avoids turning this into a heavyweight
810 // lock if the current holder is about to release it.
811 for (unsigned int i = 0; i < N_SPINS; ++i)
812 {
813 if ((he -> address & ~LOCKED) != (address & ~LOCKED)) goto retry;
814 spin(i);
815 }
816 address &= ~LOCKED;
817 if (!compare_and_swap(&(he -> address), address, address | LOCKED ))
818 {
819 wait_unlocked(he);
820 goto retry;
821 }
822 heavy_lock *hl = get_heavy(addr, he);
823 ++ (he -> heavy_count);
824 // The hl lock acquisition can't block for long, since it can
825 // only be held by other threads waiting for conversion, and
826 // they, like us, drop it quickly without blocking.
827 _Jv_MutexLock(&(hl->si.mutex));
828 assert(he -> address == address | LOCKED );
829 release_set(&(he -> address), (address | REQUEST_CONVERSION | HEAVY));
830 // release lock on he
831 while ((he -> address & ~FLAGS) == (address & ~FLAGS))
832 {
833 // Once converted, the lock has to retain heavyweight
834 // status, since heavy_count > 0 .
835 _Jv_CondWait (&(hl->si.condition), &(hl->si.mutex), 0, 0);
836 }
837 keep_live(addr);
838 // Guarantee that hl doesn't get unlinked by finalizer.
839 // This is only an issue if the client fails to release
840 // the lock, which is unlikely.
841 assert(he -> address & HEAVY);
842 // Lock has been converted, we hold the heavyweight lock,
843 // heavy_count has been incremented.
844 return;
845 }
846 }
847 obj_addr_t was_heavy = (address & HEAVY);
848 address &= ~LOCKED;
849 if (!compare_and_swap(&(he -> address), address, (address | LOCKED )))
850 {
851 wait_unlocked(he);
852 goto retry;
853 }
854 if ((address & ~(HEAVY | REQUEST_CONVERSION)) == 0)
855 {
856 // Either was_heavy is true, or something changed out from under us,
857 // since the initial test for 0 failed.
858 assert(!(address & REQUEST_CONVERSION));
859 // Can't convert a nonexistent lightweight lock.
860 heavy_lock *hl;
861 hl = (was_heavy? find_heavy(addr, he) : 0);
862 if (0 == hl)
863 {
864 // It is OK to use the lighweight lock, since either the
865 // heavyweight lock does not exist, or none of the
866 // heavyweight locks currently exist. Future threads
867 // trying to acquire the lock will see the lightweight
868 // one first and use that.
869 he -> light_thr_id = self; // OK, since nobody else can hold
870 // light lock or do this at the same time.
871 assert(he -> light_count == 0);
872 assert(was_heavy == (he -> address & HEAVY));
873 release_set(&(he -> address), (addr | was_heavy));
874 }
875 else
876 {
877 // Must use heavy lock.
878 ++ (he -> heavy_count);
879 assert(0 == (address & ~HEAVY));
880 release_set(&(he -> address), HEAVY);
881 _Jv_MutexLock(&(hl->si.mutex));
882 keep_live(addr);
883 }
884 return;
885 }
886 // Lightweight lock is held, but does not correspond to this object.
887 // We hold the lock on the hash entry, and he -> address can't
888 // change from under us. Neither can the chain of heavy locks.
889 {
890 assert(0 == he -> heavy_count || (address & HEAVY));
891 heavy_lock *hl = get_heavy(addr, he);
892 ++ (he -> heavy_count);
893 release_set(&(he -> address), address | HEAVY);
894 _Jv_MutexLock(&(hl->si.mutex));
895 keep_live(addr);
896 }
897}
898
899
900void
901_Jv_MonitorExit (jobject obj)
902{
903 obj_addr_t addr = (obj_addr_t)obj;
904 _Jv_ThreadId_t self = _Jv_ThreadSelf();
905 unsigned hash = JV_SYNC_HASH(addr);
906 hash_entry * he = light_locks + hash;
907 _Jv_ThreadId_t light_thr_id;
908 unsigned count;
909 obj_addr_t address;
910
911retry:
912 light_thr_id = he -> light_thr_id;
913 // Unfortunately, it turns out we always need to read the address
914 // first. Even if we are going to update it with compare_and_swap,
915 // we need to reset light_thr_id, and that's not safe unless we know
916 // that we hold the lock.
917 address = he -> address;
918 // First the (relatively) fast cases:
919 if (__builtin_expect(light_thr_id == self, true))
920 // Above must fail if addr == 0 .
921 {
922 count = he -> light_count;
923 if (__builtin_expect((address & ~HEAVY) == addr, true))
924 {
925 if (count != 0)
926 {
927 // We held the lightweight lock all along. Thus the values
928 // we saw for light_thr_id and light_count must have been valid.
929 he -> light_count = count - 1;
930 return;
931 }
932 else
933 {
934 // We hold the lightweight lock once.
935 he -> light_thr_id = INVALID_THREAD_ID;
936 if (compare_and_swap_release(&(he -> address), address,
937 address & HEAVY))
938 return;
939 else
940 {
941 he -> light_thr_id = light_thr_id; // Undo prior damage.
942 goto retry;
943 }
944 }
945 }
946 // else lock is not for this address, conversion is requested,
947 // or the lock bit in the address field is set.
948 }
949 else
950 {
951 if (__builtin_expect(!addr, false))
952 throw new java::lang::NullPointerException;
953 if ((address & ~(HEAVY | REQUEST_CONVERSION)) == addr)
954 {
955# ifdef LOCK_DEBUG
956 fprintf(stderr, "Lightweight lock held by other thread\n\t"
957 "light_thr_id = 0x%lx, self = 0x%lx, "
958 "address = 0x%lx, pid = %d\n",
959 light_thr_id, self, address, getpid());
960 print_he(he);
961 for(;;) {}
962# endif
963 // Someone holds the lightweight lock for this object, and
964 // it can't be us.
965 throw new java::lang::IllegalMonitorStateException(
966 JvNewStringLatin1("current thread not owner"));
967 }
968 else
969 count = he -> light_count;
970 }
971 if (address & LOCKED)
972 {
973 wait_unlocked(he);
974 goto retry;
975 }
976 // Now the unlikely cases.
977 // We do know that:
978 // - Address is set, and doesn't contain the LOCKED bit.
979 // - If address refers to the same object as addr, then he -> light_thr_id
980 // refers to this thread, and count is valid.
981 // - The case in which we held the lightweight lock has been
982 // completely handled, except for the REQUEST_CONVERSION case.
983 //
984 if ((address & ~FLAGS) == addr)
985 {
986 // The lightweight lock is assigned to this object.
987 // Thus we must be in the REQUEST_CONVERSION case.
988 if (0 != count)
989 {
990 // Defer conversion until we exit completely.
991 he -> light_count = count - 1;
992 return;
993 }
994 assert(he -> light_thr_id == self);
995 assert(address & REQUEST_CONVERSION);
996 // Conversion requested
997 // Convert now.
998 if (!compare_and_swap(&(he -> address), address, address | LOCKED))
999 goto retry;
1000 heavy_lock *hl = find_heavy(addr, he);
1001 assert (0 != hl);
1002 // Requestor created it.
1003 he -> light_count = 0;
1004 assert(he -> heavy_count > 0);
1005 // was incremented by requestor.
1006 _Jv_MutexLock(&(hl->si.mutex));
1007 // Release the he lock after acquiring the mutex.
1008 // Otherwise we can accidentally
1009 // notify a thread that has already seen a heavyweight
1010 // lock.
1011 he -> light_thr_id = INVALID_THREAD_ID;
1012 release_set(&(he -> address), HEAVY);
1013 // lightweight lock now unused.
1014 _Jv_CondNotifyAll(&(hl->si.condition), &(hl->si.mutex));
1015 _Jv_MutexUnlock(&(hl->si.mutex));
1016 // heavy_count was already incremented by original requestor.
1017 keep_live(addr);
1018 return;
1019 }
1020 // lightweight lock not for this object.
1021 assert(!(address & LOCKED));
1022 assert((address & ~FLAGS) != addr);
1023 if (!compare_and_swap(&(he -> address), address, address | LOCKED))
1024 goto retry;
1025 heavy_lock *hl = find_heavy(addr, he);
1026 if (NULL == hl)
1027 {
1028# ifdef LOCK_DEBUG
1029 fprintf(stderr, "Failed to find heavyweight lock for addr 0x%lx"
1030 " pid = %d\n", addr, getpid());
1031 print_he(he);
1032 for(;;) {}
1033# endif
1034 throw new java::lang::IllegalMonitorStateException(
1035 JvNewStringLatin1("current thread not owner"));
1036 }
1037 assert(address & HEAVY);
1038 count = he -> heavy_count;
1039 assert(count > 0);
1040 --count;
1041 he -> heavy_count = count;
1042 if (0 == count)
1043 {
1044 const unsigned test_freq = 16; // Power of 2
1045 static volatile unsigned counter = 0;
1046 unsigned my_counter = counter;
1047
1048 counter = my_counter + 1;
1049 if (my_counter%test_freq == 0)
1050 {
1051 // Randomize the interval length a bit.
1052 counter = my_counter + (my_counter >> 4) % (test_freq/2);
1053 // Unlock mutex first, to avoid self-deadlock, or worse.
1054 _Jv_MutexUnlock(&(hl->si.mutex));
1055 maybe_remove_all_heavy(he, address &~HEAVY);
1056 // release lock bit, preserving
1057 // REQUEST_CONVERSION
1058 // and object address.
1059 }
1060 else
1061 {
1062 release_set(&(he -> address), address &~HEAVY);
1063 _Jv_MutexUnlock(&(hl->si.mutex));
1064 // Unlock after releasing the lock bit, so that
1065 // we don't switch to another thread prematurely.
1066 }
1067 }
1068 else
1069 {
1070 release_set(&(he -> address), address);
1071 _Jv_MutexUnlock(&(hl->si.mutex));
1072 }
1073 keep_live(addr);
1074}
1075
1076// The rest of these are moderately thin veneers on _Jv_Cond ops.
1077// The current version of Notify might be able to make the pthread
1078// call AFTER releasing the lock, thus saving some context switches??
1079
1080void
1081java::lang::Object::wait (jlong timeout, jint nanos)
1082{
1083 obj_addr_t addr = (obj_addr_t)this;
1084 _Jv_ThreadId_t self = _Jv_ThreadSelf();
1085 unsigned hash = JV_SYNC_HASH(addr);
1086 hash_entry * he = light_locks + hash;
1087 unsigned count;
1088 obj_addr_t address;
1089 heavy_lock *hl;
1090
1091 if (__builtin_expect (timeout < 0 || nanos < 0 || nanos > 999999, false))
1092 throw new IllegalArgumentException;
1093retry:
1094 address = he -> address;
1095 address &= ~LOCKED;
1096 if (!compare_and_swap(&(he -> address), address, address | LOCKED))
1097 {
1098 wait_unlocked(he);
1099 goto retry;
1100 }
1101 // address does not have the lock bit set. We hold the lock on he.
1102 if ((address & ~FLAGS) == addr)
1103 {
1104 // Convert to heavyweight.
1105 if (he -> light_thr_id != self)
1106 {
1107# ifdef LOCK_DEBUG
1108 fprintf(stderr, "Found wrong lightweight lock owner in wait "
1109 "address = 0x%lx pid = %d\n", address, getpid());
1110 print_he(he);
1111 for(;;) {}
1112# endif
1113 release_set(&(he -> address), address);
1114 throw new IllegalMonitorStateException (JvNewStringLatin1
1115 ("current thread not owner"));
1116 }
1117 count = he -> light_count;
1118 hl = get_heavy(addr, he);
1119 he -> light_count = 0;
1120 he -> heavy_count += count + 1;
1121 for (unsigned i = 0; i <= count; ++i)
1122 _Jv_MutexLock(&(hl->si.mutex));
1123 // Again release the he lock after acquiring the mutex.
1124 he -> light_thr_id = INVALID_THREAD_ID;
1125 release_set(&(he -> address), HEAVY); // lightweight lock now unused.
1126 if (address & REQUEST_CONVERSION)
1127 _Jv_CondNotify (&(hl->si.condition), &(hl->si.mutex));
1128 }
1129 else /* We should hold the heavyweight lock. */
1130 {
1131 hl = find_heavy(addr, he);
1132 release_set(&(he -> address), address);
1133 if (0 == hl)
1134 {
1135# ifdef LOCK_DEBUG
1136 fprintf(stderr, "Couldn't find heavy lock in wait "
1137 "addr = 0x%lx pid = %d\n", addr, getpid());
1138 print_he(he);
1139 for(;;) {}
1140# endif
1141 throw new IllegalMonitorStateException (JvNewStringLatin1
1142 ("current thread not owner"));
1143 }
1144 assert(address & HEAVY);
1145 }
1146 switch (_Jv_CondWait (&(hl->si.condition), &(hl->si.mutex), timeout, nanos))
1147 {
1148 case _JV_NOT_OWNER:
1149 throw new IllegalMonitorStateException (JvNewStringLatin1
1150 ("current thread not owner"));
1151 case _JV_INTERRUPTED:
1152 if (Thread::interrupted ())
1153 throw new InterruptedException;
1154 }
1155}
1156
1157void
1158java::lang::Object::notify (void)
1159{
1160 obj_addr_t addr = (obj_addr_t)this;
1161 _Jv_ThreadId_t self = _Jv_ThreadSelf();
1162 unsigned hash = JV_SYNC_HASH(addr);
1163 hash_entry * he = light_locks + hash;
1164 heavy_lock *hl;
1165 obj_addr_t address;
1166 int result;
1167
1168retry:
1169 address = ((he -> address) & ~LOCKED);
1170 if (!compare_and_swap(&(he -> address), address, address | LOCKED))
1171 {
1172 wait_unlocked(he);
1173 goto retry;
1174 }
1175 if ((address & ~FLAGS) == addr && he -> light_thr_id == self)
1176 {
1177 // We hold lightweight lock. Since it has not
1178 // been inflated, there are no waiters.
1179 release_set(&(he -> address), address); // unlock
1180 return;
1181 }
1182 hl = find_heavy(addr, he);
1183 // Hl can't disappear since we point to the underlying object.
1184 // It's important that we release the lock bit before the notify, since
1185 // otherwise we will try to wake up thee target while we still hold the
1186 // bit. This results in lock bit contention, which we don't handle
1187 // terribly well.
1188 release_set(&(he -> address), address); // unlock
1189 if (0 == hl)
1190 {
1191 throw new IllegalMonitorStateException(JvNewStringLatin1
1192 ("current thread not owner"));
1193 return;
1194 }
1195 result = _Jv_CondNotify(&(hl->si.condition), &(hl->si.mutex));
1196 keep_live(addr);
1197 if (__builtin_expect (result, 0))
1198 throw new IllegalMonitorStateException(JvNewStringLatin1
1199 ("current thread not owner"));
1200}
1201
1202void
1203java::lang::Object::notifyAll (void)
1204{
1205 obj_addr_t addr = (obj_addr_t)this;
1206 _Jv_ThreadId_t self = _Jv_ThreadSelf();
1207 unsigned hash = JV_SYNC_HASH(addr);
1208 hash_entry * he = light_locks + hash;
1209 heavy_lock *hl;
1210 obj_addr_t address;
1211 int result;
1212
1213retry:
1214 address = (he -> address) & ~LOCKED;
1215 if (!compare_and_swap(&(he -> address), address, address | LOCKED))
1216 {
1217 wait_unlocked(he);
1218 goto retry;
1219 }
1220 hl = find_heavy(addr, he);
1221 if ((address & ~FLAGS) == addr && he -> light_thr_id == self)
1222 {
1223 // We hold lightweight lock. Since it has not
1224 // been inflated, there are no waiters.
1225 release_set(&(he -> address), address); // unlock
1226 return;
1227 }
1228 release_set(&(he -> address), address); // unlock
1229 if (0 == hl)
1230 {
1231 throw new IllegalMonitorStateException(JvNewStringLatin1
1232 ("current thread not owner"));
1233 }
1234 result = _Jv_CondNotifyAll(&(hl->si.condition), &(hl->si.mutex));
1235 if (__builtin_expect (result, 0))
1236 throw new IllegalMonitorStateException(JvNewStringLatin1
1237 ("current thread not owner"));
1238}
1239
1240// This is declared in Java code and in Object.h.
1241// It should never be called with JV_HASH_SYNCHRONIZATION
1242void
1243java::lang::Object::sync_init (void)
1244{
1245 throw new IllegalMonitorStateException(JvNewStringLatin1
1246 ("internal error: sync_init"));
1247}
1248
1249// This is called on startup and declared in Object.h.
1250// For now we just make it a no-op.
1251void
1252_Jv_InitializeSyncMutex (void)
1253{
1254}
1255
1256#endif /* JV_HASH_SYNCHRONIZATION */
1257
Note: See TracBrowser for help on using the repository browser.