Merge korg/donut into korg/master
diff --git a/adb/commandline.c b/adb/commandline.c
index 7410dce..548d362 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -151,7 +151,7 @@
         "\n"
         "networking:\n"
         "  adb ppp <tty> [parameters]   - Run PPP over USB.\n"
-        " Note: you should not automatically start a PDP connection.\n"
+        " Note: you should not automatically start a PPP connection.\n"
         " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
         " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
         "\n"
diff --git a/include/arch/freebsd-x86/AndroidConfig.h b/include/arch/freebsd-x86/AndroidConfig.h
new file mode 100644
index 0000000..cc118f4
--- /dev/null
+++ b/include/arch/freebsd-x86/AndroidConfig.h
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Android config -- "FreeBSD".  Used for desktop x86 FreeBSD.
+ */
+#ifndef _ANDROID_CONFIG_H
+#define _ANDROID_CONFIG_H
+
+/*
+ * make sure we are building for FreeBSD
+ */
+#ifndef OS_FREEBSD
+#define OS_FREEBSD
+#endif
+/*
+ * ===========================================================================
+ *                              !!! IMPORTANT !!!
+ * ===========================================================================
+ *
+ * This file is included by ALL C/C++ source files.  Don't put anything in
+ * here unless you are absolutely certain it can't go anywhere else.
+ *
+ * Any C++ stuff must be wrapped with "#ifdef __cplusplus".  Do not use "//"
+ * comments.
+ */
+
+/*
+ * Threading model.  Choose one:
+ *
+ * HAVE_PTHREADS - use the pthreads library.
+ * HAVE_WIN32_THREADS - use Win32 thread primitives.
+ *  -- combine HAVE_CREATETHREAD, HAVE_CREATEMUTEX, and HAVE__BEGINTHREADEX
+ */
+#define HAVE_PTHREADS
+
+/*
+ * Do we have the futex syscall?
+ */
+/* #define HAVE_FUTEX */
+
+/*
+ * Process creation model.  Choose one:
+ *
+ * HAVE_FORKEXEC - use fork() and exec()
+ * HAVE_WIN32_PROC - use CreateProcess()
+ */
+#define HAVE_FORKEXEC
+
+/*
+ * Process out-of-memory adjustment.  Set if running on Linux,
+ * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory
+ * badness adjustment.
+ */
+/* #define HAVE_OOM_ADJ */
+
+/*
+ * IPC model.  Choose one:
+ *
+ * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget).
+ * HAVE_MACOSX_IPC - use Macintosh IPC mechanisms (sem_open, mmap).
+ * HAVE_WIN32_IPC - use Win32 IPC (CreateSemaphore, CreateFileMapping).
+ * HAVE_ANDROID_IPC - use Android versions (?, mmap).
+ */
+#define HAVE_SYSV_IPC
+
+/*
+ * Memory-mapping model. Choose one:
+ *
+ * HAVE_POSIX_FILEMAP - use the Posix sys/mmap.h
+ * HAVE_WIN32_FILEMAP - use Win32 filemaps
+ */
+#define  HAVE_POSIX_FILEMAP
+
+/*
+ * Define this if you have <termio.h>
+ */
+/* #define  HAVE_TERMIO_H */
+
+/*
+ * Define this if you build against MSVCRT.DLL
+ */
+/* #define HAVE_MS_C_RUNTIME */
+
+/*
+ * Define this if you have sys/uio.h
+ */
+#define  HAVE_SYS_UIO_H
+
+/*
+ * Define this if your platforms implements symbolic links
+ * in its filesystems
+ */
+#define HAVE_SYMLINKS
+
+/*
+ * Define this if we have localtime_r().
+ */
+#define HAVE_LOCALTIME_R
+
+/*
+ * Define this if we have gethostbyname_r().
+ */
+/* #define HAVE_GETHOSTBYNAME_R */
+
+/*
+ * Define this if we have ioctl().
+ */
+#define HAVE_IOCTL
+
+/*
+ * Define this if we want to use WinSock.
+ */
+/* #define HAVE_WINSOCK */
+
+/*
+ * Define this if have clock_gettime() and friends
+ *
+ * Desktop Linux has this in librt, but it's broken in goobuntu, yielding
+ * mildly or wildly inaccurate results.
+ */
+#define HAVE_POSIX_CLOCKS
+
+/*
+ * Define this if we have pthread_cond_timedwait_monotonic() and
+ * clock_gettime(CLOCK_MONOTONIC).
+ */
+/* #define HAVE_TIMEDWAIT_MONOTONIC */
+
+/*
+ * Define this if we have linux style epoll()
+ */
+/* #define HAVE_EPOLL */
+
+/*
+ * Endianness of the target machine.  Choose one:
+ *
+ * HAVE_ENDIAN_H -- have endian.h header we can include.
+ * HAVE_LITTLE_ENDIAN -- we are little endian.
+ * HAVE_BIG_ENDIAN -- we are big endian.
+ */
+/* #define HAVE_ENDIAN_H */
+#define HAVE_LITTLE_ENDIAN
+
+/*
+ * Define this if you have sys/endian.h
+ * NOTE: mutually exclusive with HAVE_ENDIAN_H
+ */
+#define HAVE_SYS_ENDIAN_H
+
+/*
+ * We need to choose between 32-bit and 64-bit off_t.  All of our code should
+ * agree on the same size.  For desktop systems, use 64-bit values,
+ * because some of our libraries (e.g. wxWidgets) expect to be built that way.
+ */
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE_SOURCE 1
+
+/*
+ * Defined if we have the backtrace() call for retrieving a stack trace.
+ * Needed for CallStack to operate; if not defined, CallStack is
+ * non-functional.
+ */
+#define HAVE_BACKTRACE 0
+
+/*
+ * Defined if we have the dladdr() call for retrieving the symbol associated
+ * with a memory address.  If not defined, stack crawls will not have symbolic
+ * information.
+ */
+#define HAVE_DLADDR 1
+
+/*
+ * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
+ * not defined, stack crawls will be displayed with raw mangled symbols
+ */
+#define HAVE_CXXABI 0
+
+/*
+ * Defined if we have the gettid() system call.
+ */
+/* #define HAVE_GETTID */
+
+/* 
+ * Defined if we have the sched_setscheduler() call
+ */
+#define HAVE_SCHED_SETSCHEDULER
+
+/*
+ * Add any extra platform-specific defines here.
+ */
+
+/*
+ * Define if we have <malloc.h> header
+ */
+#define HAVE_MALLOC_H
+
+/*
+ * Define if we have Linux-style non-filesystem Unix Domain Sockets
+ */
+
+/*
+ * What CPU architecture does this platform use?
+ */
+#define ARCH_X86
+
+
+/*
+ * Define if we have Linux's inotify in <sys/inotify.h>.
+ */
+/*#define HAVE_INOTIFY 1*/
+
+/*
+ * Define if we have madvise() in <sys/mman.h>
+ */
+#define HAVE_MADVISE 1
+
+/*
+ * Define if tm struct has tm_gmtoff field
+ */
+#define HAVE_TM_GMTOFF 1
+
+/*
+ * Define if dirent struct has d_type field
+ */
+#define HAVE_DIRENT_D_TYPE 1
+
+/*
+ * Define if libc includes Android system properties implementation.
+ */
+/* #define HAVE_LIBC_SYSTEM_PROPERTIES */
+
+/*
+ * Define if system provides a system property server (should be
+ * mutually exclusive with HAVE_LIBC_SYSTEM_PROPERTIES).
+ */
+#define HAVE_SYSTEM_PROPERTY_SERVER
+
+/*
+ * sprintf() format string for shared library naming.
+ */
+#define OS_SHARED_LIB_FORMAT_STR    "lib%s.so"
+
+/*
+ * type for the third argument to mincore().
+ */
+#define MINCORE_POINTER_TYPE char *
+
+/*
+ * Do we have the sigaction flag SA_NOCLDWAIT?
+ */
+#define HAVE_SA_NOCLDWAIT
+
+/*
+ * Define if we include <sys/mount.h> for statfs()
+ */
+#define INCLUDE_SYS_MOUNT_FOR_STATFS 1
+  
+/*
+ * The default path separator for the platform
+ */
+#define OS_PATH_SEPARATOR '/'
+
+/*
+ * Is the filesystem case sensitive?
+ */
+#define OS_CASE_SENSITIVE
+
+/*
+ * Define if <sys/socket.h> exists.
+ */
+#define HAVE_SYS_SOCKET_H 1
+
+/*
+ * Define if the strlcpy() function exists on the system.
+ */
+#define HAVE_STRLCPY 1
+
+/*
+ * Define if prctl() exists
+ */
+/* #define HAVE_PRCTL 1 */
+
+/*
+ * Define if writev() exists
+ */
+#define HAVE_WRITEV 1
+
+/*
+ * Define if <alloca.h> does not exist
+ * NOTE: <alloca.h> defines alloca() which
+ *   on FreeBSD is defined in <stdlib.h>
+ */
+#define HAVE_NO_ALLOCA_H
+
+/*
+ * Defines CLOCK_PROCESS_CPUTIME_ID for clock_gettime()
+ * XXX: CLOCK_PROF seems to be commonly used replacement
+ */
+#ifndef  CLOCK_PROCESS_CPUTIME_ID
+#define CLOCK_PROCESS_CPUTIME_ID CLOCK_PROF
+#endif
+
+#endif /*_ANDROID_CONFIG_H*/
diff --git a/include/cutils/abort_socket.h b/include/cutils/abort_socket.h
new file mode 100644
index 0000000..fbb1112
--- /dev/null
+++ b/include/cutils/abort_socket.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Helper to perform abortable blocking operations on a socket:
+ *   asocket_connect()
+ *   asocket_accept()
+ *   asocket_read()
+ *   asocket_write()
+ * These calls are similar to the regular syscalls, but can be aborted with:
+ *   asocket_abort()
+ *
+ * Calling close() on a regular POSIX socket does not abort blocked syscalls on
+ * that socket in other threads.
+ *
+ * After calling asocket_abort() the socket cannot be reused.
+ *
+ * Call asocket_destory() *after* all threads have finished with the socket to
+ * finish closing the socket and free the asocket structure.
+ *
+ * The helper is implemented by setting the socket non-blocking to initiate
+ * syscalls connect(), accept(), read(), write(), then using a blocking poll()
+ * on both the primary socket and a local pipe. This makes the poll() abortable
+ * by writing a byte to the local pipe in asocket_abort().
+ *
+ * asocket_create() sets the fd to non-blocking mode. It must not be changed to
+ * blocking mode.
+ *
+ * Using asocket will triple the number of file descriptors required per
+ * socket, due to the local pipe. It may be possible to use a global pipe per
+ * process rather than per socket, but we have not been able to come up with a
+ * race-free implementation yet.
+ *
+ * All functions except asocket_init() and asocket_destroy() are thread safe.
+ */
+
+#include <stdlib.h>
+#include <sys/socket.h>
+
+#ifndef __CUTILS_ABORT_SOCKET_H__
+#define __CUTILS_ABORT_SOCKET_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct asocket {
+    int fd;           /* primary socket fd */
+    int abort_fd[2];  /* pipe used to abort */
+};
+
+/* Create an asocket from fd.
+ * Sets the socket to non-blocking mode.
+ * Returns NULL on error with errno set.
+ */
+struct asocket *asocket_init(int fd);
+
+/* Blocking socket I/O with timeout.
+ * Calling asocket_abort() from another thread will cause each of these
+ * functions to immediately return with value -1 and errno ECANCELED.
+ * timeout is in ms, use -1 to indicate no timeout. On timeout -1 is returned
+ * with errno ETIMEDOUT.
+ * EINTR is handled in-call.
+ * Other semantics are identical to the regular syscalls.
+ */
+int asocket_connect(struct asocket *s, const struct sockaddr *addr,
+        socklen_t addrlen, int timeout);
+
+int asocket_accept(struct asocket *s, struct sockaddr *addr,
+        socklen_t *addrlen, int timeout);
+
+int asocket_read(struct asocket *s, void *buf, size_t count, int timeout);
+
+int asocket_write(struct asocket *s, const void *buf, size_t count,
+        int timeout);
+
+/* Abort above calls and shutdown socket.
+ * Further I/O operations on this socket will immediately fail after this call.
+ * asocket_destroy() should be used to release resources once all threads
+ * have returned from blocking calls on the socket.
+ */
+void asocket_abort(struct asocket *s);
+
+/* Close socket and free asocket structure.
+ * Must not be called until all calls on this structure have completed.
+ */
+void asocket_destroy(struct asocket *s);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__CUTILS_ABORT_SOCKET__H__
diff --git a/init/builtins.c b/init/builtins.c
index 17df0af..93ce6e8 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -29,6 +29,7 @@
 #include <stdlib.h>
 #include <sys/mount.h>
 #include <sys/resource.h>
+#include <linux/loop.h>
 
 #include "init.h"
 #include "keywords.h"
@@ -257,7 +258,7 @@
 int do_mount(int nargs, char **args)
 {
     char tmp[64];
-    char *source;
+    char *source, *target, *system;
     char *options = NULL;
     unsigned flags = 0;
     int n, i;
@@ -275,15 +276,70 @@
             options = args[n];
     }
 
+    system = args[1];
     source = args[2];
+    target = args[3];
+
     if (!strncmp(source, "mtd@", 4)) {
         n = mtd_name_to_number(source + 4);
-        if (n >= 0) {
-            sprintf(tmp, "/dev/block/mtdblock%d", n);
-            source = tmp;
+        if (n < 0) {
+            return -1;
         }
+
+        sprintf(tmp, "/dev/block/mtdblock%d", n);
+
+        if (mount(tmp, target, system, flags, options) < 0) {
+            return -1;
+        }
+
+        return 0;
+    } else if (!strncmp(source, "loop@", 5)) {
+        int mode, loop, fd;
+        struct loop_info info;
+
+        mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
+        fd = open(source + 5, mode);
+        if (fd < 0) {
+            return -1;
+        }
+
+        for (n = 0; ; n++) {
+            sprintf(tmp, "/dev/block/loop%d", n);
+            loop = open(tmp, mode);
+            if (loop < 0) {
+                return -1;
+            }
+
+            /* if it is a blank loop device */
+            if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
+                /* if it becomes our loop device */
+                if (ioctl(loop, LOOP_SET_FD, fd) >= 0) {
+                    close(fd);
+
+                    if (mount(tmp, target, system, flags, options) < 0) {
+                        ioctl(loop, LOOP_CLR_FD, 0);
+                        close(loop);
+                        return -1;
+                    }
+
+                    close(loop);
+                    return 0;
+                }
+            }
+
+            close(loop);
+        }
+
+        close(fd);
+        ERROR("out of loopback devices");
+        return -1;
+    } else {
+        if (mount(source, target, system, flags, options) < 0) {
+            return -1;
+        }
+
+        return 0;
     }
-    return mount(source, args[3], args[1], flags, options);
 }
 
 int do_setkey(int nargs, char **args)
diff --git a/init/devices.c b/init/devices.c
index ac72b34..60f9b9c 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -393,6 +393,9 @@
         } else if(!strncmp(uevent->subsystem, "mtd", 3)) {
             base = "/dev/mtd/";
             mkdir(base, 0755);
+        } else if(!strncmp(uevent->subsystem, "sound", 5)) {
+            base = "/dev/snd/";
+            mkdir(base, 0755);
         } else if(!strncmp(uevent->subsystem, "misc", 4) &&
                     !strncmp(name, "log_", 4)) {
             base = "/dev/log/";
diff --git a/init/init.c b/init/init.c
index 0c1ad3f..dfc858a 100644
--- a/init/init.c
+++ b/init/init.c
@@ -256,7 +256,8 @@
         }
 
         if (!dynamic_args)
-            execve(svc->args[0], (char**) svc->args, (char**) ENV);
+            if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0)
+                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
         else {
             char *arg_ptrs[SVC_MAXARGS+1];
             int arg_idx = svc->nargs;
@@ -273,7 +274,8 @@
                     break;
             }
             arg_ptrs[arg_idx] = '\0';
-            execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
+            if (execve(svc->args[0], (char**) arg_ptrs, (char**) ENV) < 0)
+                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
         }
         _exit(127);
     }
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 18d0ee3..98e59ee 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -17,6 +17,7 @@
 include $(CLEAR_VARS)
 
 commonSources := \
+	abort_socket.c \
 	array.c \
 	hashmap.c \
 	atomic.c \
diff --git a/libcutils/abort_socket.c b/libcutils/abort_socket.c
new file mode 100644
index 0000000..6a5e5e4
--- /dev/null
+++ b/libcutils/abort_socket.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+
+#include "cutils/abort_socket.h"
+
+struct asocket *asocket_init(int fd) {
+    int abort_fd[2];
+    int flags;
+    struct asocket *s;
+
+    /* set primary socket to non-blocking */
+    flags = fcntl(fd, F_GETFL);
+    if (flags == -1)
+        return NULL;
+    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
+        return NULL;
+
+    /* create pipe with non-blocking write, so that asocket_close() cannot
+       block */
+    if (pipe(abort_fd))
+        return NULL;
+    flags = fcntl(abort_fd[1], F_GETFL);
+    if (flags == -1)
+        return NULL;
+    if (fcntl(abort_fd[1], F_SETFL, flags | O_NONBLOCK))
+        return NULL;
+
+    s = malloc(sizeof(struct asocket));
+    if (!s)
+        return NULL;
+
+    s->fd = fd;
+    s->abort_fd[0] = abort_fd[0];
+    s->abort_fd[1] = abort_fd[1];
+
+    return s;
+}
+
+int asocket_connect(struct asocket *s, const struct sockaddr *addr,
+        socklen_t addrlen, int timeout) {
+
+    int ret;
+
+    do {
+        ret = connect(s->fd, addr, addrlen);
+    } while (ret && errno == EINTR);
+
+    if (ret && errno == EINPROGRESS) {
+        /* ready to poll() */
+        socklen_t retlen;
+        struct pollfd pfd[2];
+
+        pfd[0].fd = s->fd;
+        pfd[0].events = POLLOUT;
+        pfd[0].revents = 0;
+        pfd[1].fd = s->abort_fd[0];
+        pfd[1].events = POLLIN;
+        pfd[1].revents = 0;
+
+        do {
+            ret = poll(pfd, 2, timeout);
+        } while (ret < 0 && errno == EINTR);
+
+        if (ret < 0)
+            return -1;
+        else if (ret == 0) {
+            /* timeout */
+            errno = ETIMEDOUT;
+            return -1;
+        }
+
+        if (pfd[1].revents) {
+            /* abort due to asocket_abort() */
+            errno = ECANCELED;
+            return -1;
+        }
+
+        if (pfd[0].revents) {
+            if (pfd[0].revents & POLLOUT) {
+                /* connect call complete, read return code */
+                retlen = sizeof(ret);
+                if (getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen))
+                    return -1;
+                /* got connect() return code */
+                if (ret) {
+                    errno = ret;
+                }
+            } else {
+                /* some error event on this fd */
+                errno = ECONNABORTED;
+                return -1;
+            }
+        }
+    }
+
+    return ret;
+}
+
+int asocket_accept(struct asocket *s, struct sockaddr *addr,
+        socklen_t *addrlen, int timeout) {
+
+    int ret;
+    struct pollfd pfd[2];
+
+    pfd[0].fd = s->fd;
+    pfd[0].events = POLLIN;
+    pfd[0].revents = 0;
+    pfd[1].fd = s->abort_fd[0];
+    pfd[1].events = POLLIN;
+    pfd[1].revents = 0;
+
+    do {
+        ret = poll(pfd, 2, timeout);
+    } while (ret < 0 && errno == EINTR);
+
+    if (ret < 0)
+        return -1;
+    else if (ret == 0) {
+        /* timeout */
+        errno = ETIMEDOUT;
+        return -1;
+    }
+
+    if (pfd[1].revents) {
+        /* abort due to asocket_abort() */
+        errno = ECANCELED;
+        return -1;
+    }
+
+    if (pfd[0].revents) {
+        if (pfd[0].revents & POLLIN) {
+            /* ready to accept() without blocking */
+            do {
+                ret = accept(s->fd, addr, addrlen);
+            } while (ret < 0 && errno == EINTR);
+        } else {
+            /* some error event on this fd */
+            errno = ECONNABORTED;
+            return -1;
+        }
+    }
+
+    return ret;
+}
+
+int asocket_read(struct asocket *s, void *buf, size_t count, int timeout) {
+    int ret;
+    struct pollfd pfd[2];
+
+    pfd[0].fd = s->fd;
+    pfd[0].events = POLLIN;
+    pfd[0].revents = 0;
+    pfd[1].fd = s->abort_fd[0];
+    pfd[1].events = POLLIN;
+    pfd[1].revents = 0;
+
+    do {
+        ret = poll(pfd, 2, timeout);
+    } while (ret < 0 && errno == EINTR);
+
+    if (ret < 0)
+        return -1;
+    else if (ret == 0) {
+        /* timeout */
+        errno = ETIMEDOUT;
+        return -1;
+    }
+
+    if (pfd[1].revents) {
+        /* abort due to asocket_abort() */
+        errno = ECANCELED;
+        return -1;
+    }
+
+    if (pfd[0].revents) {
+        if (pfd[0].revents & POLLIN) {
+            /* ready to read() without blocking */
+            do {
+                ret = read(s->fd, buf, count);
+            } while (ret < 0 && errno == EINTR);
+        } else {
+            /* some error event on this fd */
+            errno = ECONNABORTED;
+            return -1;
+        }
+    }
+
+    return ret;
+}
+
+int asocket_write(struct asocket *s, const void *buf, size_t count,
+        int timeout) {
+    int ret;
+    struct pollfd pfd[2];
+
+    pfd[0].fd = s->fd;
+    pfd[0].events = POLLOUT;
+    pfd[0].revents = 0;
+    pfd[1].fd = s->abort_fd[0];
+    pfd[1].events = POLLIN;
+    pfd[1].revents = 0;
+
+    do {
+        ret = poll(pfd, 2, timeout);
+    } while (ret < 0 && errno == EINTR);
+
+    if (ret < 0)
+        return -1;
+    else if (ret == 0) {
+        /* timeout */
+        errno = ETIMEDOUT;
+        return -1;
+    }
+
+    if (pfd[1].revents) {
+        /* abort due to asocket_abort() */
+        errno = ECANCELED;
+        return -1;
+    }
+
+    if (pfd[0].revents) {
+        if (pfd[0].revents & POLLOUT) {
+            /* ready to write() without blocking */
+            do {
+                ret = write(s->fd, buf, count);
+            } while (ret < 0 && errno == EINTR);
+        } else {
+            /* some error event on this fd */
+            errno = ECONNABORTED;
+            return -1;
+        }
+    }
+
+    return ret;
+}
+
+void asocket_abort(struct asocket *s) {
+    int ret;
+    char buf = 0;
+
+    /* Prevent further use of fd, without yet releasing the fd */
+    shutdown(s->fd, SHUT_RDWR);
+
+    /* wake up calls blocked at poll() */
+    do {
+        ret = write(s->abort_fd[1], &buf, 1);
+    } while (ret < 0 && errno == EINTR);
+}
+
+void asocket_destroy(struct asocket *s) {
+    struct asocket s_copy = *s;
+
+    /* Clients should *not* be using these fd's after calling
+       asocket_destroy(), but in case they do, set to -1 so they cannot use a
+       stale fd */
+    s->fd = -1;
+    s->abort_fd[0] = -1;
+    s->abort_fd[1] = -1;
+
+    /* Call asocket_abort() in case there are still threads blocked on this
+       socket. Clients should not rely on this behavior - it is racy because we
+       are about to close() these sockets - clients should instead make sure
+       all threads are done with the socket before calling asocket_destory().
+     */
+    asocket_abort(&s_copy);
+
+    /* enough safety checks, close and release memory */
+    close(s_copy.abort_fd[1]);
+    close(s_copy.abort_fd[0]);
+    close(s_copy.fd);
+
+    free(s);
+}
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 2cf1254..080f9e3 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -23,7 +23,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
-#include <alloca.h>
 #include <assert.h>
 #include <arpa/inet.h>
 
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index 50eb5f5..0cc85d9 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -64,12 +64,14 @@
 LOCAL_MODULE:= libpixelflinger
 LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
 LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
+
 ifneq ($(BUILD_TINY_ANDROID),true)
 # Really this should go away entirely or at least not depend on
 # libhardware, but this at least gets us built.
 LOCAL_SHARED_LIBRARIES += libhardware_legacy
 LOCAL_CFLAGS += -DWITH_LIB_HARDWARE
 endif
+
 ifeq ($(TARGET_ARCH),arm)
 LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_armv6
 endif
diff --git a/toolbox/mount.c b/toolbox/mount.c
index 86047a9..472c952 100644
--- a/toolbox/mount.c
+++ b/toolbox/mount.c
@@ -138,14 +138,17 @@
 
     if (loop) {
         int file_fd, device_fd;
+        int flags;
+
+        flags = (rwflag & MS_RDONLY) ? O_RDONLY : O_RDWR;
         
         // FIXME - only one loop mount supported at a time
-        file_fd = open(dev, O_RDWR);
+        file_fd = open(dev, flags);
         if (file_fd < -1) {
             perror("open backing file failed");
             return 1;
         }
-        device_fd = open(LOOP_DEVICE, O_RDWR);
+        device_fd = open(LOOP_DEVICE, flags);
         if (device_fd < -1) {
             perror("open loop device failed");
             close(file_fd);