bin/173332: [patch] watchdogd wires over 10MB of memory after r239769
freebsd at damnhippie.dyndns.org
Sat Nov 3 17:20:01 UTC 2012
>Synopsis: [patch] watchdogd wires over 10MB of memory after r239769
>Arrival-Date: Sat Nov 03 17:20:00 UTC 2012
>Originator: Ian Lepore
>Release: FreeBSD 10.0-CURRENT @ r241077
FreeBSD tflex 10.0-CURRENT FreeBSD 10.0-CURRENT #22: Tue Oct 16 15:10:51 UTC 2012 root at revolution.hippie.lan:/usr/obj/arm.arm/usr/src/sys/TFLEX arm
watchdogd was changed in r239769 to use mlockall(2) to wire down the memory used by the app so that it can pat the watchdog without any delays caused by waiting for its pages to be swapped back in. This has caused its resident size to increase from about 840KB to about 10MB, which is a serious problem on small-memory embedded systems.
Most of the memory increase seems to be related to jemalloc allocating vmspace in chunks of 8MB at a time. Normally this is innocuous; even if the app only uses a few bytes of allocated memory there's no large downside to having over-allocated some vmspace. However, when mlockall(MCL_FUTURE) is in effect, it is no longer a vmspace allocation, physical pages for the entire 8MB region are prefaulted and wired.
Another megabyte or so of the growth seems to be related to wiring in pages (whether needed or not) from libc and libm.
The attached patch reduces the impact of the mlockall() change on small-memory embedded systems. Such systems are often built with "option NO_SWAPPING" which eliminates most of the reason the mlockall() change was put in originally.
Note that this is not really a full fix for the problem, it just reduces the impact on the most resource-limited systems.
Patch attached with submission follows:
diff -r 5f2e07d3ae42 usr.sbin/watchdogd/watchdogd.c
--- usr.sbin/watchdogd/watchdogd.c Thu Oct 04 20:42:12 2012 -0600
+++ usr.sbin/watchdogd/watchdogd.c Sat Nov 03 11:04:31 2012 -0600
@@ -35,6 +35,7 @@
@@ -78,6 +79,7 @@ main(int argc, char *argv)
struct rtprio rtp;
struct pidfh *pfh;
+ int len, swap_enabled;
if (getuid() != 0)
errx(EX_SOFTWARE, "not super user");
@@ -118,8 +120,13 @@ main(int argc, char *argv)
if (madvise(0, 0, MADV_PROTECT) != 0)
- if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0)
- warn("mlockall failed");
+ len = sizeof(swap_enabled);
+ if (sysctlbyname("vm.swap_enabled", &swap_enabled, &len, NULL,
+ 0) == -1)
+ swap_enabled = 1; /* Assume enabled */
+ if (swap_enabled)
+ if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0)
+ warn("mlockall failed");
More information about the freebsd-bugs