am 5e0e89f2: Merge "[MIPS] Added support for file descriptor related system calls."

* commit '5e0e89f2291d7187cc7241a086e2bdcd5b511c7c':
  [MIPS] Added support for file descriptor related system calls.
This commit is contained in:
Andrew Hsieh
2013-02-21 14:21:02 -08:00
committed by Android Git Automerger
18 changed files with 1463 additions and 17 deletions

View File

@@ -36,11 +36,15 @@ libportable_arch_src_files += \
arch-mips/clone.c \
arch-mips/epoll.c \
arch-mips/errno.c \
arch-mips/eventfd.c \
arch-mips/fcntl.c \
arch-mips/filefd.c \
arch-mips/inotify.c \
arch-mips/ioctl.c \
arch-mips/mmap.c \
arch-mips/open.c \
arch-mips/poll.c \
arch-mips/pipe.c \
arch-mips/pthread.c \
arch-mips/resource.c \
arch-mips/signal.c \
@@ -50,6 +54,7 @@ libportable_arch_src_files += \
arch-mips/statfs.c \
arch-mips/syscall.c \
arch-mips/timer.c \
arch-mips/timerfd.c \
arch-mips/waitpid.c
endif

View File

@@ -23,6 +23,7 @@
#include <portability.h>
#include <stdio.h>
#include <errno.h>
#include <filefd_portable.h>
#define PORTABLE_TAG "clone_portable"
#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;
int portable_term_signum;
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("%s(fn:%p, child_stack:%p, port_flags:0x%x, arg:%p, ...) {", __func__,
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. */
va_start(args, arg);
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;
} else {
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_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);
}
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,
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);
return ret;
}

View 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;
}

View File

@@ -20,7 +20,9 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <portability.h>
#include <fcntl_portable.h>
#include <filefd_portable.h>
#include <portability.h>
@@ -331,6 +333,22 @@ int fcntl_portable(int fd, int portable_cmd, ...)
case F_GETLEASE:
case F_NOTIFY:
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;
default:

View 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;
}

View 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;
}

View File

@@ -19,6 +19,7 @@
#include <stdarg.h>
#include <portability.h>
#include <fcntl_portable.h>
#include <filefd_portable.h>
#define PORTABLE_TAG "open_portable"
#include <log_portable.h>
@@ -28,6 +29,7 @@
#error Bad build environment
#endif
static inline int open_flags_pton(int flags)
{
int mipsflags = flags & O_ACCMODE_PORTABLE;
@@ -67,7 +69,9 @@ static inline int open_flags_pton(int flags)
return mipsflags;
}
extern int __open(const char*, int, int);
int open_portable(const char *pathname, int flags, ...)
{
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 */
ALOGV("%s: fd = %d = __open(pathname:%p, native_flags:0x%x, mode:0x%x);", __func__,
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);
return fd;
}
extern int __openat(int, const char*, int, int);
int openat_portable(int dirfd, const char *pathname, int flags, ...)
{
mode_t mode = 0;
@@ -128,6 +140,12 @@ int openat_portable(int dirfd, const char *pathname, int flags, ...)
if (fd == -1) {
ALOGV("%s: fd = %d = __open(pathname:0x%p, native_flags:0x%x, mode:0x%d);", __func__,
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);
return fd;

View 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;
}

View File

@@ -25,6 +25,8 @@
#include <errno_portable.h>
#include <asm/unistd-portable.h>
#include <asm/unistd.h>
#include <signalfd_portable.h>
#include <filefd_portable.h>
#define PORTABLE_TAG "signal_portable"
#include <log_portable.h>
@@ -35,8 +37,21 @@
#endif
typedef void (*sig3handler_t)(int, siginfo_t *, void *);
static volatile int signal_handler_mapping_enabled = 1;
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
* 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);
}
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);
ALOGV("%s: return; }", __func__);
@@ -510,10 +529,18 @@ static sighandler_t sighandler_pton(sighandler_portable_t portable_handler, int
break;
default:
if (sigaction)
mips_handler = (sighandler_t) mips_sighandler;
else
mips_handler = (sighandler_t) mips_sigaction_handler;
/*
* Signal Mapping can be disabled in the rare case of the clone
* flags not being compatble for VM and file descriptors.
*/
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;
}
@@ -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
* 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
* 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
/*
* So far it appears that signalfd() isn't supported by bionic
* the kernel trap numbers are available.
* signalfd() isn't available in Bionic yet. When it is, it will be implemented like
* 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
/*
* 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 rv;

View File

@@ -21,6 +21,10 @@
#include <time.h>
#include <errno.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.h>
@@ -35,6 +39,12 @@
* Minimal syscall support for LTP testing.
* These are the system calls that LTP references explicitly.
* 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
#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
#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
#ifdef __NR_exit_group_portable
@@ -176,7 +222,16 @@ int syscall_portable(int portable_number, ...)
#endif
#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
#ifdef __NR_keyctl_portable
@@ -204,7 +259,18 @@ int syscall_portable(int portable_number, ...)
#endif
#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
#ifdef __NR_readahead_portable
@@ -312,7 +378,25 @@ int syscall_portable(int portable_number, ...)
#endif
#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
#ifdef __NR_socketcall_portable
@@ -423,7 +507,18 @@ int syscall_portable(int portable_number, ...)
#endif
#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
#ifdef __NR_timerfd_gettime_portable

View 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;
}

View File

@@ -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 */

View File

@@ -72,6 +72,15 @@
#define O_NDELAY_PORTABLE O_NONBLOCK_PORTABLE
#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
*/

View File

@@ -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_ */

View File

@@ -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 */

View File

@@ -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 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_mips_signum_to_name(int mips_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 (*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,
sigset_portable_t *portable_oldset, sigmask_fn 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,
siginfo_portable_t *uinfo);
/* Called by clone when memory and signal handlers aren't compatable. */
extern __hidden void signal_disable_mapping(void);
__END_DECLS
#endif /* _SIGNAL_PORTABLE_H_ */

View File

@@ -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 */

View File

@@ -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 */