xref: /illumos-gate/usr/src/uts/common/os/proc.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/proc.h>
30 
31 /*
32  * Install process context ops for the current process.
33  */
34 void
35 installpctx(
36 	proc_t *p,
37 	void	*arg,
38 	void	(*save)(void *),
39 	void	(*restore)(void *),
40 	void	(*fork)(void *, void *),
41 	void	(*exit)(void *),
42 	void	(*free)(void *, int))
43 {
44 	struct pctxop *pctx;
45 
46 	pctx = kmem_alloc(sizeof (struct pctxop), KM_SLEEP);
47 	pctx->save_op = save;
48 	pctx->restore_op = restore;
49 	pctx->fork_op = fork;
50 	pctx->exit_op = exit;
51 	pctx->free_op = free;
52 	pctx->arg = arg;
53 	pctx->next = p->p_pctx;
54 	p->p_pctx = pctx;
55 }
56 
57 /*
58  * Remove a process context ops from the current process.
59  */
60 int
61 removepctx(
62 	proc_t *p,
63 	void	*arg,
64 	void	(*save)(void *),
65 	void	(*restore)(void *),
66 	void	(*fork)(void *, void *),
67 	void	(*exit)(void *),
68 	void	(*free)(void *, int))
69 {
70 	struct pctxop *pctx, *prev_pctx;
71 
72 	prev_pctx = NULL;
73 	for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next) {
74 		if (pctx->save_op == save && pctx->restore_op == restore &&
75 		    pctx->fork_op == fork &&
76 		    pctx->exit_op == exit && pctx->free_op == free &&
77 		    pctx->arg == arg) {
78 			if (prev_pctx)
79 				prev_pctx->next = pctx->next;
80 			else
81 				p->p_pctx = pctx->next;
82 			if (pctx->free_op != NULL)
83 				(pctx->free_op)(pctx->arg, 0);
84 			kmem_free(pctx, sizeof (struct pctxop));
85 			return (1);
86 		}
87 		prev_pctx = pctx;
88 	}
89 	return (0);
90 }
91 
92 void
93 savepctx(proc_t *p)
94 {
95 	struct pctxop *pctx;
96 
97 	ASSERT(p == curthread->t_procp);
98 	for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
99 		if (pctx->save_op != NULL)
100 			(pctx->save_op)(pctx->arg);
101 }
102 
103 void
104 restorepctx(proc_t *p)
105 {
106 	struct pctxop *pctx;
107 
108 	ASSERT(p == curthread->t_procp);
109 	for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
110 		if (pctx->restore_op != NULL)
111 			(pctx->restore_op)(pctx->arg);
112 }
113 
114 void
115 forkpctx(proc_t *p, proc_t *cp)
116 {
117 	struct pctxop *pctx;
118 
119 	for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
120 		if (pctx->fork_op != NULL)
121 			(pctx->fork_op)(p, cp);
122 }
123 
124 /*
125  * exitpctx is called during thread/lwp exit to perform any actions
126  * needed when an LWP in the process leaves the processor for the last
127  * time. This routine is not intended to deal with freeing memory; freepctx()
128  * is used for that purpose during proc_exit(). This routine is provided to
129  * allow for clean-up that can't wait until thread_free().
130  */
131 void
132 exitpctx(proc_t *p)
133 {
134 	struct pctxop *pctx;
135 
136 	for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
137 		if (pctx->exit_op != NULL)
138 			(pctx->exit_op)(p);
139 }
140 
141 /*
142  * freepctx is called from proc_exit() to get rid of the actual context ops.
143  */
144 void
145 freepctx(proc_t *p, int isexec)
146 {
147 	struct pctxop *pctx;
148 
149 	while ((pctx = p->p_pctx) != NULL) {
150 		p->p_pctx = pctx->next;
151 		if (pctx->free_op != NULL)
152 			(pctx->free_op)(pctx->arg, isexec);
153 		kmem_free(pctx, sizeof (struct pctxop));
154 	}
155 }
156