callb.h revision 168404
1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License, Version 1.0 only 6168404Spjd * (the "License"). You may not use this file except in compliance 7168404Spjd * with the License. 8168404Spjd * 9168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10168404Spjd * or http://www.opensolaris.org/os/licensing. 11168404Spjd * See the License for the specific language governing permissions 12168404Spjd * and limitations under the License. 13168404Spjd * 14168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 15168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16168404Spjd * If applicable, add the following below this CDDL HEADER, with the 17168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 18168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 19168404Spjd * 20168404Spjd * CDDL HEADER END 21168404Spjd */ 22168404Spjd/* 23168404Spjd * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24168404Spjd * Use is subject to license terms. 25168404Spjd */ 26168404Spjd 27168404Spjd#ifndef _SYS_CALLB_H 28168404Spjd#define _SYS_CALLB_H 29168404Spjd 30168404Spjd#pragma ident "%Z%%M% %I% %E% SMI" 31168404Spjd 32168404Spjd#include <sys/t_lock.h> 33168404Spjd#include <sys/thread.h> 34168404Spjd 35168404Spjd#ifdef __cplusplus 36168404Spjdextern "C" { 37168404Spjd#endif 38168404Spjd 39168404Spjd/* 40168404Spjd * definitions of callback classes (c_class) 41168404Spjd * 42168404Spjd * Callbacks belong in the same class if (1) their callback routines 43168404Spjd * do the same kind of processing (ideally, using the same callback function) 44168404Spjd * and (2) they can/should be executed at the same time in a cpr 45168404Spjd * suspend/resume operation. 46168404Spjd * 47168404Spjd * Note: The DAEMON class, in particular, is for stopping kernel threads 48168404Spjd * and nothing else. The CALLB_* macros below should be used to deal 49168404Spjd * with kernel threads, and the callback function should be callb_generic_cpr. 50168404Spjd * Another idiosyncrasy of the DAEMON class is that if a suspend operation 51168404Spjd * fails, some of the callback functions may be called with the RESUME 52168404Spjd * code which were never called with SUSPEND. Not a problem currently, 53168404Spjd * but see bug 4201851. 54168404Spjd */ 55168404Spjd#define CB_CL_CPR_DAEMON 0 56168404Spjd#define CB_CL_CPR_VM 1 57168404Spjd#define CB_CL_CPR_CALLOUT 2 58168404Spjd#define CB_CL_CPR_OBP 3 59168404Spjd#define CB_CL_CPR_FB 4 60168404Spjd#define CB_CL_PANIC 5 61168404Spjd#define CB_CL_CPR_RPC 6 62168404Spjd#define CB_CL_CPR_PROMPRINTF 7 63168404Spjd#define CB_CL_UADMIN 8 64168404Spjd#define CB_CL_CPR_PM 9 65168404Spjd#define CB_CL_HALT 10 66168404Spjd#define CB_CL_CPR_DMA 11 67168404Spjd#define CB_CL_CPR_POST_USER 12 68168404Spjd#define CB_CL_UADMIN_PRE_VFS 13 69168404Spjd#define CB_CL_MDBOOT CB_CL_UADMIN 70168404Spjd#define CB_CL_ENTER_DEBUGGER 14 71168404Spjd#define CB_CL_CPR_POST_KERNEL 15 72168404Spjd#define NCBCLASS 16 /* CHANGE ME if classes are added/removed */ 73168404Spjd 74168404Spjd/* 75168404Spjd * CB_CL_CPR_DAEMON class specific definitions are given below: 76168404Spjd */ 77168404Spjd 78168404Spjd/* 79168404Spjd * code for CPR callb_execute_class 80168404Spjd */ 81168404Spjd#define CB_CODE_CPR_CHKPT 0 82168404Spjd#define CB_CODE_CPR_RESUME 1 83168404Spjd 84168404Spjdtypedef void * callb_id_t; 85168404Spjd/* 86168404Spjd * Per kernel thread structure for CPR daemon callbacks. 87168404Spjd * Must be protected by either a existing lock in the daemon or 88168404Spjd * a new lock created for such a purpose. 89168404Spjd */ 90168404Spjdtypedef struct callb_cpr { 91168404Spjd kmutex_t *cc_lockp; /* lock to protect this struct */ 92168404Spjd char cc_events; /* various events for CPR */ 93168404Spjd callb_id_t cc_id; /* callb id address */ 94168404Spjd kcondvar_t cc_callb_cv; /* cv for callback waiting */ 95168404Spjd kcondvar_t cc_stop_cv; /* cv to checkpoint block */ 96168404Spjd} callb_cpr_t; 97168404Spjd 98168404Spjd/* 99168404Spjd * cc_events definitions 100168404Spjd */ 101168404Spjd#define CALLB_CPR_START 1 /* a checkpoint request's started */ 102168404Spjd#define CALLB_CPR_SAFE 2 /* thread is safe for CPR */ 103168404Spjd#define CALLB_CPR_ALWAYS_SAFE 4 /* thread is ALWAYS safe for CPR */ 104168404Spjd 105168404Spjd/* 106168404Spjd * Used when checking that all kernel threads are stopped. 107168404Spjd */ 108168404Spjd#define CALLB_MAX_RETRY 3 /* when waiting for kthread to sleep */ 109168404Spjd#define CALLB_THREAD_DELAY 10 /* ticks allowed to reach sleep */ 110168404Spjd#define CPR_KTHREAD_TIMEOUT_SEC 90 /* secs before callback times out -- */ 111168404Spjd /* due to pwr mgmt of disks, make -- */ 112168404Spjd /* big enough for worst spinup time */ 113168404Spjd 114168404Spjd#ifdef _KERNEL 115168404Spjd/* 116168404Spjd * 117168404Spjd * CALLB_CPR_INIT macro is used by kernel threads to add their entry to 118168404Spjd * the callback table and perform other initialization. It automatically 119168404Spjd * adds the thread as being in the callback class CB_CL_CPR_DAEMON. 120168404Spjd * 121168404Spjd * cp - ptr to the callb_cpr_t structure for this kernel thread 122168404Spjd * 123168404Spjd * lockp - pointer to mutex protecting the callb_cpr_t stuct 124168404Spjd * 125168404Spjd * func - pointer to the callback function for this kernel thread. 126168404Spjd * It has the prototype boolean_t <func>(void *arg, int code) 127168404Spjd * where: arg - ptr to the callb_cpr_t structure 128168404Spjd * code - not used for this type of callback 129168404Spjd * returns: B_TRUE if successful; B_FALSE if unsuccessful. 130168404Spjd * 131168404Spjd * name - a string giving the name of the kernel thread 132168404Spjd * 133168404Spjd * Note: lockp is the lock to protect the callb_cpr_t (cp) structure 134168404Spjd * later on. No lock held is needed for this initialization. 135168404Spjd */ 136168404Spjd#define CALLB_CPR_INIT(cp, lockp, func, name) { \ 137168404Spjd bzero((caddr_t)(cp), sizeof (callb_cpr_t)); \ 138168404Spjd (cp)->cc_lockp = lockp; \ 139168404Spjd (cp)->cc_id = callb_add(func, (void *)(cp), \ 140168404Spjd CB_CL_CPR_DAEMON, name); \ 141168404Spjd } 142168404Spjd 143168404Spjd#ifndef __lock_lint 144168404Spjd#define CALLB_CPR_ASSERT(cp) ASSERT(MUTEX_HELD((cp)->cc_lockp)); 145168404Spjd#else 146168404Spjd#define CALLB_CPR_ASSERT(cp) 147168404Spjd#endif 148168404Spjd/* 149168404Spjd * Some threads (like the idle threads) do not adhere to the callback 150168404Spjd * protocol and are always considered safe. Such threads must never exit. 151168404Spjd * They register their presence by calling this macro during their 152168404Spjd * initialization. 153168404Spjd * 154168404Spjd * Args: 155168404Spjd * t - thread pointer of the client kernel thread 156168404Spjd * name - a string giving the name of the kernel thread 157168404Spjd */ 158168404Spjd#define CALLB_CPR_INIT_SAFE(t, name) { \ 159168404Spjd (void) callb_add_thread(callb_generic_cpr_safe, \ 160168404Spjd (void *) &callb_cprinfo_safe, CB_CL_CPR_DAEMON, \ 161168404Spjd name, t); \ 162168404Spjd } 163168404Spjd/* 164168404Spjd * The lock to protect cp's content must be held before 165168404Spjd * calling the following two macros. 166168404Spjd * 167168404Spjd * Any code region between CALLB_CPR_SAFE_BEGIN and CALLB_CPR_SAFE_END 168168404Spjd * is safe for checkpoint/resume. 169168404Spjd */ 170168404Spjd#define CALLB_CPR_SAFE_BEGIN(cp) { \ 171168404Spjd CALLB_CPR_ASSERT(cp) \ 172168404Spjd (cp)->cc_events |= CALLB_CPR_SAFE; \ 173168404Spjd if ((cp)->cc_events & CALLB_CPR_START) \ 174168404Spjd cv_signal(&(cp)->cc_callb_cv); \ 175168404Spjd } 176168404Spjd#define CALLB_CPR_SAFE_END(cp, lockp) { \ 177168404Spjd CALLB_CPR_ASSERT(cp) \ 178168404Spjd while ((cp)->cc_events & CALLB_CPR_START) \ 179168404Spjd cv_wait(&(cp)->cc_stop_cv, lockp); \ 180168404Spjd (cp)->cc_events &= ~CALLB_CPR_SAFE; \ 181168404Spjd } 182168404Spjd/* 183168404Spjd * cv_destroy is nop right now but may be needed in the future. 184168404Spjd */ 185168404Spjd#define CALLB_CPR_EXIT(cp) { \ 186168404Spjd CALLB_CPR_ASSERT(cp) \ 187168404Spjd (cp)->cc_events |= CALLB_CPR_SAFE; \ 188168404Spjd if ((cp)->cc_events & CALLB_CPR_START) \ 189168404Spjd cv_signal(&(cp)->cc_callb_cv); \ 190168404Spjd mutex_exit((cp)->cc_lockp); \ 191168404Spjd (void) callb_delete((cp)->cc_id); \ 192168404Spjd cv_destroy(&(cp)->cc_callb_cv); \ 193168404Spjd cv_destroy(&(cp)->cc_stop_cv); \ 194168404Spjd } 195168404Spjd 196168404Spjdextern callb_cpr_t callb_cprinfo_safe; 197168404Spjdextern callb_id_t callb_add(boolean_t (*)(void *, int), void *, int, char *); 198168404Spjdextern callb_id_t callb_add_thread(boolean_t (*)(void *, int), 199168404Spjd void *, int, char *, kthread_id_t); 200168404Spjdextern int callb_delete(callb_id_t); 201168404Spjdextern void callb_execute(callb_id_t, int); 202168404Spjdextern void *callb_execute_class(int, int); 203168404Spjdextern boolean_t callb_generic_cpr(void *, int); 204168404Spjdextern boolean_t callb_generic_cpr_safe(void *, int); 205168404Spjdextern boolean_t callb_is_stopped(kthread_id_t, caddr_t *); 206168404Spjdextern void callb_lock_table(void); 207168404Spjdextern void callb_unlock_table(void); 208168404Spjd#endif 209168404Spjd 210168404Spjd#ifdef __cplusplus 211168404Spjd} 212168404Spjd#endif 213168404Spjd 214168404Spjd#endif /* _SYS_CALLB_H */ 215