4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at
9 * http://www.opensource.org/licenses/cddl1.txt.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2004-2011 Emulex. All rights reserved.
24 * Use is subject to license terms.
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_THREAD_C
);
33 static void emlxs_thread(emlxs_thread_t
*ethread
);
34 static void emlxs_taskq_thread(emlxs_taskq_thread_t
*tthread
);
38 emlxs_taskq_thread(emlxs_taskq_thread_t
*tthread
)
44 taskq
= tthread
->taskq
;
46 mutex_enter(&tthread
->lock
);
47 tthread
->flags
|= EMLXS_THREAD_STARTED
;
49 while (!(tthread
->flags
& EMLXS_THREAD_KILLED
)) {
50 mutex_enter(&taskq
->put_lock
);
51 tthread
->next
= taskq
->put_head
;
52 taskq
->put_head
= tthread
;
54 mutex_exit(&taskq
->put_lock
);
56 tthread
->flags
|= EMLXS_THREAD_ASLEEP
;
57 cv_wait(&tthread
->cv_flag
, &tthread
->lock
);
58 tthread
->flags
&= ~EMLXS_THREAD_ASLEEP
;
64 tthread
->flags
|= EMLXS_THREAD_BUSY
;
65 mutex_exit(&tthread
->lock
);
67 func(taskq
->hba
, arg
);
69 mutex_enter(&tthread
->lock
);
70 tthread
->flags
&= ~EMLXS_THREAD_BUSY
;
74 tthread
->flags
|= EMLXS_THREAD_ENDED
;
75 mutex_exit(&tthread
->lock
);
79 } /* emlxs_taskq_thread() */
84 emlxs_taskq_dispatch(emlxs_taskq_t
*taskq
, void (*func
) (), void *arg
)
86 emlxs_taskq_thread_t
*tthread
= NULL
;
88 mutex_enter(&taskq
->get_lock
);
90 /* Make sure taskq is open for business */
92 mutex_exit(&taskq
->get_lock
);
96 /* Check get_list for a thread */
97 if (taskq
->get_head
) {
98 /* Get the next thread */
99 tthread
= taskq
->get_head
;
101 taskq
->get_head
= (taskq
->get_count
) ? tthread
->next
: NULL
;
102 tthread
->next
= NULL
;
105 /* Else check put_list for a thread */
106 else if (taskq
->put_head
) {
108 /* Move put_list to get_list */
109 mutex_enter(&taskq
->put_lock
);
110 taskq
->get_head
= taskq
->put_head
;
111 taskq
->get_count
= taskq
->put_count
;
112 taskq
->put_head
= NULL
;
113 taskq
->put_count
= 0;
114 mutex_exit(&taskq
->put_lock
);
116 /* Get the next thread */
117 tthread
= taskq
->get_head
;
119 taskq
->get_head
= (taskq
->get_count
) ? tthread
->next
: NULL
;
120 tthread
->next
= NULL
;
123 mutex_exit(&taskq
->get_lock
);
125 /* Wake up the thread if one exists */
127 mutex_enter(&tthread
->lock
);
128 tthread
->func
= func
;
130 cv_signal(&tthread
->cv_flag
);
131 mutex_exit(&tthread
->lock
);
138 } /* emlxs_taskq_dispatch() */
143 emlxs_taskq_create(emlxs_hba_t
*hba
, emlxs_taskq_t
*taskq
)
145 emlxs_taskq_thread_t
*tthread
;
149 /* If taskq is already open then quit */
155 bzero(taskq
, sizeof (emlxs_taskq_t
));
157 mutex_init(&taskq
->get_lock
, NULL
, MUTEX_DRIVER
,
158 DDI_INTR_PRI(hba
->intr_arg
));
160 mutex_enter(&taskq
->get_lock
);
164 mutex_init(&taskq
->put_lock
, NULL
, MUTEX_DRIVER
,
165 DDI_INTR_PRI(hba
->intr_arg
));
167 for (i
= 0; i
< EMLXS_MAX_TASKQ_THREADS
; i
++) {
168 tthread
= &taskq
->thread_list
[i
];
169 tthread
->taskq
= taskq
;
171 mutex_init(&tthread
->lock
, NULL
, MUTEX_DRIVER
,
172 DDI_INTR_PRI(hba
->intr_arg
));
174 cv_init(&tthread
->cv_flag
, NULL
, CV_DRIVER
, NULL
);
176 tthread
->flags
|= EMLXS_THREAD_INITD
;
178 thread_create(NULL
, 0, emlxs_taskq_thread
,
179 (char *)tthread
, 0, &p0
, TS_RUN
, v
.v_maxsyspri
- 2);
185 mutex_exit(&taskq
->get_lock
);
189 } /* emlxs_taskq_create() */
193 emlxs_taskq_destroy(emlxs_taskq_t
*taskq
)
195 emlxs_taskq_thread_t
*tthread
;
198 /* If taskq already closed, then quit */
203 mutex_enter(&taskq
->get_lock
);
205 /* If taskq already closed, then quit */
207 mutex_exit(&taskq
->get_lock
);
212 mutex_exit(&taskq
->get_lock
);
215 /* No more threads can be dispatched now */
217 /* Kill the threads */
218 for (i
= 0; i
< EMLXS_MAX_TASKQ_THREADS
; i
++) {
219 tthread
= &taskq
->thread_list
[i
];
222 * If the thread lock can be acquired,
223 * it is in one of these states:
224 * 1. Thread not started.
229 mutex_enter(&tthread
->lock
);
230 tthread
->flags
|= EMLXS_THREAD_KILLED
;
231 cv_signal(&tthread
->cv_flag
);
233 /* Wait for thread to die */
234 while (!(tthread
->flags
& EMLXS_THREAD_ENDED
)) {
235 mutex_exit(&tthread
->lock
);
236 delay(drv_usectohz(10000));
237 mutex_enter(&tthread
->lock
);
239 mutex_exit(&tthread
->lock
);
241 /* Clean up thread */
242 mutex_destroy(&tthread
->lock
);
243 cv_destroy(&tthread
->cv_flag
);
247 mutex_destroy(&taskq
->put_lock
);
248 mutex_destroy(&taskq
->get_lock
);
252 } /* emlxs_taskq_destroy() */
257 emlxs_thread(emlxs_thread_t
*ethread
)
264 if (ethread
->flags
& EMLXS_THREAD_RUN_ONCE
) {
266 ethread
->flags
|= EMLXS_THREAD_STARTED
;
268 if (!(ethread
->flags
& EMLXS_THREAD_KILLED
)) {
269 func
= ethread
->func
;
270 arg1
= ethread
->arg1
;
271 arg2
= ethread
->arg2
;
273 func(hba
, arg1
, arg2
);
276 ethread
->flags
|= EMLXS_THREAD_ENDED
;
277 ethread
->flags
&= ~EMLXS_THREAD_INITD
;
279 /* Remove the thread from the spawn thread list */
280 mutex_enter(&EMLXS_SPAWN_LOCK
);
281 if (hba
->spawn_thread_head
== ethread
)
282 hba
->spawn_thread_head
= ethread
->next
;
283 if (hba
->spawn_thread_tail
== ethread
)
284 hba
->spawn_thread_tail
= ethread
->prev
;
287 ethread
->prev
->next
= ethread
->next
;
289 ethread
->next
->prev
= ethread
->prev
;
291 ethread
->next
= ethread
->prev
= NULL
;
293 kmem_free(ethread
, sizeof (emlxs_thread_t
));
295 mutex_exit(&EMLXS_SPAWN_LOCK
);
300 * If the thread lock can be acquired,
301 * it is in one of these states:
302 * 1. Thread not started.
307 mutex_enter(ðread
->lock
);
308 ethread
->flags
|= EMLXS_THREAD_STARTED
;
310 while (!(ethread
->flags
& EMLXS_THREAD_KILLED
)) {
311 if (!(ethread
->flags
& EMLXS_THREAD_TRIGGERED
)) {
312 ethread
->flags
|= EMLXS_THREAD_ASLEEP
;
313 cv_wait(ðread
->cv_flag
, ðread
->lock
);
317 ~(EMLXS_THREAD_ASLEEP
| EMLXS_THREAD_TRIGGERED
);
320 func
= ethread
->func
;
321 arg1
= ethread
->arg1
;
322 arg2
= ethread
->arg2
;
323 ethread
->func
= NULL
;
324 ethread
->arg1
= NULL
;
325 ethread
->arg2
= NULL
;
327 ethread
->flags
|= EMLXS_THREAD_BUSY
;
328 mutex_exit(ðread
->lock
);
330 func(ethread
->hba
, arg1
, arg2
);
332 mutex_enter(ðread
->lock
);
333 ethread
->flags
&= ~EMLXS_THREAD_BUSY
;
337 ethread
->flags
|= EMLXS_THREAD_ENDED
;
338 mutex_exit(ðread
->lock
);
343 } /* emlxs_thread() */
347 emlxs_thread_create(emlxs_hba_t
*hba
, emlxs_thread_t
*ethread
)
351 if (ethread
->flags
& EMLXS_THREAD_INITD
) {
355 bzero(ethread
, sizeof (emlxs_thread_t
));
357 mutex_init(ðread
->lock
, NULL
, MUTEX_DRIVER
,
358 DDI_INTR_PRI(hba
->intr_arg
));
360 cv_init(ðread
->cv_flag
, NULL
, CV_DRIVER
, NULL
);
363 ethread
->flags
|= EMLXS_THREAD_INITD
;
365 pri
= v
.v_maxsyspri
- 2;
368 thread_create(NULL
, 0, emlxs_thread
, (char *)ethread
, 0, &p0
,
371 } /* emlxs_thread_create() */
375 emlxs_thread_destroy(emlxs_thread_t
*ethread
)
378 * If the thread lock can be acquired,
379 * it is in one of these states:
380 * 1. Thread not started.
385 if (!(ethread
->flags
& EMLXS_THREAD_INITD
)) {
390 mutex_enter(ðread
->lock
);
392 if (ethread
->flags
& EMLXS_THREAD_ENDED
) {
393 mutex_exit(ðread
->lock
);
397 ethread
->flags
&= ~EMLXS_THREAD_INITD
;
398 ethread
->flags
|= (EMLXS_THREAD_KILLED
| EMLXS_THREAD_TRIGGERED
);
399 ethread
->func
= NULL
;
400 ethread
->arg1
= NULL
;
401 ethread
->arg2
= NULL
;
402 cv_signal(ðread
->cv_flag
);
404 /* Wait for thread to end */
405 while (!(ethread
->flags
& EMLXS_THREAD_ENDED
)) {
406 mutex_exit(ðread
->lock
);
407 delay(drv_usectohz(10000));
408 mutex_enter(ðread
->lock
);
411 mutex_exit(ðread
->lock
);
413 cv_destroy(ðread
->cv_flag
);
414 mutex_destroy(ðread
->lock
);
418 } /* emlxs_thread_destroy() */
422 emlxs_thread_trigger1(emlxs_thread_t
*ethread
, void (*func
) ())
426 * If the thread lock can be acquired,
427 * it is in one of these states:
428 * 1. Thread not started.
433 if (!(ethread
->flags
& EMLXS_THREAD_INITD
)) {
437 mutex_enter(ðread
->lock
);
439 if (ethread
->flags
& EMLXS_THREAD_ENDED
) {
443 while (!(ethread
->flags
& EMLXS_THREAD_STARTED
)) {
444 mutex_exit(ðread
->lock
);
445 delay(drv_usectohz(10000));
446 mutex_enter(ðread
->lock
);
448 if (ethread
->flags
& EMLXS_THREAD_ENDED
) {
453 ethread
->flags
|= EMLXS_THREAD_TRIGGERED
;
454 ethread
->func
= func
;
455 ethread
->arg1
= NULL
;
456 ethread
->arg2
= NULL
;
458 if (ethread
->flags
& EMLXS_THREAD_ASLEEP
) {
459 cv_signal(ðread
->cv_flag
);
462 mutex_exit(ðread
->lock
);
466 } /* emlxs_thread_trigger1() */
470 emlxs_thread_trigger2(emlxs_thread_t
*ethread
, void (*func
) (), CHANNEL
*cp
)
474 * If the thread lock can be acquired,
475 * it is in one of these states:
476 * 1. Thread not started.
481 if (!(ethread
->flags
& EMLXS_THREAD_INITD
)) {
485 mutex_enter(ðread
->lock
);
487 if (ethread
->flags
& EMLXS_THREAD_ENDED
) {
491 while (!(ethread
->flags
& EMLXS_THREAD_STARTED
)) {
492 mutex_exit(ðread
->lock
);
493 delay(drv_usectohz(10000));
494 mutex_enter(ðread
->lock
);
496 if (ethread
->flags
& EMLXS_THREAD_ENDED
) {
501 ethread
->flags
|= EMLXS_THREAD_TRIGGERED
;
502 ethread
->func
= func
;
503 ethread
->arg1
= (void *)cp
;
504 ethread
->arg2
= NULL
;
506 if (ethread
->flags
& EMLXS_THREAD_ASLEEP
) {
507 cv_signal(ðread
->cv_flag
);
510 mutex_exit(ðread
->lock
);
514 } /* emlxs_thread_trigger2() */
518 emlxs_thread_spawn(emlxs_hba_t
*hba
, void (*func
) (), void *arg1
, void *arg2
)
520 emlxs_port_t
*port
= &PPORT
;
521 emlxs_thread_t
*ethread
;
523 /* Create a thread */
524 ethread
= (emlxs_thread_t
*)kmem_alloc(sizeof (emlxs_thread_t
),
527 if (ethread
== NULL
) {
528 EMLXS_MSGF(EMLXS_CONTEXT
, &emlxs_mem_alloc_failed_msg
,
529 "Unable to allocate thread object.");
534 bzero(ethread
, sizeof (emlxs_thread_t
));
536 ethread
->flags
= EMLXS_THREAD_INITD
| EMLXS_THREAD_RUN_ONCE
;
537 ethread
->func
= func
;
538 ethread
->arg1
= arg1
;
539 ethread
->arg2
= arg2
;
541 /* Queue the thread on the spawn thread list */
542 mutex_enter(&EMLXS_SPAWN_LOCK
);
544 /* Dont spawn the thread if the spawn list is closed */
545 if (hba
->spawn_open
== 0) {
546 mutex_exit(&EMLXS_SPAWN_LOCK
);
548 /* destroy the thread */
549 kmem_free(ethread
, sizeof (emlxs_thread_t
));
553 if (hba
->spawn_thread_head
== NULL
) {
554 hba
->spawn_thread_head
= ethread
;
558 hba
->spawn_thread_tail
->next
= ethread
;
559 ethread
->prev
= hba
->spawn_thread_tail
;
562 hba
->spawn_thread_tail
= ethread
;
563 mutex_exit(&EMLXS_SPAWN_LOCK
);
565 (void) thread_create(NULL
, 0, &emlxs_thread
, (char *)ethread
, 0, &p0
,
566 TS_RUN
, v
.v_maxsyspri
- 2);
568 } /* emlxs_thread_spawn() */
572 emlxs_thread_spawn_create(emlxs_hba_t
*hba
)
574 mutex_enter(&EMLXS_SPAWN_LOCK
);
575 if (hba
->spawn_open
) {
576 mutex_exit(&EMLXS_SPAWN_LOCK
);
580 hba
->spawn_thread_head
= NULL
;
581 hba
->spawn_thread_tail
= NULL
;
584 mutex_exit(&EMLXS_SPAWN_LOCK
);
590 emlxs_thread_spawn_destroy(emlxs_hba_t
*hba
)
592 emlxs_thread_t
*ethread
;
594 mutex_enter(&EMLXS_SPAWN_LOCK
);
595 if (hba
->spawn_open
== 0) {
596 mutex_exit(&EMLXS_SPAWN_LOCK
);
602 for (ethread
= hba
->spawn_thread_head
; ethread
;
603 ethread
= ethread
->next
) {
604 ethread
->flags
|= EMLXS_THREAD_KILLED
;
607 /* Wait for all the spawned threads to complete */
608 while (hba
->spawn_thread_head
) {
609 mutex_exit(&EMLXS_SPAWN_LOCK
);
610 delay(drv_usectohz(10000));
611 mutex_enter(&EMLXS_SPAWN_LOCK
);
614 mutex_exit(&EMLXS_SPAWN_LOCK
);