23
23
24
24
#include " precompiled.hpp"
25
25
#include " gc/shared/gc_globals.hpp"
26
+ #include " gc/shared/gcLogPrecious.hpp"
26
27
#include " gc/x/xList.inline.hpp"
27
28
#include " gc/x/xLock.inline.hpp"
28
29
#include " gc/x/xPage.inline.hpp"
@@ -35,6 +36,8 @@ XUnmapper::XUnmapper(XPageAllocator* page_allocator) :
35
36
_page_allocator(page_allocator),
36
37
_lock(),
37
38
_queue(),
39
+ _enqueued_bytes(0 ),
40
+ _warned_sync_unmapping(false ),
38
41
_stop(false ) {
39
42
set_name (" XUnmapper" );
40
43
create_and_start ();
@@ -50,13 +53,50 @@ XPage* XUnmapper::dequeue() {
50
53
51
54
XPage* const page = _queue.remove_first ();
52
55
if (page != nullptr ) {
56
+ _enqueued_bytes -= page->size ();
53
57
return page;
54
58
}
55
59
56
60
_lock.wait ();
57
61
}
58
62
}
59
63
64
+ bool XUnmapper::try_enqueue (XPage* page) {
65
+ if (ZVerifyViews) {
66
+ // Asynchronous unmap and destroy is not supported with ZVerifyViews
67
+ return false ;
68
+ }
69
+
70
+ // Enqueue for asynchronous unmap and destroy
71
+ XLocker<XConditionLock> locker (&_lock);
72
+ if (is_saturated ()) {
73
+ // The unmapper thread is lagging behind and is unable to unmap memory fast enough
74
+ if (!_warned_sync_unmapping) {
75
+ _warned_sync_unmapping = true ;
76
+ log_warning_p (gc)(" WARNING: Encountered synchronous unmapping because asynchronous unmapping could not keep up" );
77
+ }
78
+ log_debug (gc, unmap)(" Synchronous unmapping " SIZE_FORMAT " M page" , page->size () / M);
79
+ return false ;
80
+ }
81
+
82
+ log_trace (gc, unmap)(" Asynchronous unmapping " SIZE_FORMAT " M page (" SIZE_FORMAT " M / " SIZE_FORMAT " M enqueued)" ,
83
+ page->size () / M, _enqueued_bytes / M, queue_capacity () / M);
84
+
85
+ _queue.insert_last (page);
86
+ _enqueued_bytes += page->size ();
87
+ _lock.notify_all ();
88
+
89
+ return true ;
90
+ }
91
+
92
+ size_t XUnmapper::queue_capacity () const {
93
+ return align_up<size_t >(_page_allocator->max_capacity () * ZAsyncUnmappingLimit / 100.0 , XGranuleSize);
94
+ }
95
+
96
+ bool XUnmapper::is_saturated () const {
97
+ return _enqueued_bytes >= queue_capacity ();
98
+ }
99
+
60
100
void XUnmapper::do_unmap_and_destroy_page (XPage* page) const {
61
101
EventZUnmap event;
62
102
const size_t unmapped = page->size ();
@@ -70,15 +110,9 @@ void XUnmapper::do_unmap_and_destroy_page(XPage* page) const {
70
110
}
71
111
72
112
void XUnmapper::unmap_and_destroy_page (XPage* page) {
73
- // Asynchronous unmap and destroy is not supported with ZVerifyViews
74
- if (ZVerifyViews) {
75
- // Immediately unmap and destroy
113
+ if (!try_enqueue (page)) {
114
+ // Synchronously unmap and destroy
76
115
do_unmap_and_destroy_page (page);
77
- } else {
78
- // Enqueue for asynchronous unmap and destroy
79
- XLocker<XConditionLock> locker (&_lock);
80
- _queue.insert_last (page);
81
- _lock.notify_all ();
82
116
}
83
117
}
84
118
0 commit comments