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(ðread->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(ðread->cv_flag, ðread->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(ðread->lock);
329bb63f56eSSukumar Swaminathan
33082527734SSukumar Swaminathan func(ethread->hba, arg1, arg2);
331bb63f56eSSukumar Swaminathan
33282527734SSukumar Swaminathan mutex_enter(ðread->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(ðread->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(ðread->lock, NULL, MUTEX_DRIVER,
358a9800bebSGarrett D'Amore DDI_INTR_PRI(hba->intr_arg));
359fcf3ce44SJohn Forte
360*8f23e9faSHans Rosenfeld cv_init(ðread->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(ðread->lock);
391fcf3ce44SJohn Forte
392fcf3ce44SJohn Forte if (ethread->flags & EMLXS_THREAD_ENDED) {
393bb63f56eSSukumar Swaminathan mutex_exit(ðread->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(ðread->cv_flag);
403fcf3ce44SJohn Forte
404fcf3ce44SJohn Forte /* Wait for thread to end */
405fcf3ce44SJohn Forte while (!(ethread->flags & EMLXS_THREAD_ENDED)) {
406fcf3ce44SJohn Forte mutex_exit(ðread->lock);
407fcf3ce44SJohn Forte delay(drv_usectohz(10000));
408fcf3ce44SJohn Forte mutex_enter(ðread->lock);
409fcf3ce44SJohn Forte }
410fcf3ce44SJohn Forte
411fcf3ce44SJohn Forte mutex_exit(ðread->lock);
412fcf3ce44SJohn Forte
413fcf3ce44SJohn Forte cv_destroy(ðread->cv_flag);
414fcf3ce44SJohn Forte mutex_destroy(ðread->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(ðread->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(ðread->lock);
445fcf3ce44SJohn Forte delay(drv_usectohz(10000));
446fcf3ce44SJohn Forte mutex_enter(ðread->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(ðread->cv_flag);
460fcf3ce44SJohn Forte }
461291a2b48SSukumar Swaminathan
462fcf3ce44SJohn Forte mutex_exit(ðread->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(ðread->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(ðread->lock);
493fcf3ce44SJohn Forte delay(drv_usectohz(10000));
494fcf3ce44SJohn Forte mutex_enter(ðread->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(ðread->cv_flag);
508fcf3ce44SJohn Forte }
509291a2b48SSukumar Swaminathan
510fcf3ce44SJohn Forte mutex_exit(ðread->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