* src/threads/lock.cpp (sable_flc_waiting): Slight optimization, avoiding
[cacao.git] / src / threads / lock.cpp
1 /* src/threads/lock.cpp - lock implementation
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sys/time.h>
33
34 #include "vm/types.h"
35
36 #include "mm/memory.h"
37
38 #include "native/llni.h"
39
40 #include "threads/atomic.hpp"
41 #include "threads/lock.hpp"
42 #include "threads/mutex.hpp"
43 #include "threads/threadlist.hpp"
44 #include "threads/thread.hpp"
45
46 #include "toolbox/list.hpp"
47
48 #include "vm/exceptions.hpp"
49 #include "vm/finalizer.h"
50 #include "vm/global.h"
51 #include "vm/options.h"
52 #include "vm/string.hpp"
53 #include "vm/vm.hpp"
54
55 #if defined(ENABLE_STATISTICS)
56 # include "vm/statistics.h"
57 #endif
58
59 #if defined(ENABLE_VMLOG)
60 #include <vmlog_cacao.h>
61 #endif
62
63 #if defined(ENABLE_JVMTI)
64 #include "native/jvmti/cacaodbg.h"
65 #endif
66
67 #if defined(ENABLE_GC_BOEHM)
68 # include "mm/boehm-gc/include/gc.h"
69 #endif
70
71
72 /* debug **********************************************************************/
73
74 #if !defined(NDEBUG)
75 # define DEBUGLOCKS(format) \
76     do { \
77         if (opt_DebugLocks) { \
78             log_println format; \
79         } \
80     } while (0)
81 #else
82 # define DEBUGLOCKS(format)
83 #endif
84
85
86 /******************************************************************************/
87 /* MACROS                                                                     */
88 /******************************************************************************/
89
90 /* number of lock records in the first pool allocated for a thread */
91 #define LOCK_INITIAL_LOCK_RECORDS 8
92
93 #define LOCK_INITIAL_HASHTABLE_SIZE  1613  /* a prime in the middle between 1024 and 2048 */
94
95
96 /******************************************************************************/
97 /* MACROS FOR THIN/FAT LOCKS                                                  */
98 /******************************************************************************/
99
100 /* We use a variant of the tasuki locks described in the paper
101  *     
102  *     Tamiya Onodera, Kiyokuni Kawachiya
103  *     A Study of Locking Objects with Bimodal Fields
104  *     Proceedings of the ACM OOPSLA '99, pp. 223-237
105  *     1999
106  *
107  * The underlying thin locks are a variant of the thin locks described in
108  * 
109  *     Bacon, Konuru, Murthy, Serrano
110  *     Thin Locks: Featherweight Synchronization for Java
111  *         Proceedings of the ACM Conference on Programming Language Design and 
112  *         Implementation (Montreal, Canada), SIGPLAN Notices volume 33, number 6,
113  *         June 1998
114  *
115  * In thin lock mode the lockword looks like this:
116  *
117  *     ,----------------------,-----------,---,
118  *     |      thread ID       |   count   | 0 |
119  *     `----------------------'-----------'---'
120  *
121  *     thread ID......the 'index' of the owning thread, or 0
122  *     count..........number of times the lock has been entered minus 1
123  *     0..............the shape bit is 0 in thin lock mode
124  *
125  * In fat lock mode it is basically a lock_record_t *:
126  *
127  *     ,----------------------------------,---,
128  *     |    lock_record_t * (without LSB) | 1 |
129  *     `----------------------------------'---'
130  *
131  *     1..............the shape bit is 1 in fat lock mode
132  */
133
134 /* global variables ***********************************************************/
135
136 /* hashtable mapping objects to lock records */
137 static lock_hashtable_t lock_hashtable;
138
139
140 /******************************************************************************/
141 /* PROTOTYPES                                                                 */
142 /******************************************************************************/
143
144 static void lock_hashtable_init(void);
145
146 static inline Lockword* lock_lockword_get(java_handle_t* o);
147 static void lock_record_enter(threadobject *t, lock_record_t *lr);
148 static void lock_record_exit(threadobject *t, lock_record_t *lr);
149 static bool lock_record_wait(threadobject *t, lock_record_t *lr, s8 millis, s4 nanos);
150 static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one);
151
152
153 /*============================================================================*/
154 /* INITIALIZATION OF DATA STRUCTURES                                          */
155 /*============================================================================*/
156
157
158 /* lock_init *******************************************************************
159
160    Initialize global data for locking.
161
162 *******************************************************************************/
163
164 void lock_init(void)
165 {
166         /* initialize lock hashtable */
167
168         lock_hashtable_init();
169
170 #if defined(ENABLE_VMLOG)
171         vmlog_cacao_init_lock();
172 #endif
173 }
174
175
176 /* lock_record_new *************************************************************
177
178    Allocate a lock record.
179
180 *******************************************************************************/
181
182 static lock_record_t *lock_record_new(void)
183 {
184         lock_record_t *lr;
185
186         /* allocate the data structure on the C heap */
187
188         lr = NEW(lock_record_t);
189
190 #if defined(ENABLE_STATISTICS)
191         if (opt_stat)
192                 size_lock_record += sizeof(lock_record_t);
193 #endif
194
195         /* initialize the members */
196
197         lr->object  = NULL;
198         lr->owner   = NULL;
199         lr->count   = 0;
200         lr->waiters = new List<threadobject*>();
201
202 #if defined(ENABLE_GC_CACAO)
203         /* register the lock object as weak reference with the GC */
204
205         gc_weakreference_register(&(lr->object), GC_REFTYPE_LOCKRECORD);
206 #endif
207
208         // Initialize the mutex.
209         lr->mutex = new Mutex();
210
211         DEBUGLOCKS(("[lock_record_new   : lr=%p]", (void *) lr));
212
213         return lr;
214 }
215
216
217 /* lock_record_free ************************************************************
218
219    Free a lock record.
220
221    IN:
222        lr....lock record to free
223
224 *******************************************************************************/
225
226 static void lock_record_free(lock_record_t *lr)
227 {
228         DEBUGLOCKS(("[lock_record_free  : lr=%p]", (void *) lr));
229
230         // Destroy the mutex.
231         delete lr->mutex;
232
233 #if defined(ENABLE_GC_CACAO)
234         /* unregister the lock object reference with the GC */
235
236         gc_weakreference_unregister(&(lr->object));
237 #endif
238
239         // Free the waiters list.
240         delete lr->waiters;
241
242         /* Free the data structure. */
243
244         FREE(lr, lock_record_t);
245
246 #if defined(ENABLE_STATISTICS)
247         if (opt_stat)
248                 size_lock_record -= sizeof(lock_record_t);
249 #endif
250 }
251
252
253 /*============================================================================*/
254 /* HASHTABLE MAPPING OBJECTS TO LOCK RECORDS                                  */
255 /*============================================================================*/
256
257 /* lock_hashtable_init *********************************************************
258
259    Initialize the global hashtable mapping objects to lock records.
260
261 *******************************************************************************/
262
263 static void lock_hashtable_init(void)
264 {
265         lock_hashtable.mutex   = new Mutex();
266
267         lock_hashtable.size    = LOCK_INITIAL_HASHTABLE_SIZE;
268         lock_hashtable.entries = 0;
269         lock_hashtable.ptr     = MNEW(lock_record_t *, lock_hashtable.size);
270
271 #if defined(ENABLE_STATISTICS)
272         if (opt_stat)
273                 size_lock_hashtable += sizeof(lock_record_t *) * lock_hashtable.size;
274 #endif
275
276         MZERO(lock_hashtable.ptr, lock_record_t *, lock_hashtable.size);
277 }
278
279
280 /* lock_hashtable_grow *********************************************************
281
282    Grow the lock record hashtable to about twice its current size and
283    rehash the entries.
284
285 *******************************************************************************/
286
287 /* must be called with hashtable mutex locked */
288 static void lock_hashtable_grow(void)
289 {
290         u4 oldsize;
291         u4 newsize;
292         lock_record_t **oldtable;
293         lock_record_t **newtable;
294         lock_record_t *lr;
295         lock_record_t *next;
296         u4 i;
297         u4 h;
298         u4 newslot;
299
300         /* allocate a new table */
301
302         oldsize = lock_hashtable.size;
303         newsize = oldsize*2 + 1; /* XXX should use prime numbers */
304
305         DEBUGLOCKS(("growing lock hashtable to size %d", newsize));
306
307         oldtable = lock_hashtable.ptr;
308         newtable = MNEW(lock_record_t *, newsize);
309
310 #if defined(ENABLE_STATISTICS)
311         if (opt_stat)
312                 size_lock_hashtable += sizeof(lock_record_t *) * newsize;
313 #endif
314
315         MZERO(newtable, lock_record_t *, newsize);
316
317         /* rehash the entries */
318
319         for (i = 0; i < oldsize; i++) {
320                 lr = oldtable[i];
321                 while (lr) {
322                         next = lr->hashlink;
323
324                         h = heap_hashcode(lr->object);
325                         newslot = h % newsize;
326
327                         lr->hashlink = newtable[newslot];
328                         newtable[newslot] = lr;
329
330                         lr = next;
331                 }
332         }
333
334         /* replace the old table */
335
336         lock_hashtable.ptr  = newtable;
337         lock_hashtable.size = newsize;
338
339         MFREE(oldtable, lock_record_t *, oldsize);
340
341 #if defined(ENABLE_STATISTICS)
342         if (opt_stat)
343                 size_lock_hashtable -= sizeof(lock_record_t *) * oldsize;
344 #endif
345 }
346
347
348 /* lock_hashtable_cleanup ******************************************************
349
350    Removes (and frees) lock records which have a cleared object reference
351    from the hashtable. The locked object was reclaimed by the GC.
352
353 *******************************************************************************/
354
355 #if defined(ENABLE_GC_CACAO)
356 void lock_hashtable_cleanup(void)
357 {
358         threadobject  *t;
359         lock_record_t *lr;
360         lock_record_t *prev;
361         lock_record_t *next;
362         int i;
363
364         t = THREADOBJECT;
365
366         /* lock the hashtable */
367
368         Mutex_lock(lock_hashtable.mutex);
369
370         /* search the hashtable for cleared references */
371
372         for (i = 0; i < lock_hashtable.size; i++) {
373                 lr = lock_hashtable.ptr[i];
374                 prev = NULL;
375
376                 while (lr) {
377                         next = lr->hashlink;
378
379                         /* remove lock records with cleared references */
380
381                         if (lr->object == NULL) {
382
383                                 /* unlink the lock record from the hashtable */
384
385                                 if (prev == NULL)
386                                         lock_hashtable.ptr[i] = next;
387                                 else
388                                         prev->hashlink = next;
389
390                                 /* free the lock record */
391
392                                 lock_record_free(lr);
393
394                         } else {
395                                 prev = lr;
396                         }
397
398                         lr = next;
399                 }
400         }
401
402         /* unlock the hashtable */
403
404         Mutex_unlock(lock_hashtable.mutex);
405 }
406 #endif
407
408
409 /* lock_hashtable_get **********************************************************
410
411    Find the lock record for the given object.  If it does not exists,
412    yet, create it and enter it in the hashtable.
413
414    IN:
415           o....the object to look up
416
417    RETURN VALUE:
418       the lock record to use for this object
419
420 *******************************************************************************/
421
422 #if defined(ENABLE_GC_BOEHM)
423 static void lock_record_finalizer(void *object, void *p);
424 #endif
425
426 static lock_record_t *lock_hashtable_get(java_handle_t* o)
427 {
428         // This function is inside a critical section.
429         GCCriticalSection cs;
430
431         u4             slot;
432         lock_record_t *lr;
433
434         Lockword* lockword = lock_lockword_get(o);
435
436         if (lockword->is_fat_lock())
437                 return lockword->get_fat_lock();
438
439         // Lock the hashtable.
440         lock_hashtable.mutex->lock();
441
442         /* lookup the lock record in the hashtable */
443
444         slot = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
445         lr   = lock_hashtable.ptr[slot];
446
447         for (; lr != NULL; lr = lr->hashlink) {
448                 if (lr->object == LLNI_DIRECT(o))
449                         break;
450         }
451
452         if (lr == NULL) {
453                 /* not found, we must create a new one */
454
455                 lr = lock_record_new();
456
457                 lr->object = LLNI_DIRECT(o);
458
459 #if defined(ENABLE_GC_BOEHM)
460                 /* register new finalizer to clean up the lock record */
461
462                 GC_REGISTER_FINALIZER(LLNI_DIRECT(o), lock_record_finalizer, 0, 0, 0);
463 #endif
464
465                 /* enter it in the hashtable */
466
467                 lr->hashlink             = lock_hashtable.ptr[slot];
468                 lock_hashtable.ptr[slot] = lr;
469                 lock_hashtable.entries++;
470
471                 /* check whether the hash should grow */
472
473                 if (lock_hashtable.entries * 3 > lock_hashtable.size * 4) {
474                         lock_hashtable_grow();
475                 }
476         }
477
478         // Unlock the hashtable.
479         lock_hashtable.mutex->unlock();
480
481         /* return the new lock record */
482
483         return lr;
484 }
485
486
487 /* lock_hashtable_remove *******************************************************
488
489    Remove the lock record for the given object from the hashtable
490    and free it afterwards.
491
492    IN:
493        t....the current thread
494        o....the object to look up
495
496 *******************************************************************************/
497
498 static void lock_hashtable_remove(threadobject *t, java_handle_t *o)
499 {
500         lock_record_t *lr;
501         u4             slot;
502         lock_record_t *tmplr;
503
504         // Lock the hashtable.
505         lock_hashtable.mutex->lock();
506
507         /* get lock record */
508
509         Lockword* lockword = lock_lockword_get(o);
510
511         // Sanity check.
512         assert(lockword->is_fat_lock());
513
514         lr = lockword->get_fat_lock();
515
516         /* remove the lock-record from the hashtable */
517
518         slot  = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
519         tmplr = lock_hashtable.ptr[slot];
520
521         if (tmplr == lr) {
522                 /* special handling if it's the first in the chain */
523
524                 lock_hashtable.ptr[slot] = lr->hashlink;
525         }
526         else {
527                 for (; tmplr != NULL; tmplr = tmplr->hashlink) {
528                         if (tmplr->hashlink == lr) {
529                                 tmplr->hashlink = lr->hashlink;
530                                 break;
531                         }
532                 }
533
534                 assert(tmplr != NULL);
535         }
536
537         /* decrease entry count */
538
539         lock_hashtable.entries--;
540
541         // Unlock the hashtable.
542         lock_hashtable.mutex->unlock();
543
544         /* free the lock record */
545
546         lock_record_free(lr);
547 }
548
549
550 /* lock_record_finalizer *******************************************************
551
552    XXX Remove me for exact GC.
553
554 *******************************************************************************/
555
556 static void lock_record_finalizer(void *object, void *p)
557 {
558         java_handle_t *o;
559         classinfo     *c;
560
561         o = (java_handle_t *) object;
562
563 #if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
564         /* XXX this is only a dirty hack to make Boehm work with handles */
565
566         o = LLNI_WRAP((java_object_t *) o);
567 #endif
568
569         LLNI_class_get(o, c);
570
571 #if !defined(NDEBUG)
572         if (opt_DebugFinalizer) {
573                 log_start();
574                 log_print("[finalizer lockrecord: o=%p p=%p class=", object, p);
575                 class_print(c);
576                 log_print("]");
577                 log_finish();
578         }
579 #endif
580
581         /* check for a finalizer function */
582
583         if (c->finalizer != NULL)
584                 finalizer_run(object, p);
585
586         /* remove the lock-record entry from the hashtable and free it */
587
588         lock_hashtable_remove(THREADOBJECT, o);
589 }
590
591
592 /*============================================================================*/
593 /* LOCKING ALGORITHM                                                          */
594 /*============================================================================*/
595
596
597 /* lock_lockword_get ***********************************************************
598
599    Get the lockword for the given object.
600
601    IN:
602       o............the object
603
604 *******************************************************************************/
605
606 static inline Lockword* lock_lockword_get(java_handle_t* o)
607 {
608 #if defined(ENABLE_GC_CACAO)
609         // Sanity check.
610         assert(GCCriticalSection::inside() == true);
611 #endif
612
613         return &(LLNI_DIRECT(o)->lockword);
614 }
615
616
617 /* lock_record_enter ***********************************************************
618
619    Enter the lock represented by the given lock record.
620
621    IN:
622       t.................the current thread
623           lr................the lock record
624
625 *******************************************************************************/
626
627 static inline void lock_record_enter(threadobject *t, lock_record_t *lr)
628 {
629         lr->mutex->lock();
630         lr->owner = t;
631 }
632
633
634 /* lock_record_exit ************************************************************
635
636    Release the lock represented by the given lock record.
637
638    IN:
639       t.................the current thread
640           lr................the lock record
641
642    PRE-CONDITION:
643       The current thread must own the lock represented by this lock record.
644           This is NOT checked by this function!
645
646 *******************************************************************************/
647
648 static inline void lock_record_exit(threadobject *t, lock_record_t *lr)
649 {
650         lr->owner = NULL;
651         lr->mutex->unlock();
652 }
653
654
655 /* lock_inflate ****************************************************************
656
657    Inflate the lock of the given object. This may only be called by the
658    owner of the monitor of the object.
659
660    IN:
661           o............the object of which to inflate the lock
662           lr...........the lock record to install. The current thread must
663                        own the lock of this lock record!
664
665    PRE-CONDITION:
666       The current thread must be the owner of this object's monitor AND
667           of the lock record's lock!
668
669 *******************************************************************************/
670
671 static void lock_inflate(java_handle_t *o, lock_record_t *lr)
672 {
673         Lockword* lockword = lock_lockword_get(o);
674         lockword->inflate(lr);
675 }
676
677
678 static void sable_flc_waiting(Lockword *lockword, threadobject *t, java_handle_t *o)
679 {
680         int32_t index;
681         threadobject *t_other;
682         int old_flc;
683
684         index = lockword->get_thin_lock_thread_index();
685         t_other = ThreadList::get_thread_by_index(index);
686
687         // The lockword could have changed during our way here.  If the
688         // thread index is zero, the lock got unlocked and we simply
689         // return.
690         if (t_other == NULL)
691 /*              failure, TODO: add statistics */
692                 return;
693
694         t_other->flc_lock->lock();
695         old_flc = t_other->flc_bit;
696         t_other->flc_bit = true;
697
698         DEBUGLOCKS(("thread %d set flc bit for lock-holding thread %d", t->index, t_other->index));
699
700         // Set FLC bit first, then read the lockword again.
701         Atomic::memory_barrier();
702
703         lockword = lock_lockword_get(o);
704
705         /* Lockword is still the way it was seen before */
706         if (lockword->is_thin_lock() && (lockword->get_thin_lock_thread_index() == index))
707         {
708                 threadobject *f;
709                 /* Add tuple (t, o) to the other thread's FLC list */
710                 t->flc_object = o;
711                 t->flc_next = t_other->flc_list;
712                 t_other->flc_list = t;
713                 if (t->flc_next == 0)
714                         t_other->flc_tail = t;
715                 f = t_other->flc_tail;
716
717                 for (;;)
718                 {
719                         threadobject *current;
720
721                         // Wait until another thread sees the flc bit and notifies
722                         // us of unlocking.
723                         t->flc_cond->wait(t_other->flc_lock);
724
725                         if (t_other->flc_tail != f)
726                                 break;
727                         /* Traverse FLC list looking if we're still there */
728                         current = t_other->flc_list;
729                         while (current && current != t)
730                                 current = current->flc_next;
731                         if (!current)
732                                 /* not in list anymore, can stop waiting */
733                                 break;
734
735                         /* We are still in the list -- the other thread cannot have seen
736                            the FLC bit yet */
737                         assert(t_other->flc_bit);
738                 }
739
740                 t->flc_object = NULL;   /* for garbage collector? */
741                 t->flc_next = NULL;
742         }
743         else
744                 t_other->flc_bit = old_flc;
745
746         t_other->flc_lock->unlock();
747 }
748
749 static void notify_flc_waiters(threadobject *t, java_handle_t *o)
750 {
751         threadobject *current;
752
753         t->flc_lock->lock();
754
755         current = t->flc_list;
756         while (current)
757         {
758                 if (current->flc_object != o)
759                 {
760                         /* The object has to be inflated so the other threads can properly
761                            block on it. */
762
763                         // Only if not already inflated.
764                         Lockword* lockword = lock_lockword_get(current->flc_object);
765                         if (lockword->is_thin_lock()) {
766                                 lock_record_t *lr = lock_hashtable_get(current->flc_object);
767                                 lock_record_enter(t, lr);
768
769                                 DEBUGLOCKS(("thread %d inflating lock of %p to lr %p",
770                                                         t->index, (void*) current->flc_object, (void*) lr));
771
772                                 lock_inflate(current->flc_object, lr);
773                         }
774                 }
775
776                 // Wake the waiting threads.
777                 current->flc_cond->broadcast();
778
779                 current = current->flc_next;
780         }
781
782         t->flc_list = NULL;
783         t->flc_bit = false;
784
785         t->flc_lock->unlock();
786 }
787
788 /* lock_monitor_enter **********************************************************
789
790    Acquire the monitor of the given object. If the current thread already
791    owns the monitor, the lock counter is simply increased.
792
793    This function blocks until it can acquire the monitor.
794
795    IN:
796       t............the current thread
797           o............the object of which to enter the monitor
798
799    RETURN VALUE:
800       true.........the lock has been successfully acquired
801           false........an exception has been thrown
802
803 *******************************************************************************/
804
805 bool lock_monitor_enter(java_handle_t *o)
806 {
807         // This function is inside a critical section.
808         GCCriticalSection cs;
809
810         if (o == NULL) {
811                 exceptions_throw_nullpointerexception();
812                 return false;
813         }
814
815         threadobject* t = thread_get_current();
816
817         uintptr_t thinlock = t->thinlock;
818
819 retry:
820         // Most common case: try to thin-lock an unlocked object.
821         Lockword* lockword = lock_lockword_get(o);
822         bool result = lockword->lock(thinlock);
823
824         if (result == true) {
825                 // Success, we locked it.
826                 // NOTE: The Java Memory Model requires an instruction barrier
827                 // here (because of the CAS above).
828                 Atomic::instruction_barrier();
829                 return true;
830         }
831
832         // Next common case: recursive lock with small recursion count.
833         // NOTE: We don't have to worry about stale values here, as any
834         // stale value will indicate another thread holding the lock (or
835         // an inflated lock).
836         if (lockword->get_thin_lock_without_count() == thinlock) {
837                 // We own this monitor.  Check the current recursion count.
838                 if (lockword->is_max_thin_lock_count() == false) {
839                         // The recursion count is low enough.
840                         lockword->increase_thin_lock_count();
841
842                         // Success, we locked it.
843                         return true;
844                 }
845                 else {
846                         // Recursion count overflow.
847                         lock_record_t* lr = lock_hashtable_get(o);
848                         lock_record_enter(t, lr);
849                         lock_inflate(o, lr);
850                         lr->count++;
851
852                         notify_flc_waiters(t, o);
853
854                         return true;
855                 }
856         }
857
858         // The lock is either contented or fat.
859         if (lockword->is_fat_lock()) {
860                 lock_record_t* lr = lockword->get_fat_lock();
861
862                 // Check for recursive entering.
863                 if (lr->owner == t) {
864                         lr->count++;
865                         return true;
866                 }
867
868                 // Acquire the mutex of the lock record.
869                 lock_record_enter(t, lr);
870
871                 // Sanity check.
872                 assert(lr->count == 0);
873                 return true;
874         }
875
876         /****** inflation path ******/
877
878 #if defined(ENABLE_JVMTI)
879         /* Monitor Contended Enter */
880         jvmti_MonitorContendedEntering(false, o);
881 #endif
882
883         sable_flc_waiting(lockword, t, o);
884
885 #if defined(ENABLE_JVMTI)
886         /* Monitor Contended Entered */
887         jvmti_MonitorContendedEntering(true, o);
888 #endif
889         goto retry;
890 }
891
892
893 /* lock_monitor_exit ***********************************************************
894
895    Decrement the counter of a (currently owned) monitor. If the counter
896    reaches zero, release the monitor.
897
898    If the current thread is not the owner of the monitor, an 
899    IllegalMonitorState exception is thrown.
900
901    IN:
902       t............the current thread
903           o............the object of which to exit the monitor
904
905    RETURN VALUE:
906       true.........everything ok,
907           false........an exception has been thrown
908
909 *******************************************************************************/
910
911 bool lock_monitor_exit(java_handle_t* o)
912 {
913         // This function is inside a critical section.
914         GCCriticalSection cs;
915
916         if (o == NULL) {
917                 exceptions_throw_nullpointerexception();
918                 return false;
919         }
920
921         threadobject* t = thread_get_current();
922
923         uintptr_t thinlock = t->thinlock;
924
925         // We don't have to worry about stale values here, as any stale
926         // value will indicate that we don't own the lock.
927         Lockword* lockword = lock_lockword_get(o);
928
929         // Most common case: we release a thin lock that we hold once.
930         if (lockword->get_thin_lock() == thinlock) {
931                 // Memory barrier for Java Memory Model.
932                 Atomic::write_memory_barrier();
933                 lockword->unlock();
934                 // Memory barrier for thin locking.
935                 Atomic::memory_barrier();
936
937                 /* check if there has been a flat lock contention on this object */
938
939                 if (t->flc_bit) {
940                         DEBUGLOCKS(("thread %d saw flc bit", t->index));
941
942                         /* there has been a contention on this thin lock */
943                         notify_flc_waiters(t, o);
944                 }
945
946                 return true;
947         }
948
949         // Next common case: we release a recursive lock, count > 0.
950         if (lockword->get_thin_lock_without_count() == thinlock) {
951                 lockword->decrease_thin_lock_count();
952                 return true;
953         }
954
955         // Either the lock is fat, or we don't hold it at all.
956         if (lockword->is_fat_lock()) {
957                 lock_record_t* lr = lockword->get_fat_lock();
958
959                 // Check if we own this monitor.
960                 // NOTE: We don't have to worry about stale values here, as
961                 // any stale value will be != t and thus fail this check.
962                 if (lr->owner != t) {
963                         exceptions_throw_illegalmonitorstateexception();
964                         return false;
965                 }
966
967                 /* { the current thread `t` owns the lock record `lr` on object `o` } */
968
969                 if (lr->count != 0) {
970                         // We had locked this one recursively.  Just decrement, it
971                         // will still be locked.
972                         lr->count--;
973                         return true;
974                 }
975
976                 // Unlock this lock record.
977                 lock_record_exit(t, lr);
978                 return true;
979         }
980
981         // Legal thin lock cases have been handled above, so this is an
982         // error.
983         exceptions_throw_illegalmonitorstateexception();
984
985         return false;
986 }
987
988
989 /* lock_record_add_waiter ******************************************************
990
991    Add a thread to the list of waiting threads of a lock record.
992
993    IN:
994       lr...........the lock record
995       thread.......the thread to add
996
997 *******************************************************************************/
998
999 static void lock_record_add_waiter(lock_record_t *lr, threadobject* t)
1000 {
1001         // Add the thread as last entry to waiters list.
1002         lr->waiters->push_back(t);
1003
1004 #if defined(ENABLE_STATISTICS)
1005         if (opt_stat)
1006                 size_lock_waiter += sizeof(threadobject*);
1007 #endif
1008 }
1009
1010
1011 /* lock_record_remove_waiter ***************************************************
1012
1013    Remove a thread from the list of waiting threads of a lock record.
1014
1015    IN:
1016       lr...........the lock record
1017       t............the current thread
1018
1019    PRE-CONDITION:
1020       The current thread must be the owner of the lock record.
1021    
1022 *******************************************************************************/
1023
1024 static void lock_record_remove_waiter(lock_record_t *lr, threadobject* t)
1025 {
1026         // Remove the thread from the waiters.
1027         lr->waiters->remove(t);
1028
1029 #if defined(ENABLE_STATISTICS)
1030         if (opt_stat)
1031                 size_lock_waiter -= sizeof(threadobject*);
1032 #endif
1033 }
1034
1035
1036 /* lock_record_wait ************************************************************
1037
1038    Wait on a lock record for a given (maximum) amount of time.
1039
1040    IN:
1041       t............the current thread
1042           lr...........the lock record
1043           millis.......milliseconds of timeout
1044           nanos........nanoseconds of timeout
1045
1046    RETURN VALUE:
1047       true.........we have been interrupted,
1048       false........everything ok
1049
1050    PRE-CONDITION:
1051       The current thread must be the owner of the lock record.
1052           This is NOT checked by this function!
1053    
1054 *******************************************************************************/
1055
1056 static bool lock_record_wait(threadobject *thread, lock_record_t *lr, s8 millis, s4 nanos)
1057 {
1058         s4   lockcount;
1059         bool wasinterrupted = false;
1060
1061         DEBUGLOCKS(("[lock_record_wait  : lr=%p, t=%p, millis=%lld, nanos=%d]",
1062                                 lr, thread, millis, nanos));
1063
1064         /* { the thread t owns the fat lock record lr on the object o } */
1065
1066         /* register us as waiter for this object */
1067
1068         lock_record_add_waiter(lr, thread);
1069
1070         /* remember the old lock count */
1071
1072         lockcount = lr->count;
1073
1074         /* unlock this record */
1075
1076         lr->count = 0;
1077         lock_record_exit(thread, lr);
1078
1079         /* wait until notified/interrupted/timed out */
1080
1081         threads_wait_with_timeout_relative(thread, millis, nanos);
1082
1083         /* re-enter the monitor */
1084
1085         lock_record_enter(thread, lr);
1086
1087         /* remove us from the list of waiting threads */
1088
1089         lock_record_remove_waiter(lr, thread);
1090
1091         /* restore the old lock count */
1092
1093         lr->count = lockcount;
1094
1095         /* We can only be signaled OR interrupted, not both. If both flags
1096            are set, reset only signaled and leave the thread in
1097            interrupted state. Otherwise, clear both. */
1098
1099         if (!thread->signaled) {
1100                 wasinterrupted = thread->interrupted;
1101                 thread->interrupted = false;
1102         }
1103
1104         thread->signaled = false;
1105
1106         /* return if we have been interrupted */
1107
1108         return wasinterrupted;
1109 }
1110
1111
1112 /* lock_monitor_wait ***********************************************************
1113
1114    Wait on an object for a given (maximum) amount of time.
1115
1116    IN:
1117       t............the current thread
1118           o............the object
1119           millis.......milliseconds of timeout
1120           nanos........nanoseconds of timeout
1121
1122    PRE-CONDITION:
1123       The current thread must be the owner of the object's monitor.
1124    
1125 *******************************************************************************/
1126
1127 static void lock_monitor_wait(threadobject *t, java_handle_t *o, s8 millis, s4 nanos)
1128 {
1129         lock_record_t *lr;
1130
1131         Lockword* lockword = lock_lockword_get(o);
1132
1133         // Check if we own this monitor.
1134         // NOTE: We don't have to worry about stale values here, as any
1135         // stale value will fail this check.
1136         if (lockword->is_fat_lock()) {
1137                 lr = lockword->get_fat_lock();
1138
1139                 if (lr->owner != t) {
1140                         exceptions_throw_illegalmonitorstateexception();
1141                         return;
1142                 }
1143         }
1144         else {
1145                 // It's a thin lock.
1146                 if (lockword->get_thin_lock_without_count() != t->thinlock) {
1147                         exceptions_throw_illegalmonitorstateexception();
1148                         return;
1149                 }
1150
1151                 // Get the lock-record.
1152                 lr = lock_hashtable_get(o);
1153                 lock_record_enter(t, lr);
1154
1155                 // Inflate this lock.
1156                 lockword->inflate(lr);
1157
1158                 notify_flc_waiters(t, o);
1159         }
1160
1161         /* { the thread t owns the fat lock record lr on the object o } */
1162
1163         if (lock_record_wait(t, lr, millis, nanos))
1164                 exceptions_throw_interruptedexception();
1165 }
1166
1167
1168 /* lock_record_notify **********************************************************
1169
1170    Notify one thread or all threads waiting on the given lock record.
1171
1172    IN:
1173       t............the current thread
1174           lr...........the lock record
1175           one..........if true, only notify one thread
1176
1177    PRE-CONDITION:
1178       The current thread must be the owner of the lock record.
1179           This is NOT checked by this function!
1180    
1181 *******************************************************************************/
1182
1183 static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one)
1184 {
1185 #if defined(ENABLE_GC_CACAO)
1186         // Sanity check.
1187         assert(GCCriticalSection::inside() == false);
1188 #endif
1189
1190         // { The thread t owns the fat lock record lr on the object o }
1191
1192         for (List<threadobject*>::iterator it = lr->waiters->begin(); it != lr->waiters->end(); it++) {
1193                 threadobject* waiter = *it;
1194
1195                 // We must skip threads which have already been notified. They
1196                 // will remove themselves from the list.
1197                 if (waiter->signaled)
1198                         continue;
1199
1200                 // Enter the wait-mutex.
1201                 waiter->waitmutex->lock();
1202
1203                 DEBUGLOCKS(("[lock_record_notify: lr=%p, t=%p, waitingthread=%p, one=%d]", lr, t, waiter, one));
1204
1205                 // Signal the waiter.
1206                 waiter->waitcond->signal();
1207
1208                 // Mark the thread as signaled.
1209                 waiter->signaled = true;
1210
1211                 // Leave the wait-mutex.
1212                 waiter->waitmutex->unlock();
1213
1214                 // If we should only wake one thread, we are done.
1215                 if (one)
1216                         break;
1217         }
1218 }
1219
1220
1221 /* lock_monitor_notify *********************************************************
1222
1223    Notify one thread or all threads waiting on the given object.
1224
1225    IN:
1226       t............the current thread
1227           o............the object
1228           one..........if true, only notify one thread
1229
1230    PRE-CONDITION:
1231       The current thread must be the owner of the object's monitor.
1232    
1233 *******************************************************************************/
1234
1235 static void lock_monitor_notify(threadobject *t, java_handle_t *o, bool one)
1236 {
1237         lock_record_t* lr = NULL;
1238
1239         {
1240                 // This scope is inside a critical section.
1241                 GCCriticalSection cs;
1242
1243                 Lockword* lockword = lock_lockword_get(o);
1244
1245                 // Check if we own this monitor.
1246                 // NOTE: We don't have to worry about stale values here, as any
1247                 // stale value will fail this check.
1248
1249                 if (lockword->is_fat_lock()) {
1250                         lr = lockword->get_fat_lock();
1251
1252                         if (lr->owner != t) {
1253                                 exceptions_throw_illegalmonitorstateexception();
1254                                 return;
1255                         }
1256                 }
1257                 else {
1258                         // It's a thin lock.
1259                         if (lockword->get_thin_lock_without_count() != t->thinlock) {
1260                                 exceptions_throw_illegalmonitorstateexception();
1261                                 return;
1262                         }
1263
1264                         // No thread can wait on a thin lock, so there's nothing to do.
1265                         return;
1266                 }
1267         }
1268
1269         // { The thread t owns the fat lock record lr on the object o }
1270         lock_record_notify(t, lr, one);
1271 }
1272
1273
1274
1275 /*============================================================================*/
1276 /* INQUIRY FUNCIONS                                                           */
1277 /*============================================================================*/
1278
1279
1280 /* lock_is_held_by_current_thread **********************************************
1281
1282    Return true if the current thread owns the monitor of the given object.
1283
1284    IN:
1285           o............the object
1286
1287    RETURN VALUE:
1288       true, if the current thread holds the lock of this object.
1289    
1290 *******************************************************************************/
1291
1292 bool lock_is_held_by_current_thread(java_handle_t *o)
1293 {
1294         // This function is inside a critical section.
1295         GCCriticalSection cs;
1296
1297         // Check if we own this monitor.
1298         // NOTE: We don't have to worry about stale values here, as any
1299         // stale value will fail this check.
1300         threadobject* t = thread_get_current();
1301         Lockword* lockword = lock_lockword_get(o);
1302
1303         if (lockword->is_fat_lock()) {
1304                 // It's a fat lock.
1305                 lock_record_t* lr = lockword->get_fat_lock();
1306                 return (lr->owner == t);
1307         }
1308         else {
1309                 // It's a thin lock.
1310                 return (lockword->get_thin_lock_without_count() == t->thinlock);
1311         }
1312 }
1313
1314
1315
1316 /*============================================================================*/
1317 /* WRAPPERS FOR OPERATIONS ON THE CURRENT THREAD                              */
1318 /*============================================================================*/
1319
1320
1321 /* lock_wait_for_object ********************************************************
1322
1323    Wait for the given object.
1324
1325    IN:
1326           o............the object
1327           millis.......milliseconds to wait
1328           nanos........nanoseconds to wait
1329    
1330 *******************************************************************************/
1331
1332 void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos)
1333 {
1334         threadobject *thread;
1335
1336         thread = THREADOBJECT;
1337
1338         lock_monitor_wait(thread, o, millis, nanos);
1339 }
1340
1341
1342 /* lock_notify_object **********************************************************
1343
1344    Notify one thread waiting on the given object.
1345
1346    IN:
1347           o............the object
1348    
1349 *******************************************************************************/
1350
1351 void lock_notify_object(java_handle_t *o)
1352 {
1353         threadobject *thread;
1354
1355         thread = THREADOBJECT;
1356
1357         lock_monitor_notify(thread, o, true);
1358 }
1359
1360
1361 /* lock_notify_all_object ******************************************************
1362
1363    Notify all threads waiting on the given object.
1364
1365    IN:
1366           o............the object
1367    
1368 *******************************************************************************/
1369
1370 void lock_notify_all_object(java_handle_t *o)
1371 {
1372         threadobject *thread;
1373
1374         thread = THREADOBJECT;
1375
1376         lock_monitor_notify(thread, o, false);
1377 }
1378
1379
1380 /*
1381  * These are local overrides for various environment variables in Emacs.
1382  * Please do not remove this and leave it at the end of the file, where
1383  * Emacs will automagically detect them.
1384  * ---------------------------------------------------------------------
1385  * Local variables:
1386  * mode: c++
1387  * indent-tabs-mode: t
1388  * c-basic-offset: 4
1389  * tab-width: 4
1390  * End:
1391  * vim:noexpandtab:sw=4:ts=4:
1392  */