From fc6a2ad24fed0f8c9529d3ef785b0d5a153c3849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20M=C3=A5rtensson?= Date: Wed, 8 May 2013 12:01:42 +0200 Subject: [PATCH] unix: support for android builds Adds targets and fixes to ensure building for android works. To build on android, refer to the android standalone toolchain. --- LICENSE | 3 ++ common.gypi | 2 +- include/uv-private/pthread-fixes.h | 59 ++++++++++++++++++++++ include/uv-private/uv-unix.h | 3 ++ src/unix/linux-core.c | 3 ++ src/unix/linux-syscalls.h | 1 + src/unix/pthread-fixes.c | 80 ++++++++++++++++++++++++++++++ src/unix/stream.c | 19 ++++++- src/unix/thread.c | 12 ++++- uv.gyp | 20 ++++++-- 10 files changed, 194 insertions(+), 8 deletions(-) create mode 100644 include/uv-private/pthread-fixes.h create mode 100644 src/unix/pthread-fixes.c diff --git a/LICENSE b/LICENSE index 4718e345..8db13acf 100644 --- a/LICENSE +++ b/LICENSE @@ -37,3 +37,6 @@ The externally maintained libraries used by libuv are: - stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three clause BSD license. + + - pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile + Communications AB. Three clause BSD license. diff --git a/common.gypi b/common.gypi index c3462821..8693e3ff 100644 --- a/common.gypi +++ b/common.gypi @@ -129,7 +129,7 @@ }] ] }], - [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { + ['OS in "android freebsd linux openbsd solaris"', { 'cflags': [ '-Wall' ], 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ], 'target_conditions': [ diff --git a/include/uv-private/pthread-fixes.h b/include/uv-private/pthread-fixes.h new file mode 100644 index 00000000..230ce317 --- /dev/null +++ b/include/uv-private/pthread-fixes.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2013, Sony Mobile Communications AB + * Copyright (c) 2012, Google Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H +#define GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H + +#include + + +/*Android doesn't provide pthread_barrier_t for now.*/ +#ifndef PTHREAD_BARRIER_SERIAL_THREAD + +/* Anything except 0 will do here.*/ +#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 + +typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; + unsigned count; +} pthread_barrier_t; + +int pthread_barrier_init(pthread_barrier_t* barrier, + const void* barrier_attr, + unsigned count); + +int pthread_barrier_wait(pthread_barrier_t* barrier); +int pthread_barrier_destroy(pthread_barrier_t *barrier); +#endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */ + +int pthread_yield(void); +#endif /* GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H */ diff --git a/include/uv-private/uv-unix.h b/include/uv-private/uv-unix.h index 385c32a3..4be81005 100644 --- a/include/uv-private/uv-unix.h +++ b/include/uv-private/uv-unix.h @@ -37,6 +37,9 @@ #include #include +#ifdef ANDROID +#include "pthread-fixes.h" +#endif #include #if defined(__linux__) diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c index 23af7891..157938b2 100644 --- a/src/unix/linux-core.c +++ b/src/unix/linux-core.c @@ -36,7 +36,10 @@ #include #include +#ifndef ANDROID #define HAVE_IFADDRS_H 1 +#endif + #ifdef __UCLIBC__ # if __UCLIBC_MAJOR__ < 0 || __UCLIBC_MINOR__ < 9 || __UCLIBC_SUBLEVEL__ < 32 # undef HAVE_IFADDRS_H diff --git a/src/unix/linux-syscalls.h b/src/unix/linux-syscalls.h index ba44974a..1ad95185 100644 --- a/src/unix/linux-syscalls.h +++ b/src/unix/linux-syscalls.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #if defined(__alpha__) diff --git a/src/unix/pthread-fixes.c b/src/unix/pthread-fixes.c new file mode 100644 index 00000000..2e4c542b --- /dev/null +++ b/src/unix/pthread-fixes.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2013, Sony Mobile Communications AB + * Copyright (c) 2012, Google Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/*Android doesn't provide pthread_barrier_t for now.*/ +#ifndef PTHREAD_BARRIER_SERIAL_THREAD + +#include "pthread-fixes.h" + +int pthread_barrier_init(pthread_barrier_t* barrier, + const void* barrier_attr, + unsigned count) { + barrier->count = count; + pthread_mutex_init(&barrier->mutex, NULL); + pthread_cond_init(&barrier->cond, NULL); + return 0; +} + +int pthread_barrier_wait(pthread_barrier_t* barrier) { + /* Lock the mutex*/ + pthread_mutex_lock(&barrier->mutex); + /* Decrement the count. If this is the first thread to reach 0, wake up + waiters, unlock the mutex, then return PTHREAD_BARRIER_SERIAL_THREAD.*/ + if (--barrier->count == 0) { + /* First thread to reach the barrier */ + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return PTHREAD_BARRIER_SERIAL_THREAD; + } + /* Otherwise, wait for other threads until the count reaches 0, then + return 0 to indicate this is not the first thread.*/ + do { + pthread_cond_wait(&barrier->cond, &barrier->mutex); + } while (barrier->count > 0); + + pthread_mutex_unlock(&barrier->mutex); + return 0; +} + +int pthread_barrier_destroy(pthread_barrier_t *barrier) { + barrier->count = 0; + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +#endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */ + +int pthread_yield(void) { + sched_yield(); + return 0; +} diff --git a/src/unix/stream.c b/src/unix/stream.c index 7936380a..051241fb 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -696,11 +696,24 @@ static int uv__handle_fd(uv_handle_t* handle) { } } +static int uv__getiovmax() { +#if defined(IOV_MAX) + return IOV_MAX; +#elif defined(_SC_IOV_MAX) + static int iovmax = -1; + if (iovmax == -1) + iovmax = sysconf(_SC_IOV_MAX); + return iovmax; +#else + return 1024; +#endif +} static void uv__write(uv_stream_t* stream) { struct iovec* iov; QUEUE* q; uv_write_t* req; + int iovmax; int iovcnt; ssize_t n; @@ -723,9 +736,11 @@ start: iov = (struct iovec*) &(req->bufs[req->write_index]); iovcnt = req->bufcnt - req->write_index; + iovmax = uv__getiovmax(); + /* Limit iov count to avoid EINVALs from writev() */ - if (iovcnt > IOV_MAX) - iovcnt = IOV_MAX; + if (iovcnt > iovmax) + iovcnt = iovmax; /* * Now do the actual writev. Note that we've been updating the pointers diff --git a/src/unix/thread.c b/src/unix/thread.c index e44a77ff..4cc5d989 100644 --- a/src/unix/thread.c +++ b/src/unix/thread.c @@ -26,9 +26,7 @@ #include #include -#if defined(__APPLE__) && defined(__MACH__) #include -#endif /* defined(__APPLE__) && defined(__MACH__) */ #undef NANOSEC #define NANOSEC ((uint64_t) 1e9) @@ -283,8 +281,10 @@ int uv_cond_init(uv_cond_t* cond) { if (pthread_condattr_init(&attr)) return -1; +#if !defined(ANDROID) if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) goto error2; +#endif if (pthread_cond_init(cond, &attr)) goto error2; @@ -336,7 +336,15 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { timeout += uv__hrtime(); ts.tv_sec = timeout / NANOSEC; ts.tv_nsec = timeout % NANOSEC; +#if defined(ANDROID) + /* + * The bionic pthread implementation doesn't support CLOCK_MONOTONIC, + * but has this alternative function instead. + */ + r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts); +#else r = pthread_cond_timedwait(cond, mutex, &ts); +#endif /* ANDROID */ #endif diff --git a/uv.gyp b/uv.gyp index 2e228855..d8bbafce 100644 --- a/uv.gyp +++ b/uv.gyp @@ -20,7 +20,8 @@ 'conditions': [ ['OS=="solaris"', { 'cflags': [ '-pthreads' ], - }, { + }], + ['OS not in "android solaris"', { 'cflags': [ '-pthread' ], }], ], @@ -159,7 +160,8 @@ 'conditions': [ ['OS=="solaris"', { 'ldflags': [ '-pthreads' ], - }, { + }], + ['OS not in "android solaris"', { 'ldflags': [ '-pthread' ], }], ], @@ -177,7 +179,7 @@ }], ], }], - [ 'OS=="linux" or OS=="mac"', { + [ 'OS in "android linux mac"', { 'sources': [ 'src/unix/proctitle.c' ], }], [ 'OS=="mac"', { @@ -213,6 +215,18 @@ 'libraries': [ '-ldl', '-lrt' ], }, }], + [ 'OS=="android"', { + 'sources': [ + 'src/unix/linux-core.c', + 'src/unix/linux-inotify.c', + 'src/unix/linux-syscalls.c', + 'src/unix/linux-syscalls.h', + 'src/unix/pthread-fixes.c', + ], + 'link_settings': { + 'libraries': [ '-ldl' ], + }, + }], [ 'OS=="solaris"', { 'sources': [ 'src/unix/sunos.c' ], 'defines': [