xref: /illumos-gate/usr/src/uts/common/os/proc.c (revision a6bde1a23b60f140c7ed78df979c2e22b1ed9b2c)
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  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
26  */
27 
28 #include <sys/proc.h>
29 #include <sys/cpuvar.h>
30 #include <sys/disp.h>
31 
32 /*
33  * Install process context ops for the current process.
34  */
35 void
36 installpctx(
37 	proc_t *p,
38 	void	*arg,
39 	void	(*save)(void *),
40 	void	(*restore)(void *),
41 	void	(*fork)(void *, void *),
42 	void	(*exit)(void *),
43 	void	(*free)(void *, int))
44 {
45 	struct pctxop *pctx;
46 
47 	pctx = kmem_alloc(sizeof (struct pctxop), KM_SLEEP);
48 	pctx->save_op = save;
49 	pctx->restore_op = restore;
50 	pctx->fork_op = fork;
51 	pctx->exit_op = exit;
52 	pctx->free_op = free;
53 	pctx->arg = arg;
54 	pctx->next = p->p_pctx;
55 	p->p_pctx = pctx;
56 }
57 
58 /*
59  * Remove a process context ops from the current process.
60  */
61 int
62 removepctx(
63 	proc_t *p,
64 	void	*arg,
65 	void	(*save)(void *),
66 	void	(*restore)(void *),
67 	void	(*fork)(void *, void *),
68 	void	(*exit)(void *),
69 	void	(*free)(void *, int))
70 {
71 	struct pctxop *pctx, *prev_pctx;
72 
73 	prev_pctx = NULL;
74 	kpreempt_disable();
75 	for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next) {
76 		if (pctx->save_op == save && pctx->restore_op == restore &&
77 		    pctx->fork_op == fork &&
78 		    pctx->exit_op == exit && pctx->free_op == free &&
79 		    pctx->arg == arg) {
80 			if (prev_pctx)
81 				prev_pctx->next = pctx->next;
82 			else
83 				p->p_pctx = pctx->next;
84 			if (pctx->free_op != NULL)
85 				(pctx->free_op)(pctx->arg, 0);
86 			kmem_free(pctx, sizeof (struct pctxop));
87 			kpreempt_enable();
88 			return (1);
89 		}
90 		prev_pctx = pctx;
91 	}
92 	kpreempt_enable();
93 	return (0);
94 }
95 
96 void
97 savepctx(proc_t *p)
98 {
99 	struct pctxop *pctx;
100 
101 	ASSERT(p == curthread->t_procp);
102 	for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
103 		if (pctx->save_op != NULL)
104 			(pctx->save_op)(pctx->arg);
105 }
106 
107 void
108 restorepctx(proc_t *p)
109 {
110 	struct pctxop *pctx;
111 
112 	ASSERT(p == curthread->t_procp);
113 	for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
114 		if (pctx->restore_op != NULL)
115 			(pctx->restore_op)(pctx->arg);
116 }
117 
118 void
119 forkpctx(proc_t *p, proc_t *cp)
120 {
121 	struct pctxop *pctx;
122 
123 	for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
124 		if (pctx->fork_op != NULL)
125 			(pctx->fork_op)(p, cp);
126 }
127 
128 /*
129  * exitpctx is called during thread/lwp exit to perform any actions
130  * needed when an LWP in the process leaves the processor for the last
131  * time. This routine is not intended to deal with freeing memory; freepctx()
132  * is used for that purpose during proc_exit(). This routine is provided to
133  * allow for clean-up that can't wait until thread_free().
134  */
135 void
136 exitpctx(proc_t *p)
137 {
138 	struct pctxop *pctx;
139 
140 	for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
141 		if (pctx->exit_op != NULL)
142 			(pctx->exit_op)(p);
143 }
144 
145 /*
146  * freepctx is called from proc_exit() to get rid of the actual context ops.
147  */
148 void
149 freepctx(proc_t *p, int isexec)
150 {
151 	struct pctxop *pctx;
152 
153 	kpreempt_disable();
154 	while ((pctx = p->p_pctx) != NULL) {
155 		p->p_pctx = pctx->next;
156 		if (pctx->free_op != NULL)
157 			(pctx->free_op)(pctx->arg, isexec);
158 		kmem_free(pctx, sizeof (struct pctxop));
159 	}
160 	kpreempt_enable();
161 }
162