1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8*8f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
9*8f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
23*8f23e9faSHans Rosenfeld  * Copyright (c) 2004-2011 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27291a2b48SSukumar Swaminathan #include <emlxs.h>
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_THREAD_C);
32fcf3ce44SJohn Forte 
33291a2b48SSukumar Swaminathan static void	emlxs_thread(emlxs_thread_t *ethread);
34291a2b48SSukumar Swaminathan static void	emlxs_taskq_thread(emlxs_taskq_thread_t *tthread);
35fcf3ce44SJohn Forte 
36fcf3ce44SJohn Forte 
37fcf3ce44SJohn Forte static void
emlxs_taskq_thread(emlxs_taskq_thread_t * tthread)38fcf3ce44SJohn Forte emlxs_taskq_thread(emlxs_taskq_thread_t *tthread)
39fcf3ce44SJohn Forte {
40fcf3ce44SJohn Forte 	emlxs_taskq_t *taskq;
41fcf3ce44SJohn Forte 	void (*func) ();
42fcf3ce44SJohn Forte 	void *arg;
43fcf3ce44SJohn Forte 
44fcf3ce44SJohn Forte 	taskq = tthread->taskq;
45fcf3ce44SJohn Forte 
46fcf3ce44SJohn Forte 	mutex_enter(&tthread->lock);
47fcf3ce44SJohn Forte 	tthread->flags |= EMLXS_THREAD_STARTED;
48fcf3ce44SJohn Forte 
49fcf3ce44SJohn Forte 	while (!(tthread->flags & EMLXS_THREAD_KILLED)) {
50fcf3ce44SJohn Forte 		mutex_enter(&taskq->put_lock);
51fcf3ce44SJohn Forte 		tthread->next = taskq->put_head;
52fcf3ce44SJohn Forte 		taskq->put_head = tthread;
53fcf3ce44SJohn Forte 		taskq->put_count++;
54fcf3ce44SJohn Forte 		mutex_exit(&taskq->put_lock);
55fcf3ce44SJohn Forte 
56fcf3ce44SJohn Forte 		tthread->flags |= EMLXS_THREAD_ASLEEP;
57fcf3ce44SJohn Forte 		cv_wait(&tthread->cv_flag, &tthread->lock);
58fcf3ce44SJohn Forte 		tthread->flags &= ~EMLXS_THREAD_ASLEEP;
59fcf3ce44SJohn Forte 
60fcf3ce44SJohn Forte 		if (tthread->func) {
61fcf3ce44SJohn Forte 			func = tthread->func;
62fcf3ce44SJohn Forte 			arg = tthread->arg;
63fcf3ce44SJohn Forte 
64fcf3ce44SJohn Forte 			tthread->flags |= EMLXS_THREAD_BUSY;
65fcf3ce44SJohn Forte 			mutex_exit(&tthread->lock);
66fcf3ce44SJohn Forte 
67fcf3ce44SJohn Forte 			func(taskq->hba, arg);
68fcf3ce44SJohn Forte 
69fcf3ce44SJohn Forte 			mutex_enter(&tthread->lock);
70fcf3ce44SJohn Forte 			tthread->flags &= ~EMLXS_THREAD_BUSY;
71fcf3ce44SJohn Forte 		}
72fcf3ce44SJohn Forte 	}
73fcf3ce44SJohn Forte 
74fcf3ce44SJohn Forte 	tthread->flags |= EMLXS_THREAD_ENDED;
75fcf3ce44SJohn Forte 	mutex_exit(&tthread->lock);
76fcf3ce44SJohn Forte 
77291a2b48SSukumar Swaminathan 	thread_exit();
78fcf3ce44SJohn Forte 
7982527734SSukumar Swaminathan } /* emlxs_taskq_thread() */
80fcf3ce44SJohn Forte 
81fcf3ce44SJohn Forte 
82fcf3ce44SJohn Forte 
83fcf3ce44SJohn Forte uint32_t
emlxs_taskq_dispatch(emlxs_taskq_t * taskq,void (* func)(),void * arg)84291a2b48SSukumar Swaminathan emlxs_taskq_dispatch(emlxs_taskq_t *taskq, void (*func) (), void *arg)
85291a2b48SSukumar Swaminathan {
86fcf3ce44SJohn Forte 	emlxs_taskq_thread_t *tthread = NULL;
87fcf3ce44SJohn Forte 
88fcf3ce44SJohn Forte 	mutex_enter(&taskq->get_lock);
89fcf3ce44SJohn Forte 
90fcf3ce44SJohn Forte 	/* Make sure taskq is open for business */
91fcf3ce44SJohn Forte 	if (!taskq->open) {
92fcf3ce44SJohn Forte 		mutex_exit(&taskq->get_lock);
93fcf3ce44SJohn Forte 		return (0);
94fcf3ce44SJohn Forte 	}
95291a2b48SSukumar Swaminathan 
96fcf3ce44SJohn Forte 	/* Check get_list for a thread */
97fcf3ce44SJohn Forte 	if (taskq->get_head) {
98fcf3ce44SJohn Forte 		/* Get the next thread */
99fcf3ce44SJohn Forte 		tthread = taskq->get_head;
100fcf3ce44SJohn Forte 		taskq->get_count--;
101fcf3ce44SJohn Forte 		taskq->get_head = (taskq->get_count) ? tthread->next : NULL;
102fcf3ce44SJohn Forte 		tthread->next = NULL;
103fcf3ce44SJohn Forte 	}
104291a2b48SSukumar Swaminathan 
105fcf3ce44SJohn Forte 	/* Else check put_list for a thread */
106fcf3ce44SJohn Forte 	else if (taskq->put_head) {
107fcf3ce44SJohn Forte 
108fcf3ce44SJohn Forte 		/* Move put_list to get_list */
109fcf3ce44SJohn Forte 		mutex_enter(&taskq->put_lock);
110fcf3ce44SJohn Forte 		taskq->get_head = taskq->put_head;
111fcf3ce44SJohn Forte 		taskq->get_count = taskq->put_count;
112fcf3ce44SJohn Forte 		taskq->put_head = NULL;
113fcf3ce44SJohn Forte 		taskq->put_count = 0;
114fcf3ce44SJohn Forte 		mutex_exit(&taskq->put_lock);
115fcf3ce44SJohn Forte 
116fcf3ce44SJohn Forte 		/* Get the next thread */
117fcf3ce44SJohn Forte 		tthread = taskq->get_head;
118fcf3ce44SJohn Forte 		taskq->get_count--;
119fcf3ce44SJohn Forte 		taskq->get_head = (taskq->get_count) ? tthread->next : NULL;
120fcf3ce44SJohn Forte 		tthread->next = NULL;
121fcf3ce44SJohn Forte 	}
122291a2b48SSukumar Swaminathan 
123fcf3ce44SJohn Forte 	mutex_exit(&taskq->get_lock);
124fcf3ce44SJohn Forte 
125fcf3ce44SJohn Forte 	/* Wake up the thread if one exists */
126fcf3ce44SJohn Forte 	if (tthread) {
127fcf3ce44SJohn Forte 		mutex_enter(&tthread->lock);
128fcf3ce44SJohn Forte 		tthread->func = func;
129fcf3ce44SJohn Forte 		tthread->arg = arg;
130fcf3ce44SJohn Forte 		cv_signal(&tthread->cv_flag);
131fcf3ce44SJohn Forte 		mutex_exit(&tthread->lock);
132fcf3ce44SJohn Forte 
133fcf3ce44SJohn Forte 		return (1);
134fcf3ce44SJohn Forte 	}
135291a2b48SSukumar Swaminathan 
136fcf3ce44SJohn Forte 	return (0);
137fcf3ce44SJohn Forte 
13882527734SSukumar Swaminathan } /* emlxs_taskq_dispatch() */
139fcf3ce44SJohn Forte 
140fcf3ce44SJohn Forte 
141fcf3ce44SJohn Forte 
142fcf3ce44SJohn Forte void
emlxs_taskq_create(emlxs_hba_t * hba,emlxs_taskq_t * taskq)143fcf3ce44SJohn Forte emlxs_taskq_create(emlxs_hba_t *hba, emlxs_taskq_t *taskq)
144fcf3ce44SJohn Forte {
145fcf3ce44SJohn Forte 	emlxs_taskq_thread_t *tthread;
146291a2b48SSukumar Swaminathan 	uint32_t i;
147fcf3ce44SJohn Forte 
148fcf3ce44SJohn Forte 
149fcf3ce44SJohn Forte 	/* If taskq is already open then quit */
150fcf3ce44SJohn Forte 	if (taskq->open) {
151fcf3ce44SJohn Forte 		return;
152fcf3ce44SJohn Forte 	}
153291a2b48SSukumar Swaminathan 
154fcf3ce44SJohn Forte 	/* Zero the taskq */
155fcf3ce44SJohn Forte 	bzero(taskq, sizeof (emlxs_taskq_t));
156fcf3ce44SJohn Forte 
157*8f23e9faSHans Rosenfeld 	mutex_init(&taskq->get_lock, NULL, MUTEX_DRIVER,
158a9800bebSGarrett D'Amore 	    DDI_INTR_PRI(hba->intr_arg));
159fcf3ce44SJohn Forte 
160fcf3ce44SJohn Forte 	mutex_enter(&taskq->get_lock);
161fcf3ce44SJohn Forte 
162fcf3ce44SJohn Forte 	taskq->hba = hba;
163fcf3ce44SJohn Forte 
164*8f23e9faSHans Rosenfeld 	mutex_init(&taskq->put_lock, NULL, MUTEX_DRIVER,
165a9800bebSGarrett D'Amore 	    DDI_INTR_PRI(hba->intr_arg));
166fcf3ce44SJohn Forte 
167fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_MAX_TASKQ_THREADS; i++) {
168fcf3ce44SJohn Forte 		tthread = &taskq->thread_list[i];
169fcf3ce44SJohn Forte 		tthread->taskq = taskq;
170fcf3ce44SJohn Forte 
171*8f23e9faSHans Rosenfeld 		mutex_init(&tthread->lock, NULL, MUTEX_DRIVER,
172a9800bebSGarrett D'Amore 		    DDI_INTR_PRI(hba->intr_arg));
173fcf3ce44SJohn Forte 
174*8f23e9faSHans Rosenfeld 		cv_init(&tthread->cv_flag, NULL, CV_DRIVER, NULL);
175fcf3ce44SJohn Forte 
176fcf3ce44SJohn Forte 		tthread->flags |= EMLXS_THREAD_INITD;
177291a2b48SSukumar Swaminathan 		tthread->thread =
178291a2b48SSukumar Swaminathan 		    thread_create(NULL, 0, emlxs_taskq_thread,
179fcf3ce44SJohn Forte 		    (char *)tthread, 0, &p0, TS_RUN, v.v_maxsyspri - 2);
180fcf3ce44SJohn Forte 	}
181fcf3ce44SJohn Forte 
182fcf3ce44SJohn Forte 	/* Open the taskq */
183fcf3ce44SJohn Forte 	taskq->open = 1;
184fcf3ce44SJohn Forte 
185fcf3ce44SJohn Forte 	mutex_exit(&taskq->get_lock);
186fcf3ce44SJohn Forte 
187fcf3ce44SJohn Forte 	return;
188fcf3ce44SJohn Forte 
18982527734SSukumar Swaminathan } /* emlxs_taskq_create() */
190fcf3ce44SJohn Forte 
191fcf3ce44SJohn Forte 
192fcf3ce44SJohn Forte void
emlxs_taskq_destroy(emlxs_taskq_t * taskq)193fcf3ce44SJohn Forte emlxs_taskq_destroy(emlxs_taskq_t *taskq)
194fcf3ce44SJohn Forte {
195fcf3ce44SJohn Forte 	emlxs_taskq_thread_t *tthread;
196fcf3ce44SJohn Forte 	uint32_t i;
197fcf3ce44SJohn Forte 
198fcf3ce44SJohn Forte 	/* If taskq already closed, then quit */
199fcf3ce44SJohn Forte 	if (!taskq->open) {
200fcf3ce44SJohn Forte 		return;
201fcf3ce44SJohn Forte 	}
202291a2b48SSukumar Swaminathan 
203fcf3ce44SJohn Forte 	mutex_enter(&taskq->get_lock);
204fcf3ce44SJohn Forte 
205fcf3ce44SJohn Forte 	/* If taskq already closed, then quit */
206fcf3ce44SJohn Forte 	if (!taskq->open) {
207fcf3ce44SJohn Forte 		mutex_exit(&taskq->get_lock);
208fcf3ce44SJohn Forte 		return;
209fcf3ce44SJohn Forte 	}
210291a2b48SSukumar Swaminathan 
211fcf3ce44SJohn Forte 	taskq->open = 0;
212fcf3ce44SJohn Forte 	mutex_exit(&taskq->get_lock);
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte 
215fcf3ce44SJohn Forte 	/* No more threads can be dispatched now */
216fcf3ce44SJohn Forte 
217fcf3ce44SJohn Forte 	/* Kill the threads */
218fcf3ce44SJohn Forte 	for (i = 0; i < EMLXS_MAX_TASKQ_THREADS; i++) {
219fcf3ce44SJohn Forte 		tthread = &taskq->thread_list[i];
220fcf3ce44SJohn Forte 
221fcf3ce44SJohn Forte 		/*
222291a2b48SSukumar Swaminathan 		 * If the thread lock can be acquired,
223291a2b48SSukumar Swaminathan 		 * it is in one of these states:
224291a2b48SSukumar Swaminathan 		 * 1. Thread not started.
225291a2b48SSukumar Swaminathan 		 * 2. Thread asleep.
226291a2b48SSukumar Swaminathan 		 * 3. Thread busy.
227291a2b48SSukumar Swaminathan 		 * 4. Thread ended.
228fcf3ce44SJohn Forte 		 */
229fcf3ce44SJohn Forte 		mutex_enter(&tthread->lock);
230fcf3ce44SJohn Forte 		tthread->flags |= EMLXS_THREAD_KILLED;
231fcf3ce44SJohn Forte 		cv_signal(&tthread->cv_flag);
232fcf3ce44SJohn Forte 
233fcf3ce44SJohn Forte 		/* Wait for thread to die */
234fcf3ce44SJohn Forte 		while (!(tthread->flags & EMLXS_THREAD_ENDED)) {
235fcf3ce44SJohn Forte 			mutex_exit(&tthread->lock);
236fcf3ce44SJohn Forte 			delay(drv_usectohz(10000));
237fcf3ce44SJohn Forte 			mutex_enter(&tthread->lock);
238fcf3ce44SJohn Forte 		}
239fcf3ce44SJohn Forte 		mutex_exit(&tthread->lock);
240fcf3ce44SJohn Forte 
241fcf3ce44SJohn Forte 		/* Clean up thread */
242fcf3ce44SJohn Forte 		mutex_destroy(&tthread->lock);
243fcf3ce44SJohn Forte 		cv_destroy(&tthread->cv_flag);
244fcf3ce44SJohn Forte 	}
245fcf3ce44SJohn Forte 
246fcf3ce44SJohn Forte 	/* Clean up taskq */
247fcf3ce44SJohn Forte 	mutex_destroy(&taskq->put_lock);
248fcf3ce44SJohn Forte 	mutex_destroy(&taskq->get_lock);
249fcf3ce44SJohn Forte 
250fcf3ce44SJohn Forte 	return;
251fcf3ce44SJohn Forte 
25282527734SSukumar Swaminathan } /* emlxs_taskq_destroy() */
253fcf3ce44SJohn Forte 
254fcf3ce44SJohn Forte 
255fcf3ce44SJohn Forte 
256fcf3ce44SJohn Forte static void
emlxs_thread(emlxs_thread_t * ethread)257fcf3ce44SJohn Forte emlxs_thread(emlxs_thread_t *ethread)
258fcf3ce44SJohn Forte {
259bb63f56eSSukumar Swaminathan 	emlxs_hba_t *hba;
260fcf3ce44SJohn Forte 	void (*func) ();
261fcf3ce44SJohn Forte 	void *arg1;
262fcf3ce44SJohn Forte 	void *arg2;
263fcf3ce44SJohn Forte 
264bb63f56eSSukumar Swaminathan 	if (ethread->flags & EMLXS_THREAD_RUN_ONCE) {
265bb63f56eSSukumar Swaminathan 		hba = ethread->hba;
266bb63f56eSSukumar Swaminathan 		ethread->flags |= EMLXS_THREAD_STARTED;
267fcf3ce44SJohn Forte 
268bb63f56eSSukumar Swaminathan 		if (!(ethread->flags & EMLXS_THREAD_KILLED)) {
269fcf3ce44SJohn Forte 			func = ethread->func;
270fcf3ce44SJohn Forte 			arg1 = ethread->arg1;
271fcf3ce44SJohn Forte 			arg2 = ethread->arg2;
272fcf3ce44SJohn Forte 
273bb63f56eSSukumar Swaminathan 			func(hba, arg1, arg2);
274bb63f56eSSukumar Swaminathan 		}
275fcf3ce44SJohn Forte 
276bb63f56eSSukumar Swaminathan 		ethread->flags |= EMLXS_THREAD_ENDED;
277bb63f56eSSukumar Swaminathan 		ethread->flags &= ~EMLXS_THREAD_INITD;
278fcf3ce44SJohn Forte 
279bb63f56eSSukumar Swaminathan 		/* Remove the thread from the spawn thread list */
280d08970deSSukumar Swaminathan 		mutex_enter(&EMLXS_SPAWN_LOCK);
281bb63f56eSSukumar Swaminathan 		if (hba->spawn_thread_head == ethread)
282bb63f56eSSukumar Swaminathan 			hba->spawn_thread_head = ethread->next;
283bb63f56eSSukumar Swaminathan 		if (hba->spawn_thread_tail == ethread)
284bb63f56eSSukumar Swaminathan 			hba->spawn_thread_tail = ethread->prev;
285bb63f56eSSukumar Swaminathan 
286bb63f56eSSukumar Swaminathan 		if (ethread->prev)
287bb63f56eSSukumar Swaminathan 			ethread->prev->next = ethread->next;
288bb63f56eSSukumar Swaminathan 		if (ethread->next)
289bb63f56eSSukumar Swaminathan 			ethread->next->prev = ethread->prev;
290bb63f56eSSukumar Swaminathan 
291bb63f56eSSukumar Swaminathan 		ethread->next = ethread->prev = NULL;
292bb63f56eSSukumar Swaminathan 
293bb63f56eSSukumar Swaminathan 		kmem_free(ethread, sizeof (emlxs_thread_t));
294bb63f56eSSukumar Swaminathan 
295d08970deSSukumar Swaminathan 		mutex_exit(&EMLXS_SPAWN_LOCK);
296fcf3ce44SJohn Forte 	}
297bb63f56eSSukumar Swaminathan 	else
298bb63f56eSSukumar Swaminathan 	{
29982527734SSukumar Swaminathan 	/*
30082527734SSukumar Swaminathan 	 * If the thread lock can be acquired,
30182527734SSukumar Swaminathan 	 * it is in one of these states:
30282527734SSukumar Swaminathan 	 * 1. Thread not started.
30382527734SSukumar Swaminathan 	 * 2. Thread asleep.
30482527734SSukumar Swaminathan 	 * 3. Thread busy.
30582527734SSukumar Swaminathan 	 * 4. Thread ended.
30682527734SSukumar Swaminathan 	 */
30782527734SSukumar Swaminathan 	mutex_enter(&ethread->lock);
30882527734SSukumar Swaminathan 	ethread->flags |= EMLXS_THREAD_STARTED;
309fcf3ce44SJohn Forte 
31082527734SSukumar Swaminathan 	while (!(ethread->flags & EMLXS_THREAD_KILLED)) {
31182527734SSukumar Swaminathan 		if (!(ethread->flags & EMLXS_THREAD_TRIGGERED)) {
31282527734SSukumar Swaminathan 			ethread->flags |= EMLXS_THREAD_ASLEEP;
31382527734SSukumar Swaminathan 			cv_wait(&ethread->cv_flag, &ethread->lock);
31482527734SSukumar Swaminathan 		}
315fcf3ce44SJohn Forte 
31682527734SSukumar Swaminathan 		ethread->flags &=
31782527734SSukumar Swaminathan 		    ~(EMLXS_THREAD_ASLEEP | EMLXS_THREAD_TRIGGERED);
318fcf3ce44SJohn Forte 
31982527734SSukumar Swaminathan 		if (ethread->func) {
32082527734SSukumar Swaminathan 			func = ethread->func;
32182527734SSukumar Swaminathan 			arg1 = ethread->arg1;
32282527734SSukumar Swaminathan 			arg2 = ethread->arg2;
32382527734SSukumar Swaminathan 			ethread->func = NULL;
32482527734SSukumar Swaminathan 			ethread->arg1 = NULL;
32582527734SSukumar Swaminathan 			ethread->arg2 = NULL;
326bb63f56eSSukumar Swaminathan 
32782527734SSukumar Swaminathan 			ethread->flags |= EMLXS_THREAD_BUSY;
32882527734SSukumar Swaminathan 			mutex_exit(&ethread->lock);
329bb63f56eSSukumar Swaminathan 
33082527734SSukumar Swaminathan 			func(ethread->hba, arg1, arg2);
331bb63f56eSSukumar Swaminathan 
33282527734SSukumar Swaminathan 			mutex_enter(&ethread->lock);
33382527734SSukumar Swaminathan 			ethread->flags &= ~EMLXS_THREAD_BUSY;
334bb63f56eSSukumar Swaminathan 		}
33582527734SSukumar Swaminathan 	}
336bb63f56eSSukumar Swaminathan 
33782527734SSukumar Swaminathan 	ethread->flags |= EMLXS_THREAD_ENDED;
33882527734SSukumar Swaminathan 	mutex_exit(&ethread->lock);
339bb63f56eSSukumar Swaminathan 	}
340bb63f56eSSukumar Swaminathan 
341bb63f56eSSukumar Swaminathan 	thread_exit();
342fcf3ce44SJohn Forte 
34382527734SSukumar Swaminathan } /* emlxs_thread() */
344fcf3ce44SJohn Forte 
345fcf3ce44SJohn Forte 
346fcf3ce44SJohn Forte void
emlxs_thread_create(emlxs_hba_t * hba,emlxs_thread_t * ethread)347fcf3ce44SJohn Forte emlxs_thread_create(emlxs_hba_t *hba, emlxs_thread_t *ethread)
348fcf3ce44SJohn Forte {
34982527734SSukumar Swaminathan 	uint16_t pri;
350fcf3ce44SJohn Forte 
351fcf3ce44SJohn Forte 	if (ethread->flags & EMLXS_THREAD_INITD) {
352fcf3ce44SJohn Forte 		return;
353fcf3ce44SJohn Forte 	}
354291a2b48SSukumar Swaminathan 
355fcf3ce44SJohn Forte 	bzero(ethread, sizeof (emlxs_thread_t));
356fcf3ce44SJohn Forte 
357*8f23e9faSHans Rosenfeld 	mutex_init(&ethread->lock, NULL, MUTEX_DRIVER,
358a9800bebSGarrett D'Amore 	    DDI_INTR_PRI(hba->intr_arg));
359fcf3ce44SJohn Forte 
360*8f23e9faSHans Rosenfeld 	cv_init(&ethread->cv_flag, NULL, CV_DRIVER, NULL);
361fcf3ce44SJohn Forte 
362fcf3ce44SJohn Forte 	ethread->hba = hba;
363fcf3ce44SJohn Forte 	ethread->flags |= EMLXS_THREAD_INITD;
364fcf3ce44SJohn Forte 
36582527734SSukumar Swaminathan 	pri = v.v_maxsyspri - 2;
366fcf3ce44SJohn Forte 
367291a2b48SSukumar Swaminathan 	ethread->thread =
368291a2b48SSukumar Swaminathan 	    thread_create(NULL, 0, emlxs_thread, (char *)ethread, 0, &p0,
36982527734SSukumar Swaminathan 	    TS_RUN, pri);
370fcf3ce44SJohn Forte 
37182527734SSukumar Swaminathan } /* emlxs_thread_create() */
372fcf3ce44SJohn Forte 
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte void
emlxs_thread_destroy(emlxs_thread_t * ethread)375fcf3ce44SJohn Forte emlxs_thread_destroy(emlxs_thread_t *ethread)
376fcf3ce44SJohn Forte {
377fcf3ce44SJohn Forte 	/*
378291a2b48SSukumar Swaminathan 	 * If the thread lock can be acquired,
379291a2b48SSukumar Swaminathan 	 * it is in one of these states:
380291a2b48SSukumar Swaminathan 	 * 1. Thread not started.
381291a2b48SSukumar Swaminathan 	 * 2. Thread asleep.
382291a2b48SSukumar Swaminathan 	 * 3. Thread busy.
383291a2b48SSukumar Swaminathan 	 * 4. Thread ended.
384fcf3ce44SJohn Forte 	 */
385fcf3ce44SJohn Forte 	if (!(ethread->flags & EMLXS_THREAD_INITD)) {
386fcf3ce44SJohn Forte 		return;
387fcf3ce44SJohn Forte 	}
388291a2b48SSukumar Swaminathan 
38982527734SSukumar Swaminathan 
390fcf3ce44SJohn Forte 	mutex_enter(&ethread->lock);
391fcf3ce44SJohn Forte 
392fcf3ce44SJohn Forte 	if (ethread->flags & EMLXS_THREAD_ENDED) {
393bb63f56eSSukumar Swaminathan 		mutex_exit(&ethread->lock);
394fcf3ce44SJohn Forte 		return;
395fcf3ce44SJohn Forte 	}
396291a2b48SSukumar Swaminathan 
397fcf3ce44SJohn Forte 	ethread->flags &= ~EMLXS_THREAD_INITD;
398fcf3ce44SJohn Forte 	ethread->flags |= (EMLXS_THREAD_KILLED | EMLXS_THREAD_TRIGGERED);
399fcf3ce44SJohn Forte 	ethread->func = NULL;
400fcf3ce44SJohn Forte 	ethread->arg1 = NULL;
401fcf3ce44SJohn Forte 	ethread->arg2 = NULL;
402fcf3ce44SJohn Forte 	cv_signal(&ethread->cv_flag);
403fcf3ce44SJohn Forte 
404fcf3ce44SJohn Forte 	/* Wait for thread to end */
405fcf3ce44SJohn Forte 	while (!(ethread->flags & EMLXS_THREAD_ENDED)) {
406fcf3ce44SJohn Forte 		mutex_exit(&ethread->lock);
407fcf3ce44SJohn Forte 		delay(drv_usectohz(10000));
408fcf3ce44SJohn Forte 		mutex_enter(&ethread->lock);
409fcf3ce44SJohn Forte 	}
410fcf3ce44SJohn Forte 
411fcf3ce44SJohn Forte 	mutex_exit(&ethread->lock);
412fcf3ce44SJohn Forte 
413fcf3ce44SJohn Forte 	cv_destroy(&ethread->cv_flag);
414fcf3ce44SJohn Forte 	mutex_destroy(&ethread->lock);
415fcf3ce44SJohn Forte 
416fcf3ce44SJohn Forte 	return;
417fcf3ce44SJohn Forte 
41882527734SSukumar Swaminathan } /* emlxs_thread_destroy() */
419fcf3ce44SJohn Forte 
420fcf3ce44SJohn Forte 
421fcf3ce44SJohn Forte void
emlxs_thread_trigger1(emlxs_thread_t * ethread,void (* func)())422fcf3ce44SJohn Forte emlxs_thread_trigger1(emlxs_thread_t *ethread, void (*func) ())
423fcf3ce44SJohn Forte {
424fcf3ce44SJohn Forte 
425fcf3ce44SJohn Forte 	/*
426291a2b48SSukumar Swaminathan 	 * If the thread lock can be acquired,
427291a2b48SSukumar Swaminathan 	 * it is in one of these states:
428291a2b48SSukumar Swaminathan 	 * 1. Thread not started.
429291a2b48SSukumar Swaminathan 	 * 2. Thread asleep.
430291a2b48SSukumar Swaminathan 	 * 3. Thread busy.
431291a2b48SSukumar Swaminathan 	 * 4. Thread ended.
432fcf3ce44SJohn Forte 	 */
433fcf3ce44SJohn Forte 	if (!(ethread->flags & EMLXS_THREAD_INITD)) {
434fcf3ce44SJohn Forte 		return;
435fcf3ce44SJohn Forte 	}
436291a2b48SSukumar Swaminathan 
437fcf3ce44SJohn Forte 	mutex_enter(&ethread->lock);
438fcf3ce44SJohn Forte 
439fcf3ce44SJohn Forte 	if (ethread->flags & EMLXS_THREAD_ENDED) {
440fcf3ce44SJohn Forte 		return;
441fcf3ce44SJohn Forte 	}
442291a2b48SSukumar Swaminathan 
443fcf3ce44SJohn Forte 	while (!(ethread->flags & EMLXS_THREAD_STARTED)) {
444fcf3ce44SJohn Forte 		mutex_exit(&ethread->lock);
445fcf3ce44SJohn Forte 		delay(drv_usectohz(10000));
446fcf3ce44SJohn Forte 		mutex_enter(&ethread->lock);
447fcf3ce44SJohn Forte 
448fcf3ce44SJohn Forte 		if (ethread->flags & EMLXS_THREAD_ENDED) {
449fcf3ce44SJohn Forte 			return;
450fcf3ce44SJohn Forte 		}
451fcf3ce44SJohn Forte 	}
452fcf3ce44SJohn Forte 
453fcf3ce44SJohn Forte 	ethread->flags |= EMLXS_THREAD_TRIGGERED;
454fcf3ce44SJohn Forte 	ethread->func = func;
455fcf3ce44SJohn Forte 	ethread->arg1 = NULL;
456fcf3ce44SJohn Forte 	ethread->arg2 = NULL;
457fcf3ce44SJohn Forte 
458fcf3ce44SJohn Forte 	if (ethread->flags & EMLXS_THREAD_ASLEEP) {
459fcf3ce44SJohn Forte 		cv_signal(&ethread->cv_flag);
460fcf3ce44SJohn Forte 	}
461291a2b48SSukumar Swaminathan 
462fcf3ce44SJohn Forte 	mutex_exit(&ethread->lock);
463fcf3ce44SJohn Forte 
464fcf3ce44SJohn Forte 	return;
465fcf3ce44SJohn Forte 
46682527734SSukumar Swaminathan } /* emlxs_thread_trigger1() */
467fcf3ce44SJohn Forte 
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte void
emlxs_thread_trigger2(emlxs_thread_t * ethread,void (* func)(),CHANNEL * cp)47082527734SSukumar Swaminathan emlxs_thread_trigger2(emlxs_thread_t *ethread, void (*func) (), CHANNEL *cp)
471291a2b48SSukumar Swaminathan {
472fcf3ce44SJohn Forte 
473fcf3ce44SJohn Forte 	/*
474291a2b48SSukumar Swaminathan 	 * If the thread lock can be acquired,
475291a2b48SSukumar Swaminathan 	 * it is in one of these states:
476291a2b48SSukumar Swaminathan 	 * 1. Thread not started.
477291a2b48SSukumar Swaminathan 	 * 2. Thread asleep.
478291a2b48SSukumar Swaminathan 	 * 3. Thread busy.
479291a2b48SSukumar Swaminathan 	 * 4. Thread ended.
480fcf3ce44SJohn Forte 	 */
481fcf3ce44SJohn Forte 	if (!(ethread->flags & EMLXS_THREAD_INITD)) {
482fcf3ce44SJohn Forte 		return;
483fcf3ce44SJohn Forte 	}
484291a2b48SSukumar Swaminathan 
485fcf3ce44SJohn Forte 	mutex_enter(&ethread->lock);
486fcf3ce44SJohn Forte 
487fcf3ce44SJohn Forte 	if (ethread->flags & EMLXS_THREAD_ENDED) {
488fcf3ce44SJohn Forte 		return;
489fcf3ce44SJohn Forte 	}
490291a2b48SSukumar Swaminathan 
491fcf3ce44SJohn Forte 	while (!(ethread->flags & EMLXS_THREAD_STARTED)) {
492fcf3ce44SJohn Forte 		mutex_exit(&ethread->lock);
493fcf3ce44SJohn Forte 		delay(drv_usectohz(10000));
494fcf3ce44SJohn Forte 		mutex_enter(&ethread->lock);
495fcf3ce44SJohn Forte 
496fcf3ce44SJohn Forte 		if (ethread->flags & EMLXS_THREAD_ENDED) {
497fcf3ce44SJohn Forte 			return;
498fcf3ce44SJohn Forte 		}
499fcf3ce44SJohn Forte 	}
500fcf3ce44SJohn Forte 
501fcf3ce44SJohn Forte 	ethread->flags |= EMLXS_THREAD_TRIGGERED;
502fcf3ce44SJohn Forte 	ethread->func = func;
50382527734SSukumar Swaminathan 	ethread->arg1 = (void *)cp;
504fcf3ce44SJohn Forte 	ethread->arg2 = NULL;
505fcf3ce44SJohn Forte 
506fcf3ce44SJohn Forte 	if (ethread->flags & EMLXS_THREAD_ASLEEP) {
507fcf3ce44SJohn Forte 		cv_signal(&ethread->cv_flag);
508fcf3ce44SJohn Forte 	}
509291a2b48SSukumar Swaminathan 
510fcf3ce44SJohn Forte 	mutex_exit(&ethread->lock);
511fcf3ce44SJohn Forte 
512fcf3ce44SJohn Forte 	return;
513fcf3ce44SJohn Forte 
51482527734SSukumar Swaminathan } /* emlxs_thread_trigger2() */
515bb63f56eSSukumar Swaminathan 
516bb63f56eSSukumar Swaminathan 
517bb63f56eSSukumar Swaminathan void
emlxs_thread_spawn(emlxs_hba_t * hba,void (* func)(),void * arg1,void * arg2)518bb63f56eSSukumar Swaminathan emlxs_thread_spawn(emlxs_hba_t *hba, void (*func) (), void *arg1, void *arg2)
519bb63f56eSSukumar Swaminathan {
520bb63f56eSSukumar Swaminathan 	emlxs_port_t	*port = &PPORT;
521bb63f56eSSukumar Swaminathan 	emlxs_thread_t	*ethread;
522bb63f56eSSukumar Swaminathan 
523bb63f56eSSukumar Swaminathan 	/* Create a thread */
524bb63f56eSSukumar Swaminathan 	ethread = (emlxs_thread_t *)kmem_alloc(sizeof (emlxs_thread_t),
525bb63f56eSSukumar Swaminathan 	    KM_NOSLEEP);
526bb63f56eSSukumar Swaminathan 
527bb63f56eSSukumar Swaminathan 	if (ethread == NULL) {
528bb63f56eSSukumar Swaminathan 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg,
529bb63f56eSSukumar Swaminathan 		    "Unable to allocate thread object.");
530bb63f56eSSukumar Swaminathan 
531bb63f56eSSukumar Swaminathan 		return;
532bb63f56eSSukumar Swaminathan 	}
533bb63f56eSSukumar Swaminathan 
534bb63f56eSSukumar Swaminathan 	bzero(ethread, sizeof (emlxs_thread_t));
535bb63f56eSSukumar Swaminathan 	ethread->hba = hba;
536bb63f56eSSukumar Swaminathan 	ethread->flags = EMLXS_THREAD_INITD | EMLXS_THREAD_RUN_ONCE;
537bb63f56eSSukumar Swaminathan 	ethread->func = func;
538bb63f56eSSukumar Swaminathan 	ethread->arg1 = arg1;
539bb63f56eSSukumar Swaminathan 	ethread->arg2 = arg2;
540bb63f56eSSukumar Swaminathan 
541bb63f56eSSukumar Swaminathan 	/* Queue the thread on the spawn thread list */
542d08970deSSukumar Swaminathan 	mutex_enter(&EMLXS_SPAWN_LOCK);
543bb63f56eSSukumar Swaminathan 
544bb63f56eSSukumar Swaminathan 	/* Dont spawn the thread if the spawn list is closed */
545bb63f56eSSukumar Swaminathan 	if (hba->spawn_open == 0) {
546d08970deSSukumar Swaminathan 		mutex_exit(&EMLXS_SPAWN_LOCK);
547bb63f56eSSukumar Swaminathan 
548bb63f56eSSukumar Swaminathan 		/* destroy the thread */
549bb63f56eSSukumar Swaminathan 		kmem_free(ethread, sizeof (emlxs_thread_t));
550bb63f56eSSukumar Swaminathan 		return;
551bb63f56eSSukumar Swaminathan 	}
552bb63f56eSSukumar Swaminathan 
553bb63f56eSSukumar Swaminathan 	if (hba->spawn_thread_head == NULL) {
554bb63f56eSSukumar Swaminathan 		hba->spawn_thread_head = ethread;
555bb63f56eSSukumar Swaminathan 	}
556bb63f56eSSukumar Swaminathan 	else
557bb63f56eSSukumar Swaminathan 	{
558bb63f56eSSukumar Swaminathan 		hba->spawn_thread_tail->next = ethread;
559bb63f56eSSukumar Swaminathan 		ethread->prev = hba->spawn_thread_tail;
560bb63f56eSSukumar Swaminathan 	}
561bb63f56eSSukumar Swaminathan 
562bb63f56eSSukumar Swaminathan 	hba->spawn_thread_tail = ethread;
563d08970deSSukumar Swaminathan 	mutex_exit(&EMLXS_SPAWN_LOCK);
564bb63f56eSSukumar Swaminathan 
565bb63f56eSSukumar Swaminathan 	(void) thread_create(NULL, 0, &emlxs_thread, (char *)ethread, 0, &p0,
566bb63f56eSSukumar Swaminathan 	    TS_RUN, v.v_maxsyspri - 2);
567bb63f56eSSukumar Swaminathan 
56882527734SSukumar Swaminathan } /* emlxs_thread_spawn() */
569bb63f56eSSukumar Swaminathan 
570bb63f56eSSukumar Swaminathan 
571bb63f56eSSukumar Swaminathan void
emlxs_thread_spawn_create(emlxs_hba_t * hba)572bb63f56eSSukumar Swaminathan emlxs_thread_spawn_create(emlxs_hba_t *hba)
573bb63f56eSSukumar Swaminathan {
574d08970deSSukumar Swaminathan 	mutex_enter(&EMLXS_SPAWN_LOCK);
575d08970deSSukumar Swaminathan 	if (hba->spawn_open) {
576d08970deSSukumar Swaminathan 		mutex_exit(&EMLXS_SPAWN_LOCK);
577bb63f56eSSukumar Swaminathan 		return;
578d08970deSSukumar Swaminathan 	}
579bb63f56eSSukumar Swaminathan 
580bb63f56eSSukumar Swaminathan 	hba->spawn_thread_head = NULL;
581bb63f56eSSukumar Swaminathan 	hba->spawn_thread_tail = NULL;
582bb63f56eSSukumar Swaminathan 
583bb63f56eSSukumar Swaminathan 	hba->spawn_open = 1;
584d08970deSSukumar Swaminathan 	mutex_exit(&EMLXS_SPAWN_LOCK);
585bb63f56eSSukumar Swaminathan 
586bb63f56eSSukumar Swaminathan }
587bb63f56eSSukumar Swaminathan 
588bb63f56eSSukumar Swaminathan 
589bb63f56eSSukumar Swaminathan void
emlxs_thread_spawn_destroy(emlxs_hba_t * hba)590bb63f56eSSukumar Swaminathan emlxs_thread_spawn_destroy(emlxs_hba_t *hba)
591bb63f56eSSukumar Swaminathan {
592bb63f56eSSukumar Swaminathan 	emlxs_thread_t	*ethread;
593bb63f56eSSukumar Swaminathan 
594d08970deSSukumar Swaminathan 	mutex_enter(&EMLXS_SPAWN_LOCK);
595bb63f56eSSukumar Swaminathan 	if (hba->spawn_open == 0) {
596d08970deSSukumar Swaminathan 		mutex_exit(&EMLXS_SPAWN_LOCK);
597bb63f56eSSukumar Swaminathan 		return;
598bb63f56eSSukumar Swaminathan 	}
599bb63f56eSSukumar Swaminathan 
600bb63f56eSSukumar Swaminathan 	hba->spawn_open = 0;
601bb63f56eSSukumar Swaminathan 
602bb63f56eSSukumar Swaminathan 	for (ethread = hba->spawn_thread_head; ethread;
603bb63f56eSSukumar Swaminathan 	    ethread = ethread->next) {
604bb63f56eSSukumar Swaminathan 		ethread->flags |= EMLXS_THREAD_KILLED;
605bb63f56eSSukumar Swaminathan 	}
606bb63f56eSSukumar Swaminathan 
607bb63f56eSSukumar Swaminathan 	/* Wait for all the spawned threads to complete */
608bb63f56eSSukumar Swaminathan 	while (hba->spawn_thread_head) {
609d08970deSSukumar Swaminathan 		mutex_exit(&EMLXS_SPAWN_LOCK);
610bb63f56eSSukumar Swaminathan 		delay(drv_usectohz(10000));
611d08970deSSukumar Swaminathan 		mutex_enter(&EMLXS_SPAWN_LOCK);
612bb63f56eSSukumar Swaminathan 	}
613bb63f56eSSukumar Swaminathan 
614d08970deSSukumar Swaminathan 	mutex_exit(&EMLXS_SPAWN_LOCK);
615bb63f56eSSukumar Swaminathan }
616