Ruby 4.1.0dev (2026-08-15 revision 3349f4107d268658fdf8cc6b979fbb1c923e597f)
vm_map.h
1#ifndef INTERNAL_VM_MAP_H
2#define INTERNAL_VM_MAP_H
11#include "ruby/internal/config.h"
12#include <stddef.h> /* for size_t */
13
14#ifdef HAVE_SYS_MMAN_H
15# include <sys/mman.h>
16#endif
17#ifdef HAVE_ERRNO_H
18# include <errno.h> /* for errno, EAGAIN */
19#endif
20
21// On Solaris, madvise() is NOT declared for SUS (XPG4v2) or later,
22// but MADV_* macros are defined when __EXTENSIONS__ is defined.
23#ifdef NEED_MADVICE_PROTOTYPE_USING_CADDR_T
24#include <sys/types.h>
25extern int madvise(caddr_t, size_t, int);
26#endif
27
28// Reduces RSS lazily if possible, otherwise does it immediately. Keeps the mapping.
29static inline void
30rb_vm_map_reusable_lazy(void *addr, size_t len, int advice)
31{
32#ifdef __wasi__
33 /* WebAssembly doesn't support madvise. */
34#elif defined(VM_CHECK_MODE) && VM_CHECK_MODE > 0 && defined(MADV_DONTNEED)
35 if (!advice) advice = MADV_DONTNEED;
36 madvise(addr, len, advice);
37#elif defined(MADV_FREE_REUSABLE)
38 /* Darwin / macOS / iOS. Drops phys_footprint; pages stay in resident_size
39 * until the kernel reclaims them. Retry on EAGAIN. */
40 if (!advice) advice = MADV_FREE_REUSABLE;
41 while (madvise(addr, len, advice) == -1 && errno == EAGAIN);
42#elif defined(MADV_FREE)
43 /* Recent Linux. */
44 if (!advice) advice = MADV_FREE;
45 madvise(addr, len, advice);
46#elif defined(MADV_DONTNEED)
47 /* Old Linux. */
48 if (!advice) advice = MADV_DONTNEED;
49 madvise(addr, len, advice);
50#elif defined(POSIX_MADV_DONTNEED)
51 /* Solaris. */
52 if (!advice) advice = POSIX_MADV_DONTNEED;
53 posix_madvise(addr, len, advice);
54#elif defined(_WIN32)
55 VirtualAlloc(addr, len, MEM_RESET, PAGE_READWRITE);
56#endif
57}
58
59// Reduces RSS immediately if possible, otherwise does it lazily. Keeps the mapping.
60static inline void
61rb_vm_map_reusable_immediate(void *addr, size_t len, int advice)
62{
63#ifdef __wasi__
64 /* WebAssembly doesn't support madvise. */
65#elif defined(MADV_FREE_REUSABLE)
66 /* The most aggressive option is MADV_FREE_REUSABLE — same as _lazy. It drops
67 * phys_footprint immediately. Retry on EAGAIN. */
68 if (!advice) advice = MADV_FREE_REUSABLE;
69 while (madvise(addr, len, advice) == -1 && errno == EAGAIN);
70#elif defined(MADV_DONTNEED)
71 /* Linux: kernel discards physical pages immediately; next touch
72 * zero-faults and RSS drops at once. */
73 if (!advice) advice = MADV_DONTNEED;
74 madvise(addr, len, advice);
75#elif defined(POSIX_MADV_DONTNEED)
76 if (!advice) advice = POSIX_MADV_DONTNEED;
77 posix_madvise(addr, len, advice);
78#elif defined(_WIN32)
79 // Does not reduce working set immediately. We would need 2 system calls to do this.
80 VirtualAlloc(addr, len, MEM_RESET, PAGE_READWRITE);
81#endif
82}
83
84/* Re-acquire pages previously given back. Only needed for certain platforms. */
85static inline void
86rb_vm_map_reuse(void *addr, size_t len)
87{
88#if defined(MADV_FREE_REUSE)
89 /* Darwin: mandatory handshake with MADV_FREE_REUSABLE. Retry on EAGAIN. */
90 while (madvise(addr, len, MADV_FREE_REUSE) == -1 && errno == EAGAIN);
91#endif
92 /* Linux/Windows/wasi: no-op (fault re-materializes zero-filled pages). */
93}
94
95#endif /* INTERNAL_VM_MAP_H */
int len
Length of the buffer.
Definition io.h:8
#define errno
Ractor-aware version of errno.
Definition ruby.h:388