1 /* 2 * CDDL HEADER START 3 * 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. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <signal.h> 26 27 #include <fmd_alloc.h> 28 #include <fmd_thread.h> 29 #include <fmd_module.h> 30 #include <fmd_error.h> 31 #include <fmd_subr.h> 32 #include <fmd.h> 33 34 fmd_thread_t * 35 fmd_thread_xcreate(fmd_module_t *mp, pthread_t tid) 36 { 37 fmd_thread_t *tp = fmd_alloc(sizeof (fmd_thread_t), FMD_SLEEP); 38 39 tp->thr_mod = mp; 40 tp->thr_tid = tid; 41 tp->thr_func = NULL; 42 tp->thr_arg = NULL; 43 tp->thr_trdata = fmd_trace_create(); 44 tp->thr_trfunc = (fmd_tracebuf_f *)fmd.d_thr_trace; 45 tp->thr_errdepth = 0; 46 tp->thr_isdoor = 0; 47 48 (void) pthread_mutex_lock(&fmd.d_thr_lock); 49 fmd_list_append(&fmd.d_thr_list, tp); 50 (void) pthread_mutex_unlock(&fmd.d_thr_lock); 51 52 return (tp); 53 } 54 55 static void * 56 fmd_thread_start(void *arg) 57 { 58 fmd_thread_t *tp = arg; 59 60 if (pthread_setspecific(fmd.d_key, tp) != 0) 61 fmd_panic("failed to initialize thread key to %p", arg); 62 63 if (!tp->thr_isdoor) { 64 (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 65 (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 66 } 67 68 tp->thr_func(tp->thr_arg); 69 return (NULL); 70 } 71 72 static fmd_thread_t * 73 fmd_thread_create_cmn(fmd_module_t *mp, fmd_thread_f *func, void *arg, 74 int isdoor) 75 { 76 fmd_thread_t *tp = fmd_alloc(sizeof (fmd_thread_t), FMD_SLEEP); 77 sigset_t oset, nset; 78 int err; 79 80 tp->thr_mod = mp; 81 tp->thr_func = func; 82 tp->thr_arg = arg; 83 tp->thr_trdata = fmd_trace_create(); 84 tp->thr_trfunc = (fmd_tracebuf_f *)fmd.d_thr_trace; 85 tp->thr_errdepth = 0; 86 tp->thr_isdoor = isdoor; 87 88 (void) sigfillset(&nset); 89 (void) sigdelset(&nset, SIGABRT); /* always unblocked for fmd_panic() */ 90 if (!isdoor) 91 (void) sigdelset(&nset, fmd.d_thr_sig); /* fmd_thr_signal() */ 92 93 (void) pthread_sigmask(SIG_SETMASK, &nset, &oset); 94 err = pthread_create(&tp->thr_tid, NULL, fmd_thread_start, tp); 95 (void) pthread_sigmask(SIG_SETMASK, &oset, NULL); 96 97 if (err != 0) { 98 fmd_free(tp, sizeof (fmd_thread_t)); 99 return (NULL); 100 } 101 102 (void) pthread_mutex_lock(&fmd.d_thr_lock); 103 fmd_list_append(&fmd.d_thr_list, tp); 104 (void) pthread_mutex_unlock(&fmd.d_thr_lock); 105 106 return (tp); 107 } 108 109 fmd_thread_t * 110 fmd_thread_create(fmd_module_t *mp, fmd_thread_f *func, void *arg) 111 { 112 return (fmd_thread_create_cmn(mp, func, arg, 0)); 113 } 114 115 fmd_thread_t * 116 fmd_doorthread_create(fmd_module_t *mp, fmd_thread_f *func, void *arg) 117 { 118 return (fmd_thread_create_cmn(mp, func, arg, 1)); 119 } 120 121 void 122 fmd_thread_destroy(fmd_thread_t *tp, int flag) 123 { 124 if (flag == FMD_THREAD_JOIN && tp->thr_tid != pthread_self() && 125 pthread_join(tp->thr_tid, NULL) != 0) { 126 fmd_error(EFMD_MOD_JOIN, "failed to join thread for module " 127 "%s (tid %u)\n", tp->thr_mod->mod_name, tp->thr_tid); 128 } 129 130 (void) pthread_mutex_lock(&fmd.d_thr_lock); 131 fmd_list_delete(&fmd.d_thr_list, tp); 132 (void) pthread_mutex_unlock(&fmd.d_thr_lock); 133 134 fmd_trace_destroy(tp->thr_trdata); 135 fmd_free(tp, sizeof (fmd_thread_t)); 136 } 137