am 91ecb36d: ActivityManagerService use lmkd low memory killer daemon -- DO NOT MERGE

* commit '91ecb36df50be3446809e9da2a8f571d157f7549':
  ActivityManagerService use lmkd low memory killer daemon -- DO NOT MERGE
This commit is contained in:
Todd Poynor
2014-01-06 17:12:11 +00:00
committed by Android Git Automerger
4 changed files with 113 additions and 73 deletions

View File

@@ -891,19 +891,6 @@ public class Process {
return true;
}
/**
* Set the out-of-memory badness adjustment for a process.
*
* @param pid The process identifier to set.
* @param amt Adjustment value -- linux allows -16 to +15.
*
* @return Returns true if the underlying system supports this
* feature, else false.
*
* {@hide}
*/
public static final native boolean setOomAdj(int pid, int amt);
/**
* Adjust the swappiness level for a process.
*

View File

@@ -344,23 +344,6 @@ jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz,
return pri;
}
jboolean android_os_Process_setOomAdj(JNIEnv* env, jobject clazz,
jint pid, jint adj)
{
#ifdef HAVE_OOM_ADJ
char text[64];
sprintf(text, "/proc/%d/oom_adj", pid);
int fd = open(text, O_WRONLY);
if (fd >= 0) {
sprintf(text, "%d", adj);
write(fd, text, strlen(text));
close(fd);
}
return true;
#endif
return false;
}
jboolean android_os_Process_setSwappiness(JNIEnv *env, jobject clazz,
jint pid, jboolean is_increased)
{
@@ -1023,7 +1006,6 @@ static const JNINativeMethod methods[] = {
{"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup},
{"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup},
{"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup},
{"setOomAdj", "(II)Z", (void*)android_os_Process_setOomAdj},
{"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness},
{"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
{"setUid", "(I)I", (void*)android_os_Process_setUid},

View File

@@ -3592,9 +3592,13 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
private final void handleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
int pid = app.pid;
cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
if (!restarting) {
removeLruProcessLocked(app);
if (pid > 0) {
ProcessList.remove(pid);
}
}
if (mProfileProc == app) {
@@ -12319,6 +12323,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean restarting, boolean allowRestart, int index) {
if (index >= 0) {
removeLruProcessLocked(app);
ProcessList.remove(app.pid);
}
mProcessesToGc.remove(app);
@@ -15181,16 +15186,13 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (app.curAdj != app.setAdj) {
if (Process.setOomAdj(app.pid, app.curAdj)) {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
TAG, "Set " + app.pid + " " + app.processName +
" adj " + app.curAdj + ": " + app.adjType);
app.setAdj = app.curAdj;
} else {
success = false;
Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
}
ProcessList.setOomAdj(app.pid, app.curAdj);
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
TAG, "Set " + app.pid + " " + app.processName +
" adj " + app.curAdj + ": " + app.adjType);
app.setAdj = app.curAdj;
}
if (app.setSchedGroup != app.curSchedGroup) {
app.setSchedGroup = app.curSchedGroup;
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,

View File

@@ -18,6 +18,8 @@ package com.android.server.am;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import android.app.ActivityManager;
import com.android.internal.util.MemInfoReader;
@@ -26,6 +28,8 @@ import com.android.server.wm.WindowManagerService;
import android.content.res.Resources;
import android.graphics.Point;
import android.os.SystemProperties;
import android.net.LocalSocketAddress;
import android.net.LocalSocket;
import android.util.Slog;
import android.view.Display;
@@ -141,6 +145,16 @@ final class ProcessList {
// Threshold of number of cached+empty where we consider memory critical.
static final int TRIM_LOW_THRESHOLD = 5;
// Low Memory Killer Daemon command codes.
// These must be kept in sync with the definitions in lmkd.c
//
// LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs)
// LMK_PROCPRIO <pid> <prio>
// LMK_PROCREMOVE <pid>
static final byte LMK_TARGET = 0;
static final byte LMK_PROCPRIO = 1;
static final byte LMK_PROCREMOVE = 2;
// These are the various interesting memory levels that we will give to
// the OOM killer. Note that the OOM killer only supports 6 slots, so we
// can't give it a different value for every possible kind of process.
@@ -150,18 +164,18 @@ final class ProcessList {
};
// These are the low-end OOM level limits. This is appropriate for an
// HVGA or smaller phone with less than 512MB. Values are in KB.
private final long[] mOomMinFreeLow = new long[] {
private final int[] mOomMinFreeLow = new int[] {
8192, 12288, 16384,
24576, 28672, 32768
};
// These are the high-end OOM level limits. This is appropriate for a
// 1280x800 or larger screen with around 1GB RAM. Values are in KB.
private final long[] mOomMinFreeHigh = new long[] {
private final int[] mOomMinFreeHigh = new int[] {
49152, 61440, 73728,
86016, 98304, 122880
};
// The actual OOM killer memory levels we are using.
private final long[] mOomMinFree = new long[mOomAdj.length];
private final int[] mOomMinFree = new int[mOomAdj.length];
private final long mTotalMemMb;
@@ -169,6 +183,9 @@ final class ProcessList {
private boolean mHaveDisplaySize;
private static LocalSocket sLmkdSocket;
private static OutputStream sLmkdOutputStream;
ProcessList() {
MemInfoReader minfo = new MemInfoReader();
minfo.readMemInfo();
@@ -202,9 +219,6 @@ final class ProcessList {
+ " dh=" + displayHeight);
}
StringBuilder adjString = new StringBuilder();
StringBuilder memString = new StringBuilder();
float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;
if (scale < 0) scale = 0;
else if (scale > 1) scale = 1;
@@ -217,20 +231,20 @@ final class ProcessList {
}
for (int i=0; i<mOomAdj.length; i++) {
long low = mOomMinFreeLow[i];
long high = mOomMinFreeHigh[i];
mOomMinFree[i] = (long)(low + ((high-low)*scale));
int low = mOomMinFreeLow[i];
int high = mOomMinFreeHigh[i];
mOomMinFree[i] = (int)(low + ((high-low)*scale));
}
if (minfree_abs >= 0) {
for (int i=0; i<mOomAdj.length; i++) {
mOomMinFree[i] = (long)((float)minfree_abs * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]);
mOomMinFree[i] = (int)((float)minfree_abs * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]);
}
}
if (minfree_adj != 0) {
for (int i=0; i<mOomAdj.length; i++) {
mOomMinFree[i] += (long)((float)minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]);
mOomMinFree[i] += (int)((float)minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]);
if (mOomMinFree[i] < 0) {
mOomMinFree[i] = 0;
}
@@ -242,15 +256,6 @@ final class ProcessList {
// before killing background processes.
mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ)/1024) / 3;
for (int i=0; i<mOomAdj.length; i++) {
if (i > 0) {
adjString.append(',');
memString.append(',');
}
adjString.append(mOomAdj[i]);
memString.append((mOomMinFree[i]*1024)/PAGE_SIZE);
}
// Ask the kernel to try to keep enough memory free to allocate 3 full
// screen 32bpp buffers without entering direct reclaim.
int reserve = displayWidth * displayHeight * 4 * 3 / 1024;
@@ -268,10 +273,15 @@ final class ProcessList {
}
}
//Slog.i("XXXXXXX", "******************************* MINFREE: " + memString);
if (write) {
writeFile("/sys/module/lowmemorykiller/parameters/adj", adjString.toString());
writeFile("/sys/module/lowmemorykiller/parameters/minfree", memString.toString());
ByteBuffer buf = ByteBuffer.allocate(4 * (2*mOomAdj.length + 1));
buf.putInt(LMK_TARGET);
for (int i=0; i<mOomAdj.length; i++) {
buf.putInt((mOomMinFree[i]*1024)/PAGE_SIZE);
buf.putInt(mOomAdj[i]);
}
writeLmkd(buf);
SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
}
// GB: 2048,3072,4096,6144,7168,8192
@@ -506,19 +516,78 @@ final class ProcessList {
return mCachedRestoreLevel;
}
private void writeFile(String path, String data) {
FileOutputStream fos = null;
/**
* Set the out-of-memory badness adjustment for a process.
*
* @param pid The process identifier to set.
* @param amt Adjustment value -- lmkd allows -16 to +15.
*
* {@hide}
*/
public static final void setOomAdj(int pid, int amt) {
if (amt == UNKNOWN_ADJ)
return;
ByteBuffer buf = ByteBuffer.allocate(4 * 3);
buf.putInt(LMK_PROCPRIO);
buf.putInt(pid);
buf.putInt(amt);
writeLmkd(buf);
}
/*
* {@hide}
*/
public static final void remove(int pid) {
ByteBuffer buf = ByteBuffer.allocate(4 * 2);
buf.putInt(LMK_PROCREMOVE);
buf.putInt(pid);
writeLmkd(buf);
}
private static boolean openLmkdSocket() {
try {
fos = new FileOutputStream(path);
fos.write(data.getBytes());
} catch (IOException e) {
Slog.w(ActivityManagerService.TAG, "Unable to write " + path);
} finally {
if (fos != null) {
sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
sLmkdSocket.connect(
new LocalSocketAddress("lmkd",
LocalSocketAddress.Namespace.RESERVED));
sLmkdOutputStream = sLmkdSocket.getOutputStream();
} catch (IOException ex) {
Slog.w(ActivityManagerService.TAG,
"lowmemorykiller daemon socket open failed");
sLmkdSocket = null;
return false;
}
return true;
}
private static void writeLmkd(ByteBuffer buf) {
for (int i = 0; i < 3; i++) {
if (sLmkdSocket == null) {
if (openLmkdSocket() == false) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
}
continue;
}
}
try {
sLmkdOutputStream.write(buf.array(), 0, buf.position());
return;
} catch (IOException ex) {
Slog.w(ActivityManagerService.TAG,
"Error writing to lowmemorykiller socket");
try {
fos.close();
} catch (IOException e) {
sLmkdSocket.close();
} catch (IOException ex2) {
}
sLmkdSocket = null;
}
}
}