Merge "implement pthread mutex deadlock detection"
diff --git a/libc/Android.mk b/libc/Android.mk
index 71c721b..3043e62 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -512,11 +512,13 @@
   endif
 else # !arm
   ifeq ($(TARGET_ARCH),x86)
-    libc_crt_target_cflags := -m32
-
-    # Enable recent IA friendly memory routines (such as for Atom)
-    # These will not work on the earlier x86 machines
-    libc_common_cflags += -mtune=i686 -DUSE_SSSE3 -DUSE_SSE2
+    libc_crt_target_cflags :=
+    ifeq ($(ARCH_X86_HAVE_SSE2),true)
+        libc_crt_target_cflags += -DUSE_SSE2=1
+    endif
+    ifeq ($(ARCH_X86_HAVE_SSSE3),true)
+        libc_crt_target_cflags += -DUSE_SSSE3=1
+    endif
   endif # x86
 endif # !arm
 
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index fa02edc..800726a 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -50,6 +50,7 @@
 uid_t   getresuid:getresuid32 ()   209
 gid_t   getresgid:getresgid32 ()   211
 pid_t   gettid()                   224
+ssize_t readahead(int, off64_t, size_t)     225
 int     getgroups:getgroups32(int, gid_t *)    205
 pid_t   getpgid(pid_t)             132
 pid_t   getppid()		   64
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index e6c84f6..1f2a1cd 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -14,6 +14,7 @@
 syscall_src += arch-arm/syscalls/getresuid.S
 syscall_src += arch-arm/syscalls/getresgid.S
 syscall_src += arch-arm/syscalls/gettid.S
+syscall_src += arch-arm/syscalls/readahead.S
 syscall_src += arch-arm/syscalls/getgroups.S
 syscall_src += arch-arm/syscalls/getpgid.S
 syscall_src += arch-arm/syscalls/getppid.S
diff --git a/libc/arch-arm/syscalls/readahead.S b/libc/arch-arm/syscalls/readahead.S
new file mode 100644
index 0000000..6aa8265
--- /dev/null
+++ b/libc/arch-arm/syscalls/readahead.S
@@ -0,0 +1,16 @@
+/* autogenerated by gensyscalls.py */
+#include <machine/asm.h>
+#include <sys/linux-syscalls.h>
+
+ENTRY(readahead)
+    mov     ip, sp
+    .save   {r4, r5, r6, r7}
+    stmfd   sp!, {r4, r5, r6, r7}
+    ldmfd   ip, {r4, r5, r6}
+    ldr     r7, =__NR_readahead
+    swi     #0
+    ldmfd   sp!, {r4, r5, r6, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+END(readahead)
diff --git a/libc/arch-sh/syscalls.mk b/libc/arch-sh/syscalls.mk
index d4e4583..e6fba58 100644
--- a/libc/arch-sh/syscalls.mk
+++ b/libc/arch-sh/syscalls.mk
@@ -15,6 +15,7 @@
 syscall_src += arch-sh/syscalls/getresuid.S
 syscall_src += arch-sh/syscalls/getresgid.S
 syscall_src += arch-sh/syscalls/gettid.S
+syscall_src += arch-sh/syscalls/readahead.S
 syscall_src += arch-sh/syscalls/getgroups.S
 syscall_src += arch-sh/syscalls/getpgid.S
 syscall_src += arch-sh/syscalls/getppid.S
diff --git a/libc/arch-sh/syscalls/readahead.S b/libc/arch-sh/syscalls/readahead.S
new file mode 100644
index 0000000..df64b5f
--- /dev/null
+++ b/libc/arch-sh/syscalls/readahead.S
@@ -0,0 +1,32 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type readahead, @function
+    .globl readahead
+    .align 4
+
+readahead:
+
+    /* invoke trap */
+    mov.l   0f, r3  /* trap num */
+    trapa   #(4 + 0x10)
+
+    /* check return value */
+    cmp/pz  r0
+    bt      __NR_readahead_end
+
+    /* keep error number */
+    sts.l   pr, @-r15
+    mov.l   1f, r1
+    jsr     @r1
+    mov     r0, r4
+    lds.l   @r15+, pr
+
+__NR_readahead_end:
+    rts
+    nop
+
+    .align  2
+0:  .long   __NR_readahead
+1:  .long   __set_syscall_errno
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 13edeb0..f263470 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -15,6 +15,7 @@
 syscall_src += arch-x86/syscalls/getresuid.S
 syscall_src += arch-x86/syscalls/getresgid.S
 syscall_src += arch-x86/syscalls/gettid.S
+syscall_src += arch-x86/syscalls/readahead.S
 syscall_src += arch-x86/syscalls/getgroups.S
 syscall_src += arch-x86/syscalls/getpgid.S
 syscall_src += arch-x86/syscalls/getppid.S
diff --git a/libc/arch-x86/syscalls/readahead.S b/libc/arch-x86/syscalls/readahead.S
new file mode 100644
index 0000000..b89314f
--- /dev/null
+++ b/libc/arch-x86/syscalls/readahead.S
@@ -0,0 +1,32 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type readahead, @function
+    .globl readahead
+    .align 4
+
+readahead:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    pushl   %esi
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
+    mov     32(%esp), %esi
+    movl    $__NR_readahead, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %esi
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/bionic/dlmalloc.c b/libc/bionic/dlmalloc.c
index 8c75e9c..496cd1c 100644
--- a/libc/bionic/dlmalloc.c
+++ b/libc/bionic/dlmalloc.c
@@ -774,6 +774,22 @@
 void* dlmemalign(size_t, size_t);
 
 /*
+  int posix_memalign(void **memptr, size_t alignment, size_t size);
+  Places a pointer to a newly allocated chunk of size bytes, aligned
+  in accord with the alignment argument, in *memptr.
+
+  The return value is 0 on success, and ENOMEM on failure.
+
+  The alignment argument should be a power of two. If the argument is
+  not a power of two, the nearest greater power is used.
+  8-byte alignment is guaranteed by normal malloc calls, so don't
+  bother calling memalign with an argument of 8 or less.
+
+  Overreliance on posix_memalign is a sure way to fragment space.
+*/
+int posix_memalign(void **memptr, size_t alignment, size_t size);
+
+/*
   valloc(size_t n);
   Equivalent to memalign(pagesize, n), where pagesize is the page
   size of the system. If the pagesize is unknown, 4096 is used.
@@ -4507,6 +4523,18 @@
   return internal_memalign(gm, alignment, bytes);
 }
 
+int posix_memalign(void **memptr, size_t alignment, size_t size) {
+  int ret = 0;
+
+  *memptr = dlmemalign(alignment, size);
+
+  if (*memptr == 0) {
+    ret = ENOMEM;
+  }
+
+  return ret;
+}
+
 void** dlindependent_calloc(size_t n_elements, size_t elem_size,
                                  void* chunks[]) {
   size_t sz = elem_size; /* serves as 1-element array */
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 5dc8a87..e5caadd 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -67,6 +67,8 @@
 extern unsigned long long strtoull(const char *, char **, int);
 extern double strtod(const char *nptr, char **endptr);
 
+extern int posix_memalign(void **memptr, size_t alignment, size_t size);
+
 static __inline__ float strtof(const char *nptr, char **endptr)
 {
     return (float)strtod(nptr, endptr);
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index 930508a..5361ace 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -20,6 +20,7 @@
 #define __NR_getresuid32                  (__NR_SYSCALL_BASE + 209)
 #define __NR_getresgid32                  (__NR_SYSCALL_BASE + 211)
 #define __NR_gettid                       (__NR_SYSCALL_BASE + 224)
+#define __NR_readahead                    (__NR_SYSCALL_BASE + 225)
 #define __NR_getgroups32                  (__NR_SYSCALL_BASE + 205)
 #define __NR_getpgid                      (__NR_SYSCALL_BASE + 132)
 #define __NR_getppid                      (__NR_SYSCALL_BASE + 64)
diff --git a/libc/include/sys/linux-unistd.h b/libc/include/sys/linux-unistd.h
index f463127..867cfe6 100644
--- a/libc/include/sys/linux-unistd.h
+++ b/libc/include/sys/linux-unistd.h
@@ -20,6 +20,7 @@
 uid_t            getresuid (void);
 gid_t            getresgid (void);
 pid_t            gettid (void);
+ssize_t          readahead (int, off64_t, size_t);
 int              getgroups (int, gid_t *);
 pid_t            getpgid (pid_t);
 pid_t            getppid (void);
diff --git a/libc/kernel/common/video/dsscomp.h b/libc/kernel/common/video/dsscomp.h
index 92fd789..575071f 100644
--- a/libc/kernel/common/video/dsscomp.h
+++ b/libc/kernel/common/video/dsscomp.h
@@ -228,129 +228,145 @@
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  OMAP_DSS_BUFTYPE_TILER_PAGE,
 };
-struct dss2_ovl_info {
- struct dss2_ovl_cfg cfg;
+enum omapdss_buffer_addressing_type {
+ OMAP_DSS_BUFADDR_DIRECT,
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ OMAP_DSS_BUFADDR_BYTYPE,
+ OMAP_DSS_BUFADDR_ION,
+ OMAP_DSS_BUFADDR_GRALLOC,
+ OMAP_DSS_BUFADDR_OVL_IX,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ OMAP_DSS_BUFADDR_LAYER_IX,
+ OMAP_DSS_BUFADDR_FB,
+};
+struct dss2_ovl_info {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ struct dss2_ovl_cfg cfg;
+ enum omapdss_buffer_addressing_type addressing;
  union {
  struct {
- void *address;
- __u16 ba_type;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 uv_type;
+ void *address;
+ void *uv_address;
  };
  struct {
- __u32 ba;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ enum omapdss_buffer_type ba_type;
+ enum omapdss_buffer_type uv_type;
+ };
+ struct {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 ba;
  __u32 uv;
  };
  };
-};
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
 struct dss2_mgr_info {
  __u32 ix;
  __u32 default_color;
- enum omap_dss_trans_key_type trans_key_type;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ enum omap_dss_trans_key_type trans_key_type;
  __u32 trans_key;
  struct omap_dss_cpr_coefs cpr_coefs;
  __u8 trans_enabled;
- __u8 interlaced;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u8 interlaced;
  __u8 alpha_blending;
  __u8 cpr_enabled;
  __u8 swap_rb;
-} __attribute__ ((aligned(4)));
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+} __attribute__ ((aligned(4)));
 enum dsscomp_setup_mode {
  DSSCOMP_SETUP_MODE_APPLY = (1 << 0),
  DSSCOMP_SETUP_MODE_DISPLAY = (1 << 1),
- DSSCOMP_SETUP_MODE_CAPTURE = (1 << 2),
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ DSSCOMP_SETUP_MODE_CAPTURE = (1 << 2),
  DSSCOMP_SETUP_APPLY = DSSCOMP_SETUP_MODE_APPLY,
  DSSCOMP_SETUP_DISPLAY =
  DSSCOMP_SETUP_MODE_APPLY | DSSCOMP_SETUP_MODE_DISPLAY,
- DSSCOMP_SETUP_CAPTURE =
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ DSSCOMP_SETUP_CAPTURE =
  DSSCOMP_SETUP_MODE_APPLY | DSSCOMP_SETUP_MODE_CAPTURE,
  DSSCOMP_SETUP_DISPLAY_CAPTURE =
  DSSCOMP_SETUP_DISPLAY | DSSCOMP_SETUP_CAPTURE,
-};
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+};
 struct dsscomp_setup_mgr_data {
  __u32 sync_id;
  struct dss2_rect_t win;
- enum dsscomp_setup_mode mode;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ enum dsscomp_setup_mode mode;
  __u16 num_ovls;
  __u16 get_sync_obj;
  struct dss2_mgr_info mgr;
- struct dss2_ovl_info ovls[0];
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ struct dss2_ovl_info ovls[0];
 };
 struct dsscomp_check_ovl_data {
  enum dsscomp_setup_mode mode;
- struct dss2_mgr_info mgr;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ struct dss2_mgr_info mgr;
  struct dss2_ovl_info ovl;
 };
 struct dsscomp_setup_dispc_data {
- __u32 sync_id;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 sync_id;
  enum dsscomp_setup_mode mode;
  __u16 num_ovls;
  __u16 num_mgrs;
- __u16 get_sync_obj;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u16 get_sync_obj;
  struct dss2_mgr_info mgrs[3];
  struct dss2_ovl_info ovls[5];
 };
-struct dsscomp_wb_copy_data {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+struct dsscomp_wb_copy_data {
  struct dss2_ovl_info ovl, wb;
 };
 struct dsscomp_display_info {
- __u32 ix;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 ix;
  __u32 overlays_available;
  __u32 overlays_owned;
  enum omap_channel channel;
- enum omap_dss_display_state state;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ enum omap_dss_display_state state;
  __u8 enabled;
  struct omap_video_timings timings;
  struct s3d_disp_info s3d_info;
- struct dss2_mgr_info mgr;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ struct dss2_mgr_info mgr;
  __u16 width_in_mm;
  __u16 height_in_mm;
  __u32 modedb_len;
- struct dsscomp_videomode modedb[];
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ struct dsscomp_videomode modedb[];
 };
 struct dsscomp_setup_display_data {
  __u32 ix;
- struct dsscomp_videomode mode;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ struct dsscomp_videomode mode;
 };
 enum dsscomp_wait_phase {
  DSSCOMP_WAIT_PROGRAMMED = 1,
- DSSCOMP_WAIT_DISPLAYED,
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ DSSCOMP_WAIT_DISPLAYED,
  DSSCOMP_WAIT_RELEASED,
 };
 struct dsscomp_wait_data {
- __u32 timeout_us;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 timeout_us;
  enum dsscomp_wait_phase phase;
 };
-#define DSSCOMP_SETUP_MGR _IOW('O', 128, struct dsscomp_setup_mgr_data)
-#define DSSCOMP_CHECK_OVL _IOWR('O', 129, struct dsscomp_check_ovl_data)
+#define DSSCIOC_SETUP_MGR _IOW('O', 128, struct dsscomp_setup_mgr_data)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define DSSCOMP_WB_COPY _IOW('O', 130, struct dsscomp_wb_copy_data)
-#define DSSCOMP_QUERY_DISPLAY _IOWR('O', 131, struct dsscomp_display_info)
-#define DSSCOMP_WAIT _IOW('O', 132, struct dsscomp_wait_data)
-#define DSSCOMP_SETUP_DISPC _IOW('O', 133, struct dsscomp_setup_dispc_data)
+#define DSSCIOC_CHECK_OVL _IOWR('O', 129, struct dsscomp_check_ovl_data)
+#define DSSCIOC_WB_COPY _IOW('O', 130, struct dsscomp_wb_copy_data)
+#define DSSCIOC_QUERY_DISPLAY _IOWR('O', 131, struct dsscomp_display_info)
+#define DSSCIOC_WAIT _IOW('O', 132, struct dsscomp_wait_data)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define DSSCOMP_SETUP_DISPLAY _IOW('O', 134, struct dsscomp_setup_display_data)
+#define DSSCIOC_SETUP_DISPC _IOW('O', 133, struct dsscomp_setup_dispc_data)
+#define DSSCIOC_SETUP_DISPLAY _IOW('O', 134, struct dsscomp_setup_display_data)
 #endif
 
diff --git a/libc/unistd/opendir.c b/libc/unistd/opendir.c
index afa3ea0..f178bc6 100644
--- a/libc/unistd/opendir.c
+++ b/libc/unistd/opendir.c
@@ -92,6 +92,9 @@
 _readdir_unlocked(DIR*  dir)
 {
     struct dirent*  entry;
+#ifndef NDEBUG
+    unsigned reclen;
+#endif
 
     if ( !dir->_DIR_avail )
     {
@@ -115,15 +118,18 @@
     if (((long)(void*)entry & 3) != 0)
         return NULL;
 
-    if ( (unsigned)entry->d_reclen > sizeof(*entry)         ||
-         entry->d_reclen <= offsetof(struct dirent, d_name) )
+#ifndef NDEBUG
+    // paranoid testing of the interface with the kernel getdents64 system call
+    reclen = offsetof(struct dirent, d_name) + strlen(entry->d_name) + 1;
+    if ( reclen > sizeof(*entry) || reclen <= offsetof(struct dirent, d_name) )
         goto Bad;
 
-    if ( (char*)entry + entry->d_reclen > (char*)dir->_DIR_buff + sizeof(dir->_DIR_buff) )
+    if ( (char*)entry + reclen > (char*)dir->_DIR_buff + sizeof(dir->_DIR_buff) )
         goto Bad;
 
-    if ( !memchr( entry->d_name, 0, entry->d_reclen - offsetof(struct dirent, d_name)) )
+    if ( !memchr( entry->d_name, 0, reclen - offsetof(struct dirent, d_name)) )
         goto Bad; 
+#endif
 
     dir->_DIR_next   = (struct dirent*)((char*)entry + entry->d_reclen);
     dir->_DIR_avail -= entry->d_reclen;
diff --git a/libc/unistd/pathconf.c b/libc/unistd/pathconf.c
index 032f918..26b580f 100644
--- a/libc/unistd/pathconf.c
+++ b/libc/unistd/pathconf.c
@@ -70,13 +70,12 @@
     };
     int  nn = 0;
 
-    for (;;) {
-        if ( known64[nn] == EOL_MAGIC )
-            return 32;
-
-        if ( known64[nn] == s->f_type )
+    for (; known64[nn] != EOL_MAGIC; ++nn) {
+        if (known64[nn] == s->f_type) {
             return 64;
+        }
     }
+    return 32;
 }
 
 
@@ -99,12 +98,10 @@
     };
     int   nn = 0;
 
-    for (;;) {
-        if ( knownMax[nn].type == EOL_MAGIC )
-            return LINK_MAX;
-
-        if ( knownMax[nn].type == s->f_type )
+    for (; knownMax[nn].type != EOL_MAGIC; ++nn) {
+        if (knownMax[nn].type == s->f_type) {
             return knownMax[nn].max;
+        }
     }
     return LINK_MAX;
 }
@@ -121,12 +118,12 @@
     };
     int  nn = 0;
 
-    for (;;) {
-        if (knownNoSymlinks[nn] == 0)
-            return 1;
-        if (knownNoSymlinks[nn] == s->f_type)
+    for (; knownNoSymlinks[nn] != EOL_MAGIC; ++nn) {
+        if (knownNoSymlinks[nn] == s->f_type) {
             return 0;
+        }
     }
+    return 1;
 }
 
 static long