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