summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2013-07-18 00:49:01 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2013-07-18 00:49:04 +0000
commit8cb0d5d22925a6316ff1386fa13a6dbca34cfee7 (patch)
treed0c8fa919b1a107eee0f392be1ac3091bd23917c
parentccd723900c0b9504ba6263e7e9d4cdb73a234751 (diff)
parent3e7c6556c4272555ed6c5ecdbca2bf8a56df6ff5 (diff)
downloadillumos-joyent-8cb0d5d22925a6316ff1386fa13a6dbca34cfee7.tar.gz
[illumos-gate merge]
commit 3e7c6556c4272555ed6c5ecdbca2bf8a56df6ff5 3893 lvm: incorrect flag handling commit 5bc7ce93aca1e9026e3243221a9a0b1a3bc9a32e 3853 __cplusplus change and headers incompatipility with clang commit 5c069a6c4b95a7360294695998bf1d3b12473abf 3849 implement __cxa_atexit/__cxa_finalize
-rw-r--r--usr/src/head/malloc.h23
-rw-r--r--usr/src/head/unistd.h8
-rw-r--r--usr/src/lib/libc/inc/thr_uberdata.h11
-rw-r--r--usr/src/lib/libc/port/gen/atexit.c89
-rw-r--r--usr/src/lib/libc/port/mapfile-vers6
-rw-r--r--usr/src/uts/common/io/lvm/mirror/mirror.c2
6 files changed, 112 insertions, 27 deletions
diff --git a/usr/src/head/malloc.h b/usr/src/head/malloc.h
index bfb44b801e..8325420861 100644
--- a/usr/src/head/malloc.h
+++ b/usr/src/head/malloc.h
@@ -26,8 +26,6 @@
#ifndef _MALLOC_H
#define _MALLOC_H
-#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.7 */
-
#include <sys/types.h>
#ifdef __cplusplus
@@ -61,21 +59,38 @@ struct mallinfo {
#if defined(__STDC__)
+#if (!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || \
+ defined(_XPG3)
+#if __cplusplus >= 199711L
+namespace std {
+#endif
+
void *malloc(size_t);
void free(void *);
void *realloc(void *, size_t);
+void *calloc(size_t, size_t);
+
+#if __cplusplus >= 199711L
+} /* end of namespace std */
+
+using std::malloc;
+using std::free;
+using std::realloc;
+using std::calloc;
+#endif /* __cplusplus >= 199711L */
+#endif /* (!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || ... */
+
int mallopt(int, int);
struct mallinfo mallinfo(void);
-void *calloc(size_t, size_t);
#else
void *malloc();
void free();
void *realloc();
+void *calloc();
int mallopt();
struct mallinfo mallinfo();
-void *calloc();
#endif /* __STDC__ */
diff --git a/usr/src/head/unistd.h b/usr/src/head/unistd.h
index 43b34fa303..8b9de2208a 100644
--- a/usr/src/head/unistd.h
+++ b/usr/src/head/unistd.h
@@ -464,7 +464,15 @@ extern ssize_t readlink(const char *_RESTRICT_KYWD, char *_RESTRICT_KYWD,
#endif
#if (!defined(__XOPEN_OR_POSIX) || (defined(_XPG3) && !defined(_XPG4))) || \
defined(__EXTENSIONS__)
+#if __cplusplus >= 199711L
+namespace std {
+#endif
extern int rename(const char *, const char *);
+#if __cplusplus >= 199711L
+} /* end of namespace std */
+
+using std::rename;
+#endif /* __cplusplus >= 199711L */
#endif /* (!defined(__XOPEN_OR_POSIX) || (defined(_XPG3)... */
#if !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__)
extern int resolvepath(const char *, char *, size_t);
diff --git a/usr/src/lib/libc/inc/thr_uberdata.h b/usr/src/lib/libc/inc/thr_uberdata.h
index 2b8d000b29..5f67e760e2 100644
--- a/usr/src/lib/libc/inc/thr_uberdata.h
+++ b/usr/src/lib/libc/inc/thr_uberdata.h
@@ -858,16 +858,25 @@ typedef struct {
* atexit() data structures.
* See port/gen/atexit.c for details.
*/
-typedef void (*_exithdlr_func_t) (void);
+typedef void (*_exithdlr_func_t) (void*);
typedef struct _exthdlr {
struct _exthdlr *next; /* next in handler list */
_exithdlr_func_t hdlr; /* handler itself */
+ void *arg; /* argument to handler */
+ void *dso; /* DSO associated with handler */
} _exthdlr_t;
typedef struct {
mutex_t exitfns_lock;
_exthdlr_t *head;
+ /*
+ * exit_frame_monitor is part of a private contract between libc and
+ * the Sun C++ runtime.
+ *
+ * It should be NULL until exit() is called, and thereafter hold the
+ * frame pointer of the function implementing our exit processing.
+ */
void *exit_frame_monitor;
char exit_pad[64 - /* pad out to 64 bytes */
(sizeof (mutex_t) + sizeof (_exthdlr_t *) + sizeof (void *))];
diff --git a/usr/src/lib/libc/port/gen/atexit.c b/usr/src/lib/libc/port/gen/atexit.c
index fd016b5c37..32e54fae11 100644
--- a/usr/src/lib/libc/port/gen/atexit.c
+++ b/usr/src/lib/libc/port/gen/atexit.c
@@ -52,7 +52,7 @@
* See "thr_uberdata.h" for the definitions of structures used here.
*/
-static int in_range(_exithdlr_func_t, Lc_addr_range_t[], uint_t count);
+static int in_range(void *, Lc_addr_range_t[], uint_t count);
extern caddr_t _getfp(void);
@@ -88,12 +88,13 @@ atexit_unlocks()
(void) mutex_unlock(&__uberdata.atexit_root.exitfns_lock);
}
+
/*
- * atexit() is called before the primordial thread is fully set up.
+ * This is called via atexit() before the primordial thread is fully set up.
* Be careful about dereferencing self->ul_uberdata->atexit_root.
*/
int
-atexit(void (*func)(void))
+__cxa_atexit(void (*hdlr)(void *), void *arg, void *dso)
{
ulwp_t *self;
atexit_root_t *arp;
@@ -108,36 +109,71 @@ atexit(void (*func)(void))
arp = &self->ul_uberdata->atexit_root;
(void) mutex_lock(&arp->exitfns_lock);
}
- p->hdlr = func;
+ p->hdlr = hdlr;
+ p->arg = arg;
+ p->dso = dso;
p->next = arp->head;
arp->head = p;
+
if (self != NULL)
(void) mutex_unlock(&arp->exitfns_lock);
return (0);
}
+int
+atexit(void (*func)(void))
+{
+ return (__cxa_atexit((_exithdlr_func_t)func, NULL, NULL));
+}
+
+/*
+ * Note that we may be entered recursively, as we'll call __cxa_finalize(0) at
+ * exit, one of our handlers is ld.so.1`atexit_fini, and libraries may call
+ * __cxa_finalize(__dso_handle) from their _fini.
+ */
void
-_exithandle(void)
+__cxa_finalize(void *dso)
{
atexit_root_t *arp = &curthread->ul_uberdata->atexit_root;
- _exthdlr_t *p;
+ _exthdlr_t *p, *o;
int cancel_state;
/* disable cancellation while running atexit handlers */
(void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
(void) mutex_lock(&arp->exitfns_lock);
- arp->exit_frame_monitor = _getfp() + STACK_BIAS;
+
+ o = NULL;
p = arp->head;
while (p != NULL) {
- arp->head = p->next;
- p->hdlr();
- lfree(p, sizeof (_exthdlr_t));
- p = arp->head;
+ if ((dso == NULL) || (p->dso == dso)) {
+ if (o != NULL)
+ o->next = p->next;
+ else
+ arp->head = p->next;
+
+ p->hdlr(p->arg);
+ lfree(p, sizeof (_exthdlr_t));
+ o = NULL;
+ p = arp->head;
+ } else {
+ o = p;
+ p = p->next;
+ }
}
+
(void) mutex_unlock(&arp->exitfns_lock);
(void) pthread_setcancelstate(cancel_state, NULL);
}
+void
+_exithandle(void)
+{
+ atexit_root_t *arp = &curthread->ul_uberdata->atexit_root;
+
+ arp->exit_frame_monitor = _getfp() + STACK_BIAS;
+ __cxa_finalize(NULL);
+}
+
/*
* _get_exit_frame_monitor is called by the C++ runtimes.
*/
@@ -169,7 +205,7 @@ _preexec_sig_unload(Lc_addr_range_t range[], uint_t count)
again:
handler = sap->sa_handler;
if (handler != SIG_DFL && handler != SIG_IGN &&
- in_range(handler, range, count)) {
+ in_range((void *)handler, range, count)) {
rwlp = &udp->siguaction[sig].sig_lock;
lrw_wrlock(rwlp);
if (handler != sap->sa_handler) {
@@ -213,11 +249,11 @@ _preexec_atfork_unload(Lc_addr_range_t range[], uint_t count)
start_again = 0;
if (((func = atfp->prepare) != NULL &&
- in_range(func, range, count)) ||
+ in_range((void *)func, range, count)) ||
((func = atfp->parent) != NULL &&
- in_range(func, range, count)) ||
+ in_range((void *)func, range, count)) ||
((func = atfp->child) != NULL &&
- in_range(func, range, count))) {
+ in_range((void *)func, range, count))) {
if (self->ul_fork) {
/*
* dlclose() called from a fork handler.
@@ -268,7 +304,7 @@ _preexec_tsd_unload(Lc_addr_range_t range[], uint_t count)
for (key = 1; key < tsdm->tsdm_nused; key++) {
if ((func = tsdm->tsdm_destro[key]) != NULL &&
func != TSD_UNALLOCATED &&
- in_range((_exithdlr_func_t)func, range, count))
+ in_range((void *)func, range, count))
tsdm->tsdm_destro[key] = NULL;
}
lmutex_unlock(&tsdm->tsdm_lock);
@@ -296,13 +332,24 @@ _preexec_exit_handlers(Lc_addr_range_t range[], uint_t count)
o = NULL;
p = arp->head;
while (p != NULL) {
- if (in_range(p->hdlr, range, count)) {
+ /*
+ * We call even CXA handlers of functions present in the
+ * library being unloaded. The specification isn't
+ * particularly clear on this, and this seems the most sane.
+ * This is the behaviour of FreeBSD 9.1 (GNU libc leaves the
+ * handler on the exit list, and crashes at exit time).
+ *
+ * This won't cause handlers to be called twice, because
+ * anything called from a __cxa_finalize call from the
+ * language runtime will have been removed from the list.
+ */
+ if (in_range((void *)p->hdlr, range, count)) {
/* We need to execute this one */
if (o != NULL)
o->next = p->next;
else
arp->head = p->next;
- p->hdlr();
+ p->hdlr(p->arg);
lfree(p, sizeof (_exthdlr_t));
o = NULL;
p = arp->head;
@@ -322,13 +369,13 @@ _preexec_exit_handlers(Lc_addr_range_t range[], uint_t count)
}
static int
-in_range(_exithdlr_func_t addr, Lc_addr_range_t ranges[], uint_t count)
+in_range(void *addr, Lc_addr_range_t ranges[], uint_t count)
{
uint_t idx;
for (idx = 0; idx < count; idx++) {
- if ((void *)addr >= ranges[idx].lb &&
- (void *)addr < ranges[idx].ub) {
+ if (addr >= ranges[idx].lb &&
+ addr < ranges[idx].ub) {
return (1);
}
}
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index 469b73e9ca..ae0034931d 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -91,6 +91,12 @@ $if _x86 && _ELF64
$add amd64
$endif
+SYMBOL_VERSION ILLUMOS_0.5 { # common C++ ABI exit handlers
+ protected:
+ __cxa_atexit;
+ __cxa_finalize;
+} ILLUMOS_0.4;
+
SYMBOL_VERSION ILLUMOS_0.4 { # Illumos additions
protected:
pipe2;
diff --git a/usr/src/uts/common/io/lvm/mirror/mirror.c b/usr/src/uts/common/io/lvm/mirror/mirror.c
index e138fe2f64..e7893ca8c0 100644
--- a/usr/src/uts/common/io/lvm/mirror/mirror.c
+++ b/usr/src/uts/common/io/lvm/mirror/mirror.c
@@ -4015,7 +4015,7 @@ mirror_write_strategy(buf_t *pb, int flag, void *private)
* completed this resync region
*/
if ((MD_MNSET_SETNO(MD_UN2SET(un))) &&
- (!flag & MD_STR_DIRTY_RD)) {
+ (!(flag & MD_STR_DIRTY_RD))) {
if (!IN_RESYNC_REGION(un, ps))
abort_write = 1;
}