1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM *
4*7836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM *
8*7836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM * and limitations under the License.
12*7836SJohn.Forte@Sun.COM *
13*7836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM *
19*7836SJohn.Forte@Sun.COM * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM */
21*7836SJohn.Forte@Sun.COM /*
22*7836SJohn.Forte@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23*7836SJohn.Forte@Sun.COM * Use is subject to license terms.
24*7836SJohn.Forte@Sun.COM */
25*7836SJohn.Forte@Sun.COM
26*7836SJohn.Forte@Sun.COM #include <sys/types.h>
27*7836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
28*7836SJohn.Forte@Sun.COM #include <sys/errno.h>
29*7836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
30*7836SJohn.Forte@Sun.COM #include <sys/conf.h>
31*7836SJohn.Forte@Sun.COM #include <sys/kmem.h>
32*7836SJohn.Forte@Sun.COM #include <sys/ddi.h>
33*7836SJohn.Forte@Sun.COM
34*7836SJohn.Forte@Sun.COM #define __NSC_GEN__
35*7836SJohn.Forte@Sun.COM #include <sys/nsctl/nsc_rmspin.h>
36*7836SJohn.Forte@Sun.COM #include "../nsctl.h"
37*7836SJohn.Forte@Sun.COM #include "nskernd.h"
38*7836SJohn.Forte@Sun.COM
39*7836SJohn.Forte@Sun.COM struct nsc_nlwp {
40*7836SJohn.Forte@Sun.COM struct nsc_nlwp *next;
41*7836SJohn.Forte@Sun.COM void (*fn)(void *);
42*7836SJohn.Forte@Sun.COM void *arg;
43*7836SJohn.Forte@Sun.COM volatile int ready;
44*7836SJohn.Forte@Sun.COM int errno;
45*7836SJohn.Forte@Sun.COM kcondvar_t child_cv;
46*7836SJohn.Forte@Sun.COM };
47*7836SJohn.Forte@Sun.COM
48*7836SJohn.Forte@Sun.COM kmutex_t nsc_proc_lock;
49*7836SJohn.Forte@Sun.COM kcondvar_t nsc_proc_cv;
50*7836SJohn.Forte@Sun.COM
51*7836SJohn.Forte@Sun.COM static struct nsc_nlwp *nsc_nlwp_top;
52*7836SJohn.Forte@Sun.COM
53*7836SJohn.Forte@Sun.COM void
_nsc_start_proc(void)54*7836SJohn.Forte@Sun.COM _nsc_start_proc(void)
55*7836SJohn.Forte@Sun.COM {
56*7836SJohn.Forte@Sun.COM mutex_init(&nsc_proc_lock, NULL, MUTEX_DRIVER, NULL);
57*7836SJohn.Forte@Sun.COM cv_init(&nsc_proc_cv, NULL, CV_DRIVER, NULL);
58*7836SJohn.Forte@Sun.COM }
59*7836SJohn.Forte@Sun.COM
60*7836SJohn.Forte@Sun.COM
61*7836SJohn.Forte@Sun.COM void
_nsc_stop_proc(void)62*7836SJohn.Forte@Sun.COM _nsc_stop_proc(void)
63*7836SJohn.Forte@Sun.COM {
64*7836SJohn.Forte@Sun.COM mutex_destroy(&nsc_proc_lock);
65*7836SJohn.Forte@Sun.COM cv_destroy(&nsc_proc_cv);
66*7836SJohn.Forte@Sun.COM }
67*7836SJohn.Forte@Sun.COM
68*7836SJohn.Forte@Sun.COM
69*7836SJohn.Forte@Sun.COM /*
70*7836SJohn.Forte@Sun.COM * Create a daemon (server) proc.
71*7836SJohn.Forte@Sun.COM *
72*7836SJohn.Forte@Sun.COM * If 'rt' is TRUE, then increase the scheduling priority of the lwp.
73*7836SJohn.Forte@Sun.COM * Exactly how, if at all, this feature is implemented is at the
74*7836SJohn.Forte@Sun.COM * discretion of nskernd.
75*7836SJohn.Forte@Sun.COM *
76*7836SJohn.Forte@Sun.COM * Returns 0 or errno.
77*7836SJohn.Forte@Sun.COM */
78*7836SJohn.Forte@Sun.COM
79*7836SJohn.Forte@Sun.COM int
nsc_create_process(void (* func)(void *),void * arg,boolean_t rt)80*7836SJohn.Forte@Sun.COM nsc_create_process(void (*func)(void *), void *arg, boolean_t rt)
81*7836SJohn.Forte@Sun.COM {
82*7836SJohn.Forte@Sun.COM struct nsc_nlwp *nlwp, **nlwpp;
83*7836SJohn.Forte@Sun.COM struct nskernd *nsk = NULL;
84*7836SJohn.Forte@Sun.COM int rc = 0;
85*7836SJohn.Forte@Sun.COM
86*7836SJohn.Forte@Sun.COM nlwp = kmem_zalloc(sizeof (*nlwp), KM_NOSLEEP);
87*7836SJohn.Forte@Sun.COM nsk = kmem_zalloc(sizeof (*nsk), KM_NOSLEEP);
88*7836SJohn.Forte@Sun.COM if (!nlwp || !nsk) {
89*7836SJohn.Forte@Sun.COM if (nlwp) {
90*7836SJohn.Forte@Sun.COM kmem_free(nlwp, sizeof (*nlwp));
91*7836SJohn.Forte@Sun.COM }
92*7836SJohn.Forte@Sun.COM if (nsk) {
93*7836SJohn.Forte@Sun.COM kmem_free(nsk, sizeof (*nsk));
94*7836SJohn.Forte@Sun.COM }
95*7836SJohn.Forte@Sun.COM return (ENOMEM);
96*7836SJohn.Forte@Sun.COM }
97*7836SJohn.Forte@Sun.COM
98*7836SJohn.Forte@Sun.COM nlwp->fn = func;
99*7836SJohn.Forte@Sun.COM nlwp->arg = arg;
100*7836SJohn.Forte@Sun.COM
101*7836SJohn.Forte@Sun.COM mutex_enter(&nsc_proc_lock);
102*7836SJohn.Forte@Sun.COM
103*7836SJohn.Forte@Sun.COM nlwp->next = nsc_nlwp_top;
104*7836SJohn.Forte@Sun.COM nsc_nlwp_top = nlwp;
105*7836SJohn.Forte@Sun.COM
106*7836SJohn.Forte@Sun.COM mutex_exit(&nsc_proc_lock);
107*7836SJohn.Forte@Sun.COM
108*7836SJohn.Forte@Sun.COM nsk->command = NSKERND_NEWLWP;
109*7836SJohn.Forte@Sun.COM nsk->data1 = (uint64_t)(unsigned long)nlwp;
110*7836SJohn.Forte@Sun.COM nsk->data2 = (uint64_t)rt;
111*7836SJohn.Forte@Sun.COM
112*7836SJohn.Forte@Sun.COM rc = nskernd_get(nsk);
113*7836SJohn.Forte@Sun.COM
114*7836SJohn.Forte@Sun.COM /* user level returns error in nsk->data1 */
115*7836SJohn.Forte@Sun.COM if (!rc && nsk->data1)
116*7836SJohn.Forte@Sun.COM rc = nsk->data1;
117*7836SJohn.Forte@Sun.COM
118*7836SJohn.Forte@Sun.COM mutex_enter(&nsc_proc_lock);
119*7836SJohn.Forte@Sun.COM
120*7836SJohn.Forte@Sun.COM if (!rc) {
121*7836SJohn.Forte@Sun.COM /*
122*7836SJohn.Forte@Sun.COM * wait for the child to start and check in.
123*7836SJohn.Forte@Sun.COM */
124*7836SJohn.Forte@Sun.COM
125*7836SJohn.Forte@Sun.COM while (! nlwp->ready) {
126*7836SJohn.Forte@Sun.COM cv_wait(&nsc_proc_cv, &nsc_proc_lock);
127*7836SJohn.Forte@Sun.COM }
128*7836SJohn.Forte@Sun.COM }
129*7836SJohn.Forte@Sun.COM
130*7836SJohn.Forte@Sun.COM /*
131*7836SJohn.Forte@Sun.COM * remove from list of outstanding requests.
132*7836SJohn.Forte@Sun.COM */
133*7836SJohn.Forte@Sun.COM
134*7836SJohn.Forte@Sun.COM for (nlwpp = &nsc_nlwp_top; (*nlwpp); nlwpp = &((*nlwpp)->next)) {
135*7836SJohn.Forte@Sun.COM if (*nlwpp == nlwp) {
136*7836SJohn.Forte@Sun.COM *nlwpp = nlwp->next;
137*7836SJohn.Forte@Sun.COM break;
138*7836SJohn.Forte@Sun.COM }
139*7836SJohn.Forte@Sun.COM }
140*7836SJohn.Forte@Sun.COM
141*7836SJohn.Forte@Sun.COM mutex_exit(&nsc_proc_lock);
142*7836SJohn.Forte@Sun.COM
143*7836SJohn.Forte@Sun.COM kmem_free(nlwp, sizeof (*nlwp));
144*7836SJohn.Forte@Sun.COM kmem_free(nsk, sizeof (*nsk));
145*7836SJohn.Forte@Sun.COM return (rc);
146*7836SJohn.Forte@Sun.COM }
147*7836SJohn.Forte@Sun.COM
148*7836SJohn.Forte@Sun.COM
149*7836SJohn.Forte@Sun.COM /*
150*7836SJohn.Forte@Sun.COM * Child lwp calls this function when it returns to the kernel.
151*7836SJohn.Forte@Sun.COM *
152*7836SJohn.Forte@Sun.COM * Check if the args are still on the pending list. If they are, then
153*7836SJohn.Forte@Sun.COM * run the required function. If they are not, then something went
154*7836SJohn.Forte@Sun.COM * wrong, so just return back to userland and die.
155*7836SJohn.Forte@Sun.COM */
156*7836SJohn.Forte@Sun.COM void
nsc_runlwp(uint64_t arg)157*7836SJohn.Forte@Sun.COM nsc_runlwp(uint64_t arg)
158*7836SJohn.Forte@Sun.COM {
159*7836SJohn.Forte@Sun.COM struct nsc_nlwp *nlwp;
160*7836SJohn.Forte@Sun.COM void (*fn)(void *);
161*7836SJohn.Forte@Sun.COM void *fn_arg;
162*7836SJohn.Forte@Sun.COM
163*7836SJohn.Forte@Sun.COM fn_arg = NULL;
164*7836SJohn.Forte@Sun.COM fn = NULL;
165*7836SJohn.Forte@Sun.COM
166*7836SJohn.Forte@Sun.COM mutex_enter(&nsc_proc_lock);
167*7836SJohn.Forte@Sun.COM
168*7836SJohn.Forte@Sun.COM /*
169*7836SJohn.Forte@Sun.COM * check that the request is still on the list of work to do
170*7836SJohn.Forte@Sun.COM */
171*7836SJohn.Forte@Sun.COM
172*7836SJohn.Forte@Sun.COM for (nlwp = nsc_nlwp_top; nlwp; nlwp = nlwp->next) {
173*7836SJohn.Forte@Sun.COM if (nlwp == (struct nsc_nlwp *)(unsigned long)arg) {
174*7836SJohn.Forte@Sun.COM fn_arg = nlwp->arg;
175*7836SJohn.Forte@Sun.COM fn = nlwp->fn;
176*7836SJohn.Forte@Sun.COM
177*7836SJohn.Forte@Sun.COM /* mark as ready */
178*7836SJohn.Forte@Sun.COM nlwp->ready = 1;
179*7836SJohn.Forte@Sun.COM cv_broadcast(&nsc_proc_cv);
180*7836SJohn.Forte@Sun.COM
181*7836SJohn.Forte@Sun.COM break;
182*7836SJohn.Forte@Sun.COM }
183*7836SJohn.Forte@Sun.COM }
184*7836SJohn.Forte@Sun.COM
185*7836SJohn.Forte@Sun.COM mutex_exit(&nsc_proc_lock);
186*7836SJohn.Forte@Sun.COM
187*7836SJohn.Forte@Sun.COM if (fn) {
188*7836SJohn.Forte@Sun.COM (*fn)(fn_arg);
189*7836SJohn.Forte@Sun.COM }
190*7836SJohn.Forte@Sun.COM }
191*7836SJohn.Forte@Sun.COM
192*7836SJohn.Forte@Sun.COM
193*7836SJohn.Forte@Sun.COM /*
194*7836SJohn.Forte@Sun.COM * Create a thread that acquires an inter-node lock.
195*7836SJohn.Forte@Sun.COM *
196*7836SJohn.Forte@Sun.COM * mode - 0 (read), 1 (write).
197*7836SJohn.Forte@Sun.COM * lockp - used to return the opaque address of a sync structure, which
198*7836SJohn.Forte@Sun.COM * must be passed to nsc_do_unlock() later.
199*7836SJohn.Forte@Sun.COM *
200*7836SJohn.Forte@Sun.COM * Returns 0 or errno.
201*7836SJohn.Forte@Sun.COM */
202*7836SJohn.Forte@Sun.COM
203*7836SJohn.Forte@Sun.COM int
nsc_do_lock(int mode,void ** lockp)204*7836SJohn.Forte@Sun.COM nsc_do_lock(int mode, void **lockp)
205*7836SJohn.Forte@Sun.COM {
206*7836SJohn.Forte@Sun.COM struct nsc_nlwp *nlwp = NULL, **nlwpp;
207*7836SJohn.Forte@Sun.COM struct nskernd *nsk = NULL;
208*7836SJohn.Forte@Sun.COM int rc = 0;
209*7836SJohn.Forte@Sun.COM
210*7836SJohn.Forte@Sun.COM nlwp = kmem_zalloc(sizeof (*nlwp), KM_NOSLEEP);
211*7836SJohn.Forte@Sun.COM nsk = kmem_zalloc(sizeof (*nsk), KM_NOSLEEP);
212*7836SJohn.Forte@Sun.COM if (!nlwp || !nsk) {
213*7836SJohn.Forte@Sun.COM if (nlwp) {
214*7836SJohn.Forte@Sun.COM kmem_free(nlwp, sizeof (*nlwp));
215*7836SJohn.Forte@Sun.COM }
216*7836SJohn.Forte@Sun.COM if (nsk) {
217*7836SJohn.Forte@Sun.COM kmem_free(nsk, sizeof (*nsk));
218*7836SJohn.Forte@Sun.COM }
219*7836SJohn.Forte@Sun.COM return (ENOMEM);
220*7836SJohn.Forte@Sun.COM }
221*7836SJohn.Forte@Sun.COM
222*7836SJohn.Forte@Sun.COM cv_init(&nlwp->child_cv, NULL, CV_DRIVER, NULL);
223*7836SJohn.Forte@Sun.COM
224*7836SJohn.Forte@Sun.COM mutex_enter(&nsc_proc_lock);
225*7836SJohn.Forte@Sun.COM
226*7836SJohn.Forte@Sun.COM nlwp->next = nsc_nlwp_top;
227*7836SJohn.Forte@Sun.COM nsc_nlwp_top = nlwp;
228*7836SJohn.Forte@Sun.COM
229*7836SJohn.Forte@Sun.COM mutex_exit(&nsc_proc_lock);
230*7836SJohn.Forte@Sun.COM
231*7836SJohn.Forte@Sun.COM nsk->command = NSKERND_LOCK;
232*7836SJohn.Forte@Sun.COM nsk->data1 = (uint64_t)(unsigned long)nlwp;
233*7836SJohn.Forte@Sun.COM nsk->data2 = (uint64_t)mode;
234*7836SJohn.Forte@Sun.COM
235*7836SJohn.Forte@Sun.COM rc = nskernd_get(nsk);
236*7836SJohn.Forte@Sun.COM
237*7836SJohn.Forte@Sun.COM /* user level returns error in nsk->data1 */
238*7836SJohn.Forte@Sun.COM if (!rc && nsk->data1)
239*7836SJohn.Forte@Sun.COM rc = nsk->data1;
240*7836SJohn.Forte@Sun.COM
241*7836SJohn.Forte@Sun.COM mutex_enter(&nsc_proc_lock);
242*7836SJohn.Forte@Sun.COM
243*7836SJohn.Forte@Sun.COM if (!rc) {
244*7836SJohn.Forte@Sun.COM /*
245*7836SJohn.Forte@Sun.COM * wait for the child to start and check in.
246*7836SJohn.Forte@Sun.COM */
247*7836SJohn.Forte@Sun.COM
248*7836SJohn.Forte@Sun.COM while (! nlwp->ready) {
249*7836SJohn.Forte@Sun.COM cv_wait(&nsc_proc_cv, &nsc_proc_lock);
250*7836SJohn.Forte@Sun.COM }
251*7836SJohn.Forte@Sun.COM
252*7836SJohn.Forte@Sun.COM /* retrieve errno from child's lock operation */
253*7836SJohn.Forte@Sun.COM rc = (int)nlwp->errno;
254*7836SJohn.Forte@Sun.COM }
255*7836SJohn.Forte@Sun.COM
256*7836SJohn.Forte@Sun.COM if (rc) {
257*7836SJohn.Forte@Sun.COM /*
258*7836SJohn.Forte@Sun.COM * error - remove from list of outstanding requests as
259*7836SJohn.Forte@Sun.COM * child will not be checking in (nskernd_get() failed
260*7836SJohn.Forte@Sun.COM * or user thread create failed) or will not be waiting
261*7836SJohn.Forte@Sun.COM * (child thread lock failure).
262*7836SJohn.Forte@Sun.COM */
263*7836SJohn.Forte@Sun.COM
264*7836SJohn.Forte@Sun.COM for (nlwpp = &nsc_nlwp_top; (*nlwpp);
265*7836SJohn.Forte@Sun.COM nlwpp = &((*nlwpp)->next)) {
266*7836SJohn.Forte@Sun.COM if (*nlwpp == nlwp) {
267*7836SJohn.Forte@Sun.COM *nlwpp = nlwp->next;
268*7836SJohn.Forte@Sun.COM break;
269*7836SJohn.Forte@Sun.COM }
270*7836SJohn.Forte@Sun.COM }
271*7836SJohn.Forte@Sun.COM
272*7836SJohn.Forte@Sun.COM mutex_exit(&nsc_proc_lock);
273*7836SJohn.Forte@Sun.COM
274*7836SJohn.Forte@Sun.COM cv_destroy(&nlwp->child_cv);
275*7836SJohn.Forte@Sun.COM kmem_free(nlwp, sizeof (*nlwp));
276*7836SJohn.Forte@Sun.COM kmem_free(nsk, sizeof (*nsk));
277*7836SJohn.Forte@Sun.COM *lockp = NULL;
278*7836SJohn.Forte@Sun.COM return (rc);
279*7836SJohn.Forte@Sun.COM }
280*7836SJohn.Forte@Sun.COM
281*7836SJohn.Forte@Sun.COM /* success, return argument for nsc_do_unlock() */
282*7836SJohn.Forte@Sun.COM
283*7836SJohn.Forte@Sun.COM mutex_exit(&nsc_proc_lock);
284*7836SJohn.Forte@Sun.COM
285*7836SJohn.Forte@Sun.COM kmem_free(nsk, sizeof (*nsk));
286*7836SJohn.Forte@Sun.COM *lockp = nlwp;
287*7836SJohn.Forte@Sun.COM return (0);
288*7836SJohn.Forte@Sun.COM }
289*7836SJohn.Forte@Sun.COM
290*7836SJohn.Forte@Sun.COM
291*7836SJohn.Forte@Sun.COM void
nsc_do_unlock(void * arg)292*7836SJohn.Forte@Sun.COM nsc_do_unlock(void *arg)
293*7836SJohn.Forte@Sun.COM {
294*7836SJohn.Forte@Sun.COM struct nsc_nlwp *nlwp;
295*7836SJohn.Forte@Sun.COM
296*7836SJohn.Forte@Sun.COM /* find child on work list */
297*7836SJohn.Forte@Sun.COM
298*7836SJohn.Forte@Sun.COM mutex_enter(&nsc_proc_lock);
299*7836SJohn.Forte@Sun.COM
300*7836SJohn.Forte@Sun.COM for (nlwp = nsc_nlwp_top; nlwp; nlwp = nlwp->next) {
301*7836SJohn.Forte@Sun.COM if (nlwp == (struct nsc_nlwp *)arg) {
302*7836SJohn.Forte@Sun.COM /* signal unlock */
303*7836SJohn.Forte@Sun.COM nlwp->ready = 0;
304*7836SJohn.Forte@Sun.COM cv_broadcast(&nlwp->child_cv);
305*7836SJohn.Forte@Sun.COM }
306*7836SJohn.Forte@Sun.COM }
307*7836SJohn.Forte@Sun.COM
308*7836SJohn.Forte@Sun.COM mutex_exit(&nsc_proc_lock);
309*7836SJohn.Forte@Sun.COM }
310*7836SJohn.Forte@Sun.COM
311*7836SJohn.Forte@Sun.COM
312*7836SJohn.Forte@Sun.COM /*
313*7836SJohn.Forte@Sun.COM * Lock child thread calls this function when it returns to the kernel.
314*7836SJohn.Forte@Sun.COM *
315*7836SJohn.Forte@Sun.COM * Check if the args are still on the pending list. If they are, then
316*7836SJohn.Forte@Sun.COM * post the lock results and wait for the unlock. If they are not,
317*7836SJohn.Forte@Sun.COM * then something went wrong, so just return back to userland and die.
318*7836SJohn.Forte@Sun.COM */
319*7836SJohn.Forte@Sun.COM void
nsc_lockchild(uint64_t arg,uint64_t errno)320*7836SJohn.Forte@Sun.COM nsc_lockchild(uint64_t arg, uint64_t errno)
321*7836SJohn.Forte@Sun.COM {
322*7836SJohn.Forte@Sun.COM struct nsc_nlwp *nlwp, **nlwpp;
323*7836SJohn.Forte@Sun.COM
324*7836SJohn.Forte@Sun.COM if (!arg) {
325*7836SJohn.Forte@Sun.COM return;
326*7836SJohn.Forte@Sun.COM }
327*7836SJohn.Forte@Sun.COM
328*7836SJohn.Forte@Sun.COM mutex_enter(&nsc_proc_lock);
329*7836SJohn.Forte@Sun.COM
330*7836SJohn.Forte@Sun.COM /*
331*7836SJohn.Forte@Sun.COM * check that the request is still on the list of work to do
332*7836SJohn.Forte@Sun.COM */
333*7836SJohn.Forte@Sun.COM
334*7836SJohn.Forte@Sun.COM for (nlwp = nsc_nlwp_top; nlwp; nlwp = nlwp->next) {
335*7836SJohn.Forte@Sun.COM if (nlwp == (struct nsc_nlwp *)(unsigned long)arg) {
336*7836SJohn.Forte@Sun.COM /* mark as ready */
337*7836SJohn.Forte@Sun.COM nlwp->errno = (int)errno;
338*7836SJohn.Forte@Sun.COM nlwp->ready = 1;
339*7836SJohn.Forte@Sun.COM cv_broadcast(&nsc_proc_cv);
340*7836SJohn.Forte@Sun.COM break;
341*7836SJohn.Forte@Sun.COM }
342*7836SJohn.Forte@Sun.COM }
343*7836SJohn.Forte@Sun.COM
344*7836SJohn.Forte@Sun.COM if (!nlwp || errno) {
345*7836SJohn.Forte@Sun.COM /*
346*7836SJohn.Forte@Sun.COM * Error - either this request is no longer on the work
347*7836SJohn.Forte@Sun.COM * queue, or there was an error in the userland lock code
348*7836SJohn.Forte@Sun.COM * in which case the lock caller (currently blocked in
349*7836SJohn.Forte@Sun.COM * nsc_do_lock() will do the cleanup.
350*7836SJohn.Forte@Sun.COM */
351*7836SJohn.Forte@Sun.COM mutex_exit(&nsc_proc_lock);
352*7836SJohn.Forte@Sun.COM return;
353*7836SJohn.Forte@Sun.COM }
354*7836SJohn.Forte@Sun.COM
355*7836SJohn.Forte@Sun.COM /*
356*7836SJohn.Forte@Sun.COM * no errors, so wait for an unlock
357*7836SJohn.Forte@Sun.COM */
358*7836SJohn.Forte@Sun.COM
359*7836SJohn.Forte@Sun.COM while (nlwp->ready) {
360*7836SJohn.Forte@Sun.COM cv_wait(&nlwp->child_cv, &nsc_proc_lock);
361*7836SJohn.Forte@Sun.COM }
362*7836SJohn.Forte@Sun.COM
363*7836SJohn.Forte@Sun.COM /*
364*7836SJohn.Forte@Sun.COM * remove self from list of outstanding requests.
365*7836SJohn.Forte@Sun.COM */
366*7836SJohn.Forte@Sun.COM
367*7836SJohn.Forte@Sun.COM for (nlwpp = &nsc_nlwp_top; (*nlwpp); nlwpp = &((*nlwpp)->next)) {
368*7836SJohn.Forte@Sun.COM if (*nlwpp == nlwp) {
369*7836SJohn.Forte@Sun.COM *nlwpp = nlwp->next;
370*7836SJohn.Forte@Sun.COM break;
371*7836SJohn.Forte@Sun.COM }
372*7836SJohn.Forte@Sun.COM }
373*7836SJohn.Forte@Sun.COM
374*7836SJohn.Forte@Sun.COM /*
375*7836SJohn.Forte@Sun.COM * cleanup
376*7836SJohn.Forte@Sun.COM */
377*7836SJohn.Forte@Sun.COM
378*7836SJohn.Forte@Sun.COM cv_destroy(&nlwp->child_cv);
379*7836SJohn.Forte@Sun.COM kmem_free(nlwp, sizeof (*nlwp));
380*7836SJohn.Forte@Sun.COM
381*7836SJohn.Forte@Sun.COM mutex_exit(&nsc_proc_lock);
382*7836SJohn.Forte@Sun.COM }
383