Merge "[MIPS] Added support for file descriptor related system calls."
This commit is contained in:
@@ -36,11 +36,15 @@ libportable_arch_src_files += \
|
|||||||
arch-mips/clone.c \
|
arch-mips/clone.c \
|
||||||
arch-mips/epoll.c \
|
arch-mips/epoll.c \
|
||||||
arch-mips/errno.c \
|
arch-mips/errno.c \
|
||||||
|
arch-mips/eventfd.c \
|
||||||
arch-mips/fcntl.c \
|
arch-mips/fcntl.c \
|
||||||
|
arch-mips/filefd.c \
|
||||||
|
arch-mips/inotify.c \
|
||||||
arch-mips/ioctl.c \
|
arch-mips/ioctl.c \
|
||||||
arch-mips/mmap.c \
|
arch-mips/mmap.c \
|
||||||
arch-mips/open.c \
|
arch-mips/open.c \
|
||||||
arch-mips/poll.c \
|
arch-mips/poll.c \
|
||||||
|
arch-mips/pipe.c \
|
||||||
arch-mips/pthread.c \
|
arch-mips/pthread.c \
|
||||||
arch-mips/resource.c \
|
arch-mips/resource.c \
|
||||||
arch-mips/signal.c \
|
arch-mips/signal.c \
|
||||||
@@ -50,6 +54,7 @@ libportable_arch_src_files += \
|
|||||||
arch-mips/statfs.c \
|
arch-mips/statfs.c \
|
||||||
arch-mips/syscall.c \
|
arch-mips/syscall.c \
|
||||||
arch-mips/timer.c \
|
arch-mips/timer.c \
|
||||||
|
arch-mips/timerfd.c \
|
||||||
arch-mips/waitpid.c
|
arch-mips/waitpid.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <portability.h>
|
#include <portability.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
|
||||||
#define PORTABLE_TAG "clone_portable"
|
#define PORTABLE_TAG "clone_portable"
|
||||||
#include <log_portable.h>
|
#include <log_portable.h>
|
||||||
@@ -58,11 +59,32 @@ int clone_portable(int (*fn)(void *), void *child_stack, int port_flags, void *a
|
|||||||
char *mips_term_signame;
|
char *mips_term_signame;
|
||||||
int portable_term_signum;
|
int portable_term_signum;
|
||||||
char *portable_term_signame;
|
char *portable_term_signame;
|
||||||
|
int cloning_vm = ((port_flags & CLONE_VM) == CLONE_VM);
|
||||||
|
int cloning_files = ((port_flags & CLONE_FILES) == CLONE_FILES);
|
||||||
|
int cloning_sighand = ((port_flags & CLONE_SIGHAND) == CLONE_SIGHAND);
|
||||||
|
|
||||||
ALOGV(" ");
|
ALOGV(" ");
|
||||||
ALOGV("%s(fn:%p, child_stack:%p, port_flags:0x%x, arg:%p, ...) {", __func__,
|
ALOGV("%s(fn:%p, child_stack:%p, port_flags:0x%x, arg:%p, ...) {", __func__,
|
||||||
fn, child_stack, port_flags, arg);
|
fn, child_stack, port_flags, arg);
|
||||||
|
|
||||||
|
/* Shared file descriptor table requires shared memory. */
|
||||||
|
if (cloning_files != cloning_vm) {
|
||||||
|
ALOGE("%s: cloning_files:%d != cloning_vm:%d) ...", __func__,
|
||||||
|
cloning_files, cloning_vm);
|
||||||
|
|
||||||
|
ALOGE("%s: ... port_flags:0x%x Not Supported by Lib-Portable!", __func__,
|
||||||
|
port_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shared signal handler table requires shared memory. */
|
||||||
|
if (cloning_sighand != cloning_vm) {
|
||||||
|
ALOGE("%s: cloning_sighand:%d != cloning_vm:%d) ...", __func__,
|
||||||
|
cloning_sighand, cloning_vm);
|
||||||
|
|
||||||
|
ALOGE("%s: ... port_flags:0x%x Not Supported by Lib-Portable!", __func__,
|
||||||
|
port_flags);
|
||||||
|
}
|
||||||
|
|
||||||
/* Extract optional parameters - they are cumulative. */
|
/* Extract optional parameters - they are cumulative. */
|
||||||
va_start(args, arg);
|
va_start(args, arg);
|
||||||
if (port_flags & (CLONE_PARENT_SETTID|CLONE_SETTLS|CLONE_CHILD_SETTID)) {
|
if (port_flags & (CLONE_PARENT_SETTID|CLONE_SETTLS|CLONE_CHILD_SETTID)) {
|
||||||
@@ -84,14 +106,34 @@ int clone_portable(int (*fn)(void *), void *child_stack, int port_flags, void *a
|
|||||||
mips_flags = port_flags;
|
mips_flags = port_flags;
|
||||||
} else {
|
} else {
|
||||||
portable_term_signame = map_portable_signum_to_name(portable_term_signum);
|
portable_term_signame = map_portable_signum_to_name(portable_term_signum);
|
||||||
|
ALOGV("%s: portable_term_signum:0x%x:'%s'", __func__,
|
||||||
|
portable_term_signum, portable_term_signame);
|
||||||
mips_term_signum = signum_pton(portable_term_signum);
|
mips_term_signum = signum_pton(portable_term_signum);
|
||||||
mips_term_signame = map_mips_signum_to_name(mips_term_signum);
|
mips_term_signame = map_mips_signum_to_name(mips_term_signum);
|
||||||
|
ALOGV("%s: mips_term_signum:0x%x:'%s'", __func__,
|
||||||
|
mips_term_signum, mips_term_signame);
|
||||||
mips_flags = (port_flags & ~0xFF) | (mips_term_signum & 0xFF);
|
mips_flags = (port_flags & ~0xFF) | (mips_term_signum & 0xFF);
|
||||||
}
|
}
|
||||||
|
ALOGV("%s: clone(%p, %p, 0x%x, %p, %p, %p, %p);", __func__,
|
||||||
|
fn, child_stack, mips_flags, arg, parent_tidptr, new_tls, child_tidptr);
|
||||||
|
|
||||||
ret = clone(fn, child_stack, mips_flags, arg, parent_tidptr,
|
ret = clone(fn, child_stack, mips_flags, arg, parent_tidptr,
|
||||||
new_tls, child_tidptr);
|
new_tls, child_tidptr);
|
||||||
|
|
||||||
|
if (ret > 0) {
|
||||||
|
/*
|
||||||
|
* Disable mapping in the parent if the child could interfere
|
||||||
|
* and make things even worse than skipping the signal and
|
||||||
|
* file read mapping.
|
||||||
|
*/
|
||||||
|
if (cloning_files != cloning_vm) {
|
||||||
|
filefd_disable_mapping();
|
||||||
|
}
|
||||||
|
if (cloning_sighand != cloning_vm) {
|
||||||
|
signal_disable_mapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ALOGV("%s: return(ret:%d); }", __func__, ret);
|
ALOGV("%s: return(ret:%d); }", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
95
ndk/sources/android/libportable/arch-mips/eventfd.c
Normal file
95
ndk/sources/android/libportable/arch-mips/eventfd.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* 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 <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <asm/unistd-portable.h>
|
||||||
|
#include <asm/unistd.h>
|
||||||
|
|
||||||
|
#include <fcntl_portable.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#include <eventfd_portable.h>
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
|
||||||
|
#define PORTABLE_TAG "eventfd_portable"
|
||||||
|
#include <log_portable.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: LTP defaults to using O_NONBLOCK even if EFD_NONBLOCK is defined */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Portable to Native event flags mapper.
|
||||||
|
*/
|
||||||
|
static inline int efd_flags_pton(int portable_flags)
|
||||||
|
{
|
||||||
|
int native_flags = 0;
|
||||||
|
|
||||||
|
ALOGV("%s(portable_flags:0x%x) {", __func__, portable_flags);
|
||||||
|
|
||||||
|
if (portable_flags & EFD_NONBLOCK_PORTABLE) {
|
||||||
|
native_flags |= EFD_NONBLOCK;
|
||||||
|
portable_flags &= ~EFD_NONBLOCK_PORTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portable_flags & EFD_CLOEXEC_PORTABLE) {
|
||||||
|
native_flags |= EFD_CLOEXEC;
|
||||||
|
portable_flags &= EFD_CLOEXEC_PORTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portable_flags & EFD_SEMAPHORE_PORTABLE) {
|
||||||
|
native_flags |= EFD_SEMAPHORE;
|
||||||
|
portable_flags &= EFD_SEMAPHORE_PORTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portable_flags != 0) {
|
||||||
|
ALOGW("%s: portable_flags:0x%x != 0; Unsupported Flags being used!",
|
||||||
|
__func__, portable_flags);
|
||||||
|
}
|
||||||
|
ALOGV("%s: return(native_flags:%d); }", __func__, native_flags);
|
||||||
|
return native_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the original eventfd() the portable_flags were unused up to
|
||||||
|
* linux 2.6.26 and had to be zero. Android simply uses the
|
||||||
|
* new eventfd2 system call number, so it likely best to just use
|
||||||
|
* the Android eventfd() for both eventfd and eventfd2 system calls.
|
||||||
|
*/
|
||||||
|
int eventfd_portable(unsigned int initval, int portable_flags) {
|
||||||
|
int rv;
|
||||||
|
int native_flags;
|
||||||
|
|
||||||
|
ALOGV(" ");
|
||||||
|
ALOGV("%s(initval:%u, portable_flags:%d) {", __func__,
|
||||||
|
initval, portable_flags);
|
||||||
|
|
||||||
|
native_flags = efd_flags_pton(portable_flags);
|
||||||
|
|
||||||
|
rv = eventfd(initval, native_flags);
|
||||||
|
if (rv >= 0) {
|
||||||
|
if (native_flags & EFD_CLOEXEC) {
|
||||||
|
filefd_CLOEXEC_enabled(rv);
|
||||||
|
}
|
||||||
|
filefd_opened(rv, EVENT_FD_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -20,7 +20,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <portability.h>
|
||||||
#include <fcntl_portable.h>
|
#include <fcntl_portable.h>
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
|
||||||
#include <portability.h>
|
#include <portability.h>
|
||||||
|
|
||||||
@@ -331,6 +333,22 @@ int fcntl_portable(int fd, int portable_cmd, ...)
|
|||||||
case F_GETLEASE:
|
case F_GETLEASE:
|
||||||
case F_NOTIFY:
|
case F_NOTIFY:
|
||||||
result = __fcntl64(fd, mips_cmd, arg);
|
result = __fcntl64(fd, mips_cmd, arg);
|
||||||
|
if (result < 0) {
|
||||||
|
ALOGV("%s: result = %d = __fcntl64(fd:%d, mips_cmd:0x%x, arg:%p);", __func__,
|
||||||
|
result, fd, mips_cmd, arg);
|
||||||
|
} else {
|
||||||
|
if (mips_cmd == F_SETFD) {
|
||||||
|
/*
|
||||||
|
* File descriptor flag bits got set or cleared.
|
||||||
|
*/
|
||||||
|
flags = (int)arg;
|
||||||
|
if (flags & FD_CLOEXEC) {
|
||||||
|
filefd_CLOEXEC_enabled(fd);
|
||||||
|
} else {
|
||||||
|
filefd_CLOEXEC_disabled(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
502
ndk/sources/android/libportable/arch-mips/filefd.c
Normal file
502
ndk/sources/android/libportable/arch-mips/filefd.c
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
/*
|
||||||
|
* 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 <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <portability.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <errno_portable.h>
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
#include <signal_portable.h>
|
||||||
|
#include <sys/atomics.h>
|
||||||
|
|
||||||
|
#define PORTABLE_TAG "filefd_portable"
|
||||||
|
#include <log_portable.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maintaining a list of special file descriptors in lib-portable:
|
||||||
|
* ---------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* These are file descriptors which were opened with system calls
|
||||||
|
* which make it possible to read kernel data structures via the
|
||||||
|
* read system call. See man pages for:
|
||||||
|
* signalfd(2)
|
||||||
|
* eventfd(2)
|
||||||
|
* timerfd_create(2)
|
||||||
|
*
|
||||||
|
* The files conditioned with signalfd(2) need to have their reads
|
||||||
|
* intercepted to correct signal numbers. This is done using this table
|
||||||
|
* of mapped files.
|
||||||
|
*
|
||||||
|
* The signalfd(2) semantics are maintained across execve(2) by exporting
|
||||||
|
* and importing environment variables for file descriptors that are not
|
||||||
|
* marked as close-on-execute. For example testing import code with:
|
||||||
|
* Eg:
|
||||||
|
* export ANDROID_PORTABLE_MAPPED_FILE_DESCRIPTORS=10,17
|
||||||
|
* export ANDROID_PORTABLE_MAPPED_FILE_TYPES=2,1
|
||||||
|
*
|
||||||
|
* Where
|
||||||
|
* filefd_mapped_file[10] = SIGNAL_FD_TYPE:2
|
||||||
|
* filefd_FD_CLOEXEC_file[10] = 0;
|
||||||
|
* and
|
||||||
|
* filefd_mapped_file[17] = EVENT_FD_TYPE:1
|
||||||
|
* filefd_FD_CLOEXEC_file[17] = 0;
|
||||||
|
*
|
||||||
|
* A table of CLOEXEC_files is maintained via call-backs
|
||||||
|
* in open_portable() and fcntl_portable() which indicates
|
||||||
|
* the files with close-on-execute semantics.
|
||||||
|
*
|
||||||
|
* The signalfd(2) fork(2) and thread semantics are not
|
||||||
|
* affected by the mapping of signalfd() file descriptor reads.
|
||||||
|
*
|
||||||
|
* This algorithm requires that threads have the same sharing
|
||||||
|
* attributes for file descriptors and memory and will be disabled
|
||||||
|
* by a call from clone() if the environment is unsuitable for it's use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char *fd_env_name = "ANDROID_PORTABLE_MAPPED_FILE_DESCRIPTORS";
|
||||||
|
static char *type_env_name = "ANDROID_PORTABLE_MAPPED_FILE_TYPES";
|
||||||
|
static enum filefd_type filefd_mapped_file[__FD_SETSIZE];
|
||||||
|
static int filefd_FD_CLOEXEC_file[__FD_SETSIZE];
|
||||||
|
|
||||||
|
static volatile int filefd_mapped_files = 0;
|
||||||
|
static volatile int filefd_enabled = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assuming sizeof(int)==4, and __FD_SETSIZE < 10000 each token will
|
||||||
|
* occupy a maximum of 5 characters (4 digits + delimiter:','). The tokens
|
||||||
|
* are the numbers above, a file descriptor (0..9999), and the filefd_type's
|
||||||
|
* which are a single digit.
|
||||||
|
*
|
||||||
|
* The arrays used to manipulate the environment variables are allocated using
|
||||||
|
* malloc to avoid overrunning the stack.
|
||||||
|
*/
|
||||||
|
#if __FD_SETSIZE >= 10000
|
||||||
|
#error MAX_ENV_SIZE must be increased
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_ENV_SIZE (__FD_SETSIZE * 5)
|
||||||
|
|
||||||
|
static int export_fd_env()
|
||||||
|
{
|
||||||
|
const int max_env_size = MAX_ENV_SIZE;
|
||||||
|
int type_env_bytes_remaining = max_env_size;
|
||||||
|
char *type_env_allocated = NULL, *type_env;
|
||||||
|
int fd_env_bytes_remaining = max_env_size;
|
||||||
|
char *fd_env_allocated = NULL, *fd_env;
|
||||||
|
int exported_file_descriptors = 0;
|
||||||
|
enum filefd_type fd_type;
|
||||||
|
int overwrite = 1;
|
||||||
|
int fd_count = 0;
|
||||||
|
int saved_errno;
|
||||||
|
int fd_cloexec;
|
||||||
|
int len;
|
||||||
|
int rv1;
|
||||||
|
int rv2;
|
||||||
|
int rv;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
ALOGV("%s:() {", __func__);
|
||||||
|
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
type_env_allocated = malloc(max_env_size);
|
||||||
|
fd_env_allocated = malloc(max_env_size);
|
||||||
|
if (type_env_allocated == NULL || fd_env_allocated == NULL) {
|
||||||
|
ALOGE("%s: type_env_allocated:%p, fd_env_allocated:%p; FIXME!", __func__,
|
||||||
|
type_env_allocated, fd_env_allocated);
|
||||||
|
|
||||||
|
rv = -1;
|
||||||
|
goto done;
|
||||||
|
} else {
|
||||||
|
ALOGV("%s: type_env_allocated:%p, fd_env_allocated:%p;", __func__,
|
||||||
|
type_env_allocated, fd_env_allocated);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_env = type_env_allocated;
|
||||||
|
fd_env = fd_env_allocated;
|
||||||
|
|
||||||
|
for (fd = 0; fd < __FD_SETSIZE; fd++) {
|
||||||
|
fd_type = filefd_mapped_file[fd];
|
||||||
|
if (fd_type != UNUSED_FD_TYPE) {
|
||||||
|
++fd_count;
|
||||||
|
ALOGV("%s: fd_type = %d = filefd_mapped_file[fd:%d]; ++fdcount:%d;", __func__,
|
||||||
|
fd_type, fd, fd_count);
|
||||||
|
|
||||||
|
fd_cloexec = filefd_FD_CLOEXEC_file[fd];
|
||||||
|
ALOGV("%s: fd_cloexec = %d = filefd_FD_CLOEXEC_file[fd:%d];", __func__,
|
||||||
|
fd_cloexec, fd);
|
||||||
|
|
||||||
|
if (fd_cloexec == 0) {
|
||||||
|
rv = snprintf(fd_env, fd_env_bytes_remaining, "%d,", fd);
|
||||||
|
ASSERT(rv > 0);
|
||||||
|
fd_env += rv;
|
||||||
|
fd_env_bytes_remaining -= rv;
|
||||||
|
rv = snprintf(type_env, type_env_bytes_remaining, "%d,", filefd_mapped_file[fd]);
|
||||||
|
ASSERT(rv > 0);
|
||||||
|
type_env += rv;
|
||||||
|
type_env_bytes_remaining -= rv;
|
||||||
|
exported_file_descriptors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is a chance of inconsistent results here if
|
||||||
|
* another thread is updating the array while it was
|
||||||
|
* being copied, but this code is only run during exec
|
||||||
|
* so the state of the file descriptors that the child
|
||||||
|
* sees will be inconsistent anyway.
|
||||||
|
*/
|
||||||
|
if (fd_count == filefd_mapped_files)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fd_count != filefd_mapped_files) {
|
||||||
|
ALOGE("%s: fd_count:%d != filefd_mapped_files:%d; [Likely Race; add futex?]", __func__,
|
||||||
|
fd_count, filefd_mapped_files);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (exported_file_descriptors == 0) {
|
||||||
|
rv1 = unsetenv(fd_env_name);
|
||||||
|
rv2 = unsetenv(type_env_name);
|
||||||
|
if (rv1 != 0 || rv2 != 0) {
|
||||||
|
ALOGV("%s: Note: unsetenv() failed!", __func__);
|
||||||
|
}
|
||||||
|
rv = 0;
|
||||||
|
} else {
|
||||||
|
if (fd_env > fd_env_allocated) {
|
||||||
|
fd_env--; /* backup fd_env to last ',' */
|
||||||
|
}
|
||||||
|
*fd_env = '\0';
|
||||||
|
|
||||||
|
if (type_env > type_env_allocated) {
|
||||||
|
type_env--; /* backup type_env to last ',' */
|
||||||
|
}
|
||||||
|
*type_env = '\0';
|
||||||
|
|
||||||
|
rv = setenv(fd_env_name, fd_env_allocated, overwrite);
|
||||||
|
if (rv != 0) {
|
||||||
|
ALOGE("%s: rv:%d = setenv(fd_env_name:'%s', fd_env_allocated:'%s' ...);", __func__,
|
||||||
|
rv, fd_env_name, fd_env_allocated);
|
||||||
|
} else {
|
||||||
|
ALOGV("%s: rv:%d = setenv(fd_env_name:'%s', fd_env_allocated:'%s' ...);", __func__,
|
||||||
|
rv, fd_env_name, fd_env_allocated);
|
||||||
|
}
|
||||||
|
if (rv != 0) goto done;
|
||||||
|
|
||||||
|
rv = setenv(type_env_name, type_env_allocated, overwrite);
|
||||||
|
|
||||||
|
if (rv != 0) {
|
||||||
|
ALOGE("%s: rv:%d = setenv(type_env_name:'%s', type_env_allocated:'%s' ...);",
|
||||||
|
__func__, rv, type_env_name, type_env_allocated);
|
||||||
|
} else {
|
||||||
|
ALOGV("%s: rv:%d = setenv(type_env_name:'%s', type_env_allocated:'%s' ...);",
|
||||||
|
__func__, rv, type_env_name, type_env_allocated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (type_env_allocated)
|
||||||
|
free(type_env_allocated);
|
||||||
|
|
||||||
|
if (fd_env_allocated)
|
||||||
|
free(fd_env_allocated);
|
||||||
|
|
||||||
|
errno = saved_errno;
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int import_fd_env(int verify)
|
||||||
|
{
|
||||||
|
char *type_env_allocated = NULL;
|
||||||
|
char *fd_env_allocated = NULL;
|
||||||
|
char *type_token_saved_ptr;
|
||||||
|
char *fd_token_saved_ptr;
|
||||||
|
enum filefd_type fd_type;
|
||||||
|
char *type_env, *fd_env;
|
||||||
|
int saved_errno;
|
||||||
|
char *type_token;
|
||||||
|
char *fd_token;
|
||||||
|
int rv = 0;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
ALOGV("%s:(verify:%d) {", __func__, verify);
|
||||||
|
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get file descriptor environment pointer and make a
|
||||||
|
* a copy of the string.
|
||||||
|
*/
|
||||||
|
fd_env = getenv(fd_env_name);
|
||||||
|
if (fd_env == NULL) {
|
||||||
|
ALOGV("%s: fd_env = NULL = getenv('%s');", __func__,
|
||||||
|
fd_env_name);
|
||||||
|
goto done;
|
||||||
|
} else {
|
||||||
|
ALOGV("%s: fd_env = '%s' = getenv('%s');", __func__,
|
||||||
|
fd_env, fd_env_name);
|
||||||
|
|
||||||
|
fd_env_allocated = malloc(strlen(fd_env)+1);
|
||||||
|
if (fd_env_allocated == NULL) {
|
||||||
|
ALOGE("%s: fd_env_allocated = NULL; malloc failed", __func__);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
strcpy(fd_env_allocated, fd_env);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get file descriptor environment pointer and make a copy of
|
||||||
|
* the string to our stack.
|
||||||
|
*/
|
||||||
|
type_env = getenv(type_env_name);
|
||||||
|
if (type_env == NULL) {
|
||||||
|
ALOGV("%s: type_env = NULL = getenv(type_env_name:'%s');", __func__,
|
||||||
|
type_env_name);
|
||||||
|
goto done;
|
||||||
|
} else {
|
||||||
|
ALOGV("%s: type_env = '%s' = getenv(type_env_name:'%s');", __func__,
|
||||||
|
type_env, type_env_name);
|
||||||
|
|
||||||
|
type_env_allocated = malloc(strlen(type_env)+1);
|
||||||
|
if (type_env_allocated == NULL) {
|
||||||
|
ALOGE("%s: type_env_allocated = NULL; malloc failed", __func__);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
strcpy(type_env_allocated, type_env);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup strtok_r(), use it to parse the env tokens, and
|
||||||
|
* initialise the filefd_mapped_file array.
|
||||||
|
*/
|
||||||
|
fd_token = strtok_r(fd_env_allocated, ",", &fd_token_saved_ptr);
|
||||||
|
type_token = strtok_r(type_env_allocated, ",", &type_token_saved_ptr);
|
||||||
|
while (fd_token && type_token) {
|
||||||
|
fd = atoi(fd_token);
|
||||||
|
ASSERT(fd >= 0 );
|
||||||
|
ASSERT(fd < __FD_SETSIZE);
|
||||||
|
|
||||||
|
fd_type = (enum filefd_type) atoi(type_token);
|
||||||
|
ASSERT(fd_type > UNUSED_FD_TYPE);
|
||||||
|
ASSERT(fd_type < MAX_FD_TYPE);
|
||||||
|
|
||||||
|
if (fd >= 0 && fd < __FD_SETSIZE) {
|
||||||
|
if (fd_type > UNUSED_FD_TYPE && fd_type < MAX_FD_TYPE) {
|
||||||
|
if (verify) {
|
||||||
|
ASSERT(filefd_mapped_file[fd] == fd_type);
|
||||||
|
ALOGV("%s: filefd_mapped_file[fd:%d] == fd_type:%d;", __func__,
|
||||||
|
fd, fd_type);
|
||||||
|
} else {
|
||||||
|
ASSERT(filefd_mapped_file[fd] == UNUSED_FD_TYPE);
|
||||||
|
|
||||||
|
__atomic_inc(&filefd_mapped_files);
|
||||||
|
ALOGV("%s: ++filefd_mapped_files:%d;", __func__,
|
||||||
|
filefd_mapped_files);
|
||||||
|
|
||||||
|
filefd_mapped_file[fd] = fd_type;
|
||||||
|
ALOGV("%s: filefd_mapped_file[fd:%d] = fd_type:%d;", __func__,
|
||||||
|
fd, fd_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_token = strtok_r(NULL, ",", &fd_token_saved_ptr);
|
||||||
|
type_token = strtok_r(NULL, ",", &type_token_saved_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (type_env_allocated)
|
||||||
|
free(type_env_allocated);
|
||||||
|
if (fd_env_allocated)
|
||||||
|
free(fd_env_allocated);
|
||||||
|
|
||||||
|
errno = saved_errno;
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function will get run by the linker when the library is loaded.
|
||||||
|
*/
|
||||||
|
static void __attribute__ ((constructor)) linker_import_fd_env(void)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
int verify_consistancy = 0;
|
||||||
|
|
||||||
|
ALOGV(" ");
|
||||||
|
ALOGV("%s() {", __func__);
|
||||||
|
|
||||||
|
rv = import_fd_env(verify_consistancy); /* File type table not verified. */
|
||||||
|
|
||||||
|
ALOGV("%s: }", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__hidden void filefd_opened(int fd, enum filefd_type fd_type)
|
||||||
|
{
|
||||||
|
ALOGV("%s(fd:%d) {", __func__, fd);
|
||||||
|
|
||||||
|
if (fd >= 0 && fd < __FD_SETSIZE) {
|
||||||
|
if (filefd_mapped_file[fd] == UNUSED_FD_TYPE) {
|
||||||
|
__atomic_inc(&filefd_mapped_files);
|
||||||
|
filefd_mapped_file[fd] = fd_type;
|
||||||
|
}
|
||||||
|
ASSERT(filefd_mapped_file[fd] == fd_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: }", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
__hidden void filefd_closed(int fd)
|
||||||
|
{
|
||||||
|
ALOGV("%s(fd:%d) {", __func__, fd);
|
||||||
|
|
||||||
|
if (fd >= 0 && fd < __FD_SETSIZE) {
|
||||||
|
if (filefd_mapped_file[fd] != UNUSED_FD_TYPE) {
|
||||||
|
filefd_mapped_file[fd] = UNUSED_FD_TYPE;
|
||||||
|
filefd_FD_CLOEXEC_file[fd] = 0;
|
||||||
|
__atomic_dec(&filefd_mapped_files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ALOGV("%s: }", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__hidden void filefd_CLOEXEC_enabled(int fd)
|
||||||
|
{
|
||||||
|
ALOGV("%s:(fd:%d) {", __func__, fd);
|
||||||
|
|
||||||
|
if (fd >= 0 && fd < __FD_SETSIZE) {
|
||||||
|
filefd_FD_CLOEXEC_file[fd] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: }", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
__hidden void filefd_CLOEXEC_disabled(int fd)
|
||||||
|
{
|
||||||
|
ALOGV("%s:(fd:%d) {", __func__, fd);
|
||||||
|
|
||||||
|
if (fd >= 0 && fd < __FD_SETSIZE) {
|
||||||
|
filefd_FD_CLOEXEC_file[fd] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: }", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__hidden void filefd_disable_mapping()
|
||||||
|
{
|
||||||
|
ALOGV("%s:() {", __func__);
|
||||||
|
|
||||||
|
filefd_enabled = 0;
|
||||||
|
|
||||||
|
ALOGV("%s: }", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int close_portable(int fd)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
ALOGV(" ");
|
||||||
|
ALOGV("%s(fd:%d) {", __func__, fd);
|
||||||
|
|
||||||
|
rv = close(fd);
|
||||||
|
filefd_closed(fd);
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_portable(int fd, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
enum filefd_type fd_type;
|
||||||
|
|
||||||
|
ALOGV(" ");
|
||||||
|
ALOGV("%s(fd:%d, buf:0x%p, count:%d) {", __func__,
|
||||||
|
fd, buf, count);
|
||||||
|
|
||||||
|
fd_type = filefd_mapped_file[fd];
|
||||||
|
ALOGV("%s:fd_type:%d", __func__,
|
||||||
|
fd_type);
|
||||||
|
|
||||||
|
switch (fd_type) {
|
||||||
|
/* Reads on these descriptors are portable; no need to be mapped. */
|
||||||
|
case UNUSED_FD_TYPE:
|
||||||
|
case EVENT_FD_TYPE:
|
||||||
|
case INOTIFY_FD_TYPE:
|
||||||
|
case TIMER_FD_TYPE:
|
||||||
|
rv = read(fd, buf, count);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* The read() of a signalfd() file descriptor needs to be mapped. */
|
||||||
|
case SIGNAL_FD_TYPE:
|
||||||
|
if (filefd_enabled) {
|
||||||
|
rv = read_signalfd_mapper(fd, buf, count);
|
||||||
|
} else {
|
||||||
|
rv = read(fd, buf, count);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ALOGE("Unknown fd_type:%d!", fd_type);
|
||||||
|
rv = read(fd, buf, count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Export PORTABLE environment variables before execve().
|
||||||
|
* Tries a second time if it detects an extremely unlikely
|
||||||
|
* race condition.
|
||||||
|
*/
|
||||||
|
int execve_portable(const char *filename, char *const argv[], char *const envp[])
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
int mapped_files = filefd_mapped_files;
|
||||||
|
int verify_consistancy = 1;
|
||||||
|
|
||||||
|
ALOGV(" ");
|
||||||
|
ALOGV("%s(filename:%p, argv:%p, envp:%p) {", __func__,
|
||||||
|
filename, argv, envp);
|
||||||
|
|
||||||
|
export_fd_env();
|
||||||
|
|
||||||
|
if (mapped_files != filefd_mapped_files) {
|
||||||
|
export_fd_env();
|
||||||
|
}
|
||||||
|
import_fd_env(verify_consistancy); /* File type table consistancy verified. */
|
||||||
|
|
||||||
|
rv = execve(filename, argv, envp);
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
84
ndk/sources/android/libportable/arch-mips/inotify.c
Normal file
84
ndk/sources/android/libportable/arch-mips/inotify.c
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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 <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <asm/unistd.h>
|
||||||
|
#include <asm/unistd-portable.h>
|
||||||
|
|
||||||
|
#include <fcntl_portable.h>
|
||||||
|
#include <inotify_portable.h>
|
||||||
|
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define PORTABLE_TAG "inotify_portable"
|
||||||
|
#include <log_portable.h>
|
||||||
|
|
||||||
|
extern int syscall(int, ...);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: LTP defaults to using O_CLOEXEC for IN_CLOEXEC,
|
||||||
|
* and 02000000 if O_CLOEXEC isn't defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Portable to Native event flags mapper.
|
||||||
|
*/
|
||||||
|
static inline int in_flags_pton(int portable_flags)
|
||||||
|
{
|
||||||
|
int native_flags = 0;
|
||||||
|
|
||||||
|
ALOGV("%s(portable_flags:0x%x) {", __func__, portable_flags);
|
||||||
|
|
||||||
|
if (portable_flags & IN_NONBLOCK_PORTABLE) {
|
||||||
|
native_flags |= IN_NONBLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portable_flags & IN_CLOEXEC_PORTABLE) {
|
||||||
|
native_flags |= IN_CLOEXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(native_flags:%d); }", __func__, native_flags);
|
||||||
|
return native_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int inotify_init1_portable(int portable_flags) {
|
||||||
|
int rv;
|
||||||
|
int native_flags;
|
||||||
|
|
||||||
|
ALOGV(" ");
|
||||||
|
ALOGV("%s(portable_flags:%d) {", __func__,
|
||||||
|
portable_flags);
|
||||||
|
|
||||||
|
native_flags = in_flags_pton(portable_flags);
|
||||||
|
|
||||||
|
rv = syscall(__NR_inotify_init1, native_flags);
|
||||||
|
if (rv >= 0) {
|
||||||
|
if (native_flags & IN_CLOEXEC) {
|
||||||
|
filefd_CLOEXEC_enabled(rv);
|
||||||
|
}
|
||||||
|
filefd_opened(rv, INOTIFY_FD_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <portability.h>
|
#include <portability.h>
|
||||||
#include <fcntl_portable.h>
|
#include <fcntl_portable.h>
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
|
||||||
#define PORTABLE_TAG "open_portable"
|
#define PORTABLE_TAG "open_portable"
|
||||||
#include <log_portable.h>
|
#include <log_portable.h>
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
#error Bad build environment
|
#error Bad build environment
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline int open_flags_pton(int flags)
|
static inline int open_flags_pton(int flags)
|
||||||
{
|
{
|
||||||
int mipsflags = flags & O_ACCMODE_PORTABLE;
|
int mipsflags = flags & O_ACCMODE_PORTABLE;
|
||||||
@@ -67,7 +69,9 @@ static inline int open_flags_pton(int flags)
|
|||||||
return mipsflags;
|
return mipsflags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern int __open(const char*, int, int);
|
extern int __open(const char*, int, int);
|
||||||
|
|
||||||
int open_portable(const char *pathname, int flags, ...)
|
int open_portable(const char *pathname, int flags, ...)
|
||||||
{
|
{
|
||||||
mode_t mode = 0;
|
mode_t mode = 0;
|
||||||
@@ -95,12 +99,20 @@ int open_portable(const char *pathname, int flags, ...)
|
|||||||
/* Can't print pathname as a string, might be bogus */
|
/* Can't print pathname as a string, might be bogus */
|
||||||
ALOGV("%s: fd = %d = __open(pathname:%p, native_flags:0x%x, mode:0x%x);", __func__,
|
ALOGV("%s: fd = %d = __open(pathname:%p, native_flags:0x%x, mode:0x%x);", __func__,
|
||||||
fd, pathname, native_flags, mode);
|
fd, pathname, native_flags, mode);
|
||||||
|
} else {
|
||||||
|
if (flags & O_CLOEXEC) {
|
||||||
|
filefd_CLOEXEC_enabled(fd);
|
||||||
|
} else {
|
||||||
|
filefd_CLOEXEC_disabled(fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ALOGV("%s: return(fd:%d); }", __func__, fd);
|
ALOGV("%s: return(fd:%d); }", __func__, fd);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern int __openat(int, const char*, int, int);
|
extern int __openat(int, const char*, int, int);
|
||||||
|
|
||||||
int openat_portable(int dirfd, const char *pathname, int flags, ...)
|
int openat_portable(int dirfd, const char *pathname, int flags, ...)
|
||||||
{
|
{
|
||||||
mode_t mode = 0;
|
mode_t mode = 0;
|
||||||
@@ -128,6 +140,12 @@ int openat_portable(int dirfd, const char *pathname, int flags, ...)
|
|||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
ALOGV("%s: fd = %d = __open(pathname:0x%p, native_flags:0x%x, mode:0x%d);", __func__,
|
ALOGV("%s: fd = %d = __open(pathname:0x%p, native_flags:0x%x, mode:0x%d);", __func__,
|
||||||
fd, pathname, native_flags, mode);
|
fd, pathname, native_flags, mode);
|
||||||
|
} else {
|
||||||
|
if (flags & O_CLOEXEC) {
|
||||||
|
filefd_CLOEXEC_enabled(fd);
|
||||||
|
} else {
|
||||||
|
filefd_CLOEXEC_disabled(fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ALOGV("%s: return(fd:%d); }", __func__, fd);
|
ALOGV("%s: return(fd:%d); }", __func__, fd);
|
||||||
return fd;
|
return fd;
|
||||||
|
|||||||
86
ndk/sources/android/libportable/arch-mips/pipe.c
Normal file
86
ndk/sources/android/libportable/arch-mips/pipe.c
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE /* GLibc compatibility to declare pipe2(2) */
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <portability.h>
|
||||||
|
#include <asm/unistd.h>
|
||||||
|
#include <asm/unistd-portable.h>
|
||||||
|
|
||||||
|
#include <fcntl_portable.h>
|
||||||
|
#include <asm/unistd-portable.h>
|
||||||
|
#include <asm/unistd.h>
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define PORTABLE_TAG "pipe_portable"
|
||||||
|
#include <log_portable.h>
|
||||||
|
|
||||||
|
extern int syscall(int, ...);
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: LTP defaults to using O_NONBLOCK even if O_NONBLOCK is defined */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Portable to Native event flags mapper.
|
||||||
|
*/
|
||||||
|
static inline int tdf_flags_pton(int portable_flags)
|
||||||
|
{
|
||||||
|
int native_flags = 0;
|
||||||
|
|
||||||
|
ALOGV("%s(portable_flags:0x%x) {", __func__, portable_flags);
|
||||||
|
|
||||||
|
if (portable_flags & O_NONBLOCK_PORTABLE) {
|
||||||
|
native_flags |= O_NONBLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portable_flags & O_CLOEXEC_PORTABLE) {
|
||||||
|
native_flags |= O_CLOEXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(native_flags:%d); }", __func__, native_flags);
|
||||||
|
return native_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int pipe2_portable(int pipefd[2], int portable_flags) {
|
||||||
|
int native_flags;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
ALOGV(" ");
|
||||||
|
ALOGV("%s(pipefd[2]:%p, portable_flags:0x%x) {", __func__,
|
||||||
|
pipefd, portable_flags);
|
||||||
|
|
||||||
|
native_flags = tdf_flags_pton(portable_flags);
|
||||||
|
|
||||||
|
rv = pipe2(pipefd, native_flags);
|
||||||
|
if (rv >= 0) {
|
||||||
|
ALOGV("%s: pipe2() returned pipefd[0]:%d, pipefd[1]:%d", __func__,
|
||||||
|
pipefd[0], pipefd[1]);
|
||||||
|
|
||||||
|
if (native_flags & O_CLOEXEC) {
|
||||||
|
filefd_CLOEXEC_enabled(pipefd[0]);
|
||||||
|
filefd_CLOEXEC_enabled(pipefd[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
#include <errno_portable.h>
|
#include <errno_portable.h>
|
||||||
#include <asm/unistd-portable.h>
|
#include <asm/unistd-portable.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
|
#include <signalfd_portable.h>
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
|
||||||
#define PORTABLE_TAG "signal_portable"
|
#define PORTABLE_TAG "signal_portable"
|
||||||
#include <log_portable.h>
|
#include <log_portable.h>
|
||||||
@@ -35,8 +37,21 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void (*sig3handler_t)(int, siginfo_t *, void *);
|
typedef void (*sig3handler_t)(int, siginfo_t *, void *);
|
||||||
|
|
||||||
|
static volatile int signal_handler_mapping_enabled = 1;
|
||||||
|
|
||||||
extern int syscall(int, ...);
|
extern int syscall(int, ...);
|
||||||
|
|
||||||
|
|
||||||
|
__hidden void signal_disable_mapping()
|
||||||
|
{
|
||||||
|
ALOGV("%s(): signal_handler_mapping_enabled:%d = 0;", __func__,
|
||||||
|
signal_handler_mapping_enabled);
|
||||||
|
|
||||||
|
signal_handler_mapping_enabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The next five hidden functions are not exposed in the
|
* The next five hidden functions are not exposed in the
|
||||||
* libportable shared object. They are used here and other
|
* libportable shared object. They are used here and other
|
||||||
@@ -473,6 +488,10 @@ static void mips_sigaction_handler(int mips_signum, siginfo_t *sip, void *ucp)
|
|||||||
siginfo_ntop(sip, portable_sip);
|
siginfo_ntop(sip, portable_sip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ALOGV("%s: Calling portable_sighandler:%p(portable_signum:%d, portable_sip:%p, ucp:%p);",
|
||||||
|
__func__, portable_sighandler, portable_signum, portable_sip, ucp);
|
||||||
|
|
||||||
portable_sighandler(portable_signum, portable_sip, ucp);
|
portable_sighandler(portable_signum, portable_sip, ucp);
|
||||||
|
|
||||||
ALOGV("%s: return; }", __func__);
|
ALOGV("%s: return; }", __func__);
|
||||||
@@ -510,10 +529,18 @@ static sighandler_t sighandler_pton(sighandler_portable_t portable_handler, int
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (sigaction)
|
/*
|
||||||
mips_handler = (sighandler_t) mips_sighandler;
|
* Signal Mapping can be disabled in the rare case of the clone
|
||||||
else
|
* flags not being compatble for VM and file descriptors.
|
||||||
mips_handler = (sighandler_t) mips_sigaction_handler;
|
*/
|
||||||
|
if (signal_handler_mapping_enabled) {
|
||||||
|
if (sigaction)
|
||||||
|
mips_handler = (sighandler_t) mips_sighandler;
|
||||||
|
else
|
||||||
|
mips_handler = (sighandler_t) mips_sigaction_handler;
|
||||||
|
} else {
|
||||||
|
mips_handler = portable_handler; /* Don't MAP */
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,7 +557,7 @@ static sighandler_t sighandler_pton(sighandler_portable_t portable_handler, int
|
|||||||
*
|
*
|
||||||
* The last 2 parameters to this static function, mips_signal_fn*, specify which of
|
* 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(),
|
* these functions to call. We intercept the above to functions, as well as signal(),
|
||||||
* functions below.
|
* and call the associated *_portable() functions below.
|
||||||
*
|
*
|
||||||
* In addition, we intercept the signal_handler with our own handlers that map the
|
* 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.
|
* signal number from the MIPS convention to the PORTABLE/ARM convention.
|
||||||
@@ -1057,22 +1084,125 @@ int sigaction_portable(int portable_signum, const struct sigaction_portable *act
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently signalfd() isn't supported by bionic with
|
||||||
|
* only the portable syscall.c code using this code by
|
||||||
|
* intercepting the syscall(__NR_signalfd4, ...) in bionic.
|
||||||
|
*/
|
||||||
|
__hidden int do_signalfd4_portable(int fd, const sigset_portable_t *portable_sigmask,
|
||||||
|
int portable_sigsetsize, int portable_flags)
|
||||||
|
{
|
||||||
|
sigset_t native_sigmask;
|
||||||
|
int native_sigsetsize = sizeof(native_sigmask);
|
||||||
|
int native_flags = 0;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
ALOGV("%s(fd:%d, portable_sigmask:%p, portable_sigsetsize:%d, portable_flags:0x%x) {",
|
||||||
|
__func__, fd, portable_sigmask, portable_sigsetsize, portable_flags);
|
||||||
|
|
||||||
|
sigset_pton((sigset_portable_t *)portable_sigmask, &native_sigmask);
|
||||||
|
|
||||||
|
if (portable_flags & SFD_NONBLOCK_PORTABLE) {
|
||||||
|
native_flags |= SFD_NONBLOCK;
|
||||||
|
}
|
||||||
|
if (portable_flags & SFD_CLOEXEC_PORTABLE) {
|
||||||
|
native_flags |= SFD_CLOEXEC;
|
||||||
|
}
|
||||||
|
rv = syscall(__NR_signalfd4, fd, &native_sigmask, native_sigsetsize, native_flags);
|
||||||
|
|
||||||
|
if (rv >= 0) {
|
||||||
|
if (native_flags & SFD_CLOEXEC) {
|
||||||
|
filefd_CLOEXEC_enabled(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads on this file descriptor must be mapped to be portable.
|
||||||
|
* The mapping should survive a fork and most clones naturally.
|
||||||
|
* For the system call to be completely portable it has to propagate
|
||||||
|
* these mapped files after an execve(). Environment variables have
|
||||||
|
* been added to do that. See filefd.c for details.
|
||||||
|
*/
|
||||||
|
filefd_opened(rv, SIGNAL_FD_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
* So far it appears that signalfd() isn't supported by bionic
|
* signalfd() isn't available in Bionic yet. When it is, it will be implemented like
|
||||||
* the kernel trap numbers are available.
|
* the glibc version where the sigsetsize is computed in the bionic code and passed
|
||||||
|
* down to the kernel with __NR_signalfd4.
|
||||||
|
*
|
||||||
|
* This function can't be called from bionic, so there isn't an entry in the experimental
|
||||||
|
* linker.cpp table for testing and this function.
|
||||||
*/
|
*/
|
||||||
int signalfd_portable(int fd, const sigset_t *portable_sigmask, int flags)
|
int signalfd_portable(int fd, const sigset_portable_t *portable_sigmask, int portable_flags)
|
||||||
{
|
{
|
||||||
sigset_t mips_sigmask;
|
int portable_sigsetsize = sizeof(sigset_portable_t);
|
||||||
|
int rv;
|
||||||
|
|
||||||
sigset_pton(portable_sigmask, &mips_sigmask);
|
ALOGV("%s(fd:%d, portable_sigmask:%p, portable_flags:0x%x) {", __func__,
|
||||||
|
fd, portable_sigmask, portable_flags);
|
||||||
|
|
||||||
return signalfd(fd, &mips_sigmask, flags);
|
rv = do_signalfd4_portable(fd, portable_sigsetsize, portable_sigmask, portable_flags);
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called by read_portable() to do signalfd read() mapping.
|
||||||
|
*/
|
||||||
|
__hidden int read_signalfd_mapper(int fd, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
ALOGV("%s(fd:%d, buf:0x%p, count:%d) {", __func__,
|
||||||
|
fd, buf, count);
|
||||||
|
|
||||||
|
rv = read(fd, buf, count);
|
||||||
|
if (rv > 0) {
|
||||||
|
int siginfos = rv/sizeof(struct signalfd_siginfo);
|
||||||
|
struct signalfd_siginfo *si = (struct signalfd_siginfo *) buf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Read signalfd_siginfo structure(s) if read is large enough */
|
||||||
|
for (i = 0; i < siginfos; i++, si++) {
|
||||||
|
int ssi_signo;
|
||||||
|
|
||||||
|
ssi_signo = si->ssi_signo;
|
||||||
|
si->ssi_signo = signum_ntop(si->ssi_signo);
|
||||||
|
ALOGV("%s: si->ssi_signo:%d = signum_ntop(si->ssi_signo:%d); i:%d", __func__,
|
||||||
|
si->ssi_signo, ssi_signo, i);
|
||||||
|
|
||||||
|
si->ssi_errno = errno_ntop(si->ssi_errno);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The ssi_codes appear to be generic; defined in
|
||||||
|
* the kernel in include/asm-generic/siginfo.h
|
||||||
|
*/
|
||||||
|
if (si->ssi_status > 0 && si->ssi_status <= NSIG) {
|
||||||
|
si->ssi_status = signum_ntop(si->ssi_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The rest of the struct members, like
|
||||||
|
* ssi_trapno, ssi_int, ssi_ptr
|
||||||
|
* are not likely worth dealing with.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int sigsuspend_portable(const sigset_portable_t *portable_sigmask)
|
int sigsuspend_portable(const sigset_portable_t *portable_sigmask)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|||||||
@@ -21,6 +21,10 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <errno_portable.h>
|
#include <errno_portable.h>
|
||||||
|
#include <eventfd_portable.h>
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
#include <inotify_portable.h>
|
||||||
|
#include <timerfd_portable.h>
|
||||||
#include <asm/unistd-portable.h>
|
#include <asm/unistd-portable.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
|
|
||||||
@@ -35,6 +39,12 @@
|
|||||||
* Minimal syscall support for LTP testing.
|
* Minimal syscall support for LTP testing.
|
||||||
* These are the system calls that LTP references explicitly.
|
* These are the system calls that LTP references explicitly.
|
||||||
* Not all of them are exported via bionic header so use #ifdef.
|
* Not all of them are exported via bionic header so use #ifdef.
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
* Add existing portable system calls currently redirected from
|
||||||
|
* experimental Bionic linker code so that calls to them via
|
||||||
|
* syscall() are also processed. For example, LTP only calls open()
|
||||||
|
* directly and never does a syscall(__NR_open, ...).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -100,11 +110,47 @@ int syscall_portable(int portable_number, ...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_eventfd_portable
|
#ifdef __NR_eventfd_portable
|
||||||
case __NR_eventfd_portable: native_number = __NR_eventfd; break;
|
/*
|
||||||
|
* Prior to 2.6.27 we only had this system call,
|
||||||
|
* which didn't have a flags argument. The kernel
|
||||||
|
* just provides a zero for flags when this system
|
||||||
|
* call number is used.
|
||||||
|
*/
|
||||||
|
case __NR_eventfd_portable: {
|
||||||
|
unsigned int initval; /* 64-bit counter initial value */
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
va_start(ap, portable_number);
|
||||||
|
|
||||||
|
initval = va_arg(ap, int);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
ret = eventfd_portable(initval, flags); /* Android uses __NR_eventfd2 in eventfd() */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_eventfd2_portable
|
#ifdef __NR_eventfd2_portable
|
||||||
case __NR_eventfd2_portable: native_number = __NR_eventfd2; break;
|
/*
|
||||||
|
* Starting with Linux 2.6.27 a flags argument was added.
|
||||||
|
* Both Bionic and glibc implement the eventfd() now with
|
||||||
|
* the additional flags argument.
|
||||||
|
*/
|
||||||
|
case __NR_eventfd2_portable: {
|
||||||
|
unsigned int initval; /* 64-bit counter initial value */
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
va_start(ap, portable_number);
|
||||||
|
|
||||||
|
initval = va_arg(ap, int);
|
||||||
|
flags = va_arg(ap, int);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
ret = eventfd_portable(initval, flags); /* Android uses __NR_eventfd2 in eventfd() */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_exit_group_portable
|
#ifdef __NR_exit_group_portable
|
||||||
@@ -176,7 +222,16 @@ int syscall_portable(int portable_number, ...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_inotify_init1_portable
|
#ifdef __NR_inotify_init1_portable
|
||||||
case __NR_inotify_init1_portable: native_number = __NR_inotify_init1; break;
|
case __NR_inotify_init1_portable: {
|
||||||
|
int portable_flags;
|
||||||
|
|
||||||
|
va_start(ap, portable_number);
|
||||||
|
portable_flags = va_arg(ap, int);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
ret = inotify_init1_portable(portable_flags);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_keyctl_portable
|
#ifdef __NR_keyctl_portable
|
||||||
@@ -204,7 +259,18 @@ int syscall_portable(int portable_number, ...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_pipe2_portable
|
#ifdef __NR_pipe2_portable
|
||||||
case __NR_pipe2_portable: native_number = __NR_pipe2; break;
|
case __NR_pipe2_portable: {
|
||||||
|
int *pipefd_ptr;
|
||||||
|
int portable_flags;
|
||||||
|
|
||||||
|
va_start(ap, portable_number);
|
||||||
|
pipefd_ptr = va_arg(ap, int *);
|
||||||
|
portable_flags = va_arg(ap, int);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
ret = pipe2_portable(pipefd_ptr, portable_flags);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_readahead_portable
|
#ifdef __NR_readahead_portable
|
||||||
@@ -312,7 +378,25 @@ int syscall_portable(int portable_number, ...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_signalfd4_portable
|
#ifdef __NR_signalfd4_portable
|
||||||
case __NR_signalfd4_portable: native_number = __NR_signalfd4; break;
|
case __NR_signalfd4_portable: {
|
||||||
|
int fd;
|
||||||
|
sigset_portable_t *portable_sigmask;
|
||||||
|
int sigsetsize;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
va_start(ap, portable_number);
|
||||||
|
|
||||||
|
fd = va_arg(ap, int);
|
||||||
|
portable_sigmask = va_arg(ap, sigset_portable_t *);
|
||||||
|
sigsetsize = va_arg(ap, int);
|
||||||
|
flags = va_arg(ap, int);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
ret = do_signalfd4_portable(fd, (const sigset_portable_t *) portable_sigmask, sigsetsize,
|
||||||
|
flags);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_socketcall_portable
|
#ifdef __NR_socketcall_portable
|
||||||
@@ -423,7 +507,18 @@ int syscall_portable(int portable_number, ...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_timerfd_create_portable
|
#ifdef __NR_timerfd_create_portable
|
||||||
case __NR_timerfd_create_portable: native_number = __NR_timerfd_create; break;
|
case __NR_timerfd_create_portable: {
|
||||||
|
int clockid;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
va_start(ap, portable_number);
|
||||||
|
clockid = va_arg(ap, int); /* clockid is portable */
|
||||||
|
flags = va_arg(ap, int); /* flags need to be mapped */
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
ret = timerfd_create_portable(clockid, flags);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NR_timerfd_gettime_portable
|
#ifdef __NR_timerfd_gettime_portable
|
||||||
|
|||||||
81
ndk/sources/android/libportable/arch-mips/timerfd.c
Normal file
81
ndk/sources/android/libportable/arch-mips/timerfd.c
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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 <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <asm/unistd.h>
|
||||||
|
#include <asm/unistd-portable.h>
|
||||||
|
|
||||||
|
#include <fcntl_portable.h>
|
||||||
|
#include <timerfd_portable.h>
|
||||||
|
|
||||||
|
#include <filefd_portable.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define PORTABLE_TAG "timerfd_portable"
|
||||||
|
#include <log_portable.h>
|
||||||
|
|
||||||
|
extern int syscall(int, ...);
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: LTP defaults to using O_NONBLOCK even if TFD_NONBLOCK is defined */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Portable to Native event flags mapper.
|
||||||
|
*/
|
||||||
|
static inline int tdf_flags_pton(int portable_flags)
|
||||||
|
{
|
||||||
|
int native_flags = 0;
|
||||||
|
|
||||||
|
ALOGV("%s(portable_flags:0x%x) {", __func__, portable_flags);
|
||||||
|
|
||||||
|
if (portable_flags & TFD_NONBLOCK_PORTABLE) {
|
||||||
|
native_flags |= TFD_NONBLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (portable_flags & TFD_CLOEXEC_PORTABLE) {
|
||||||
|
native_flags |= TFD_CLOEXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(native_flags:%d); }", __func__, native_flags);
|
||||||
|
return native_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int timerfd_create_portable(int clockid, int portable_flags) {
|
||||||
|
int rv;
|
||||||
|
int native_flags;
|
||||||
|
|
||||||
|
ALOGV(" ");
|
||||||
|
ALOGV("%s(clockid:%d, portable_flags:%d) {", __func__,
|
||||||
|
clockid, portable_flags);
|
||||||
|
|
||||||
|
native_flags = tdf_flags_pton(portable_flags);
|
||||||
|
|
||||||
|
rv = syscall(__NR_timerfd_create, clockid, native_flags);
|
||||||
|
if (rv >= 0) {
|
||||||
|
if (native_flags & TFD_CLOEXEC) {
|
||||||
|
filefd_CLOEXEC_enabled(rv);
|
||||||
|
}
|
||||||
|
filefd_opened(rv, TIMER_FD_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("%s: return(rv:%d); }", __func__, rv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Derived from bionic/libc/include/sys/eventfd.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 _SYS_EVENTFD_PORTABLE_H
|
||||||
|
#define _SYS_EVENTFD_PORTABLE_H
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <portability.h>
|
||||||
|
#include <fcntl_portable.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EFD_SEMAPHORE is defined in recent linux kernels;
|
||||||
|
* but isn't mentioned elsewhere. See linux 3.4
|
||||||
|
* include/linux/eventfd.h for example.
|
||||||
|
*/
|
||||||
|
#define EFD_SEMAPHORE (1 << 0)
|
||||||
|
|
||||||
|
#define EFD_SEMAPHORE_PORTABLE EFD_SEMAPHORE
|
||||||
|
#define EFD_CLOEXEC_PORTABLE O_CLOEXEC_PORTABLE
|
||||||
|
#define EFD_NONBLOCK_PORTABLE O_NONBLOCK_PORTABLE
|
||||||
|
|
||||||
|
/* type of event counter */
|
||||||
|
typedef uint64_t eventfd_portable_t;
|
||||||
|
|
||||||
|
extern int eventfd_portable(unsigned int initval, int flags);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Compatibility with GLibc; libportable versions don't appear to be necessary */
|
||||||
|
extern int eventfd_read(int fd, eventfd_t *counter);
|
||||||
|
extern int eventfd_write(int fd, const eventfd_t counter);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif /* _SYS_EVENTFD_H */
|
||||||
@@ -72,6 +72,15 @@
|
|||||||
#define O_NDELAY_PORTABLE O_NONBLOCK_PORTABLE
|
#define O_NDELAY_PORTABLE O_NONBLOCK_PORTABLE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* From Bionic libc/kernel/common/asm-generic/fcntl.h */
|
||||||
|
#ifndef O_CLOEXEC_PORTABLE
|
||||||
|
#define O_CLOEXEC_PORTABLE 02000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ARCH_FLOCK64_PAD
|
||||||
|
#define __ARCH_FLOCK64_PAD
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For use with F_GETLK and F_SETLK
|
* For use with F_GETLK and F_SETLK
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FILEFD_PORTABLE_H_
|
||||||
|
#define _FILEFD_PORTABLE_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maintaining a list of special file descriptors in lib-portable
|
||||||
|
* which are maintained across a execve() via environment variables.
|
||||||
|
* See portable/arch-mips/filefd.c for details.
|
||||||
|
*/
|
||||||
|
enum filefd_type {
|
||||||
|
UNUSED_FD_TYPE = 0,
|
||||||
|
EVENT_FD_TYPE,
|
||||||
|
INOTIFY_FD_TYPE,
|
||||||
|
SIGNAL_FD_TYPE,
|
||||||
|
TIMER_FD_TYPE,
|
||||||
|
MAX_FD_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
extern __hidden void filefd_opened(int fd, enum filefd_type fd_type);
|
||||||
|
extern __hidden void filefd_closed(int fd);
|
||||||
|
extern __hidden void filefd_CLOEXEC_enabled(int fd);
|
||||||
|
extern __hidden void filefd_CLOEXEC_disabled(int fd);
|
||||||
|
extern __hidden void filefd_disable_mapping(void);
|
||||||
|
|
||||||
|
extern int close_portable(int fd);
|
||||||
|
extern int read_portable(int fd, void *buf, size_t count);
|
||||||
|
extern int pipe2_portable(int pipefd[2], int portable_flags);
|
||||||
|
|
||||||
|
#endif /* _FILEFD_PORTABLE_H_ */
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Derived from bionic/libc/include/sys/eventfd.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 _SYS_INOTIFY_PORTABLE_H
|
||||||
|
#define _SYS_INOTIFY_PORTABLE_H
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <portability.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <fcntl_portable.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define IN_CLOEXEC O_CLOEXEC
|
||||||
|
#define IN_NONBLOCK O_NONBLOCK
|
||||||
|
|
||||||
|
#define IN_CLOEXEC_PORTABLE O_CLOEXEC_PORTABLE
|
||||||
|
#define IN_NONBLOCK_PORTABLE O_NONBLOCK_PORTABLE
|
||||||
|
|
||||||
|
extern int inotify_init1_portable(int flags);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif /* _SYS_INOTIFY_H */
|
||||||
@@ -142,7 +142,14 @@ extern int tkill_portable(int tid, int portable_signum);
|
|||||||
extern int sigaltstack_portable(const portable_stack_t *ss, portable_stack_t *oss);
|
extern int sigaltstack_portable(const portable_stack_t *ss, portable_stack_t *oss);
|
||||||
extern int timer_create_portable(clockid_t, struct sigevent *, timer_t *);
|
extern int timer_create_portable(clockid_t, struct sigevent *, timer_t *);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
extern int signalfd_portable(int fd, const sigset_portable_t *portable_sigmask, int flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern __hidden int do_signalfd4_portable(int fd, const sigset_portable_t *portable_sigmask,
|
||||||
|
int portable_sigsetsize, int flags);
|
||||||
|
|
||||||
|
extern __hidden int read_signalfd_mapper(int fd, void *buf, size_t count);
|
||||||
extern __hidden char *map_portable_signum_to_name(int portable_signum);
|
extern __hidden char *map_portable_signum_to_name(int portable_signum);
|
||||||
extern __hidden char *map_mips_signum_to_name(int mips_signum);
|
extern __hidden char *map_mips_signum_to_name(int mips_signum);
|
||||||
extern __hidden int signum_pton(int portable_signum);
|
extern __hidden int signum_pton(int portable_signum);
|
||||||
@@ -153,6 +160,7 @@ typedef int (*rt_sigmask_fn)(int, const sigset_t *, sigset_t *, size_t);
|
|||||||
typedef int (*sigaction_fn)(int, const struct sigaction *, struct sigaction *);
|
typedef int (*sigaction_fn)(int, const struct sigaction *, struct sigaction *);
|
||||||
typedef int (*rt_sigaction_fn)(int, const struct sigaction *, struct sigaction *, size_t);
|
typedef int (*rt_sigaction_fn)(int, const struct sigaction *, struct sigaction *, size_t);
|
||||||
|
|
||||||
|
|
||||||
extern __hidden int do_sigmask(int portable_how, const sigset_portable_t *portable_sigset,
|
extern __hidden int do_sigmask(int portable_how, const sigset_portable_t *portable_sigset,
|
||||||
sigset_portable_t *portable_oldset, sigmask_fn fn,
|
sigset_portable_t *portable_oldset, sigmask_fn fn,
|
||||||
rt_sigmask_fn rt_fn);
|
rt_sigmask_fn rt_fn);
|
||||||
@@ -181,6 +189,10 @@ extern __hidden int rt_sigqueueinfo_portable(pid_t pid, int sig, siginfo_portabl
|
|||||||
extern __hidden int rt_tgsigqueueinfo_portable(pid_t tgid, pid_t pid, int sig,
|
extern __hidden int rt_tgsigqueueinfo_portable(pid_t tgid, pid_t pid, int sig,
|
||||||
siginfo_portable_t *uinfo);
|
siginfo_portable_t *uinfo);
|
||||||
|
|
||||||
|
|
||||||
|
/* Called by clone when memory and signal handlers aren't compatable. */
|
||||||
|
extern __hidden void signal_disable_mapping(void);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* _SIGNAL_PORTABLE_H_ */
|
#endif /* _SIGNAL_PORTABLE_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Derived from Goldfish include/linux/signalfd.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LINUX_SIGNALFD_PORTABLE_H
|
||||||
|
#define _LINUX_SIGNALFD_PORTABLE_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
/* Flags for signalfd4. */
|
||||||
|
#define SFD_CLOEXEC O_CLOEXEC
|
||||||
|
#define SFD_NONBLOCK O_NONBLOCK
|
||||||
|
|
||||||
|
/* For O_CLOEXEC_PORTABLE and O_NONBLOCK_PORTABLE */
|
||||||
|
#include "fcntl_portable.h"
|
||||||
|
|
||||||
|
#define SFD_CLOEXEC_PORTABLE O_CLOEXEC_PORTABLE
|
||||||
|
#define SFD_NONBLOCK_PORTABLE O_NONBLOCK_PORTABLE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure is the same for Native and Portable.
|
||||||
|
* However for MIPS ssi_signo and ssi_errno differ in their
|
||||||
|
* values and need to be mapped.
|
||||||
|
*/
|
||||||
|
struct signalfd_siginfo {
|
||||||
|
__u32 ssi_signo;
|
||||||
|
__s32 ssi_errno;
|
||||||
|
__s32 ssi_code;
|
||||||
|
__u32 ssi_pid;
|
||||||
|
__u32 ssi_uid;
|
||||||
|
__s32 ssi_fd;
|
||||||
|
__u32 ssi_tid;
|
||||||
|
__u32 ssi_band;
|
||||||
|
__u32 ssi_overrun;
|
||||||
|
__u32 ssi_trapno;
|
||||||
|
__s32 ssi_status;
|
||||||
|
__s32 ssi_int;
|
||||||
|
__u64 ssi_ptr;
|
||||||
|
__u64 ssi_utime;
|
||||||
|
__u64 ssi_stime;
|
||||||
|
__u64 ssi_addr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pad structure to 128 bytes. Remember to update the
|
||||||
|
* pad size when you add new members. We use a fixed
|
||||||
|
* size structure to avoid compatibility problems with
|
||||||
|
* future versions, and we leave extra space for additional
|
||||||
|
* members. We use fixed size members because this structure
|
||||||
|
* comes out of a read(2) and we really don't want to have
|
||||||
|
* a compat (sp?) on read(2).
|
||||||
|
*/
|
||||||
|
__u8 __pad[48];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _LINUX_SIGNALFD_PORTABLE_H */
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Derived from bionic/libc/include/sys/eventfd.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 _SYS_TIMERFD_PORTABLE_H
|
||||||
|
#define _SYS_TIMERFD_PORTABLE_H
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <portability.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <fcntl_portable.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define TFD_CLOEXEC O_CLOEXEC
|
||||||
|
#define TFD_NONBLOCK O_NONBLOCK
|
||||||
|
|
||||||
|
#define TFD_CLOEXEC_PORTABLE O_CLOEXEC_PORTABLE
|
||||||
|
#define TFD_NONBLOCK_PORTABLE O_NONBLOCK_PORTABLE
|
||||||
|
|
||||||
|
extern int timerfd_create_portable(int clockid, int flags);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif /* _SYS_TIMERFD_H */
|
||||||
Reference in New Issue
Block a user