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
installpctx(proc_t * p,void * arg,void (* save)(void *),void (* restore)(void *),void (* fork)(void *,void *),void (* exit)(void *),void (* free)(void *,int))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
removepctx(proc_t * p,void * arg,void (* save)(void *),void (* restore)(void *),void (* fork)(void *,void *),void (* exit)(void *),void (* free)(void *,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
savepctx(proc_t * p)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
restorepctx(proc_t * p)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
forkpctx(proc_t * p,proc_t * cp)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
exitpctx(proc_t * p)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
freepctx(proc_t * p,int isexec)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