diff options
| author | Daichi Hirono <hirono@google.com> | 2017-04-03 13:18:40 +0900 |
|---|---|---|
| committer | Daichi Hirono <hirono@google.com> | 2017-04-03 05:03:03 +0000 |
| commit | ea6e6e17a0cd6fffd1c293972e138728851d4372 (patch) | |
| tree | 36bb8cb9d0390d9203182e41de8d69d0a617defd /core/java | |
| parent | 21a5edcc24cbca1ae3f0855d71737b22ab81ad6d (diff) | |
Process FuseAppLoop messages in Handler.Callback
Previously FuseAppLoop instantiates Runnable for each command, which
causes lots of instantiation and GC.
Test: CTS
Bug: 35229514
Change-Id: Ifea098e5ade044b1a954c0b714c5b3270a95cd1a
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/com/android/internal/os/FuseAppLoop.java | 206 |
1 files changed, 123 insertions, 83 deletions
diff --git a/core/java/com/android/internal/os/FuseAppLoop.java b/core/java/com/android/internal/os/FuseAppLoop.java index 8edd637ea814..088e7268b984 100644 --- a/core/java/com/android/internal/os/FuseAppLoop.java +++ b/core/java/com/android/internal/os/FuseAppLoop.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.ProxyFileDescriptorCallback; import android.os.Handler; +import android.os.Message; import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.OsConstants; @@ -28,10 +29,11 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import java.util.HashMap; +import java.util.LinkedList; import java.util.Map; import java.util.concurrent.ThreadFactory; -public class FuseAppLoop { +public class FuseAppLoop implements Handler.Callback { private static final String TAG = "FuseAppLoop"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); public static final int ROOT_INODE = 1; @@ -43,13 +45,11 @@ public class FuseAppLoop { } }; private static final int FUSE_OK = 0; + private static final int ARGS_POOL_SIZE = 50; private final Object mLock = new Object(); private final int mMountPointId; private final Thread mThread; - private final Handler mDefaultHandler; - - private static final int CMD_FSYNC = 1; @GuardedBy("mLock") private final SparseArray<CallbackEntry> mCallbackMap = new SparseArray<>(); @@ -57,6 +57,9 @@ public class FuseAppLoop { @GuardedBy("mLock") private final BytesMap mBytesMap = new BytesMap(); + @GuardedBy("mLock") + private final LinkedList<Args> mArgsPool = new LinkedList<>(); + /** * Sequential number can be used as file name and inode in AppFuse. * 0 is regarded as an error, 1 is mount point. So we start the number from 2. @@ -83,7 +86,6 @@ public class FuseAppLoop { } }); mThread.start(); - mDefaultHandler = null; } public int registerCallback(@NonNull ProxyFileDescriptorCallback callback, @@ -110,7 +112,8 @@ public class FuseAppLoop { break; } } - mCallbackMap.put(id, new CallbackEntry(callback, handler)); + mCallbackMap.put(id, new CallbackEntry( + callback, new Handler(handler.getLooper(), this))); return id; } } @@ -137,78 +140,113 @@ public class FuseAppLoop { // Defined in FuseBuffer.h private static final int FUSE_MAX_WRITE = 256 * 1024; + @Override + public boolean handleMessage(Message msg) { + final Args args = (Args) msg.obj; + final CallbackEntry entry = args.entry; + final long inode = args.inode; + final long unique = args.unique; + final int size = args.size; + final long offset = args.offset; + final byte[] data = args.data; + + try { + switch (msg.what) { + case FUSE_LOOKUP: { + final long fileSize = entry.callback.onGetSize(); + synchronized (mLock) { + if (mInstance != 0) { + native_replyLookup(mInstance, unique, inode, fileSize); + } + recycleLocked(args); + } + break; + } + case FUSE_GETATTR: { + final long fileSize = entry.callback.onGetSize(); + synchronized (mLock) { + if (mInstance != 0) { + native_replyGetAttr(mInstance, unique, inode, fileSize); + } + recycleLocked(args); + } + break; + } + case FUSE_READ: + final int readSize = entry.callback.onRead( + offset, size, data); + synchronized (mLock) { + if (mInstance != 0) { + native_replyRead(mInstance, unique, readSize, data); + } + recycleLocked(args); + } + break; + case FUSE_WRITE: + final int writeSize = entry.callback.onWrite(offset, size, data); + synchronized (mLock) { + if (mInstance != 0) { + native_replyWrite(mInstance, unique, writeSize); + } + recycleLocked(args); + } + break; + case FUSE_FSYNC: + entry.callback.onFsync(); + synchronized (mLock) { + if (mInstance != 0) { + native_replySimple(mInstance, unique, FUSE_OK); + } + recycleLocked(args); + } + break; + case FUSE_RELEASE: + entry.callback.onRelease(); + synchronized (mLock) { + if (mInstance != 0) { + native_replySimple(mInstance, unique, FUSE_OK); + } + mBytesMap.stopUsing(entry.getThreadId()); + recycleLocked(args); + } + break; + default: + throw new IllegalArgumentException("Unknown FUSE command: " + msg.what); + } + } catch (Exception error) { + synchronized (mLock) { + Log.e(TAG, "", error); + replySimpleLocked(unique, getError(error)); + recycleLocked(args); + } + } + + return true; + } + // Called by JNI. @SuppressWarnings("unused") private void onCommand(int command, long unique, long inode, long offset, int size, byte[] data) { - synchronized(mLock) { + synchronized (mLock) { try { - final CallbackEntry entry = getCallbackEntryOrThrowLocked(inode); - entry.postRunnable(() -> { - try { - switch (command) { - case FUSE_LOOKUP: { - final long fileSize = entry.callback.onGetSize(); - synchronized (mLock) { - if (mInstance != 0) { - native_replyLookup(mInstance, unique, inode, fileSize); - } - } - break; - } - case FUSE_GETATTR: { - final long fileSize = entry.callback.onGetSize(); - synchronized (mLock) { - if (mInstance != 0) { - native_replyGetAttr(mInstance, unique, inode, fileSize); - } - } - break; - } - case FUSE_READ: - final int readSize = entry.callback.onRead(offset, size, data); - synchronized (mLock) { - if (mInstance != 0) { - native_replyRead(mInstance, unique, readSize, data); - } - } - break; - case FUSE_WRITE: - final int writeSize = entry.callback.onWrite(offset, size, data); - synchronized (mLock) { - if (mInstance != 0) { - native_replyWrite(mInstance, unique, writeSize); - } - } - break; - case FUSE_FSYNC: - entry.callback.onFsync(); - synchronized (mLock) { - if (mInstance != 0) { - native_replySimple(mInstance, unique, FUSE_OK); - } - } - break; - case FUSE_RELEASE: - entry.callback.onRelease(); - synchronized (mLock) { - if (mInstance != 0) { - native_replySimple(mInstance, unique, FUSE_OK); - } - mBytesMap.stopUsing(entry.getThreadId()); - } - break; - default: - throw new IllegalArgumentException( - "Unknown FUSE command: " + command); - } - } catch (Exception error) { - Log.e(TAG, "", error); - replySimple(unique, getError(error)); - } - }); - } catch (ErrnoException error) { - Log.e(TAG, "", error); + final Args args; + if (mArgsPool.size() == 0) { + args = new Args(); + } else { + args = mArgsPool.pop(); + } + args.unique = unique; + args.inode = inode; + args.offset = offset; + args.size = size; + args.data = data; + args.entry = getCallbackEntryOrThrowLocked(inode); + if (!args.entry.handler.sendMessage( + Message.obtain(args.entry.handler, command, 0, 0, args))) { + throw new ErrnoException("onCommand", OsConstants.EBADF); + } + } catch (Exception error) { replySimpleLocked(unique, getError(error)); } } @@ -253,9 +291,9 @@ public class FuseAppLoop { return entry; } - private void replySimple(long unique, int result) { - synchronized (mLock) { - replySimpleLocked(unique, result); + private void recycleLocked(Args args) { + if (mArgsPool.size() < ARGS_POOL_SIZE) { + mArgsPool.add(args); } } @@ -296,13 +334,6 @@ public class FuseAppLoop { long getThreadId() { return handler.getLooper().getThread().getId(); } - - void postRunnable(Runnable runnable) throws ErrnoException { - final boolean result = handler.post(runnable); - if (!result) { - throw new ErrnoException("postRunnable", OsConstants.EBADF); - } - } } /** @@ -342,4 +373,13 @@ public class FuseAppLoop { mEntries.clear(); } } + + private static class Args { + long unique; + long inode; + long offset; + int size; + byte[] data; + CallbackEntry entry; + } } |
