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 }