Add MCL_ONFAULT to mlockall

This way, we don't fault in the entirety of our DSOs immediately;
instead, used pages are "sticky" in memory. Works only on kernel 4.4
and up: downlevel, we ignore the mlockall failure.

Once we get statically-linked lmkd in better shape, we'll just switch
to that.

Change-Id: I07a75ee3bc1264a1db41635c2acf611fede99b91
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index fd83ecc..b486a17 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -900,7 +900,16 @@
     downgrade_pressure = (int64_t)property_get_int32("ro.lmk.downgrade_pressure", 60);
     is_go_device = property_get_bool("ro.config.low_ram", false);
 
-    if (mlockall(MCL_CURRENT | MCL_FUTURE))
+    // MCL_ONFAULT pins pages as they fault instead of loading
+    // everything immediately all at once. (Which would be bad,
+    // because as of this writing, we have a lot of mapped pages we
+    // never use.) Old kernels will see MCL_ONFAULT and fail with
+    // EINVAL; we ignore this failure.
+    //
+    // N.B. read the man page for mlockall. MCL_CURRENT | MCL_ONFAULT
+    // pins ⊆ MCL_CURRENT, converging to just MCL_CURRENT as we fault
+    // in pages.
+    if (mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) && errno != EINVAL)
         ALOGW("mlockall failed: errno=%d", errno);
 
     sched_setscheduler(0, SCHED_FIFO, &param);