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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/param.h> 29 #include <sys/t_lock.h> 30 #include <sys/types.h> 31 #include <sys/time.h> 32 #include <sys/sysmacros.h> 33 #include <sys/systm.h> 34 #include <sys/cpuvar.h> 35 #include <sys/user.h> 36 #include <sys/proc.h> 37 #include <sys/callb.h> 38 #include <sys/kmem.h> 39 #include <sys/cmn_err.h> 40 #include <sys/swap.h> 41 #include <sys/vmsystm.h> 42 #include <sys/class.h> 43 #include <sys/debug.h> 44 #include <sys/thread.h> 45 #include <sys/kobj.h> 46 #include <sys/ddi.h> /* for delay() */ 47 #include <sys/taskq.h> /* For TASKQ_NAMELEN */ 48 49 #define CB_MAXNAME TASKQ_NAMELEN 50 51 /* 52 * The callb mechanism provides generic event scheduling/echoing. 53 * A callb function is registered and called on behalf of the event. 54 */ 55 typedef struct callb { 56 struct callb *c_next; /* next in class or on freelist */ 57 kthread_id_t c_thread; /* ptr to caller's thread struct */ 58 char c_flag; /* info about the callb state */ 59 uchar_t c_class; /* this callb's class */ 60 kcondvar_t c_done_cv; /* signal callb completion */ 61 boolean_t (*c_func)(); /* cb function: returns true if ok */ 62 void *c_arg; /* arg to c_func */ 63 char c_name[CB_MAXNAME+1]; /* debug:max func name length */ 64 } callb_t; 65 66 /* 67 * callb c_flag bitmap definitions 68 */ 69 #define CALLB_FREE 0x0 70 #define CALLB_TAKEN 0x1 71 #define CALLB_EXECUTING 0x2 72 73 /* 74 * Basic structure for a callb table. 75 * All callbs are organized into different class groups described 76 * by ct_class array. 77 * The callbs within a class are single-linked and normally run by a 78 * serial execution. 79 */ 80 typedef struct callb_table { 81 kmutex_t ct_lock; /* protect all callb states */ 82 callb_t *ct_freelist; /* free callb structures */ 83 int ct_busy; /* != 0 prevents additions */ 84 kcondvar_t ct_busy_cv; /* to wait for not busy */ 85 int ct_ncallb; /* num of callbs allocated */ 86 callb_t *ct_first_cb[NCBCLASS]; /* ptr to 1st callb in a class */ 87 } callb_table_t; 88 89 int callb_timeout_sec = CPR_KTHREAD_TIMEOUT_SEC; 90 91 static callb_id_t callb_add_common(boolean_t (*)(void *, int), 92 void *, int, char *, kthread_id_t); 93 94 static callb_table_t callb_table; /* system level callback table */ 95 static callb_table_t *ct = &callb_table; 96 static kmutex_t callb_safe_mutex; 97 callb_cpr_t callb_cprinfo_safe = { 98 &callb_safe_mutex, CALLB_CPR_ALWAYS_SAFE, 0, 0, 0 }; 99 100 /* 101 * Init all callb tables in the system. 102 */ 103 void 104 callb_init() 105 { 106 callb_table.ct_busy = 0; /* mark table open for additions */ 107 mutex_init(&callb_safe_mutex, NULL, MUTEX_DEFAULT, NULL); 108 mutex_init(&callb_table.ct_lock, NULL, MUTEX_DEFAULT, NULL); 109 } 110 111 /* 112 * callout_add() is called to register func() be called later. 113 */ 114 static callb_id_t 115 callb_add_common(boolean_t (*func)(void *arg, int code), 116 void *arg, int class, char *name, kthread_id_t t) 117 { 118 callb_t *cp; 119 120 ASSERT(class < NCBCLASS); 121 122 mutex_enter(&ct->ct_lock); 123 while (ct->ct_busy) 124 cv_wait(&ct->ct_busy_cv, &ct->ct_lock); 125 if ((cp = ct->ct_freelist) == NULL) { 126 ct->ct_ncallb++; 127 cp = (callb_t *)kmem_zalloc(sizeof (callb_t), KM_SLEEP); 128 } 129 ct->ct_freelist = cp->c_next; 130 cp->c_thread = t; 131 cp->c_func = func; 132 cp->c_arg = arg; 133 cp->c_class = (uchar_t)class; 134 cp->c_flag |= CALLB_TAKEN; 135 #ifdef DEBUG 136 if (strlen(name) > CB_MAXNAME) 137 cmn_err(CE_WARN, "callb_add: name of callback function '%s' " 138 "too long -- truncated to %d chars", 139 name, CB_MAXNAME); 140 #endif 141 (void) strncpy(cp->c_name, name, CB_MAXNAME); 142 cp->c_name[CB_MAXNAME] = '\0'; 143 144 /* 145 * Insert the new callb at the head of its class list. 146 */ 147 cp->c_next = ct->ct_first_cb[class]; 148 ct->ct_first_cb[class] = cp; 149 150 mutex_exit(&ct->ct_lock); 151 return ((callb_id_t)cp); 152 } 153 154 /* 155 * The default function to add an entry to the callback table. Since 156 * it uses curthread as the thread identifier to store in the table, 157 * it should be used for the normal case of a thread which is calling 158 * to add ITSELF to the table. 159 */ 160 callb_id_t 161 callb_add(boolean_t (*func)(void *arg, int code), 162 void *arg, int class, char *name) 163 { 164 return (callb_add_common(func, arg, class, name, curthread)); 165 } 166 167 /* 168 * A special version of callb_add() above for use by threads which 169 * might be adding an entry to the table on behalf of some other 170 * thread (for example, one which is constructed but not yet running). 171 * In this version the thread id is an argument. 172 */ 173 callb_id_t 174 callb_add_thread(boolean_t (*func)(void *arg, int code), 175 void *arg, int class, char *name, kthread_id_t t) 176 { 177 return (callb_add_common(func, arg, class, name, t)); 178 } 179 180 /* 181 * callout_delete() is called to remove an entry identified by id 182 * that was originally placed there by a call to callout_add(). 183 * return -1 if fail to delete a callb entry otherwise return 0. 184 */ 185 int 186 callb_delete(callb_id_t id) 187 { 188 callb_t **pp; 189 callb_t *me = (callb_t *)id; 190 191 mutex_enter(&ct->ct_lock); 192 193 for (;;) { 194 pp = &ct->ct_first_cb[me->c_class]; 195 while (*pp != NULL && *pp != me) 196 pp = &(*pp)->c_next; 197 198 #ifdef DEBUG 199 if (*pp != me) { 200 cmn_err(CE_WARN, "callb delete bogus entry 0x%p", 201 (void *)me); 202 mutex_exit(&ct->ct_lock); 203 return (-1); 204 } 205 #endif /* DEBUG */ 206 207 /* 208 * It is not allowed to delete a callb in the middle of 209 * executing otherwise, the callb_execute() will be confused. 210 */ 211 if (!(me->c_flag & CALLB_EXECUTING)) 212 break; 213 214 cv_wait(&me->c_done_cv, &ct->ct_lock); 215 } 216 /* relink the class list */ 217 *pp = me->c_next; 218 219 /* clean up myself and return the free callb to the head of freelist */ 220 me->c_flag = CALLB_FREE; 221 me->c_next = ct->ct_freelist; 222 ct->ct_freelist = me; 223 224 mutex_exit(&ct->ct_lock); 225 return (0); 226 } 227 228 /* 229 * class: indicates to execute all callbs in the same class; 230 * code: optional argument for the callb functions. 231 * return: = 0: success 232 * != 0: ptr to string supplied when callback was registered 233 */ 234 void * 235 callb_execute_class(int class, int code) 236 { 237 callb_t *cp; 238 void *ret = NULL; 239 240 ASSERT(class < NCBCLASS); 241 242 mutex_enter(&ct->ct_lock); 243 244 for (cp = ct->ct_first_cb[class]; 245 cp != NULL && ret == 0; cp = cp->c_next) { 246 while (cp->c_flag & CALLB_EXECUTING) 247 cv_wait(&cp->c_done_cv, &ct->ct_lock); 248 /* 249 * cont if the callb is deleted while we're sleeping 250 */ 251 if (cp->c_flag == CALLB_FREE) 252 continue; 253 cp->c_flag |= CALLB_EXECUTING; 254 255 #ifdef CALLB_DEBUG 256 printf("callb_execute: name=%s func=%p arg=%p\n", 257 cp->c_name, (void *)cp->c_func, (void *)cp->c_arg); 258 #endif /* CALLB_DEBUG */ 259 260 mutex_exit(&ct->ct_lock); 261 /* If callback function fails, pass back client's name */ 262 if (!(*cp->c_func)(cp->c_arg, code)) 263 ret = cp->c_name; 264 mutex_enter(&ct->ct_lock); 265 266 cp->c_flag &= ~CALLB_EXECUTING; 267 cv_broadcast(&cp->c_done_cv); 268 } 269 mutex_exit(&ct->ct_lock); 270 return (ret); 271 } 272 273 /* 274 * callers make sure no recursive entries to this func. 275 * dp->cc_lockp is registered by callb_add to protect callb_cpr_t structure. 276 * 277 * When calling to stop a kernel thread (code == CB_CODE_CPR_CHKPT) we 278 * use a cv_timedwait() in case the kernel thread is blocked. 279 * 280 * Note that this is a generic callback handler for daemon CPR and 281 * should NOT be changed to accommodate any specific requirement in a daemon. 282 * Individual daemons that require changes to the handler shall write 283 * callback routines in their own daemon modules. 284 */ 285 boolean_t 286 callb_generic_cpr(void *arg, int code) 287 { 288 callb_cpr_t *cp = (callb_cpr_t *)arg; 289 clock_t ret = 0; /* assume success */ 290 291 mutex_enter(cp->cc_lockp); 292 293 switch (code) { 294 case CB_CODE_CPR_CHKPT: 295 cp->cc_events |= CALLB_CPR_START; 296 #ifdef CPR_NOT_THREAD_SAFE 297 while (!(cp->cc_events & CALLB_CPR_SAFE)) 298 /* cv_timedwait() returns -1 if it times out. */ 299 if ((ret = cv_timedwait(&cp->cc_callb_cv, 300 cp->cc_lockp, 301 lbolt + callb_timeout_sec * hz)) == -1) 302 break; 303 #endif 304 break; 305 306 case CB_CODE_CPR_RESUME: 307 cp->cc_events &= ~CALLB_CPR_START; 308 cv_signal(&cp->cc_stop_cv); 309 break; 310 } 311 mutex_exit(cp->cc_lockp); 312 return (ret != -1); 313 } 314 315 /* 316 * The generic callback function associated with kernel threads which 317 * are always considered safe. 318 */ 319 /* ARGSUSED */ 320 boolean_t 321 callb_generic_cpr_safe(void *arg, int code) 322 { 323 return (B_TRUE); 324 } 325 /* 326 * Prevent additions to callback table. 327 */ 328 void 329 callb_lock_table(void) 330 { 331 mutex_enter(&ct->ct_lock); 332 ASSERT(ct->ct_busy == 0); 333 ct->ct_busy = 1; 334 mutex_exit(&ct->ct_lock); 335 } 336 337 /* 338 * Allow additions to callback table. 339 */ 340 void 341 callb_unlock_table(void) 342 { 343 mutex_enter(&ct->ct_lock); 344 ASSERT(ct->ct_busy != 0); 345 ct->ct_busy = 0; 346 cv_broadcast(&ct->ct_busy_cv); 347 mutex_exit(&ct->ct_lock); 348 } 349 350 /* 351 * Return a boolean value indicating whether a particular kernel thread is 352 * stopped in accordance with the cpr callback protocol. If returning 353 * false, also return a pointer to the thread name via the 2nd argument. 354 */ 355 boolean_t 356 callb_is_stopped(kthread_id_t tp, caddr_t *thread_name) 357 { 358 callb_t *cp; 359 boolean_t ret_val; 360 361 mutex_enter(&ct->ct_lock); 362 363 for (cp = ct->ct_first_cb[CB_CL_CPR_DAEMON]; 364 cp != NULL && tp != cp->c_thread; cp = cp->c_next) 365 ; 366 367 ret_val = (cp != NULL); 368 if (ret_val) { 369 /* 370 * We found the thread in the callback table and have 371 * provisionally set the return value to true. Now 372 * see if it is marked "safe" and is sleeping or stopped. 373 */ 374 callb_cpr_t *ccp = (callb_cpr_t *)cp->c_arg; 375 376 *thread_name = cp->c_name; /* in case not stopped */ 377 mutex_enter(ccp->cc_lockp); 378 379 if (ccp->cc_events & CALLB_CPR_SAFE) { 380 int retry; 381 382 mutex_exit(ccp->cc_lockp); 383 for (retry = 0; retry < CALLB_MAX_RETRY; retry++) { 384 thread_lock(tp); 385 if (tp->t_state & (TS_SLEEP | TS_STOPPED)) { 386 thread_unlock(tp); 387 break; 388 } 389 thread_unlock(tp); 390 delay(CALLB_THREAD_DELAY); 391 } 392 ret_val = retry < CALLB_MAX_RETRY; 393 } else { 394 ret_val = 395 (ccp->cc_events & CALLB_CPR_ALWAYS_SAFE) != 0; 396 mutex_exit(ccp->cc_lockp); 397 } 398 } else { 399 /* 400 * Thread not found in callback table. Make the best 401 * attempt to identify the thread in the error message. 402 */ 403 ulong_t offset; 404 char *sym = kobj_getsymname((uintptr_t)tp->t_startpc, 405 &offset); 406 407 *thread_name = sym ? sym : "*unknown*"; 408 } 409 410 mutex_exit(&ct->ct_lock); 411 return (ret_val); 412 } 413