xref: /onnv-gate/usr/src/uts/common/avs/ns/solaris/nsc_proc.c (revision 7836:4e95154b5b7a)
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