5454import com .oracle .svm .core .c .CGlobalDataFactory ;
5555import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
5656import com .oracle .svm .core .feature .InternalFeature ;
57+ import com .oracle .svm .core .nmt .NativeMemoryTracking ;
58+ import com .oracle .svm .core .nmt .NmtCategory ;
59+ import com .oracle .svm .core .nmt .NmtPreImageHeapData ;
60+ import com .oracle .svm .core .nmt .NmtPreImageHeapDataAccess ;
5761import com .oracle .svm .core .os .VirtualMemoryProvider ;
5862import com .oracle .svm .core .posix .headers .Unistd ;
5963import com .oracle .svm .core .util .PointerUtils ;
6064import com .oracle .svm .core .util .UnsignedUtils ;
65+ import com .oracle .svm .core .VMInspectionOptions ;
6166
6267@ AutomaticallyRegisteredFeature
6368class PosixVirtualMemoryProviderFeature implements InternalFeature {
@@ -109,7 +114,18 @@ public UnsignedWord getGranularity() {
109114
110115 @ Override
111116 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
112- public Pointer reserve (UnsignedWord nbytes , UnsignedWord alignment , boolean executable ) {
117+ public Pointer reserve (UnsignedWord nbytes , UnsignedWord alignment , boolean executable , NmtPreImageHeapData nmtData ) {
118+ return reserve0 (nbytes , alignment , executable , nmtData , NmtCategory .ImageHeap );
119+ }
120+
121+ @ Override
122+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
123+ public Pointer reserve (UnsignedWord nbytes , UnsignedWord alignment , boolean executable , NmtCategory category ) {
124+ return reserve0 (nbytes , alignment , executable , WordFactory .nullPointer (), category );
125+ }
126+
127+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
128+ private Pointer reserve0 (UnsignedWord nbytes , UnsignedWord alignment , boolean executable , NmtPreImageHeapData nmtData , NmtCategory category ) {
113129 if (nbytes .equal (0 )) {
114130 return WordFactory .nullPointer ();
115131 }
@@ -128,25 +144,50 @@ public Pointer reserve(UnsignedWord nbytes, UnsignedWord alignment, boolean exec
128144 return nullPointer ();
129145 }
130146 if (!customAlignment ) {
147+ if (nmtData .isNull () && VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
148+ NativeMemoryTracking .singleton ().trackReserve (mappingBegin , mappingSize , category );
149+ } else {
150+ NmtPreImageHeapDataAccess .enqueueReserve (nmtData , mappingBegin , mappingSize , category );
151+ }
131152 return mappingBegin ;
132153 }
154+ UnsignedWord unmappedSize = WordFactory .zero ();
133155 Pointer begin = PointerUtils .roundUp (mappingBegin , alignment );
134156 UnsignedWord clippedBegin = begin .subtract (mappingBegin );
135157 if (clippedBegin .aboveOrEqual (granularity )) {
136- munmap (mappingBegin , UnsignedUtils .roundDown (clippedBegin , granularity ));
158+ UnsignedWord unmapSize = UnsignedUtils .roundDown (clippedBegin , granularity );
159+ munmap (mappingBegin , unmapSize );
160+ unmappedSize = unmappedSize .add (unmapSize );
137161 }
138162 Pointer mappingEnd = mappingBegin .add (mappingSize );
139163 UnsignedWord clippedEnd = mappingEnd .subtract (begin .add (nbytes ));
140164 if (clippedEnd .aboveOrEqual (granularity )) {
141165 UnsignedWord rounded = UnsignedUtils .roundDown (clippedEnd , granularity );
142166 munmap (mappingEnd .subtract (rounded ), rounded );
167+ unmappedSize = unmappedSize .add (rounded );
168+ }
169+ if (nmtData .isNull () && VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
170+ NativeMemoryTracking .singleton ().trackReserve (begin , mappingSize .subtract (unmappedSize ), category );
171+ } else {
172+ NmtPreImageHeapDataAccess .enqueueReserve (nmtData , begin , mappingSize .subtract (unmappedSize ), category );
143173 }
144174 return begin ;
145175 }
146176
147177 @ Override
148178 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
149- public Pointer mapFile (PointerBase start , UnsignedWord nbytes , WordBase fileHandle , UnsignedWord offset , int access ) {
179+ public Pointer mapFile (PointerBase start , UnsignedWord nbytes , WordBase fileHandle , UnsignedWord offset , int access , NmtPreImageHeapData nmtData ) {
180+ return mapFile0 (start , nbytes , fileHandle , offset , access , nmtData , NmtCategory .ImageHeap );
181+ }
182+
183+ @ Override
184+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
185+ public Pointer mapFile (PointerBase start , UnsignedWord nbytes , WordBase fileHandle , UnsignedWord offset , int access , NmtCategory category ) {
186+ return mapFile0 (start , nbytes , fileHandle , offset , access , WordFactory .nullPointer (), category );
187+ }
188+
189+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
190+ private Pointer mapFile0 (PointerBase start , UnsignedWord nbytes , WordBase fileHandle , UnsignedWord offset , int access , NmtPreImageHeapData nmtData , NmtCategory category ) {
150191 if ((start .isNonNull () && !isAligned (start )) || nbytes .equal (0 )) {
151192 return WordFactory .nullPointer ();
152193 }
@@ -157,12 +198,27 @@ public Pointer mapFile(PointerBase start, UnsignedWord nbytes, WordBase fileHand
157198 }
158199 int fd = (int ) fileHandle .rawValue ();
159200 Pointer result = mmap (start , nbytes , accessAsProt (access ), flags , fd , offset .rawValue ());
160- return result .notEqual (MAP_FAILED ()) ? result : WordFactory .nullPointer ();
201+ if (result .notEqual (MAP_FAILED ())) {
202+ trackCommitAndMaybeReserve (result , start , nbytes , nmtData , category );
203+ return result ;
204+ }
205+ return WordFactory .nullPointer ();
206+ }
207+
208+ @ Override
209+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
210+ public Pointer commit (PointerBase start , UnsignedWord nbytes , int access , NmtPreImageHeapData nmtData ) {
211+ return commit0 (start , nbytes , access , nmtData , NmtCategory .ImageHeap );
161212 }
162213
163214 @ Override
164215 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
165- public Pointer commit (PointerBase start , UnsignedWord nbytes , int access ) {
216+ public Pointer commit (PointerBase start , UnsignedWord nbytes , int access , NmtCategory category ) {
217+ return commit0 (start , nbytes , access , WordFactory .nullPointer (), category );
218+ }
219+
220+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
221+ private Pointer commit0 (PointerBase start , UnsignedWord nbytes , int access , NmtPreImageHeapData nmtData , NmtCategory category ) {
166222 if ((start .isNonNull () && !isAligned (start )) || nbytes .equal (0 )) {
167223 return WordFactory .nullPointer ();
168224 }
@@ -177,7 +233,28 @@ public Pointer commit(PointerBase start, UnsignedWord nbytes, int access) {
177233 }
178234 /* The memory returned by mmap is guaranteed to be zeroed. */
179235 final Pointer result = mmap (start , nbytes , accessAsProt (access ), flags , NO_FD , NO_FD_OFFSET );
180- return result .notEqual (MAP_FAILED ()) ? result : nullPointer ();
236+ if (result .notEqual (MAP_FAILED ())) {
237+ trackCommitAndMaybeReserve (result , start , nbytes , nmtData , category );
238+ return result ;
239+ }
240+ return nullPointer ();
241+ }
242+
243+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
244+ private static void trackCommitAndMaybeReserve (PointerBase baseAddr , PointerBase start , UnsignedWord nbytes , NmtPreImageHeapData nmtData , NmtCategory category ) {
245+ // Account for possible reserve before commit
246+ if (start .isNull ()) {
247+ if (nmtData .isNull () && VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
248+ NativeMemoryTracking .singleton ().trackReserve (baseAddr , nbytes , category );
249+ } else {
250+ NmtPreImageHeapDataAccess .enqueueReserve (nmtData , baseAddr , nbytes , category );
251+ }
252+ }
253+ if (nmtData .isNull () && VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
254+ NativeMemoryTracking .singleton ().trackCommit (baseAddr , nbytes , category );
255+ } else {
256+ NmtPreImageHeapDataAccess .enqueueCommit (nmtData , baseAddr , nbytes , category );
257+ }
181258 }
182259
183260 @ Override
@@ -196,22 +273,37 @@ public int uncommit(PointerBase start, UnsignedWord nbytes) {
196273 if (start .isNull () || !isAligned (start ) || nbytes .equal (0 )) {
197274 return -1 ;
198275 }
199-
200276 final Pointer result = mmap (start , nbytes , PROT_NONE (), MAP_FIXED () | MAP_ANON () | MAP_PRIVATE () | MAP_NORESERVE (), NO_FD , NO_FD_OFFSET );
201- return result .notEqual (MAP_FAILED ()) ? 0 : -1 ;
277+ if (result .notEqual (MAP_FAILED ())) {
278+ if (VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
279+ NativeMemoryTracking .singleton ().trackUncommit (start , nbytes );
280+ }
281+ return 0 ;
282+ }
283+ return -1 ;
202284 }
203285
204286 @ Override
205287 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
206288 public int free (PointerBase start , UnsignedWord nbytes ) {
289+ return free (start , nbytes , WordFactory .nullPointer ());
290+ }
291+
292+ @ Override
293+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
294+ public int free (PointerBase start , UnsignedWord nbytes , NmtPreImageHeapData nmtData ) {
207295 if (start .isNull () || !isAligned (start ) || nbytes .equal (0 )) {
208296 return -1 ;
209297 }
210298
211299 UnsignedWord granularity = getGranularity ();
212300 Pointer mappingBegin = PointerUtils .roundDown (start , granularity );
213301 UnsignedWord mappingSize = UnsignedUtils .roundUp (nbytes , granularity );
214- return munmap (mappingBegin , mappingSize );
302+ int ret = munmap (mappingBegin , mappingSize );
303+ if (ret == 0 && nmtData .isNull () && VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
304+ NativeMemoryTracking .singleton ().trackFree (start );
305+ }
306+ return ret ;
215307 }
216308
217309 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
0 commit comments