OSDN Git Service

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