summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/proc.c')
-rw-r--r--usr/src/uts/common/os/proc.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/usr/src/uts/common/os/proc.c b/usr/src/uts/common/os/proc.c
new file mode 100644
index 0000000000..83563f34a9
--- /dev/null
+++ b/usr/src/uts/common/os/proc.c
@@ -0,0 +1,155 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/proc.h>
+
+/*
+ * Install process context ops for the current process.
+ */
+void
+installpctx(
+ proc_t *p,
+ void *arg,
+ void (*save)(void *),
+ void (*restore)(void *),
+ void (*fork)(void *, void *),
+ void (*exit)(void *),
+ void (*free)(void *, int))
+{
+ struct pctxop *pctx;
+
+ pctx = kmem_alloc(sizeof (struct pctxop), KM_SLEEP);
+ pctx->save_op = save;
+ pctx->restore_op = restore;
+ pctx->fork_op = fork;
+ pctx->exit_op = exit;
+ pctx->free_op = free;
+ pctx->arg = arg;
+ pctx->next = p->p_pctx;
+ p->p_pctx = pctx;
+}
+
+/*
+ * Remove a process context ops from the current process.
+ */
+int
+removepctx(
+ proc_t *p,
+ void *arg,
+ void (*save)(void *),
+ void (*restore)(void *),
+ void (*fork)(void *, void *),
+ void (*exit)(void *),
+ void (*free)(void *, int))
+{
+ struct pctxop *pctx, *prev_pctx;
+
+ prev_pctx = NULL;
+ for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next) {
+ if (pctx->save_op == save && pctx->restore_op == restore &&
+ pctx->fork_op == fork &&
+ pctx->exit_op == exit && pctx->free_op == free &&
+ pctx->arg == arg) {
+ if (prev_pctx)
+ prev_pctx->next = pctx->next;
+ else
+ p->p_pctx = pctx->next;
+ if (pctx->free_op != NULL)
+ (pctx->free_op)(pctx->arg, 0);
+ kmem_free(pctx, sizeof (struct pctxop));
+ return (1);
+ }
+ prev_pctx = pctx;
+ }
+ return (0);
+}
+
+void
+savepctx(proc_t *p)
+{
+ struct pctxop *pctx;
+
+ ASSERT(p == curthread->t_procp);
+ for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
+ if (pctx->save_op != NULL)
+ (pctx->save_op)(pctx->arg);
+}
+
+void
+restorepctx(proc_t *p)
+{
+ struct pctxop *pctx;
+
+ ASSERT(p == curthread->t_procp);
+ for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
+ if (pctx->restore_op != NULL)
+ (pctx->restore_op)(pctx->arg);
+}
+
+void
+forkpctx(proc_t *p, proc_t *cp)
+{
+ struct pctxop *pctx;
+
+ for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
+ if (pctx->fork_op != NULL)
+ (pctx->fork_op)(p, cp);
+}
+
+/*
+ * exitpctx is called during thread/lwp exit to perform any actions
+ * needed when an LWP in the process leaves the processor for the last
+ * time. This routine is not intended to deal with freeing memory; freepctx()
+ * is used for that purpose during proc_exit(). This routine is provided to
+ * allow for clean-up that can't wait until thread_free().
+ */
+void
+exitpctx(proc_t *p)
+{
+ struct pctxop *pctx;
+
+ for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
+ if (pctx->exit_op != NULL)
+ (pctx->exit_op)(p);
+}
+
+/*
+ * freepctx is called from proc_exit() to get rid of the actual context ops.
+ */
+void
+freepctx(proc_t *p, int isexec)
+{
+ struct pctxop *pctx;
+
+ while ((pctx = p->p_pctx) != NULL) {
+ p->p_pctx = pctx->next;
+ if (pctx->free_op != NULL)
+ (pctx->free_op)(pctx->arg, isexec);
+ kmem_free(pctx, sizeof (struct pctxop));
+ }
+}