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,54 @@ public Pointer reserve(UnsignedWord nbytes, UnsignedWord alignment, boolean exec
128144 return nullPointer ();
129145 }
130146 if (!customAlignment ) {
147+ if (VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
148+ if (nmtData .isNull ()) {
149+ NativeMemoryTracking .singleton ().trackReserve (mappingBegin , mappingSize , category );
150+ } else {
151+ NmtPreImageHeapDataAccess .enqueueReserve (nmtData , mappingBegin , mappingSize , category );
152+ }
153+ }
131154 return mappingBegin ;
132155 }
156+ UnsignedWord unmappedSize = WordFactory .zero ();
133157 Pointer begin = PointerUtils .roundUp (mappingBegin , alignment );
134158 UnsignedWord clippedBegin = begin .subtract (mappingBegin );
135159 if (clippedBegin .aboveOrEqual (granularity )) {
136- munmap (mappingBegin , UnsignedUtils .roundDown (clippedBegin , granularity ));
160+ UnsignedWord unmapSize = UnsignedUtils .roundDown (clippedBegin , granularity );
161+ munmap (mappingBegin , unmapSize );
162+ unmappedSize = unmappedSize .add (unmapSize );
137163 }
138164 Pointer mappingEnd = mappingBegin .add (mappingSize );
139165 UnsignedWord clippedEnd = mappingEnd .subtract (begin .add (nbytes ));
140166 if (clippedEnd .aboveOrEqual (granularity )) {
141167 UnsignedWord rounded = UnsignedUtils .roundDown (clippedEnd , granularity );
142168 munmap (mappingEnd .subtract (rounded ), rounded );
169+ unmappedSize = unmappedSize .add (rounded );
170+ }
171+ if (VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
172+ if (nmtData .isNull ()) {
173+ NativeMemoryTracking .singleton ().trackReserve (begin , mappingSize .subtract (unmappedSize ), category );
174+ } else {
175+ NmtPreImageHeapDataAccess .enqueueReserve (nmtData , begin , mappingSize .subtract (unmappedSize ), category );
176+ }
143177 }
144178 return begin ;
145179 }
146180
147181 @ Override
148182 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
149- public Pointer mapFile (PointerBase start , UnsignedWord nbytes , WordBase fileHandle , UnsignedWord offset , int access ) {
183+ public Pointer mapFile (PointerBase start , UnsignedWord nbytes , WordBase fileHandle , UnsignedWord offset , int access , NmtPreImageHeapData nmtData ) {
184+ return mapFile0 (start , nbytes , fileHandle , offset , access , nmtData , NmtCategory .ImageHeap );
185+ }
186+
187+ @ Override
188+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
189+ public Pointer mapFile (PointerBase start , UnsignedWord nbytes , WordBase fileHandle , UnsignedWord offset , int access , NmtCategory category ) {
190+ return mapFile0 (start , nbytes , fileHandle , offset , access , WordFactory .nullPointer (), category );
191+ }
192+
193+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
194+ private Pointer mapFile0 (PointerBase start , UnsignedWord nbytes , WordBase fileHandle , UnsignedWord offset , int access , NmtPreImageHeapData nmtData , NmtCategory category ) {
150195 if ((start .isNonNull () && !isAligned (start )) || nbytes .equal (0 )) {
151196 return WordFactory .nullPointer ();
152197 }
@@ -157,12 +202,27 @@ public Pointer mapFile(PointerBase start, UnsignedWord nbytes, WordBase fileHand
157202 }
158203 int fd = (int ) fileHandle .rawValue ();
159204 Pointer result = mmap (start , nbytes , accessAsProt (access ), flags , fd , offset .rawValue ());
160- return result .notEqual (MAP_FAILED ()) ? result : WordFactory .nullPointer ();
205+ if (result .notEqual (MAP_FAILED ())) {
206+ trackCommitAndMaybeReserve (result , start , nbytes , nmtData , category );
207+ return result ;
208+ }
209+ return WordFactory .nullPointer ();
161210 }
162211
163212 @ Override
164213 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
165- public Pointer commit (PointerBase start , UnsignedWord nbytes , int access ) {
214+ public Pointer commit (PointerBase start , UnsignedWord nbytes , int access , NmtPreImageHeapData nmtData ) {
215+ return commit0 (start , nbytes , access , nmtData , NmtCategory .ImageHeap );
216+ }
217+
218+ @ Override
219+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
220+ public Pointer commit (PointerBase start , UnsignedWord nbytes , int access , NmtCategory category ) {
221+ return commit0 (start , nbytes , access , WordFactory .nullPointer (), category );
222+ }
223+
224+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
225+ private Pointer commit0 (PointerBase start , UnsignedWord nbytes , int access , NmtPreImageHeapData nmtData , NmtCategory category ) {
166226 if ((start .isNonNull () && !isAligned (start )) || nbytes .equal (0 )) {
167227 return WordFactory .nullPointer ();
168228 }
@@ -177,7 +237,31 @@ public Pointer commit(PointerBase start, UnsignedWord nbytes, int access) {
177237 }
178238 /* The memory returned by mmap is guaranteed to be zeroed. */
179239 final Pointer result = mmap (start , nbytes , accessAsProt (access ), flags , NO_FD , NO_FD_OFFSET );
180- return result .notEqual (MAP_FAILED ()) ? result : nullPointer ();
240+ if (result .notEqual (MAP_FAILED ())) {
241+ trackCommitAndMaybeReserve (result , start , nbytes , nmtData , category );
242+ return result ;
243+ }
244+ return nullPointer ();
245+ }
246+
247+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
248+ private static void trackCommitAndMaybeReserve (PointerBase baseAddr , PointerBase start , UnsignedWord nbytes , NmtPreImageHeapData nmtData , NmtCategory category ) {
249+ if (!VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
250+ return ;
251+ }
252+ // Account for possible reserve before commit
253+ if (start .isNull ()) {
254+ if (nmtData .isNull ()) {
255+ NativeMemoryTracking .singleton ().trackReserve (baseAddr , nbytes , category );
256+ } else {
257+ NmtPreImageHeapDataAccess .enqueueReserve (nmtData , baseAddr , nbytes , category );
258+ }
259+ }
260+ if (nmtData .isNull ()) {
261+ NativeMemoryTracking .singleton ().trackCommit (baseAddr , nbytes , category );
262+ } else {
263+ NmtPreImageHeapDataAccess .enqueueCommit (nmtData , baseAddr , nbytes , category );
264+ }
181265 }
182266
183267 @ Override
@@ -196,22 +280,37 @@ public int uncommit(PointerBase start, UnsignedWord nbytes) {
196280 if (start .isNull () || !isAligned (start ) || nbytes .equal (0 )) {
197281 return -1 ;
198282 }
199-
200283 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 ;
284+ if (result .notEqual (MAP_FAILED ())) {
285+ if (VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
286+ NativeMemoryTracking .singleton ().trackUncommit (start , nbytes );
287+ }
288+ return 0 ;
289+ }
290+ return -1 ;
202291 }
203292
204293 @ Override
205294 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
206295 public int free (PointerBase start , UnsignedWord nbytes ) {
296+ return free (start , nbytes , WordFactory .nullPointer ());
297+ }
298+
299+ @ Override
300+ @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
301+ public int free (PointerBase start , UnsignedWord nbytes , NmtPreImageHeapData nmtData ) {
207302 if (start .isNull () || !isAligned (start ) || nbytes .equal (0 )) {
208303 return -1 ;
209304 }
210305
211306 UnsignedWord granularity = getGranularity ();
212307 Pointer mappingBegin = PointerUtils .roundDown (start , granularity );
213308 UnsignedWord mappingSize = UnsignedUtils .roundUp (nbytes , granularity );
214- return munmap (mappingBegin , mappingSize );
309+ int ret = munmap (mappingBegin , mappingSize );
310+ if (ret == 0 && nmtData .isNull () && VMInspectionOptions .hasNativeMemoryTrackingSupport ()) {
311+ NativeMemoryTracking .singleton ().trackFree (start );
312+ }
313+ return ret ;
215314 }
216315
217316 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
0 commit comments