summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_brand.c4
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_misc.c92
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_pid.c41
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_ptrace.c1
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_brand.h25
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_misc.h5
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_pid.h61
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_futex.c1
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_getpid.c1
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_kill.c1
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_sched.c1
-rw-r--r--usr/src/uts/common/brand/sn1/sn1_brand.c13
-rw-r--r--usr/src/uts/common/brand/sngl/sngl_brand.c13
-rw-r--r--usr/src/uts/common/brand/solaris10/s10_brand.c13
-rw-r--r--usr/src/uts/common/os/brand.c9
-rw-r--r--usr/src/uts/common/os/exec.c13
-rw-r--r--usr/src/uts/common/os/lwp.c45
-rw-r--r--usr/src/uts/common/sys/brand.h13
-rw-r--r--usr/src/uts/common/sys/proc.h1
19 files changed, 188 insertions, 165 deletions
diff --git a/usr/src/uts/common/brand/lx/os/lx_brand.c b/usr/src/uts/common/brand/lx/os/lx_brand.c
index c7d6e93edb..2be3082d48 100644
--- a/usr/src/uts/common/brand/lx/os/lx_brand.c
+++ b/usr/src/uts/common/brand/lx/os/lx_brand.c
@@ -147,7 +147,6 @@
#include <sys/machbrand.h>
#include <sys/lx_syscalls.h>
#include <sys/lx_misc.h>
-#include <sys/lx_pid.h>
#include <sys/lx_futex.h>
#include <sys/lx_brand.h>
#include <sys/param.h>
@@ -244,7 +243,8 @@ struct brand_ops lx_brops = {
lx_proc_exit, /* b_proc_exit */
lx_exec, /* b_exec */
lx_setrval, /* b_lwp_setrval */
- lx_brandlwp, /* b_brandlwp */
+ lx_lwpdata_alloc, /* b_lwpdata_alloc */
+ lx_lwpdata_free, /* b_lwpdata_free */
lx_initlwp, /* b_initlwp */
lx_forklwp, /* b_forklwp */
lx_freelwp, /* b_freelwp */
diff --git a/usr/src/uts/common/brand/lx/os/lx_misc.c b/usr/src/uts/common/brand/lx/os/lx_misc.c
index 8b089af0a9..5d9577f453 100644
--- a/usr/src/uts/common/brand/lx/os/lx_misc.c
+++ b/usr/src/uts/common/brand/lx/os/lx_misc.c
@@ -37,7 +37,6 @@
#include <sys/brand.h>
#include <sys/lx_brand.h>
#include <sys/lx_misc.h>
-#include <sys/lx_pid.h>
#include <sys/lx_futex.h>
#include <sys/cmn_err.h>
#include <sys/siginfo.h>
@@ -256,16 +255,68 @@ lx_freelwp(klwp_t *lwp)
kmem_free(lwpd, sizeof (struct lx_lwp_data));
}
-int
-lx_brandlwp(klwp_t *lwp)
+void *
+lx_lwpdata_alloc(proc_t *p)
{
lx_lwp_data_t *lwpd;
+ struct lx_pid *lpidp;
+ pid_t newpid = 0;
+ struct pid *pidp = NULL;
+
+ VERIFY(MUTEX_NOT_HELD(&p->p_lock));
+
+ /*
+ * LWPs beyond the first will require a pid to be allocated to emulate
+ * Linux's goofy thread model. While this allocation may be
+ * unnecessary when a single-lwp process undergoes branding, it cannot
+ * be performed during b_initlwp due to p_lock being held.
+ */
+ if (p->p_lwpcnt > 0) {
+ if ((newpid = pid_allocate(p, 0, 0)) < 0) {
+ return (NULL);
+ }
+ pidp = pid_find(newpid);
+ }
+
+ lwpd = kmem_zalloc(sizeof (struct lx_lwp_data), KM_SLEEP);
+ lpidp = kmem_zalloc(sizeof (struct lx_pid), KM_SLEEP);
+
+ lpidp->l_pid = newpid;
+ lpidp->l_pidp = pidp;
+ lwpd->br_lpid = lpidp;
+ return (lwpd);
+}
+
+/*
+ * Free lwp brand data if an error occurred during lwp_create.
+ * Otherwise, lx_freelwp will be used to free the resources after they're
+ * associated with the lwp via lx_initlwp.
+ */
+void
+lx_lwpdata_free(void *lwpbd)
+{
+ lx_lwp_data_t *lwpd = (lx_lwp_data_t *)lwpbd;
+ VERIFY(lwpd != NULL);
+ VERIFY(lwpd->br_lpid != NULL);
+
+ if (lwpd->br_lpid->l_pidp != NULL) {
+ (void) pid_rele(lwpd->br_lpid->l_pidp);
+ }
+ kmem_free(lwpd->br_lpid, sizeof (*lwpd->br_lpid));
+ kmem_free(lwpd, sizeof (*lwpd));
+}
+
+void
+lx_initlwp(klwp_t *lwp, void *lwpbd)
+{
+ lx_lwp_data_t *lwpd = (lx_lwp_data_t *)lwpbd;
lx_lwp_data_t *plwpd = ttolxlwp(curthread);
kthread_t *tp = lwptot(lwp);
+ proc_t *p = lwptoproc(lwp);
+ VERIFY(MUTEX_HELD(&p->p_lock));
VERIFY(lwp->lwp_brand == NULL);
- lwpd = kmem_zalloc(sizeof (struct lx_lwp_data), KM_SLEEP);
lwpd->br_exitwhy = CLD_EXITED;
lwpd->br_lwp = lwp;
lwpd->br_clear_ctidp = NULL;
@@ -302,12 +353,28 @@ lx_brandlwp(klwp_t *lwp)
}
lwp->lwp_brand = lwpd;
- if (lx_pid_assign(tp)) {
- kmem_free(lwpd, sizeof (struct lx_lwp_data));
- lwp->lwp_brand = NULL;
- return (-1);
- }
+ /*
+ * When during lx_lwpdata_alloc, we must decide whether or not to
+ * allocate a new pid to associate with the lwp. Since p_lock is not
+ * held at that point, the only time we can guarantee a new pid isn't
+ * needed is when p_lwpcnt == 0. This is because other lwps won't be
+ * present to race with us with regards to pid allocation.
+ *
+ * This means that in all other cases (where p_lwpcnt > 0), we expect
+ * that lx_lwpdata_alloc will allocate a pid for us to use here, even
+ * if it is uneeded. If this process is undergoing an exec, for
+ * example, the single existing lwp will not need a new pid when it is
+ * rebranded. In that case, lx_pid_assign will free the uneeded pid.
+ */
+ VERIFY(lwpd->br_lpid->l_pidp != NULL || p->p_lwpcnt == 0);
+
+ lx_pid_assign(tp, lwpd->br_lpid);
lwpd->br_tgid = lwpd->br_pid;
+ /*
+ * Having performed the lx pid assignement, the lpid reference is no
+ * longer needed. The underlying data will be freed during lx_freelwp.
+ */
+ lwpd->br_lpid = NULL;
installctx(lwptot(lwp), lwp, lx_save, lx_restore, NULL, NULL,
lx_save, NULL);
@@ -316,14 +383,7 @@ lx_brandlwp(klwp_t *lwp)
* Install branded system call hook for this LWP:
*/
lwp->lwp_brand_syscall = lx_syscall_enter;
- return (0);
-}
-void
-lx_initlwp(klwp_t *lwp)
-{
- lx_lwp_data_t *lwpd = lwptolxlwp(lwp);
- lx_lwp_data_t *plwpd = ttolxlwp(curthread);
/*
* If the parent LWP has a ptrace(2) tracer, the new LWP may
* need to inherit that same tracer.
diff --git a/usr/src/uts/common/brand/lx/os/lx_pid.c b/usr/src/uts/common/brand/lx/os/lx_pid.c
index 8552754c43..40179bbdaf 100644
--- a/usr/src/uts/common/brand/lx/os/lx_pid.c
+++ b/usr/src/uts/common/brand/lx/os/lx_pid.c
@@ -35,7 +35,6 @@
#include <sys/brand.h>
#include <sys/zone.h>
#include <sys/lx_brand.h>
-#include <sys/lx_pid.h>
#define LINUX_PROC_FACTOR 8 /* factor down the hash table by this */
static int hash_len = 4; /* desired average hash chain length */
@@ -101,47 +100,45 @@ lx_pid_remove_hash(pid_t pid, id_t tid)
return (lpidp);
}
-struct pid *pid_find(pid_t pid);
-
/*
* given a solaris pid/tid pair, create a linux pid
*/
-int
-lx_pid_assign(kthread_t *t)
+void
+lx_pid_assign(kthread_t *t, struct lx_pid *lpidp)
{
proc_t *p = ttoproc(t);
+ lx_lwp_data_t *lwpd = ttolxlwp(t);
pid_t s_pid = p->p_pid;
id_t s_tid = t->t_tid;
- struct pid *pidp;
- struct lx_pid *lpidp;
- lx_lwp_data_t *lwpd = ttolxlwp(t);
- pid_t newpid;
/*
* When lx_initlwp is called from lx_setbrand, p_lwpcnt will already be
* equal to 1. Since lx_initlwp is being called against an lwp that
- * already exists, pid_allocate is not necessary.
+ * already exists, an additional pid allocation is not necessary.
*
* We check for this by testing br_ppid == 0.
*/
if (p->p_lwpcnt > 0 && lwpd->br_ppid != 0) {
/*
- * Allocate a pid for any thread other than the first
+ * Assign allocated pid to any thread other than the first.
+ * The l_pid and l_pidp fields should be populated.
*/
- if ((newpid = pid_allocate(p, 0, 0)) < 0)
- return (-1);
-
- pidp = pid_find(newpid);
+ VERIFY(lpidp->l_pidp != NULL);
+ VERIFY(lpidp->l_pid != 0);
} else {
- pidp = NULL;
- newpid = s_pid;
+ /*
+ * There are cases where a pid is speculatively allocated but
+ * is not needed. We are obligated to free it here.
+ */
+ if (lpidp->l_pidp != NULL) {
+ (void) pid_rele(lpidp->l_pidp);
+ }
+ lpidp->l_pidp = NULL;
+ lpidp->l_pid = s_pid;
}
- lpidp = kmem_alloc(sizeof (struct lx_pid), KM_SLEEP);
- lpidp->l_pid = newpid;
lpidp->s_pid = s_pid;
lpidp->s_tid = s_tid;
- lpidp->l_pidp = pidp;
lpidp->l_start = t->t_start;
/*
@@ -152,9 +149,7 @@ lx_pid_assign(kthread_t *t)
lx_pid_insert_hash(lpidp);
mutex_exit(&hash_lock);
- lwpd->br_pid = newpid;
-
- return (0);
+ lwpd->br_pid = lpidp->l_pid;
}
/*
diff --git a/usr/src/uts/common/brand/lx/os/lx_ptrace.c b/usr/src/uts/common/brand/lx/os/lx_ptrace.c
index e64b5daf76..95df7b2d53 100644
--- a/usr/src/uts/common/brand/lx/os/lx_ptrace.c
+++ b/usr/src/uts/common/brand/lx/os/lx_ptrace.c
@@ -207,7 +207,6 @@
#include <sys/lx_brand.h>
#include <sys/lx_impl.h>
#include <sys/lx_misc.h>
-#include <sys/lx_pid.h>
#include <lx_syscall.h>
#include <lx_signum.h>
diff --git a/usr/src/uts/common/brand/lx/sys/lx_brand.h b/usr/src/uts/common/brand/lx/sys/lx_brand.h
index d384c09033..8bd351b635 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_brand.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_brand.h
@@ -24,7 +24,7 @@
*/
/*
- * Copyright 2015 Joyent, Inc. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
*/
#ifndef _LX_BRAND_H
@@ -499,6 +499,16 @@ typedef enum lx_stack_mode {
LX_STACK_MODE_BRAND
} lx_stack_mode_t;
+struct lx_pid {
+ pid_t s_pid; /* the SunOS pid and ... */
+ id_t s_tid; /* ... tid pair */
+ pid_t l_pid; /* the corresponding linux pid */
+ time_t l_start; /* birthday of this pid */
+ struct pid *l_pidp;
+ struct lx_pid *stol_next; /* link in stol hash table */
+ struct lx_pid *ltos_next; /* link in ltos hash table */
+};
+
/*
* lx-specific data in the klwp_t
*/
@@ -578,6 +588,11 @@ struct lx_lwp_data {
* usermode.
*/
boolean_t br_strict_failure;
+
+ /*
+ * Hold a pre-allocated lx_pid structure to be used during lx_initlwp.
+ */
+ struct lx_pid *br_lpid;
};
/*
@@ -646,6 +661,14 @@ extern void lx_emulate_user32(klwp_t *, int, uintptr_t *);
extern int lx_debug;
#define lx_print if (lx_debug) printf
+extern void lx_pid_assign(kthread_t *, struct lx_pid *);
+extern void lx_pid_reassign(kthread_t *);
+extern void lx_pid_rele(pid_t, id_t);
+extern pid_t lx_lpid_to_spair(pid_t, pid_t *, id_t *);
+extern pid_t lx_lwp_ppid(klwp_t *, pid_t *, id_t *);
+extern void lx_pid_init(void);
+extern void lx_pid_fini(void);
+
/*
* In-Kernel Linux System Call Description.
*/
diff --git a/usr/src/uts/common/brand/lx/sys/lx_misc.h b/usr/src/uts/common/brand/lx/sys/lx_misc.h
index 892b2bd00d..949cbd8f86 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_misc.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_misc.h
@@ -28,8 +28,9 @@ extern void lx_setrval(klwp_t *, int, int);
extern void lx_exec();
extern void lx_exitlwp(klwp_t *);
extern void lx_freelwp(klwp_t *);
-extern int lx_brandlwp(klwp_t *);
-extern void lx_initlwp(klwp_t *);
+extern void *lx_lwpdata_alloc(proc_t *);
+extern void lx_lwpdata_free(void *);
+extern void lx_initlwp(klwp_t *, void *);
extern void lx_forklwp(klwp_t *, klwp_t *);
extern void lx_set_gdt(int, user_desc_t *);
diff --git a/usr/src/uts/common/brand/lx/sys/lx_pid.h b/usr/src/uts/common/brand/lx/sys/lx_pid.h
deleted file mode 100644
index 80c8079f0b..0000000000
--- a/usr/src/uts/common/brand/lx/sys/lx_pid.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_LX_PID_H
-#define _SYS_LX_PID_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/note.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef _KERNEL
-struct lx_pid {
- pid_t s_pid; /* the solaris pid and ... */
- id_t s_tid; /* ... tid pair */
- pid_t l_pid; /* the corresponding linux pid */
- time_t l_start; /* birthday of this pid */
- struct pid *l_pidp;
- struct lx_pid *stol_next; /* link in stol hash table */
- struct lx_pid *ltos_next; /* link in ltos hash table */
-};
-
-extern int lx_pid_assign(kthread_t *);
-extern void lx_pid_reassign(kthread_t *);
-extern void lx_pid_rele(pid_t, id_t);
-extern pid_t lx_lpid_to_spair(pid_t, pid_t *, id_t *);
-extern pid_t lx_lwp_ppid(klwp_t *, pid_t *, id_t *);
-extern void lx_pid_init(void);
-extern void lx_pid_fini(void);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_LX_PID_H */
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_futex.c b/usr/src/uts/common/brand/lx/syscall/lx_futex.c
index 519f9bbf4d..f6a8f33f46 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_futex.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_futex.c
@@ -45,7 +45,6 @@
#include <sys/lx_brand.h>
#include <sys/lx_futex.h>
#include <sys/lx_impl.h>
-#include <sys/lx_pid.h>
/*
* Futexes are a Linux-specific implementation of inter-process mutexes.
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_getpid.c b/usr/src/uts/common/brand/lx/syscall/lx_getpid.c
index 88b1792d3c..c2506f52c5 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_getpid.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_getpid.c
@@ -33,7 +33,6 @@
#include <sys/cpuvar.h>
#include <sys/brand.h>
#include <sys/lx_brand.h>
-#include <sys/lx_pid.h>
/*
* return the pid
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_kill.c b/usr/src/uts/common/brand/lx/syscall/lx_kill.c
index a4f04376e2..f6830f5a07 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_kill.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_kill.c
@@ -36,7 +36,6 @@
#include <sys/signal.h>
#include <sys/brand.h>
#include <sys/lx_brand.h>
-#include <sys/lx_pid.h>
#include <lx_signum.h>
#include <sys/contract/process_impl.h>
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_sched.c b/usr/src/uts/common/brand/lx/syscall/lx_sched.c
index 4ebb7ff387..0def559e29 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_sched.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_sched.c
@@ -35,7 +35,6 @@
#include <sys/tspriocntl.h>
#include <sys/processor.h>
#include <sys/brand.h>
-#include <sys/lx_pid.h>
#include <sys/lx_sched.h>
#include <sys/lx_brand.h>
diff --git a/usr/src/uts/common/brand/sn1/sn1_brand.c b/usr/src/uts/common/brand/sn1/sn1_brand.c
index ff11c58ae5..176044f68d 100644
--- a/usr/src/uts/common/brand/sn1/sn1_brand.c
+++ b/usr/src/uts/common/brand/sn1/sn1_brand.c
@@ -53,7 +53,7 @@ int sn1_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
void sn1_copy_procdata(proc_t *, proc_t *);
void sn1_proc_exit(struct proc *);
void sn1_exec();
-int sn1_brandlwp(klwp_t *);
+void sn1_initlwp(klwp_t *, void *);
void sn1_forklwp(klwp_t *, klwp_t *);
void sn1_freelwp(klwp_t *);
void sn1_lwpexit(klwp_t *);
@@ -72,8 +72,9 @@ struct brand_ops sn1_brops = {
sn1_proc_exit, /* b_proc_exit */
sn1_exec, /* b_exec */
lwp_setrval, /* b_lwp_setrval */
- sn1_brandlwp, /* b_brandlwp */
- NULL, /* b_initlwp */
+ NULL, /* b_lwpdata_alloc */
+ NULL, /* b_lwpdata_free */
+ sn1_initlwp, /* b_initlwp */
sn1_forklwp, /* b_forklwp */
sn1_freelwp, /* b_freelwp */
sn1_lwpexit, /* b_lwpexit */
@@ -210,10 +211,10 @@ sn1_exec()
brand_solaris_exec(&sn1_brand);
}
-int
-sn1_brandlwp(klwp_t *l)
+void
+sn1_initlwp(klwp_t *l, void *bd)
{
- return (brand_solaris_brandlwp(l, &sn1_brand));
+ brand_solaris_initlwp(l, &sn1_brand);
}
void
diff --git a/usr/src/uts/common/brand/sngl/sngl_brand.c b/usr/src/uts/common/brand/sngl/sngl_brand.c
index 9a1d76d157..3d4da3c441 100644
--- a/usr/src/uts/common/brand/sngl/sngl_brand.c
+++ b/usr/src/uts/common/brand/sngl/sngl_brand.c
@@ -54,7 +54,7 @@ int sngl_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
void sngl_copy_procdata(proc_t *, proc_t *);
void sngl_proc_exit(struct proc *);
void sngl_exec();
-int sngl_brandlwp(klwp_t *);
+void sngl_initlwp(klwp_t *, void *);
void sngl_forklwp(klwp_t *, klwp_t *);
void sngl_freelwp(klwp_t *);
void sngl_lwpexit(klwp_t *);
@@ -73,8 +73,9 @@ struct brand_ops sngl_brops = {
sngl_proc_exit, /* b_proc_exit */
sngl_exec, /* b_exec */
lwp_setrval, /* b_lwp_setrval */
- sngl_brandlwp, /* b_brandlwp */
- NULL, /* b_initlwp */
+ NULL, /* b_lwpdata_alloc */
+ NULL, /* b_lwpdata_free */
+ sngl_initlwp, /* b_initlwp */
sngl_forklwp, /* b_forklwp */
sngl_freelwp, /* b_freelwp */
sngl_lwpexit, /* b_lwpexit */
@@ -196,10 +197,10 @@ sngl_exec()
brand_solaris_exec(&sngl_brand);
}
-int
-sngl_brandlwp(klwp_t *l)
+void
+sngl_initlwp(klwp_t *l, void *bd)
{
- return (brand_solaris_brandlwp(l, &sngl_brand));
+ brand_solaris_initlwp(l, &sngl_brand);
}
void
diff --git a/usr/src/uts/common/brand/solaris10/s10_brand.c b/usr/src/uts/common/brand/solaris10/s10_brand.c
index 1239dcc323..1dc2671386 100644
--- a/usr/src/uts/common/brand/solaris10/s10_brand.c
+++ b/usr/src/uts/common/brand/solaris10/s10_brand.c
@@ -56,7 +56,7 @@ int s10_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
void s10_copy_procdata(proc_t *, proc_t *);
void s10_proc_exit(struct proc *);
void s10_exec();
-int s10_brandlwp(klwp_t *);
+void s10_initlwp(klwp_t *, void *);
void s10_forklwp(klwp_t *, klwp_t *);
void s10_freelwp(klwp_t *);
void s10_lwpexit(klwp_t *);
@@ -77,8 +77,9 @@ struct brand_ops s10_brops = {
s10_proc_exit, /* b_proc_exit */
s10_exec, /* b_exec */
lwp_setrval, /* b_lwp_setrval */
- s10_brandlwp, /* b_brandlwp */
- NULL, /* b_initlwp */
+ NULL, /* b_lwpdata_alloc */
+ NULL, /* b_lwpdata_free */
+ s10_initlwp, /* b_initlwp */
s10_forklwp, /* b_forklwp */
s10_freelwp, /* b_freelwp */
s10_lwpexit, /* b_lwpexit */
@@ -365,10 +366,10 @@ s10_exec()
brand_solaris_exec(&s10_brand);
}
-int
-s10_brandlwp(klwp_t *l)
+void
+s10_initlwp(klwp_t *l, void *bd)
{
- return (brand_solaris_brandlwp(l, &s10_brand));
+ brand_solaris_initlwp(l, &s10_brand);
}
void
diff --git a/usr/src/uts/common/os/brand.c b/usr/src/uts/common/os/brand.c
index 61aa562f73..00f2ce0440 100644
--- a/usr/src/uts/common/os/brand.c
+++ b/usr/src/uts/common/os/brand.c
@@ -1037,7 +1037,7 @@ brand_solaris_exec(struct brand *pbrand)
/* Upon exec, reset our lwp brand data. */
(void) brand_solaris_freelwp(ttolwp(curthread), pbrand);
- (void) brand_solaris_brandlwp(ttolwp(curthread), pbrand);
+ (void) brand_solaris_initlwp(ttolwp(curthread), pbrand);
/*
* Upon exec, reset all the proc brand data, except for the elf
@@ -1081,7 +1081,7 @@ brand_solaris_forklwp(klwp_t *p, klwp_t *c, struct brand *pbrand)
/*
* Both LWPs have already had been initialized via
- * brand_solaris_brandlwp().
+ * brand_solaris_initlwp().
*/
ASSERT(p->lwp_brand != NULL);
ASSERT(c->lwp_brand != NULL);
@@ -1098,14 +1098,13 @@ brand_solaris_freelwp(klwp_t *l, struct brand *pbrand)
}
/*ARGSUSED*/
-int
-brand_solaris_brandlwp(klwp_t *l, struct brand *pbrand)
+void
+brand_solaris_initlwp(klwp_t *l, struct brand *pbrand)
{
ASSERT(l->lwp_procp->p_brand == pbrand);
ASSERT(l->lwp_procp->p_brand_data != NULL);
ASSERT(l->lwp_brand == NULL);
l->lwp_brand = (void *)-1;
- return (0);
}
/*ARGSUSED*/
diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c
index 4b6c79997e..7e32fb0506 100644
--- a/usr/src/uts/common/os/exec.c
+++ b/usr/src/uts/common/os/exec.c
@@ -301,19 +301,20 @@ exec_common(const char *fname, const char **argp, const char **envp,
/* If necessary, brand this process/lwp before we start the exec. */
if (brandme) {
+ void *brand_data = NULL;
+
brand_setbrand(p);
- if (BROP(p)->b_brandlwp(lwp) != 0) {
+ if (BROP(p)->b_lwpdata_alloc != NULL &&
+ (brand_data = BROP(p)->b_lwpdata_alloc(p)) == NULL) {
VN_RELE(vp);
if (dir != NULL)
VN_RELE(dir);
pn_free(&resolvepn);
goto fail;
}
- if (BROP(p)->b_initlwp != NULL) {
- mutex_enter(&p->p_lock);
- BROP(p)->b_initlwp(lwp);
- mutex_exit(&p->p_lock);
- }
+ mutex_enter(&p->p_lock);
+ BROP(p)->b_initlwp(lwp, brand_data);
+ mutex_exit(&p->p_lock);
}
if ((error = gexec(&vp, &ua, &args, NULL, 0, &execsz,
diff --git a/usr/src/uts/common/os/lwp.c b/usr/src/uts/common/os/lwp.c
index 6b91e410d7..f5be1b40b3 100644
--- a/usr/src/uts/common/os/lwp.c
+++ b/usr/src/uts/common/os/lwp.c
@@ -115,7 +115,7 @@ lwp_create(void (*proc)(), caddr_t arg, size_t len, proc_t *p,
ret_tidhash_t *ret_tidhash = NULL;
int i;
int rctlfail = 0;
- boolean_t branded = B_FALSE;
+ void *brand_data = NULL;
struct ctxop *ctx = NULL;
ASSERT(cid != sysdccid); /* system threads must start in SYS */
@@ -283,6 +283,19 @@ lwp_create(void (*proc)(), caddr_t arg, size_t len, proc_t *p,
*/
lep = kmem_zalloc(sizeof (*lep), KM_SLEEP);
+ /*
+ * If necessary, speculatively allocate lwp brand data. This is done
+ * ahead of time so p_lock need not be dropped during lwp branding.
+ */
+ if (PROC_IS_BRANDED(p) && BROP(p)->b_lwpdata_alloc != NULL) {
+ if ((brand_data = BROP(p)->b_lwpdata_alloc(p)) == NULL) {
+ mutex_enter(&p->p_lock);
+ err = 1;
+ atomic_inc_32(&p->p_zone->zone_ffmisc);
+ goto error;
+ }
+ }
+
mutex_enter(&p->p_lock);
grow:
/*
@@ -682,25 +695,15 @@ grow:
t->t_pre_sys = 1;
t->t_post_sys = 1;
- mutex_exit(&p->p_lock);
- /*
- * If this is a branded process, allocate any brand-specific lwp data.
- */
- if (PROC_IS_BRANDED(p)) {
- if (BROP(p)->b_brandlwp(lwp) != 0) {
- mutex_enter(&p->p_lock);
- err = 1;
- atomic_inc_32(&p->p_zone->zone_ffmisc);
- goto error;
- }
- branded = B_TRUE;
- }
-
- mutex_enter(&p->p_lock);
-
/* Complete branded lwp initialization */
- if (branded && BROP(p)->b_initlwp != NULL) {
- BROP(p)->b_initlwp(lwp);
+ if (PROC_IS_BRANDED(p)) {
+ BROP(p)->b_initlwp(lwp, brand_data);
+ /*
+ * The b_initlwp hook is expected to consume any preallocated
+ * brand_data in a way that prepares it for deallocation by the
+ * b_freelwp hook.
+ */
+ brand_data = NULL;
}
/*
@@ -762,8 +765,8 @@ error:
if (cid != NOCLASS && bufp != NULL)
CL_FREE(cid, bufp);
- if (branded) {
- BROP(p)->b_freelwp(lwp);
+ if (brand_data != NULL) {
+ BROP(p)->b_lwpdata_free(brand_data);
}
mutex_exit(&p->p_lock);
diff --git a/usr/src/uts/common/sys/brand.h b/usr/src/uts/common/sys/brand.h
index f94c93d748..79e02dcf17 100644
--- a/usr/src/uts/common/sys/brand.h
+++ b/usr/src/uts/common/sys/brand.h
@@ -117,7 +117,7 @@ struct execa;
* b_proc_exit - Perform process brand exit processing
* b_exec - Reset branded process state on exec
* b_lwp_setrval - Set return code for forked child
- * b_brandlwp - Allocate lwp brand data (p_lock not held)
+ * b_initlwp - Initialize lwp brand data
* b_forklwp - Copy lwp brand data during fork
* b_freelwp - Free lwp brand data
* b_lwpexit - Perform lwp-specific brand exit processing
@@ -128,7 +128,9 @@ struct execa;
* b_sendsig - Update process state after sendsig
*
* Optional Fields:
- * b_initlwp - Populate lwp brand data after b_brandlwp (p_lock held)
+ * b_lwpdata_alloc - Speculatively allocate data for use in b_initlwp
+ * b_lwpdata_free - Free data from allocated by b_lwpdata_alloc if errors occur
+ * during lwp creation before b_initlwp could be called.
* b_exit_with_sig - Instead of sending SIGCLD, exit with custom behavior
* b_psig_to_proc - Custom additional behavior during psig
* b_wait_filter - Filter processes from being matched by waitid
@@ -157,8 +159,9 @@ struct brand_ops {
void (*b_proc_exit)(struct proc *);
void (*b_exec)();
void (*b_lwp_setrval)(klwp_t *, int, int);
- int (*b_brandlwp)(klwp_t *);
- void (*b_initlwp)(klwp_t *);
+ void *(*b_lwpdata_alloc)(struct proc *);
+ void (*b_lwpdata_free)(void *);
+ void (*b_initlwp)(klwp_t *, void *);
void (*b_forklwp)(klwp_t *, klwp_t *);
void (*b_freelwp)(klwp_t *);
void (*b_lwpexit)(klwp_t *);
@@ -251,7 +254,7 @@ extern int brand_solaris_fini(char **, struct modlinkage *,
struct brand *);
extern void brand_solaris_forklwp(klwp_t *, klwp_t *, struct brand *);
extern void brand_solaris_freelwp(klwp_t *, struct brand *);
-extern int brand_solaris_brandlwp(klwp_t *, struct brand *);
+extern void brand_solaris_initlwp(klwp_t *, struct brand *);
extern void brand_solaris_lwpexit(klwp_t *, struct brand *);
extern void brand_solaris_proc_exit(struct proc *, struct brand *);
extern void brand_solaris_setbrand(proc_t *, struct brand *);
diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h
index 8c70743aa4..e811bebf25 100644
--- a/usr/src/uts/common/sys/proc.h
+++ b/usr/src/uts/common/sys/proc.h
@@ -629,6 +629,7 @@ extern int signal_is_blocked(kthread_t *, int);
extern int sigcheck(proc_t *, kthread_t *);
extern void sigdefault(proc_t *);
+extern struct pid *pid_find(pid_t pid);
extern void pid_setmin(void);
extern pid_t pid_allocate(proc_t *, pid_t, int);
extern int pid_rele(struct pid *);