[MIPS] Add Support signal.

Change-Id: Ie2aa6cd24a119f96cd01c6b3d6352f011a0825b5
Signed-off-by: Pete Delaney  <piet@mips.com>
Signed-off-by: Chris Dearman <chris@mips.com>
diff --git a/ndk/sources/android/libportable/Android.mk b/ndk/sources/android/libportable/Android.mk
index 3cc203a..70b45a4 100644
--- a/ndk/sources/android/libportable/Android.mk
+++ b/ndk/sources/android/libportable/Android.mk
@@ -38,6 +38,7 @@
 			arch-mips/open.c \
 			arch-mips/poll.c \
 			arch-mips/resource.c \
+			arch-mips/signal.c \
 			arch-mips/socket.c \
 			arch-mips/sockopt.c \
 			arch-mips/stat.c \
diff --git a/ndk/sources/android/libportable/arch-mips/signal.c b/ndk/sources/android/libportable/arch-mips/signal.c
new file mode 100644
index 0000000..6c325e4
--- /dev/null
+++ b/ndk/sources/android/libportable/arch-mips/signal.c
@@ -0,0 +1,1140 @@
+/*
+ * Copyright 2012, 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 <stdarg.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <signal_portable.h>
+#include <portability.h>
+#include <stdio.h>
+#include <errno.h>
+#include <errno_portable.h>
+
+#define PORTABLE_TAG "signal_portable"
+#include <log_portable.h>
+
+
+#if SIGBUS_PORTABLE == SIGBUS
+#error Bad build environment
+#endif
+
+/*
+ * The next five hidden functions are not exposed in the
+ * libportable shared object. They are used here and other
+ * functions, like waitpid(), which need to map signal numbers.
+ */
+__hidden char *map_portable_signum_to_name(int portable_signum)
+{
+    char *name;
+
+    switch(portable_signum) {
+    case SIGHUP_PORTABLE:       name = "SIGHUP_PORTABLE:1";             break;
+    case SIGINT_PORTABLE:       name = "SIGINT_PORTABLE:2";             break;
+    case SIGQUIT_PORTABLE:      name = "SIGQUIT_PORTABLE:3";            break;
+    case SIGILL_PORTABLE:       name = "SIGILL_PORTABLE:4";             break;
+    case SIGTRAP_PORTABLE:      name = "SIGTRAP_PORTABLE:5";            break;
+    case SIGABRT_PORTABLE:      name = "SIGABRT_PORTABLE:6";            break;
+    case SIGBUS_PORTABLE:       name = "SIGBUS_PORTABLE:7";             break;
+    case SIGFPE_PORTABLE:       name = "SIGFPE_PORTABLE:8";             break;
+    case SIGKILL_PORTABLE:      name = "SIGKILL_PORTABLE:9";            break;
+    case SIGUSR1_PORTABLE:      name = "SIGUSR1_PORTABLE:10";           break;
+    case SIGSEGV_PORTABLE:      name = "SIGSEGV_PORTABLE:11";           break;
+    case SIGUSR2_PORTABLE:      name = "SIGUSR2_PORTABLE:12";           break;
+    case SIGPIPE_PORTABLE:      name = "SIGPIPE_PORTABLE:13";           break;
+    case SIGALRM_PORTABLE:      name = "SIGALRM_PORTABLE:14";           break;
+    case SIGTERM_PORTABLE:      name = "SIGTERM_PORTABLE:15";           break;
+    case SIGSTKFLT_PORTABLE:    name = "SIGSTKFLT_PORTABLE:16";         break;
+    case SIGCHLD_PORTABLE:      name = "SIGCHLD_PORTABLE:17";           break;
+    case SIGCONT_PORTABLE:      name = "SIGCONT_PORTABLE:18";           break;
+    case SIGSTOP_PORTABLE:      name = "SIGSTOP_PORTABLE:19";           break;
+    case SIGTSTP_PORTABLE:      name = "SIGTSTP_PORTABLE:20";           break;
+    case SIGTTIN_PORTABLE:      name = "SIGTTIN_PORTABLE:21";           break;
+    case SIGTTOU_PORTABLE:      name = "SIGTTOU_PORTABLE:22";           break;
+    case SIGURG_PORTABLE:       name = "SIGURG_PORTABLE:23";            break;
+    case SIGXCPU_PORTABLE:      name = "SIGXCPU_PORTABLE:24";           break;
+    case SIGXFSZ_PORTABLE:      name = "SIGXFSZ_PORTABLE:25";           break;
+    case SIGVTALRM_PORTABLE:    name = "SIGVTALRM_PORTABLE:26";         break;
+    case SIGPROF_PORTABLE:      name = "SIGPROF_PORTABLE:27";           break;
+    case SIGWINCH_PORTABLE:     name = "SIGWINCH_PORTABLE:28";          break;
+    case SIGIO_PORTABLE:        name = "SIGIO_PORTABLE:29";             break;
+    case SIGPWR_PORTABLE:       name = "SIGPWR_PORTABLE:30";            break;
+    case SIGSYS_PORTABLE:       name = "SIGSYS_PORTABLE:31";            break;
+    case SIGRTMIN_PORTABLE:     name = "SIGRTMIN_PORTABLE:32";          break;
+    default:                    name = "<<UNKNOWN>>";                   break;
+    }
+    return name;
+}
+
+__hidden char *map_mips_signum_to_name(int mips_signum)
+{
+    char *name;
+
+    switch(mips_signum) {
+    case SIGHUP:        name = "SIGHUP:1";      break;
+    case SIGINT:        name = "SIGINT:2";      break;
+    case SIGQUIT:       name = "SIGQUIT:3";     break;
+    case SIGILL:        name = "SIGILL:4";      break;
+    case SIGTRAP:       name = "SIGTRAP:5";     break;
+    case SIGIOT:        name = "SIGIOT:6";      break;
+    case SIGEMT:        name = "SIGEMT:7";      break;
+    case SIGFPE:        name = "SIGFPE:8";      break;
+    case SIGKILL:       name = "SIGKILL:9";     break;
+    case SIGBUS:        name = "SIGBUS:10";     break;
+    case SIGSEGV:       name = "SIGSEGV:11";    break;
+    case SIGSYS:        name = "SIGSYS:12";     break;
+    case SIGPIPE:       name = "SIGPIPE:13";    break;
+    case SIGALRM:       name = "SIGALRM:14";    break;
+    case SIGTERM:       name = "SIGTERM:15";    break;
+    case SIGUSR1:       name = "SIGUSR1:16";    break;
+    case SIGUSR2:       name = "SIGUSR2:17";    break;
+    case SIGCHLD:       name = "SIGCHLD:18";    break;
+    case SIGPWR:        name = "SIGPWR:19";     break;
+    case SIGWINCH:      name = "SIGWINCH:20";   break;
+    case SIGURG:        name = "SIGURG:21";     break;
+    case SIGIO:         name = "SIGIO:22";      break;
+    case SIGSTOP:       name = "SIGSTOP:23";    break;
+    case SIGTSTP:       name = "SIGTSTP:24";    break;
+    case SIGCONT:       name = "SIGCONT:25";    break;
+    case SIGTTIN:       name = "SIGTTIN:26";    break;
+    case SIGTTOU:       name = "SIGTTOU:27";    break;
+    case SIGVTALRM:     name = "SIGVTALRM:28";  break;
+    case SIGPROF:       name = "SIGPROF:29";    break;
+    case SIGXCPU:       name = "SIGXCPU:30";    break;
+    case SIGXFSZ:       name = "SIGXFSZ:31";    break;
+
+    case SIGRTMIN:      name = "SIGRTMIN:32";   break;
+    default:            name = "<<UNKNOWN>>";   break;
+    }
+    return name;
+}
+
+__hidden int map_portable_signum_to_mips(int portable_signum)
+{
+    int mips_signum = -1;
+
+    switch(portable_signum) {
+    case SIGHUP_PORTABLE:               /* 1 */
+        return SIGHUP;
+
+    case SIGINT_PORTABLE:               /* 2 */
+        return SIGINT;
+
+    case SIGQUIT_PORTABLE:              /* 3 */
+        return SIGQUIT;
+
+    case SIGILL_PORTABLE:               /* 4 */
+        return SIGILL;
+
+    case SIGTRAP_PORTABLE:              /* 5 */
+        return SIGTRAP;
+
+    case SIGABRT_PORTABLE:              /* 6 */
+        return SIGABRT;
+
+    case SIGBUS_PORTABLE:               /* 7 --> 10 */
+        return SIGBUS;
+
+    case SIGFPE_PORTABLE:               /* 8 */
+        return SIGFPE;
+
+    case SIGKILL_PORTABLE:              /* 9 */
+        return SIGKILL;
+
+    case SIGUSR1_PORTABLE:              /* 10 --> 16 */
+        return SIGUSR1;
+
+    case SIGSEGV_PORTABLE:              /* 11 */
+        return SIGSEGV;
+
+    case SIGUSR2_PORTABLE:              /* 12 --> 17 */
+        return SIGUSR2;
+
+    case SIGPIPE_PORTABLE:              /* 13 */
+        return SIGPIPE;
+
+    case SIGALRM_PORTABLE:              /* 14 */
+        return SIGALRM;
+
+    case SIGTERM_PORTABLE:              /* 15 */
+        return SIGTERM;
+
+    case SIGSTKFLT_PORTABLE:            /* 16 --> VOID:0  */
+        /* No MIPS SIGSTKFLT Exits; try mapping it to zero */
+        return(0);
+
+    case SIGCHLD_PORTABLE:              /* 17 --> 18 */
+        return SIGCHLD;
+
+    case SIGCONT_PORTABLE:
+        return SIGCONT;                 /* 18 --> 25 */
+
+    case SIGSTOP_PORTABLE:              /* 19 --> 23 */
+        return SIGSTOP;
+
+    case SIGTSTP_PORTABLE:              /* 20 --> 24 */
+        return SIGTSTP;
+
+    case SIGTTIN_PORTABLE:              /* 21 --> 26 */
+        return SIGTTIN;
+
+    case SIGTTOU_PORTABLE:              /* 22 --> 27 */
+        return SIGTTOU;
+
+    case SIGURG_PORTABLE:               /* 23 --> 21 */
+        return SIGURG;
+
+    case SIGXCPU_PORTABLE:              /* 24 --> 30 */
+        return SIGXCPU;
+
+    case SIGXFSZ_PORTABLE:              /* 25 --> 31 */
+        return SIGXFSZ;
+
+    case SIGVTALRM_PORTABLE:            /* 26 --> 28 */
+        return SIGVTALRM;
+
+    case SIGPROF_PORTABLE:              /* 27 --> 29 */
+        return SIGPROF;
+
+    case SIGWINCH_PORTABLE:             /* 28 --> 20 */
+        return SIGWINCH;
+
+    case SIGIO_PORTABLE:                /* 29 --> 22 */
+        return SIGIO;
+
+    case SIGPWR_PORTABLE:               /* 30 --> 19 */
+        return SIGPWR;
+
+    case SIGSYS_PORTABLE:               /* 31 --> 12 */
+        return SIGSYS;
+
+    case SIGRTMIN_PORTABLE:             /* 32 */
+        return SIGRTMIN;
+
+    default:
+        ALOGE("%s: switch default: NOTE portable_signum:%d not supported.", __func__,
+                                        portable_signum);
+        /*
+         * User could be LTP testing with bogus signal numbers,
+         * if so we mimic the test.
+         *
+         * If the signal is just outside the PORTABLE range
+         * we use a signal just outside the MIPS range.
+         */
+        if (portable_signum < 0) {
+                mips_signum = portable_signum;
+        } else if (portable_signum > NSIG_PORTABLE) {
+                mips_signum = (portable_signum - NSIG_PORTABLE) +  NSIG;
+        } else {
+                ALOGE("%s: 0 <= portable_signum:%d <= NSIG_PORTABLE:%d; not supported, Return(0);", __func__,
+                                portable_signum,      NSIG_PORTABLE);
+                mips_signum = 0;
+        }
+        break;
+    }
+    ALOGV("%s(portable_signum:%d): return(mips_signum:%d);", __func__,
+              portable_signum,            mips_signum);
+
+    return mips_signum;
+}
+
+
+__hidden int map_mips_signum_to_portable(int mips_signum)
+{
+    int portable_ssignum = -1;
+
+    switch(mips_signum) {
+    case SIGHUP:                        /* 1 */
+        return SIGHUP_PORTABLE;
+
+    case SIGINT:                        /* 2 */
+        return SIGINT_PORTABLE;
+
+    case SIGQUIT:                       /* 3 */
+        return SIGQUIT_PORTABLE;
+
+    case SIGILL:                        /* 4 */
+        return SIGILL_PORTABLE;
+
+    case SIGTRAP:                       /* 5 */
+        return SIGTRAP_PORTABLE;
+
+    case SIGABRT:                       /* 6 */
+        return SIGABRT_PORTABLE;
+
+    case SIGBUS:                        /* 7 <-- 10 */
+        return SIGBUS_PORTABLE;
+
+    case SIGFPE:                        /* 8 */
+        return SIGFPE_PORTABLE;
+
+    case SIGKILL:                       /* 9 */
+        return SIGKILL_PORTABLE;
+
+    case SIGUSR1:                       /* 10 <-- 16 */
+        return SIGUSR1_PORTABLE;
+
+    case SIGSEGV:                       /* 11 */
+        return SIGSEGV_PORTABLE;
+
+    case SIGUSR2:                       /* 12 <-- 17 */
+        return SIGUSR2_PORTABLE;
+
+    case SIGPIPE:                       /* 13 */
+        return SIGPIPE_PORTABLE;
+
+    case SIGALRM:                       /* 14 */
+        return SIGALRM_PORTABLE;
+
+    case SIGTERM_PORTABLE:              /* 15 */
+        return SIGTERM;
+
+#if defined(SIGSTKFLT)
+    case SIGSTKFLT:                     /* 16 <--- VOID; NOT SUPPORTED */
+        ASSERT(mips_signum != SIGSTKFLT_PORTABLE);
+        return(-1);
+#endif
+
+    case SIGCHLD:                       /* 17 <-- 18 */
+        return SIGCHLD_PORTABLE;
+
+    case SIGCONT:                       /* 18 <-- 15 */
+        return SIGCONT_PORTABLE;
+
+    case SIGSTOP:                       /* 19 <-- 23 */
+        return SIGSTOP_PORTABLE;
+
+    case SIGTSTP:                       /* 20 <-- 24 */
+        return SIGTSTP_PORTABLE;
+
+    case SIGTTIN:                       /* 21 <-- 26 */
+        return SIGTTIN_PORTABLE;
+
+    case SIGTTOU:                       /* 22 <-- 27 */
+        return SIGTTOU_PORTABLE;
+
+    case SIGURG:                        /* 23 <-- 21 */
+        return SIGURG_PORTABLE;
+
+    case SIGXCPU:                       /* 24 <-- 30 */
+        return SIGXCPU_PORTABLE;
+
+    case SIGXFSZ:                       /* 25 <-- 31 */
+        return SIGXFSZ_PORTABLE;
+
+    case SIGVTALRM:                     /* 26 <-- 28 */
+        return SIGVTALRM_PORTABLE;
+
+    case SIGPROF:                       /* 27 <-- 29 */
+        return SIGPROF_PORTABLE;
+
+    case SIGWINCH:                      /* 28 <-- 20 */
+        return SIGWINCH_PORTABLE;
+
+    case SIGIO:                         /* 29 <-- 22 */
+        return SIGIO_PORTABLE;
+
+    case SIGPWR:                        /* 30 <-- 19 */
+        return SIGPWR_PORTABLE;
+
+    case SIGSYS:                        /* 31 <-- 12 */
+        return SIGSYS_PORTABLE;
+
+    case SIGRTMIN_PORTABLE:             /* 32 */
+        return SIGRTMIN;
+
+    default:
+        ALOGE("%s: switch default: mips_signum:%d not supported! return(0);", __func__, mips_signum);
+#if 0
+        LOG_FATAL("%s: mips_signum:%d is not portable;", __func__, mips_signum);
+#endif
+        return(0);
+    }
+    return portable_ssignum;
+}
+
+/*
+ * Array of signal handlers as the portable users expects they
+ * they have been registered in the kernel. Problem is we need
+ * to have our own handler to map the MIPS signal number to a
+ * portable signal number.
+ */
+sig3handler_portable_t mips_portable_sighandler[NSIG_PORTABLE] = { NULL };
+
+static void mips_sigaction_handler(int mips_signum, siginfo_t *sip, void *ucp)
+{
+    int portable_signum;
+    char *portable_signame;
+    char *mips_signame = map_mips_signum_to_name(mips_signum);
+    sig3handler_portable_t portable_sighandler;
+    siginfo_portable_t portable_si;
+    siginfo_portable_t *portable_sip;
+
+    ALOGV("%s(mips_signum:%d:'%s', sip:%p, ucp:%p) {", __func__,
+              mips_signum,
+              mips_signame,        sip,    ucp);
+
+    portable_signum = map_mips_signum_to_portable(mips_signum);
+    portable_signame = map_portable_signum_to_name(portable_signum);
+    portable_sighandler = mips_portable_sighandler[portable_signum];
+
+    ASSERT(portable_sighandler != NULL);
+    ASSERT(portable_sighandler != (sig3handler_portable_t) SIG_DFL);
+    ASSERT(portable_sighandler != (sig3handler_portable_t) SIG_IGN);
+    ASSERT(portable_sighandler != (sig3handler_portable_t) SIG_ERR);
+
+    if (sip == NULL) {
+        portable_sip = NULL;
+    } else {
+        int portable_si_errno;
+        int portable_si_signo;
+        char *mips_si_signame;
+        char *portable_si_signame;
+
+        /*
+         * Map Structure members from MIPS to Portable.
+         */
+        portable_si_signo = map_mips_signum_to_portable(sip->si_signo);
+        portable_si_signame = map_portable_signum_to_name(portable_si_signo);
+        portable_si_errno = ntop_errno(sip->si_errno);
+
+        mips_si_signame = map_mips_signum_to_name(sip->si_signo);
+
+        /*
+         * Deal with siginfo structure being a bit different.
+         */
+        ASSERT(sizeof(siginfo_portable_t) == sizeof(siginfo_t));
+        memcpy(&portable_si, sip, sizeof(portable_si)); /* Default to the same structure members */
+        portable_si.si_signo = portable_si_signo;
+        portable_si.si_code = sip->si_code;                     /* code and errno are swapped between ARM and MIPS ... */
+        portable_si.si_errno = portable_si_errno;               /* ... and errno needs to be translated. */
+
+        portable_sip = &portable_si;
+    } /* if sip */
+
+    portable_sighandler(portable_signum, portable_sip, ucp);
+
+    ALOGV("%s: return; }", __func__);
+}
+
+static void mips_sighandler(int mips_signum)
+{
+    int portable_signum;
+    char *portable_signame;
+    char *mips_signame = map_mips_signum_to_name(mips_signum);
+    sig3handler_portable_t portable_sighandler;
+
+    ALOGV("%s(mips_signum:%d:'%s') {", __func__, mips_signum, mips_signame);
+
+    mips_sigaction_handler(mips_signum, NULL, NULL);
+
+    ALOGV("%s: return; }", __func__);
+}
+
+static sighandler_t map_portable_sighandler_to_mips(sighandler_portable_t portable_handler, int sigaction)
+{
+    sighandler_t mips_handler;
+
+    ALOGV("%s(portable_handler:%p, sigaction:%d) {", __func__,
+              portable_handler,    sigaction);
+
+    switch((int) portable_handler) {
+    case (int) SIG_DFL:
+    case (int) SIG_IGN:
+    case (int) SIG_ERR:
+        mips_handler = portable_handler;
+        break;
+
+    default:
+        if (sigaction)
+            mips_handler = (sighandler_t) mips_sighandler;
+        else
+            mips_handler = (sighandler_t) mips_sigaction_handler;
+        break;
+    }
+
+    ALOGV("%s: return(mips_handler:%p); }", __func__, mips_handler);
+    return(mips_handler);
+}
+
+
+/*
+ * This function maps the signal number and calls one of the low level mips signal()
+ * functions implemented in portable-jb/bionic/libc/unistd/signal.c:
+ *              sysv_signal()
+ *              bsd_signal()
+ *
+ * The last 2 parameters to this static function, mips_signal_fn*, specify which of these functions to call.
+ * We intercept the above to functions, as well as signal(), and call the associated *_portable()
+ * functions below.
+ *
+ * In addition, we intercept the signal_handler with our own handlers that map the signal number from
+ * the MIPS convention to the PORTABLE/ARM convention.
+ */
+static sighandler_portable_t _signal_portable(int portable_signum, sighandler_portable_t portable_handler,
+                                                __sighandler_t (mips_signal_fn)(int, __sighandler_t), char *mips_signal_fn_name)
+{
+    char *portable_signame = map_portable_signum_to_name(portable_signum);
+    int mips_signum;
+    sighandler_t mips_handler;
+    sighandler_portable_t ret;
+    sighandler_portable_t prev_portable_handler;
+
+    ALOGV("%s(portable_signum:%d:%s, portable_handler:%p,  mips_signal_fn:%p, mips_signal_fn_name:'%s') {", __func__,
+              portable_signum, portable_signame,
+                                     portable_handler,     mips_signal_fn,    mips_signal_fn_name);
+
+    mips_signum = map_portable_signum_to_mips(portable_signum);
+
+    if ((portable_signum != 0) && ((mips_signum <= 0) || (mips_signum > NSIG))) {
+        /*
+         * Invalid request; Let the kernel generate the proper return value and set errno.
+         */
+        mips_handler = map_portable_sighandler_to_mips(portable_handler, 0);
+        ret = mips_signal_fn(mips_signum, mips_handler);
+    } else {
+        /*
+         * We have a usable signal number, redirect it to our signal handler
+         * if a portable handler was provided so we can convert the signal number.
+         * Save our current mapped signal handler for likely return.
+         */
+        prev_portable_handler = (sighandler_portable_t) mips_portable_sighandler[portable_signum];
+
+        mips_handler = map_portable_sighandler_to_mips(portable_handler, 0);
+        if (mips_handler != portable_handler) {
+            mips_portable_sighandler[portable_signum] = (sig3handler_portable_t) portable_handler;
+        }
+        ret = mips_signal_fn(mips_signum, mips_handler);
+
+        if ((ret == (sighandler_portable_t) mips_sighandler) ||
+            (ret == (sighandler_portable_t) mips_sigaction_handler)) {
+            ret = (sighandler_t) prev_portable_handler;
+        }
+    }
+    ALOGV("%s: return(ret:%p); }", __func__, ret);
+    return(ret);
+}
+
+/*
+ * signal() can't be called directly, due to an in-line function in signal.h which
+ * redirects the call to bsd_signal(). _signal() is a static function; not to be called
+ * directly. This function isn't actually needed.
+ */
+sighandler_portable_t signal_portable(int portable_signum, sighandler_portable_t handler)
+{
+    sighandler_portable_t ret;
+
+    ALOGV(" ");
+    ALOGV("%s(portable_signum:%d, handler:%p);", __func__,
+              portable_signum,    handler);
+
+    /* bsd does a SA_RESTART */
+    ret = _signal_portable(portable_signum, handler, bsd_signal, "bsd_signal");
+
+    ALOGV("%s: return(ret:%p); }", __func__, ret);
+    return(ret);
+}
+
+sighandler_portable_t sysv_signal_portable(int portable_signum, sighandler_portable_t handler)
+{
+    sighandler_portable_t ret;
+
+    ALOGV(" ");
+    ALOGV("%s(portable_signum:%d, handler:%p);", __func__,
+              portable_signum,    handler);
+
+    /* sysv does a SA_RESETHAND */
+    ret = _signal_portable(portable_signum, handler, sysv_signal, "sysv_signal");
+
+    ALOGV("%s: return(ret:%p); }", __func__, ret);
+    return(ret);
+}
+
+sighandler_portable_t bsd_signal_portable(int portable_signum, sighandler_portable_t handler)
+{
+    sighandler_portable_t ret;
+
+    ALOGV(" ");
+    ALOGV("%s(portable_signum:%d, handler:%p) {", __func__,
+              portable_signum,    handler);
+
+    /* bsd does a SA_RESTART */
+    ret = _signal_portable(portable_signum, handler, bsd_signal, "bsd_signal");
+
+    ALOGV("%s: return(ret:%p); }", __func__, ret);
+    return(ret);
+}
+
+static int kill_helper(int id, int portable_signum, int (*fn)(int, int), const char *name)
+{
+    char *portable_signame = map_portable_signum_to_name(portable_signum);
+    int mips_signum;
+    int ret;
+
+    ALOGV("%s(id:%d, portable_signum:%d:'%s');", name,
+              id,    portable_signum, portable_signame);
+
+    mips_signum = map_portable_signum_to_mips(portable_signum);
+
+    if ((portable_signum != 0) && (mips_signum == 0))
+        return 0;
+    return  fn(id, mips_signum);
+}
+
+int killpg_portable(int pgrp, int portable_signum)
+{
+    return kill_helper(pgrp, portable_signum, killpg, __func__);
+}
+
+int kill_portable(pid_t pid, int portable_signum)
+{
+    return kill_helper(pid, portable_signum, kill, __func__);
+}
+
+int tkill_portable(int tid, int portable_signum)
+{
+    extern int tkill(int, int);
+    return kill_helper(tid, portable_signum, tkill, __func__);
+}
+
+/* tgkill is not exported from android-14 libc.so */
+#if 0
+int tgkill_portable(int tgid, int tid, int portable_signum)
+{
+    extern int tgkill(int, int, int);
+    char *portable_signame = map_portable_signum_to_name(portable_signum);
+    int mips_signum;
+    int rv;
+
+    ALOGV("%s(tgid:%d, tid:%d, portable_signum:%d:'%s');", __func__,
+              tgid,    tid,    portable_signum, portable_signame);
+
+    mips_signum = map_portable_signum_to_mips(portable_signum);
+
+    if ((portable_signum != 0) && (mips_signum == 0))
+        rv = 0;
+    else
+        rv = tgkill(tgid, tid, mips_signum);
+
+    ALOGV("%s: return rv:%d;", __func__, rv);
+    return rv;
+}
+#endif
+
+int raise_portable(int portable_signum)
+{
+    char *portable_signame = map_portable_signum_to_name(portable_signum);
+    int mips_signum = map_portable_signum_to_mips(portable_signum);
+    int rv;
+
+    ALOGV("%s(portable_signum:%d:'%s') {", __func__, portable_signum, portable_signame);
+
+    if ((portable_signum != 0) && (mips_signum == 0))
+        rv = 0;
+    else
+        rv = raise(mips_signum);
+
+    ALOGV("%s: return(rv:%d); }", __func__, rv);
+    return(rv);
+}
+
+
+void map_portable_sigset_to_mips(sigset_portable_t *portable_sigset, sigset_t *mips_sigset)
+{
+    int portable_signum;
+
+    ASSERT(mips_sigset != NULL);
+
+    ALOGV("%s(portable_sigset:%p, mips_sigset:%p) {", __func__,
+              portable_sigset,    mips_sigset);
+
+    sigemptyset(mips_sigset);
+    if (invalid_pointer((void *)portable_sigset)) {
+        ALOGE("%s: portable_sigset:%p is not valid; returning empty set.", __func__,
+                   portable_sigset);
+        goto done;
+    }
+
+    for(portable_signum = 1; portable_signum <= NSIG_PORTABLE; portable_signum++) {
+
+        if (sigismember_portable(portable_sigset, portable_signum)) {
+            char *portable_signame = map_portable_signum_to_name(portable_signum);
+            int mips_signum = map_portable_signum_to_mips(portable_signum);
+            char *mips_signame;
+
+            if (mips_signum != 0) {
+                int err;
+
+                mips_signame = map_mips_signum_to_name(mips_signum);
+                ALOGV("%s: sigaddset(mips_sigset:%p, mips_signum:%d:'%s'); [portable_signum:%d:'%s']", __func__,
+                                     mips_sigset,    mips_signum,
+                                                     mips_signame,          portable_signum,
+                                                                            portable_signame);
+
+                err = sigaddset(mips_sigset, mips_signum);
+                if (err == -1) {
+                    PERROR("sigaddset");
+                }
+            }
+        }
+    }
+
+done:
+    ALOGV("%s: return; }", __func__);
+    return;
+}
+
+
+void map_mips_sigset_to_portable(const sigset_t *const_mips_sigset, sigset_portable_t *portable_sigset)
+{
+    int mips_signum;
+    sigset_t *mips_sigset = (sigset_t *) const_mips_sigset;
+
+    ALOGV("%s(const_mips_sigset:%p, portable_sigset:%p) {", __func__,
+              const_mips_sigset,    portable_sigset);
+
+    ASSERT(mips_sigset != NULL);
+
+    if (invalid_pointer((void *)portable_sigset)) {
+        ALOGE("%s: portable_sigset:%p is not Valid; can't return sigset", __func__,
+                   portable_sigset);
+        goto done;
+    }
+    sigemptyset_portable(portable_sigset);
+
+    for(mips_signum = 1; mips_signum <= NSIG; mips_signum++) {
+        if (sigismember(mips_sigset, mips_signum)) {
+            int portable_signum = map_mips_signum_to_portable(mips_signum);
+
+            if (portable_signum != 0)
+                sigaddset_portable(portable_sigset, portable_signum);
+        }
+    }
+
+done:
+    ALOGV("%s: return; }", __func__);
+    return;
+}
+
+
+static int map_portable_sigaction_flags_to_mips(int portable_flags)
+{
+    int mips_flags = 0;
+
+    if (portable_flags & SA_NOCLDSTOP_PORTABLE)
+        mips_flags |= SA_NOCLDSTOP;
+
+    if (portable_flags & SA_NOCLDWAIT_PORTABLE)
+        mips_flags |= SA_NOCLDWAIT;
+
+    if (portable_flags & SA_SIGINFO_PORTABLE)
+        mips_flags |= SA_SIGINFO;
+
+    if (portable_flags & SA_THIRTYTWO_PORTABLE) {
+        ALOGV("%s: SA_THIRTYTWO_PORTABLE isn't SUPPORTED.", __func__);
+    }
+    if (portable_flags & SA_RESTORER_PORTABLE)
+        mips_flags |= SA_RESTORER;
+
+    if (portable_flags & SA_ONSTACK_PORTABLE)
+        mips_flags |= SA_ONSTACK;
+
+    if (portable_flags & SA_RESTART_PORTABLE)
+        mips_flags |= SA_RESTART;
+
+    if (portable_flags & SA_NODEFER_PORTABLE)
+        mips_flags |= SA_NODEFER;
+
+    if (portable_flags & SA_RESETHAND_PORTABLE)
+        mips_flags |= SA_RESETHAND;
+
+    ALOGV("%s(portable_flags:0x%x) return(mips_flags:0x%x);", __func__,
+              portable_flags,             mips_flags);
+
+    return(mips_flags);
+}
+
+int map_mips_sigaction_flags_to_portable(int mips_flags)
+{
+    int portable_flags = 0;
+
+    if (mips_flags & SA_NOCLDSTOP)      portable_flags |= SA_NOCLDSTOP_PORTABLE;
+    if (mips_flags & SA_NOCLDWAIT)      portable_flags |= SA_NOCLDWAIT_PORTABLE;
+    if (mips_flags & SA_SIGINFO)        portable_flags |= SA_SIGINFO_PORTABLE;
+#ifdef SA_THIRTYTWO
+    if (mips_flags & SA_THIRTYTWO)      portable_flags |= SA_THIRTYTWO_PORTABLE;
+#endif
+    if (mips_flags & SA_RESTORER)       portable_flags |= SA_RESTORER_PORTABLE;
+    if (mips_flags & SA_ONSTACK)        portable_flags |= SA_ONSTACK_PORTABLE;
+    if (mips_flags & SA_RESTART)        portable_flags |= SA_RESTART_PORTABLE;
+    if (mips_flags & SA_NODEFER)        portable_flags |= SA_NODEFER_PORTABLE;
+    if (mips_flags & SA_RESETHAND)      portable_flags |= SA_RESETHAND_PORTABLE;
+
+    ALOGV("%s(mips_flags:0x%x) return(portable_flags:0x%x);", __func__,
+              mips_flags,             portable_flags);
+
+    return(portable_flags);
+}
+
+/*
+ * Called by portable/ARM code, which we map and do MIPS system calls.
+ *
+ * The incoming system call used a Portable/ARM sigaction structure:
+ * ------------------------------------------------------------------
+ *   struct sigaction_portable {
+ *     union {
+ *       __sighandler_portable_t        _sa_handler;
+ *       __sigaction_handler_portable_t _sa_sigaction;
+ *     } _u;
+ *     sigset_portable_t sa_mask;
+ *     unsigned long sa_flags;
+ *     void (*sa_restorer)(void);
+ * };
+ *
+ * A similar, but different, structure is used in the MIPS/Native system call:
+ * ---------------------------------------------------------------------------
+ *    struct sigaction {
+ *      unsigned int sa_flags;
+ *      union {
+ *        __sighandler_t                  sa_handler;
+ *        __sigaction_handler_portable_t _sa_sigaction;
+ *      } __u;
+ *      sigset_t sa_mask;
+ *  };
+ *
+ * This sigaction structure needs to be mapped before the MIPS systems call as well as after for
+ * returning the old/previous sigaction. Also, like signal_portable() above, we need to maintain
+ * a table of signal handlers that our intercepting handler can call after it converts the signal
+ * numbers.
+ */
+int sigaction_portable(int portable_signum, const struct sigaction_portable *act, struct sigaction_portable *oldact)
+{
+    int mips_signum;
+    char *mips_signame;
+    struct sigaction mips_act;
+    struct sigaction mips_oldact;
+    sighandler_t mips_handler;
+    sighandler_portable_t portable_handler;
+    sig3handler_portable_t prev_portable_handler;
+    char *portable_signame = map_portable_signum_to_name(portable_signum);
+    int rv;
+
+    ALOGV(" ");
+    ALOGV("%s(portable_signum:%d:'%s', act:%p, oldact:%p) {", __func__,
+              portable_signum,
+              portable_signame,        act,    oldact);
+
+    mips_signum = map_portable_signum_to_mips(portable_signum);
+    mips_signame = map_mips_signum_to_name(mips_signum);
+    if ((portable_signum != 0) && (mips_signum == 0)) {
+        /* We got a portable signum that we can't map; Ignore the request */
+        rv = 0;
+        goto done;
+    }
+    if (portable_signum >= 0 && portable_signum < NSIG_PORTABLE)
+        prev_portable_handler = mips_portable_sighandler[portable_signum];
+    else
+        prev_portable_handler = NULL;
+
+    memset(&mips_act, 0, sizeof(mips_act));
+
+    if (invalid_pointer((void *)act)) {
+        rv = sigaction(mips_signum, (struct sigaction *)act, &mips_oldact);
+    } else {
+        /*
+         * Make the MIPS version of sigaction, which has no sa_restorer function pointer. Also the handler
+         * will be called with a pointer to a to a sigcontext structure which is totally non-portable.
+         */
+        map_portable_sigset_to_mips(((sigset_portable_t *)&act->sa_mask), ((sigset_t *) &mips_act.sa_mask));
+
+        mips_act.sa_flags = map_portable_sigaction_flags_to_mips(act->sa_flags);
+
+        if (mips_act.sa_flags & SA_SIGINFO) {
+            /*
+             * Providing the three argument version of a signal handler.
+             */
+            if (portable_signum >= 0 && portable_signum < NSIG_PORTABLE) {
+                mips_portable_sighandler[portable_signum] = (sig3handler_portable_t) act->sa_sigaction_portable;
+
+                mips_act.sa_sigaction = mips_sigaction_handler;
+            }
+            else {
+                mips_act.sa_sigaction = act->sa_sigaction_portable;
+            }
+        } else {
+            /*
+             * Providing the classic single argument version of a signal handler.
+             */
+            portable_handler = act->sa_handler_portable;
+            if ((portable_signum < 0) || (portable_signum > NSIG_PORTABLE)) {
+                /*
+                 * Let the kernel generate the proper return value and set errno.
+                 */
+                mips_act.sa_handler = (sighandler_t) portable_handler;
+            } else {
+                mips_handler = map_portable_sighandler_to_mips(portable_handler, 1);
+                if (mips_handler != portable_handler) {
+                        mips_portable_sighandler[portable_signum] = (sig3handler_portable_t) portable_handler;
+                }
+                mips_act.sa_handler = mips_handler;
+            }
+        }
+        rv = sigaction(mips_signum, &mips_act, &mips_oldact);
+    }
+
+    if (oldact) {
+        if ((mips_oldact.sa_sigaction == (__sigaction_handler_portable_t) mips_sighandler) ||
+            (mips_oldact.sa_sigaction == (__sigaction_handler_portable_t) mips_sigaction_handler)) {
+                oldact->sa_sigaction_portable = (__sigaction_handler_portable_t) prev_portable_handler;
+        } else {
+                oldact->sa_sigaction_portable = (__sigaction_handler_portable_t) mips_oldact.sa_sigaction;
+        }
+        map_mips_sigset_to_portable((sigset_t *) &(mips_oldact.sa_mask), (sigset_portable_t *) &(oldact->sa_mask));
+
+        oldact->sa_flags = map_mips_sigaction_flags_to_portable(mips_oldact.sa_flags);
+        oldact->sa_restorer = NULL;
+    }
+
+done:
+    ALOGV("%s: return(rv:%d); }", __func__, rv);
+    return(rv);
+}
+
+
+#if 0
+/*
+ * So far it appears that signalfd() isn't supported by bionic
+ * the kernel trap numbers are available.
+ */
+int signalfd_portable(int fd, const sigset_t *portable_sigmask, int flags)
+{
+    sigset_t mips_sigmask;
+
+    map_portable_sigset_to_mips(portable_sigmask, &mips_sigmask);
+
+    return signalfd(fd, &mips_sigmask, flags);
+}
+#endif
+
+
+int sigsuspend_portable(const sigset_portable_t *portable_sigmask)
+{
+    int rv;
+    sigset_t mips_sigmask;
+
+    ALOGV("%s(portable_sigmask:%p) {", __func__, portable_sigmask);
+
+    if (invalid_pointer((void *)portable_sigmask)) {
+        errno = EFAULT;
+        rv = -1;
+    } else {
+        map_portable_sigset_to_mips((sigset_portable_t *)portable_sigmask, &mips_sigmask);
+        rv = sigsuspend(&mips_sigmask);
+    }
+
+    ALOGV("%s: return(rv:%d);", __func__, rv);
+    return(rv);
+}
+
+
+int sigpending_portable(sigset_portable_t *portable_sigset)
+{
+    int rv;
+    sigset_t mips_sigset;
+
+    ALOGV("%s(portable_sigset:%p) {", __func__,
+              portable_sigset);
+
+    if (invalid_pointer((void *)portable_sigset)) {
+        errno = EFAULT;
+        rv = -1;
+    } else {
+        rv = sigpending(&mips_sigset);
+        map_mips_sigset_to_portable(&mips_sigset, portable_sigset);
+    }
+
+    ALOGV("%s: return(rv:%d);", __func__, rv);
+    return(rv);
+}
+
+
+int sigwait_portable(const sigset_portable_t *portable_sigset, int *ptr_to_portable_sig)
+{
+    int rv;
+    sigset_t mips_sigset;
+    int mips_sig;
+    int portable_sig;
+
+    ALOGV("%s(portable_sigset:%p, ptr_to_portable_sig:%p) {", __func__,
+              portable_sigset,    ptr_to_portable_sig);
+
+    if (invalid_pointer((void *)portable_sigset)) {
+        errno = EFAULT;
+        rv = -1;
+    } else {
+        map_portable_sigset_to_mips((sigset_portable_t *)portable_sigset, &mips_sigset);
+
+        rv = sigwait(&mips_sigset, &mips_sig);
+
+        portable_sig = map_mips_signum_to_portable(mips_sig);
+        *ptr_to_portable_sig = portable_sig;
+    }
+    ALOGV("%s: return(rv:%d);", __func__, rv);
+    return(rv);
+}
+
+
+int siginterrupt_portable(int portable_signum, int flag)
+
+{
+    int rv;
+    int mips_signum;
+
+    ALOGV("%s(portable_signum:%d, flag:0x%x) {", __func__,
+              portable_signum,    flag);
+
+    mips_signum = map_portable_signum_to_mips(portable_signum);
+
+    if ((portable_signum != 0) && (mips_signum == 0)) {
+        ALOGE("%s: Unsupported portable_signum:%d; Ignoring.", __func__,
+                               portable_signum);
+        rv = 0;
+    } else {
+        rv = siginterrupt(mips_signum, flag);
+    }
+    ALOGV("%s: return(rv:%d);", __func__, rv);
+    return(rv);
+}
+
+__hidden int sigmask_helper(int portable_how, const sigset_portable_t *portable_sigset, sigset_portable_t *portable_oldset, sigmask_fn fn, char *fname)
+{
+    int rv;
+    int how;
+    char *how_name;
+    sigset_t mips_sigset, *mips_sigset_p;
+    sigset_t mips_oldset, *mips_oldset_p;
+
+    ALOGV(" ");
+    ALOGV("%s(portable_how:%d, portable_sigset:%p, portable_oldset:%p) {", __func__,
+              portable_how,    portable_sigset,    portable_oldset);
+
+   switch(portable_how) {
+   case SIG_BLOCK_PORTABLE:     how = SIG_BLOCK;        how_name = "SIG_BLOCK";         break;
+   case SIG_UNBLOCK_PORTABLE:   how = SIG_UNBLOCK;      how_name = "SIG_UNBLOCK";       break;
+   case SIG_SETMASK_PORTABLE:   how = SIG_SETMASK;      how_name = "SIG_SETMASK";       break;
+
+   default:
+        ALOGE("%s: portable_how:%d NOT SUPPORTED!", __func__, portable_how);
+        how = -1;
+        break;
+   }
+
+    if (invalid_pointer((void *)portable_sigset)) {
+        mips_sigset_p = (sigset_t *) portable_sigset;
+    } else {
+        mips_sigset_p = &mips_sigset;
+        memset(mips_sigset_p, 0, sizeof(mips_sigset));
+        sigemptyset(mips_sigset_p);
+        map_portable_sigset_to_mips((sigset_portable_t *)portable_sigset, &mips_sigset);
+    }
+
+    if (invalid_pointer((void *)portable_oldset)) {
+        mips_oldset_p = (sigset_t *) portable_oldset;
+    } else {
+        mips_oldset_p = &mips_oldset;
+        memset(mips_oldset_p, 0, sizeof(mips_oldset));
+        sigemptyset(mips_oldset_p);
+    }
+
+    rv = fn(how, mips_sigset_p, mips_oldset_p);
+
+    if (rv == 0 && !invalid_pointer(portable_oldset)) {
+        /* Map returned mips_oldset to portable_oldset for return to caller */
+        map_mips_sigset_to_portable(mips_oldset_p, portable_oldset);
+    }
+
+    ALOGV("%s: return(rv:%d); }", __func__, rv);
+    return(rv);
+}
+
+int sigprocmask_portable(int portable_how,
+                         const sigset_portable_t *portable_sigset,
+                         sigset_portable_t *portable_oldset)
+{
+    return sigmask_helper(portable_how, portable_sigset, portable_oldset, sigprocmask, "sigprocmask");
+}
+
+/*
+ * ss_flags and ss_size are located in different locations in stack_t structure:
+ *
+ * Incomming ARM/Portable stack_t:                  Outgoing MIPS stack_t:
+ * -------------------------------              ----------------------------
+ *    typedef struct sigaltstack {              typedef struct sigaltstack {
+ *        void __user *ss_sp;                       void *ss_sp;
+ *        int ss_flags;                             size_t ss_size;
+ *        size_t ss_size;                           int ss_flags;
+ *    } stack_t;
+ *
+ */
+int sigaltstack_portable(const portable_stack_t *ss, portable_stack_t *oss)
+{
+    int rv;
+    stack_t new_stack, *mips_ss;
+    stack_t old_stack, *mips_oss;
+
+    ALOGV(" ");
+    ALOGV("%s(ss:%p, oss:%p) {", __func__, ss, oss);
+
+    if (ss == NULL) {
+        mips_ss = NULL;
+    } else {
+        if (invalid_pointer((void *)ss)) {
+            ALOGE("%s: invalid_pointer(ss:%p): Let kernel set proper errno and set return value.", __func__,
+                                       ss);
+            mips_ss = (stack_t *) ss;
+        } else {
+            memset(&new_stack, 0, sizeof(stack_t));
+            new_stack.ss_sp = ss->ss_sp;
+            new_stack.ss_flags = ss->ss_flags;
+            new_stack.ss_size = ss->ss_size;
+            mips_ss = &new_stack;
+        }
+    }
+    if (oss == NULL) {
+        mips_oss = NULL;
+    } else {
+        if (invalid_pointer((void *)oss)) {
+            ALOGE("%s: invalid_pointer(oss:%p): Let kernel set proper errno and set return value.", __func__,
+                                       oss);
+            mips_oss = (stack_t *)oss;
+        } else {
+            memset(&old_stack, 0, sizeof(stack_t));
+            mips_oss = &old_stack;
+        }
+    }
+
+    rv = sigaltstack(mips_ss, mips_oss);
+
+    if (!invalid_pointer(oss)) {
+        oss->ss_sp = old_stack.ss_sp;
+        oss->ss_flags = old_stack.ss_flags;
+        oss->ss_size = old_stack.ss_size;
+    }
+    ALOGV("%s: return(rv:%d); }", __func__, rv);
+
+    return(rv);
+}
+
+
diff --git a/ndk/sources/android/libportable/common/include/asm-generic/siginfo_portable.h b/ndk/sources/android/libportable/common/include/asm-generic/siginfo_portable.h
new file mode 100644
index 0000000..1f13ad8
--- /dev/null
+++ b/ndk/sources/android/libportable/common/include/asm-generic/siginfo_portable.h
@@ -0,0 +1,221 @@
+/****************************************************************************
+ Derived from platforms/android-14/arch-arm/usr/include/asm-generic/siginfo.h
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _ASM_PORTABLE_GENERIC_SIGINFO_H
+#define _ASM_PORTABLE_GENERIC_SIGINFO_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+typedef union sigval_portable {
+    int sival_int;
+    void __user *sival_ptr;
+} sigval_portable_t;
+
+#ifndef __ARCH_SI_PREAMBLE_SIZE
+#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int))
+#endif
+
+#define SI_MAX_SIZE 128
+#ifndef SI_PAD_SIZE
+#define SI_PAD_SIZE ((SI_MAX_SIZE - __ARCH_SI_PREAMBLE_SIZE) / sizeof(int))
+#endif
+
+#ifndef __ARCH_SI_UID_T
+#define __ARCH_SI_UID_T uid_t
+#endif
+
+#ifndef __ARCH_SI_BAND_T
+#define __ARCH_SI_BAND_T long
+#endif
+
+typedef struct siginfo_portable {
+    int si_signo;
+    int si_errno;
+    int si_code;
+
+    union {
+        int _pad[SI_PAD_SIZE];
+
+        struct {
+                pid_t _pid;
+                __ARCH_SI_UID_T _uid;
+        } _kill;
+
+        struct {
+            timer_t _tid;
+            int _overrun;
+            char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
+            sigval_portable_t _sigval;
+            int _sys_private;
+        } _timer;
+
+        struct {
+            pid_t _pid;
+            __ARCH_SI_UID_T _uid;
+            sigval_t _sigval;
+        } _rt;
+
+        struct {
+            pid_t _pid;
+            __ARCH_SI_UID_T _uid;
+            int _status;
+            clock_t _utime;
+            clock_t _stime;
+        } _sigchld;
+
+        struct {
+            void __user *_addr;
+#ifdef __ARCH_SI_TRAPNO
+            int _trapno;
+#endif
+        } _sigfault;
+
+        struct {
+            __ARCH_SI_BAND_T _band;
+            int _fd;
+        } _sigpoll;
+
+    } _sifields;
+} siginfo_portable_t;
+
+#ifndef si_pid
+#define si_pid _sifields._kill._pid
+#define si_uid _sifields._kill._uid
+#define si_tid _sifields._timer._tid
+#define si_overrun _sifields._timer._overrun
+#define si_sys_private _sifields._timer._sys_private
+#define si_status _sifields._sigchld._status
+#define si_utime _sifields._sigchld._utime
+#define si_stime _sifields._sigchld._stime
+#define si_value _sifields._rt._sigval
+#define si_int _sifields._rt._sigval.sival_int
+#define si_ptr _sifields._rt._sigval.sival_ptr
+#define si_addr _sifields._sigfault._addr
+#ifdef __ARCH_SI_TRAPNO
+#define si_trapno _sifields._sigfault._trapno
+#endif
+#define si_band _sifields._sigpoll._band
+#define si_fd _sifields._sigpoll._fd
+#endif
+
+#ifndef __SI_KILL
+#define __SI_KILL 0
+#define __SI_TIMER 0
+#define __SI_POLL 0
+#define __SI_FAULT 0
+#define __SI_CHLD 0
+#define __SI_RT 0
+#define __SI_MESGQ 0
+#define __SI_CODE(T,N) (N)
+#endif
+
+#ifndef SI_USER
+#define SI_USER 0
+#define SI_KERNEL 0x80
+#define SI_QUEUE -1
+#define SI_TIMER __SI_CODE(__SI_TIMER,-2)
+#define SI_MESGQ __SI_CODE(__SI_MESGQ,-3)
+#define SI_ASYNCIO -4
+#define SI_SIGIO -5
+#define SI_TKILL -6
+#define SI_DETHREAD -7
+
+#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
+#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
+#endif
+
+#ifndef ILL_ILLOPC
+#define ILL_ILLOPC (__SI_FAULT|1)
+#define ILL_ILLOPN (__SI_FAULT|2)
+#define ILL_ILLADR (__SI_FAULT|3)
+#define ILL_ILLTRP (__SI_FAULT|4)
+#define ILL_PRVOPC (__SI_FAULT|5)
+#define ILL_PRVREG (__SI_FAULT|6)
+#define ILL_COPROC (__SI_FAULT|7)
+#define ILL_BADSTK (__SI_FAULT|8)
+#define NSIGILL 8
+#endif
+
+#ifndef FPE_INTDIV
+#define FPE_INTDIV (__SI_FAULT|1)
+#define FPE_INTOVF (__SI_FAULT|2)
+#define FPE_FLTDIV (__SI_FAULT|3)
+#define FPE_FLTOVF (__SI_FAULT|4)
+#define FPE_FLTUND (__SI_FAULT|5)
+#define FPE_FLTRES (__SI_FAULT|6)
+#define FPE_FLTINV (__SI_FAULT|7)
+#define FPE_FLTSUB (__SI_FAULT|8)
+#define NSIGFPE 8
+
+#define SEGV_MAPERR (__SI_FAULT|1)
+#define SEGV_ACCERR (__SI_FAULT|2)
+#define NSIGSEGV 2
+
+#define BUS_ADRALN (__SI_FAULT|1)
+#define BUS_ADRERR (__SI_FAULT|2)
+#define BUS_OBJERR (__SI_FAULT|3)
+#define NSIGBUS 3
+
+#define TRAP_BRKPT (__SI_FAULT|1)
+#define TRAP_TRACE (__SI_FAULT|2)
+#define NSIGTRAP 2
+
+#define CLD_EXITED (__SI_CHLD|1)
+#define CLD_KILLED (__SI_CHLD|2)
+#define CLD_DUMPED (__SI_CHLD|3)
+#define CLD_TRAPPED (__SI_CHLD|4)
+#define CLD_STOPPED (__SI_CHLD|5)
+#define CLD_CONTINUED (__SI_CHLD|6)
+#define NSIGCHLD 6
+
+#define POLL_IN (__SI_POLL|1)
+#define POLL_OUT (__SI_POLL|2)
+#define POLL_MSG (__SI_POLL|3)
+#define POLL_ERR (__SI_POLL|4)
+#define POLL_PRI (__SI_POLL|5)
+#define POLL_HUP (__SI_POLL|6)
+#define NSIGPOLL 6
+
+#define SIGEV_SIGNAL 0
+#define SIGEV_NONE 1
+#define SIGEV_THREAD 2
+#define SIGEV_THREAD_ID 4
+#endif /* FPE_INTDIV */
+
+#ifndef __ARCH_SIGEV_PREAMBLE_SIZE
+#define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(int) * 2 + sizeof(sigval_portable_t))
+#endif
+
+#define SIGEV_MAX_SIZE 64
+#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE - __ARCH_SIGEV_PREAMBLE_SIZE)   / sizeof(int))
+
+typedef struct sigevent_portable {
+    sigval_portable_t sigev_value;
+    int sigev_signo;
+    int sigev_notify;
+    union {
+        int _pad[SIGEV_PAD_SIZE];
+        int _tid;
+
+        struct {
+            void (*_function)(sigval_portable_t);
+            void *_attribute;
+        } _sigev_thread;
+     } _sigev_un;
+} sigevent_portable_t;
+
+#define sigev_notify_function _sigev_un._sigev_thread._function
+#define sigev_notify_attributes _sigev_un._sigev_thread._attribute
+#define sigev_notify_thread_id _sigev_un._tid
+
+#endif
diff --git a/ndk/sources/android/libportable/common/include/asm-generic/signal_portable.h b/ndk/sources/android/libportable/common/include/asm-generic/signal_portable.h
new file mode 100644
index 0000000..97b1b40
--- /dev/null
+++ b/ndk/sources/android/libportable/common/include/asm-generic/signal_portable.h
@@ -0,0 +1,21 @@
+/****************************************************************************
+ Derived from platforms/android-14/arch-arm/usr/include/asm-generic/signal.h
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __ASM_GENERIC_SIGNAL_PORTABLE_H
+#define __ASM_GENERIC_SIGNAL_PORTABLE_H
+
+#define SIG_BLOCK_PORTABLE   0
+#define SIG_UNBLOCK_PORTABLE 1
+#define SIG_SETMASK_PORTABLE 2
+
+#endif
+
diff --git a/ndk/sources/android/libportable/common/include/asm/sigcontext_portable.h b/ndk/sources/android/libportable/common/include/asm/sigcontext_portable.h
new file mode 100644
index 0000000..477b3e8
--- /dev/null
+++ b/ndk/sources/android/libportable/common/include/asm/sigcontext_portable.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+ Derived from gdk/platforms/android-14/arch-arm/usr/include/asm/sigcontext.h
+ ****************************************************************************
+ ***
+ ***   This header was ORIGINALLY automatically generated from a Linux kernel 
+ ***   header of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _ASMARM_SIGCONTEXT_PORTABLE_H
+#define _ASMARM_SIGCONTEXT_PORTABLE_H
+
+struct sigcontext_portable {
+ unsigned long trap_no;
+ unsigned long error_code;
+ unsigned long oldmask;
+ unsigned long arm_r0;
+ unsigned long arm_r1;
+ unsigned long arm_r2;
+ unsigned long arm_r3;
+ unsigned long arm_r4;
+ unsigned long arm_r5;
+ unsigned long arm_r6;
+ unsigned long arm_r7;
+ unsigned long arm_r8;
+ unsigned long arm_r9;
+ unsigned long arm_r10;
+ unsigned long arm_fp;
+ unsigned long arm_ip;
+ unsigned long arm_sp;
+ unsigned long arm_lr;
+ unsigned long arm_pc;
+ unsigned long arm_cpsr;
+ unsigned long fault_address;
+};
+
+#endif
diff --git a/ndk/sources/android/libportable/common/include/asm/siginfo_portable.h b/ndk/sources/android/libportable/common/include/asm/siginfo_portable.h
new file mode 100644
index 0000000..283f23e
--- /dev/null
+++ b/ndk/sources/android/libportable/common/include/asm/siginfo_portable.h
@@ -0,0 +1,17 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _ASM_PORTABLE_SIGINFO_H
+#define _ASM_PORTABLE_SIGINFO_H
+
+#include <asm-generic/siginfo_portable.h>
+
+#endif
diff --git a/ndk/sources/android/libportable/common/include/asm/signal_portable.h b/ndk/sources/android/libportable/common/include/asm/signal_portable.h
new file mode 100644
index 0000000..821d883
--- /dev/null
+++ b/ndk/sources/android/libportable/common/include/asm/signal_portable.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+  Derived from gdk/platforms/android-14/arch-arm/usr/include/asm/signal.h
+ ****************************************************************************
+ ***
+ ***   This header was ORIGINALLY automatically generated from a Linux kernel 
+ ***   header of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _ASMARM_SIGNAL_PORTABLE_H
+#define _ASMARM_SIGNAL_PORTABLE_H
+
+struct siginfo;                         /* TODO: Change to siginfo_portable */
+
+#define NSIG_PORTABLE 32
+typedef unsigned long sigset_portable_t;
+
+#define SIGHUP_PORTABLE 1
+#define SIGINT_PORTABLE 2
+#define SIGQUIT_PORTABLE 3
+#define SIGILL_PORTABLE 4
+#define SIGTRAP_PORTABLE 5
+#define SIGABRT_PORTABLE 6
+#define SIGIOT_PORTABLE 6
+#define SIGBUS_PORTABLE 7
+#define SIGFPE_PORTABLE 8
+#define SIGKILL_PORTABLE 9
+#define SIGUSR1_PORTABLE 10
+#define SIGSEGV_PORTABLE 11
+#define SIGUSR2_PORTABLE 12
+#define SIGPIPE_PORTABLE 13
+#define SIGALRM_PORTABLE 14
+#define SIGTERM_PORTABLE 15
+#define SIGSTKFLT_PORTABLE 16
+#define SIGCHLD_PORTABLE 17
+#define SIGCONT_PORTABLE 18
+#define SIGSTOP_PORTABLE 19
+#define SIGTSTP_PORTABLE 20
+#define SIGTTIN_PORTABLE 21
+#define SIGTTOU_PORTABLE 22
+#define SIGURG_PORTABLE 23
+#define SIGXCPU_PORTABLE 24
+#define SIGXFSZ_PORTABLE 25
+#define SIGVTALRM_PORTABLE 26
+#define SIGPROF_PORTABLE 27
+#define SIGWINCH_PORTABLE 28
+#define SIGIO_PORTABLE 29
+#define SIGPOLL_PORTABLE SIGIO
+
+#define SIGPWR_PORTABLE 30
+#define SIGSYS_PORTABLE 31
+#define SIGUNUSED_PORTABLE 31
+
+#define SIGRTMIN_PORTABLE 32
+#define SIGRTMAX_PORTABLE _NSIG_PORTABLE
+#define SIGSWI_PORTABLE 32
+
+#define SA_NOCLDSTOP_PORTABLE   0x00000001
+#define SA_NOCLDWAIT_PORTABLE   0x00000002
+#define SA_SIGINFO_PORTABLE     0x00000004
+#define SA_THIRTYTWO_PORTABLE   0x02000000
+#define SA_RESTORER_PORTABLE    0x04000000
+#define SA_ONSTACK_PORTABLE     0x08000000
+#define SA_RESTART_PORTABLE     0x10000000
+#define SA_NODEFER_PORTABLE     0x40000000
+#define SA_RESETHAND_PORTABLE   0x80000000
+
+#define SA_NOMASK_PORTSBLE      SA_NODEFER_PORTABLE
+#define SA_ONESHOT_PORTABLE     SA_RESETHAND_PORABLE
+
+
+#include <asm-generic/signal_portable.h>
+
+typedef __signalfn_t __user *__sighandler_portable_t;
+typedef void (*__sigaction_handler_portable_t)(int, struct siginfo *, void *);
+
+struct sigaction_portable {
+ union {
+   __sighandler_portable_t        _sa_handler;
+   __sigaction_handler_portable_t _sa_sigaction;
+ } _u;
+ sigset_portable_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+#define sa_handler_portable     _u._sa_handler
+#define sa_sigaction_portable   _u._sa_sigaction
+
+typedef struct sigaltstack_portable {
+ void __user *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} portable_stack_t;
+
+#endif
diff --git a/ndk/sources/android/libportable/common/include/signal_portable.h b/ndk/sources/android/libportable/common/include/signal_portable.h
new file mode 100644
index 0000000..73ad58e
--- /dev/null
+++ b/ndk/sources/android/libportable/common/include/signal_portable.h
@@ -0,0 +1,148 @@
+/*
+ * Derived from gdk/platforms/android-14/arch-arm/usr/include/signal.h
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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 _SIGNAL_PORTABLE_H_
+#define _SIGNAL_PORTABLE_H_
+
+#include <portability.h>
+#include <sys/cdefs.h>
+#include <limits.h>             /* For LONG_BIT */
+#include <string.h>             /* For memset() */
+#include <sys/types.h>
+#include <asm/signal_portable.h>
+#include <asm/sigcontext_portable.h>
+
+#define __ARCH_SI_UID_T __kernel_uid32_t
+#include <asm/siginfo_portable.h>
+#undef __ARCH_SI_UID_T
+
+__BEGIN_DECLS
+
+typedef int sig_atomic_t;
+
+#if 0
+/* _NSIG is used by the SIGRTMAX definition under <asm/signal.h>, however
+ * its definition is part of a #if __KERNEL__ .. #endif block in the original
+ * kernel headers and is thus not part of our cleaned-up versions.
+ *
+ * Looking at the current kernel sources, it is defined as 64 for all
+ * architectures except for the 'mips' one which set it to 128.
+ */
+#ifndef _NSIG_PORTABLE
+#  define _NSIG_PORTABLE  64
+#endif
+#endif
+
+extern const char * const sys_siglist[];
+extern const char * const sys_signame[];
+
+static __inline__ int sigismember_portable(sigset_portable_t *set, int signum)
+{
+    unsigned long *local_set = (unsigned long *)set;
+    signum--;
+    return (int)((local_set[signum/LONG_BIT] >> (signum%LONG_BIT)) & 1);
+}
+
+
+static __inline__ int sigaddset_portable(sigset_portable_t *set, int signum)
+{
+    unsigned long *local_set = (unsigned long *)set;
+    signum--;
+    local_set[signum/LONG_BIT] |= 1UL << (signum%LONG_BIT);
+    return 0;
+}
+
+
+static __inline__ int sigdelset_portable(sigset_portable_t *set, int signum)
+{
+    unsigned long *local_set = (unsigned long *)set;
+    signum--;
+    local_set[signum/LONG_BIT] &= ~(1UL << (signum%LONG_BIT));
+    return 0;
+}
+
+
+static __inline__ int sigemptyset_portable(sigset_portable_t *set)
+{
+    memset(set, 0, sizeof *set);
+    return 0;
+}
+
+static __inline__ int sigfillset_portable(sigset_portable_t *set)
+{
+    memset(set, ~0, sizeof *set);
+    return 0;
+}
+
+/* compatibility types */
+typedef void            (*sig_portable_t)(int);
+typedef sig_portable_t   sighandler_portable_t;
+
+/* Extended compatibility types, for processing a siginfo_t argument */
+typedef void            (*sig3_portable_t)(int, siginfo_portable_t *, void *);
+typedef sig3_portable_t   sig3handler_portable_t;
+
+/* differentiater between sysv and bsd behaviour 8*/
+extern __sighandler_t sysv_signal(int, __sighandler_portable_t);
+extern __sighandler_t bsd_signal(int, __sighandler_portable_t);
+
+#if 0
+/* the default is bsd */
+static __inline__ __sighandler_portable_t signal_portable(int s, sighandler_portable_t f)
+{
+    return bsd_signal(s,f);
+}
+#endif
+
+/* the portable mapped syscall itself */
+extern __sighandler_portable_t __signal_portable(int, __sighandler_portable_t);
+
+extern int sigprocmask_portable(int, const sigset_portable_t *, sigset_portable_t *);
+extern int sigaction_portable(int, const struct sigaction_portable *, struct sigaction_portable *);
+
+extern int sigpending_portable(sigset_portable_t *);
+extern int sigsuspend_portable(const sigset_portable_t *);
+extern int sigwait_portable(const sigset_portable_t *set, int *sig);
+extern int siginterrupt_portable(int  sig, int  flag);
+
+extern int raise_portable(int);
+extern int kill_portable(pid_t, int);
+extern int killpg_portable(int pgrp, int sig);
+extern int sigaltstack_portable(const portable_stack_t *ss, portable_stack_t *oss);
+
+extern __hidden char *map_portable_signum_to_name(int portable_signum);
+extern __hidden char *map_mips_signum_to_name(int mips_signum);
+extern __hidden int map_portable_signum_to_mips(int portable_signum);
+extern __hidden int map_mips_signum_to_portable(int mips_signum);
+typedef int (*sigmask_fn)(int, const sigset_t *, sigset_t *);
+extern __hidden int sigmask_helper(int portable_how, const sigset_portable_t *portable_sigset, sigset_portable_t *portable_oldset, sigmask_fn fn, char *fname);
+
+__END_DECLS
+
+#endif /* _SIGNAL_PORTABLE_H_ */