[MIPS] Add Support errno, Added Logging, sorted Android.mk files.
Change-Id: Ibeeab51feb77be07ea8ccacf2f448bb5135d7373
Signed-off-by: Chris Dearman <chris@mips.com>
Signed-off-by: Pete Delaney <piet@mips.com>
diff --git a/ndk/sources/android/libportable/Android.mk b/ndk/sources/android/libportable/Android.mk
index 86b097c..3cc203a 100644
--- a/ndk/sources/android/libportable/Android.mk
+++ b/ndk/sources/android/libportable/Android.mk
@@ -30,43 +30,45 @@
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 7372c67..b862902 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 <pthread.h>
#include <errno.h>
#include <errno_portable.h>
+#define PORTABLE_TAG "errno_portable"
+#include <log_portable.h>
+
#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 @@
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 c2f6523..07b8731 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 <portability.h>
+
+/*
+ * 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 0000000..59a44f9
--- /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 <cutils/log.h>
+
+# 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 0000000..4293d9d
--- /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_ */