I'm having a hard time understanding how Solaris 10 x86 swap allocations work in the
presence of mlocked share memory.
I wrote a small program that:
- Gets a 1G SHM segment (
shmget) - Attaches it to the process (
shmat) - Locks a part of that (
mlock, first round locks nothing, then 512M, then the whole thing) - Write on the last, then the first, page of the SHM region
- Writes on the whole segment progressively
- Release the lock (if any)
- Detaches and cleans up.
It prints out the values of swap -s in MB after each action.
The output is as follows:
- Round 1, no
mlock: (values on the right are relative to the first reading)
pid: 2221 mlock size: 0
header: alloc resvd used free [+/- alloc resvd used free]
init: 325 130 456 2873 [+/- 0 0 0 0]
shmget: 326 1154 1480 1849 [+/- 1 1024 1024 -1024]
shmat: 326 1154 1480 1849 [+/- 1 1024 1024 -1024]
touchE: 326 1154 1480 1849 [+/- 1 1024 1024 -1024]
touchS: 326 1154 1480 1849 [+/- 1 1024 1024 -1024]
set1: 582 898 1480 1848 [+/- 257 768 1024 -1025]
set2: 838 642 1480 1848 [+/- 513 512 1024 -1025]
set3: 1093 386 1480 1847 [+/- 768 256 1024 -1026]
set4: 1350 130 1480 1847 [+/- 1025 0 1024 -1026]
set: 1350 130 1480 1847 [+/- 1025 0 1024 -1026]
shmdt: 1350 130 1480 1847 [+/- 1025 0 1024 -1026]
shmctl: 326 130 456 2871 [+/- 1 0 0 -2]
Here, all good. free column was at most ~1G smaller than it was at startup.
- Round 2,
mlockthe first 512M of the shared segment:
pid: 2221 mlock size: 536870912
header: alloc resvd used free [+/- alloc resvd used free]
init: 326 130 456 2871 [+/- 0 0 0 0]
shmget: 326 1154 1480 1847 [+/- 0 1024 1024 -1024]
shmat: 326 1154 1480 1847 [+/- 0 1024 1024 -1024]
mlock: 838 642 1480 1334 [+/- 512 512 1024 -1537] <<<<
touchE: 838 642 1480 1334 [+/- 512 512 1024 -1537]
touchS: 838 642 1480 1334 [+/- 512 512 1024 -1537]
set1: 838 642 1480 1334 [+/- 512 512 1024 -1537]
set2: 838 642 1480 1334 [+/- 512 512 1024 -1537]
set3: 1094 386 1480 1334 [+/- 768 256 1024 -1537]
set4: 1350 130 1480 1334 [+/- 1024 0 1024 -1537]
set: 1350 130 1480 1334 [+/- 1024 0 1024 -1537] <<<<
munlock: 1350 130 1480 1846 [+/- 1024 0 1024 -1025]
shmdt: 1350 130 1480 1847 [+/- 1024 0 1024 -1024]
shmctl: 326 130 456 2871 [+/- 0 0 0 0]
- Round 3,
mlockthe whole segment:
pid: 2221 mlock size: 1073741824
header: alloc resvd used free [+/- alloc resvd used free]
init: 326 130 456 2871 [+/- 0 0 0 0]
shmget: 326 1154 1480 1847 [+/- 0 1024 1024 -1024]
shmat: 326 1154 1480 1847 [+/- 0 1024 1024 -1024]
mlock: 1350 130 1480 822 [+/- 1024 0 1024 -2049] <<<<
touchE: 1350 130 1480 822 [+/- 1024 0 1024 -2049]
touchS: 1350 130 1480 822 [+/- 1024 0 1024 -2049]
set1: 1350 130 1480 822 [+/- 1024 0 1024 -2049]
set2: 1350 130 1480 822 [+/- 1024 0 1024 -2049]
set3: 1350 130 1480 822 [+/- 1024 0 1024 -2049]
set4: 1350 130 1480 822 [+/- 1024 0 1024 -2049]
set: 1350 130 1480 822 [+/- 1024 0 1024 -2049] <<<<
munlock: 1350 130 1480 1846 [+/- 1024 0 1024 -1025]
shmdt: 1350 130 1480 1847 [+/- 1024 0 1024 -1024]
shmctl: 326 130 456 2871 [+/- 0 0 0 0]
In the last two rounds, the free column goes down an extra 512M or 1G right
after the mlock, but before any page is actually touched. This "double accounting"
disappears after the munlock call.
Can anyone explain this behavior? Are mlocked pages reserved both in real RAM and in backing store or something like that?
SunOS myhost 5.10 Generic_142910-17 i86pc i386 i86pc