diff --git a/ndk/sources/android/libportable/Android.mk b/ndk/sources/android/libportable/Android.mk index 3cc203a9f..70b45a4a5 100644 --- a/ndk/sources/android/libportable/Android.mk +++ b/ndk/sources/android/libportable/Android.mk @@ -38,6 +38,7 @@ libportable_arch_src_files += \ 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 000000000..6c325e45e --- /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 +#include +#include +#include +#include +#include +#include +#include + +#define PORTABLE_TAG "signal_portable" +#include + + +#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 = "<>"; 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 = "<>"; 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 000000000..1f13ad8ea --- /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 +#include + +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 000000000..97b1b405a --- /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 000000000..477b3e847 --- /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 000000000..283f23ece --- /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 + +#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 000000000..821d8832a --- /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 + +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 000000000..73ad58e1b --- /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 +#include +#include /* For LONG_BIT */ +#include /* For memset() */ +#include +#include +#include + +#define __ARCH_SI_UID_T __kernel_uid32_t +#include +#undef __ARCH_SI_UID_T + +__BEGIN_DECLS + +typedef int sig_atomic_t; + +#if 0 +/* _NSIG is used by the SIGRTMAX definition under , 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_ */