From 25cabbf92e61969cb6acdc0934fb9446c1321e04 Mon Sep 17 00:00:00 2001 From: Pete Delaney Date: Fri, 5 Oct 2012 00:23:49 -0700 Subject: [PATCH] [MIPS] Add Support errno, Added Logging, sorted Android.mk files. Change-Id: Ibeeab51feb77be07ea8ccacf2f448bb5135d7373 Signed-off-by: Chris Dearman Signed-off-by: Pete Delaney --- ndk/sources/android/libportable/Android.mk | 28 ++- .../android/libportable/arch-mips/errno.c | 237 +++++++++++++++++- .../common/include/errno_portable.h | 11 +- .../libportable/common/include/log_portable.h | 75 ++++++ .../libportable/common/include/portability.h | 48 ++++ 5 files changed, 377 insertions(+), 22 deletions(-) create mode 100644 ndk/sources/android/libportable/common/include/log_portable.h create mode 100644 ndk/sources/android/libportable/common/include/portability.h diff --git a/ndk/sources/android/libportable/Android.mk b/ndk/sources/android/libportable/Android.mk index 86b097c29..3cc203a9f 100644 --- a/ndk/sources/android/libportable/Android.mk +++ b/ndk/sources/android/libportable/Android.mk @@ -30,43 +30,45 @@ LOCAL_CFLAGS := -I $(LOCAL_PATH)/common/include ifeq ($(TARGET_ARCH),mips) libportable_arch_src_files += \ + arch-mips/errno.c \ + arch-mips/epoll.c \ + arch-mips/fcntl.c \ arch-mips/ioctl.c \ arch-mips/mmap.c \ - arch-mips/resource.c \ - arch-mips/stat.c \ - arch-mips/statfs.c \ arch-mips/open.c \ arch-mips/poll.c \ + arch-mips/resource.c \ arch-mips/socket.c \ arch-mips/sockopt.c \ - arch-mips/fcntl.c \ - arch-mips/epoll.c \ - arch-mips/errno.c + arch-mips/stat.c \ + arch-mips/statfs.c endif ifeq ($(TARGET_ARCH),arm) libportable_arch_src_files += \ - arch-arm/stat.c \ + arch-arm/epoll.c \ + arch-arm/errno.c \ arch-arm/socket.c \ arch-arm/sockopt.c \ - arch-arm/epoll.c \ - arch-arm/errno.c + arch-arm/stat.c endif ifeq ($(TARGET_ARCH),x86) libportable_arch_src_files += \ + arch-x86/epoll.c \ + arch-x86/errno.c \ + arch-x86/fcntl.c \ arch-x86/ioctl.c \ - arch-x86/stat.c \ arch-x86/open.c \ arch-x86/socket.c \ arch-x86/sockopt.c \ - arch-x86/fcntl.c \ - arch-x86/epoll.c \ - arch-x86/errno.c + arch-x86/stat.c endif LOCAL_SRC_FILES := \ $(libportable_common_src_files) \ $(libportable_arch_src_files) +LOCAL_SHARED_LIBRARIES += liblog + include $(BUILD_SHARED_LIBRARY) diff --git a/ndk/sources/android/libportable/arch-mips/errno.c b/ndk/sources/android/libportable/arch-mips/errno.c index 7372c6789..b86290221 100644 --- a/ndk/sources/android/libportable/arch-mips/errno.c +++ b/ndk/sources/android/libportable/arch-mips/errno.c @@ -14,16 +14,20 @@ * limitations under the License. */ +#include #include #include +#define PORTABLE_TAG "errno_portable" +#include + #if ENAMETOOLONG==ENAMETOOLONG_PORTABLE #error Bad build environment #endif -static inline int mips_change_errno(int mips_errno) +__hidden int ntop_errno(int native_errno) { - switch (mips_errno) { + switch (native_errno) { case ENAMETOOLONG: return ENAMETOOLONG_PORTABLE; case ENOLCK: return ENOLCK_PORTABLE; case ENOSYS: return ENOSYS_PORTABLE; @@ -121,14 +125,231 @@ static inline int mips_change_errno(int mips_errno) case EOWNERDEAD: return EOWNERDEAD_PORTABLE; case ENOTRECOVERABLE: return ENOTRECOVERABLE_PORTABLE; } - return mips_errno; + return native_errno; } -extern volatile int* __errno(void); +static inline int pton_errno(int portable_errno) +{ + switch (portable_errno) { + case ENAMETOOLONG_PORTABLE: return ENAMETOOLONG; + case ENOLCK_PORTABLE: return ENOLCK; + case ENOSYS_PORTABLE: return ENOSYS; + case ENOTEMPTY_PORTABLE: return ENOTEMPTY; + case ELOOP_PORTABLE: return ELOOP; + case EWOULDBLOCK_PORTABLE: return EWOULDBLOCK; + case ENOMSG_PORTABLE: return ENOMSG; + case EIDRM_PORTABLE: return EIDRM; + case ECHRNG_PORTABLE: return ECHRNG; + case EL2NSYNC_PORTABLE: return EL2NSYNC; + case EL3HLT_PORTABLE: return EL3HLT; + case EL3RST_PORTABLE: return EL3RST; + case ELNRNG_PORTABLE: return ELNRNG; + case EUNATCH_PORTABLE: return EUNATCH; + case ENOCSI_PORTABLE: return ENOCSI; + case EL2HLT_PORTABLE: return EL2HLT; + case EBADE_PORTABLE: return EBADE; + case EBADR_PORTABLE: return EBADR; + case EXFULL_PORTABLE: return EXFULL; + case ENOANO_PORTABLE: return ENOANO; + case EBADRQC_PORTABLE: return EBADRQC; + case EBADSLT_PORTABLE: return EBADSLT; + case EDEADLOCK_PORTABLE: return EDEADLOCK; + case EBFONT_PORTABLE: return EBFONT; + case ENOSTR_PORTABLE: return ENOSTR; + case ENODATA_PORTABLE: return ENODATA; + case ETIME_PORTABLE: return ETIME; + case ENOSR_PORTABLE: return ENOSR; + case ENONET_PORTABLE: return ENONET; + case ENOPKG_PORTABLE: return ENOPKG; + case EREMOTE_PORTABLE: return EREMOTE; + case ENOLINK_PORTABLE: return ENOLINK; + case EADV_PORTABLE: return EADV; + case ESRMNT_PORTABLE: return ESRMNT; + case ECOMM_PORTABLE: return ECOMM; + case EPROTO_PORTABLE: return EPROTO; + case EMULTIHOP_PORTABLE: return EMULTIHOP; + case EDOTDOT_PORTABLE: return EDOTDOT; + case EBADMSG_PORTABLE: return EBADMSG; + case EOVERFLOW_PORTABLE: return EOVERFLOW; + case ENOTUNIQ_PORTABLE: return ENOTUNIQ; + case EBADFD_PORTABLE: return EBADFD; + case EREMCHG_PORTABLE: return EREMCHG; + case ELIBACC_PORTABLE: return ELIBACC; + case ELIBBAD_PORTABLE: return ELIBBAD; + case ELIBSCN_PORTABLE: return ELIBSCN; + case ELIBMAX_PORTABLE: return ELIBMAX; + case ELIBEXEC_PORTABLE: return ELIBEXEC; + case EILSEQ_PORTABLE: return EILSEQ; + case ERESTART_PORTABLE: return ERESTART; + case ESTRPIPE_PORTABLE: return ESTRPIPE; + case EUSERS_PORTABLE: return EUSERS; + case ENOTSOCK_PORTABLE: return ENOTSOCK; + case EDESTADDRREQ_PORTABLE: return EDESTADDRREQ; + case EMSGSIZE_PORTABLE: return EMSGSIZE; + case EPROTOTYPE_PORTABLE: return EPROTOTYPE; + case ENOPROTOOPT_PORTABLE: return ENOPROTOOPT; + case EPROTONOSUPPORT_PORTABLE: return EPROTONOSUPPORT; + case ESOCKTNOSUPPORT_PORTABLE: return ESOCKTNOSUPPORT; + case EOPNOTSUPP_PORTABLE: return EOPNOTSUPP; + case EPFNOSUPPORT_PORTABLE: return EPFNOSUPPORT; + case EAFNOSUPPORT_PORTABLE: return EAFNOSUPPORT; + case EADDRINUSE_PORTABLE: return EADDRINUSE; + case EADDRNOTAVAIL_PORTABLE: return EADDRNOTAVAIL; + case ENETDOWN_PORTABLE: return ENETDOWN; + case ENETUNREACH_PORTABLE: return ENETUNREACH; + case ENETRESET_PORTABLE: return ENETRESET; + case ECONNABORTED_PORTABLE: return ECONNABORTED; + case ECONNRESET_PORTABLE: return ECONNRESET; + case ENOBUFS_PORTABLE: return ENOBUFS; + case EISCONN_PORTABLE: return EISCONN; + case ENOTCONN_PORTABLE: return ENOTCONN; + case ESHUTDOWN_PORTABLE: return ESHUTDOWN; + case ETOOMANYREFS_PORTABLE: return ETOOMANYREFS; + case ETIMEDOUT_PORTABLE: return ETIMEDOUT; + case ECONNREFUSED_PORTABLE: return ECONNREFUSED; + case EHOSTDOWN_PORTABLE: return EHOSTDOWN; + case EHOSTUNREACH_PORTABLE: return EHOSTUNREACH; + case EALREADY_PORTABLE: return EALREADY; + case EINPROGRESS_PORTABLE: return EINPROGRESS; + case ESTALE_PORTABLE: return ESTALE; + case EUCLEAN_PORTABLE: return EUCLEAN; + case ENOTNAM_PORTABLE: return ENOTNAM; + case ENAVAIL_PORTABLE: return ENAVAIL; + case EISNAM_PORTABLE: return EISNAM; + case EREMOTEIO_PORTABLE: return EREMOTEIO; + case EDQUOT_PORTABLE: return EDQUOT; + case ENOMEDIUM_PORTABLE: return ENOMEDIUM; + case EMEDIUMTYPE_PORTABLE: return EMEDIUMTYPE; + case ECANCELED_PORTABLE: return ECANCELED; + case ENOKEY_PORTABLE: return ENOKEY; + case EKEYEXPIRED_PORTABLE: return EKEYEXPIRED; + case EKEYREVOKED_PORTABLE: return EKEYREVOKED; + case EKEYREJECTED_PORTABLE: return EKEYREJECTED; + case EOWNERDEAD_PORTABLE: return EOWNERDEAD; + case ENOTRECOVERABLE_PORTABLE: return ENOTRECOVERABLE; + } + return portable_errno; +} + +/* Key for the thread-specific portable errno */ +static pthread_key_t errno_key; + +/* Once-only initialisation of the key */ +static pthread_once_t errno_key_once = PTHREAD_ONCE_INIT; + +/* Free the thread-specific portable errno */ +static void errno_key_destroy(void *buf) +{ + if (buf) + free(buf); +} + +/* Allocate the key */ +static void errno_key_create(void) +{ + pthread_key_create(&errno_key, errno_key_destroy); +} + +struct errno_state { + int pshadow; /* copy of last portable errno */ + int perrno; /* portable errno that may be modified by app */ +}; + +/* Return the thread-specific portable errno */ +static struct errno_state *errno_key_data(void) +{ + struct errno_state *data; + static struct errno_state errno_state; + + pthread_once(&errno_key_once, errno_key_create); + data = (struct errno_state *)pthread_getspecific(errno_key); + if (data == NULL) { + data = malloc(sizeof(struct errno_state)); + pthread_setspecific(errno_key, data); + } + if (data == NULL) + data = &errno_state; + return data; +} + +/* + * Attempt to return a thread specific location containnig the portable errno. + * This can be assigned to without affecting the native errno. If the key + * allocation fails fall back to using the native errno location. + */ volatile int* __errno_portable() { - /* Note that writing to static_errno will not affect the underlying system. */ - static int static_errno; - static_errno = mips_change_errno(*__errno()); - return &static_errno; + struct errno_state *p; + int save_errno; + + /* pthread_* calls may modify errno so use a copy */ + save_errno = errno; + + p = errno_key_data(); + + ALOGV("%s(): { save_errno:%d p=%p->{pshadow:%d perrno:%d}", __func__, + save_errno, p, p->pshadow,p->perrno); + + if (save_errno == 0 && p->pshadow != p->perrno) { + /* + * portable errno has changed but native hasn't + * - copy portable error back to native + */ + p->pshadow = p->perrno; + save_errno = pton_errno(p->perrno); + } + else if (save_errno != 0 && p->pshadow == p->perrno) { + /* + * native errno has changed but portable hasn't + * - copy native error to portable + */ + p->pshadow = p->perrno = ntop_errno(save_errno); + save_errno = 0; + } + else if (save_errno != 0 && p->pshadow != p->perrno) { + /* + * both native and portable errno values have changed + * so give priority to native errno + * - copy native error to portable + */ + p->pshadow = p->perrno = ntop_errno(save_errno); + save_errno = 0; + } + + ALOGV("%s: new save_errno=%d p=%p->{pshadow=%d perrno=%d}", __func__, + save_errno, p, p->pshadow,p->perrno); + + errno = save_errno; + + ALOGV("%s: return &p->perrno:%p; }", __func__, &p->perrno); + + /* return pointer to the modifiable portable errno value */ + return &p->perrno; +} + + +/* set portable errno */ +void __set_errno_portable(int portable_errno) +{ + struct errno_state *p; + int save_errno; + + /* pthread_* calls may modify errno so use a copy */ + save_errno = errno; + + p = errno_key_data(); + + ALOGV("%s(): { save_errno:%d p=%p->{pshadow:%d perrno:%d}", __func__, + save_errno, p, p->pshadow,p->perrno); + + p->pshadow = p->perrno = portable_errno; + + save_errno = pton_errno(portable_errno); + + ALOGV("%s: new save_errno=%d p=%p->{pshadow=%d perrno=%d}", __func__, + save_errno, p, p->pshadow,p->perrno); + + errno = save_errno; + + ALOGV("%s: return; }", __func__); } diff --git a/ndk/sources/android/libportable/common/include/errno_portable.h b/ndk/sources/android/libportable/common/include/errno_portable.h index c2f6523c2..07b87318f 100644 --- a/ndk/sources/android/libportable/common/include/errno_portable.h +++ b/ndk/sources/android/libportable/common/include/errno_portable.h @@ -17,7 +17,14 @@ #ifndef _ERRNO_PORTABLE_H_ #define _ERRNO_PORTABLE_H_ -/* Derived from development/ndk/platforms/android-3/include/asm-generic/errno.h */ +#include + +/* + * Derived from development/ndk/platforms/android-3/include/asm-generic/errno.h + * NOTE: + * Base errno #defines from 1...35 are ARCH independent and not defined; + * they are defined in ./asm-generic/errno-base.h + */ #define EDEADLK_PORTABLE 35 #define ENAMETOOLONG_PORTABLE 36 #define ENOLCK_PORTABLE 37 @@ -120,4 +127,6 @@ #define EOWNERDEAD_PORTABLE 130 #define ENOTRECOVERABLE_PORTABLE 131 +extern __hidden int ntop_errno(int native_errno); + #endif /* _ERRNO_PORTABLE_H */ diff --git a/ndk/sources/android/libportable/common/include/log_portable.h b/ndk/sources/android/libportable/common/include/log_portable.h new file mode 100644 index 000000000..59a44f9cd --- /dev/null +++ b/ndk/sources/android/libportable/common/include/log_portable.h @@ -0,0 +1,75 @@ +/* + * ALOG Levels: F - Fatal, E - Error, W - Warning, I - Info, D - Debug, V - Verbose + * + * Using them to work within the Android logcat logging mechanism: + * + * % logcat '*:v' [To display Verbose Logging] + * % logcat 'fcntl_portable:v' [To display just this fcntl logging] + * + * NOTE: This assumes you only use the portable TAG; which is the default. + * For debugging LTP it's been helpful to include the LTP program being tested. + * + * Logging routines also support ALOG*_IF() and ASSERT(); For details See: + * + * ${ANDROID_TOP}/system/core/include/cutils/log.h + * and + * http://developer.android.com/tools/debugging/debugging-log.html + * + * ALOGV is turned off by release builds: Use the #define below with LOG_NDEBUG=0 to enable. + * + * Strace works fine with ALOG out if a large max string size is used via the -s option; Ex: + * + * strace -s 132 ./sigaction01 + * + * writev(3, [{"\2", 1}, + * {"./sigaction01`signal_portable\0", 30}, + * {"sigaction_portable(portable_signum:10:'SIGUSR1_PORTABLE:10', act:0x7fe47a08, oldact:0x0) {\0", 91}], 3) = 122 + * {"map_portable_sigset_to_mips(portable_sigset:0x7fe47a0c, mips_sigset:0x7fe479b8) {\0", 82}], 3) = 113 + * ... + */ + +/* + * Remove the // below to have debug code visible in logcat output by default. + * It's Also possible via libportable/Android.mk: + * LOCAL_CFLAGS += -DLOG_NDEBUG=0 + */ +// # define LOG_NDEBUG 0 + + + +// #define EXTENDED_LOGGING +#ifdef EXTENDED_LOGGING +/* + * Inline function to put the current LTP program and this library into the logcat prefix; Ex: + * + * V/./sigaction01`signal_portable(605): sigaction_portable(portable_signum:10:'SIGUSR1_PORTABLE:10', act:0x7fe47a08, oldact:0x0) { + * ----------------------------- + * + * Disabled by default, enable by removing the // above. Useful when debugging more than one program; Ex: LTP has thousands. + */ +#define MAX_TAG_LEN 128 +static char my_portable_tag[MAX_TAG_LEN + 1]; + +static inline char *portable_tag() { + extern char *__progname; + + if (my_portable_tag[0] == '\000') { + + strncat(&my_portable_tag[0], __progname, MAX_TAG_LEN); + strncat(&my_portable_tag[0], ".", MAX_TAG_LEN - strlen(my_portable_tag)); + strncat(&my_portable_tag[0], PORTABLE_TAG, MAX_TAG_LEN - strlen(my_portable_tag)); + } + return(my_portable_tag); +} +#define LOG_TAG portable_tag() +#else /* !EXTENDED_LOGGING */ +#define LOG_TAG PORTABLE_TAG +#endif + +# include + +# define PERROR(str) { ALOGE("%s: PERROR('%s'): errno:%d:'%s'", __func__, str, errno, strerror(errno)); } + +# define ASSERT(cond) ALOG_ASSERT(cond, "assertion failed:(%s), file: %s, line: %d:%s", \ + #cond, __FILE__, __LINE__, __func__); + diff --git a/ndk/sources/android/libportable/common/include/portability.h b/ndk/sources/android/libportable/common/include/portability.h new file mode 100644 index 000000000..4293d9d54 --- /dev/null +++ b/ndk/sources/android/libportable/common/include/portability.h @@ -0,0 +1,48 @@ +/* + * 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 _PORTABILITY_H_ +#define _PORTABILITY_H_ + +/* + * Common portability helper routines + */ + +/* + * Check a portable pointer before we access it + * Well behaved programs should not be passing bad pointers + * to the kernel but this routine can be used to check a pointer + * if we need to use it before calling the kernel + * + * It does not catch every possible case but it is sufficient for LTP + */ +inline static int invalid_pointer(void *p) +{ + return p == NULL + || p == (void *)-1 +#ifdef __mips__ + || (int)p < 0 +#endif + ; +} + +/* + * Hidden functions are exposed while linking the libportable shared object + * but are not exposed thereafter. + */ +#define __hidden __attribute__((visibility("hidden"))) + +#endif /* _PORTABILITY_H_ */