]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/cddl/contrib/opensolaris/uts/common/sys/callb.h
Copy head to stable/8 as part of 8.0 Release cycle.
[FreeBSD/stable/8.git] / sys / cddl / contrib / opensolaris / uts / common / sys / callb.h
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26
27 #ifndef _SYS_CALLB_H
28 #define _SYS_CALLB_H
29
30 #pragma ident   "@(#)callb.h    1.29    05/06/23 SMI"
31
32 #include <sys/kcondvar.h>
33
34 #ifdef  __cplusplus
35 extern "C" {
36 #endif
37
38 /*
39  * definitions of callback classes (c_class)
40  *
41  * Callbacks belong in the same class if (1) their callback routines
42  * do the same kind of processing (ideally, using the same callback function)
43  * and (2) they can/should be executed at the same time in a cpr
44  * suspend/resume operation.
45  *
46  * Note: The DAEMON class, in particular, is for stopping kernel threads
47  * and nothing else.  The CALLB_* macros below should be used to deal
48  * with kernel threads, and the callback function should be callb_generic_cpr.
49  * Another idiosyncrasy of the DAEMON class is that if a suspend operation
50  * fails, some of the callback functions may be called with the RESUME
51  * code which were never called with SUSPEND.  Not a problem currently,
52  * but see bug 4201851.
53  */
54 #define CB_CL_CPR_DAEMON        0
55 #define CB_CL_CPR_VM            1
56 #define CB_CL_CPR_CALLOUT       2
57 #define CB_CL_CPR_OBP           3
58 #define CB_CL_CPR_FB            4
59 #define CB_CL_PANIC             5
60 #define CB_CL_CPR_RPC           6
61 #define CB_CL_CPR_PROMPRINTF    7
62 #define CB_CL_UADMIN            8
63 #define CB_CL_CPR_PM            9
64 #define CB_CL_HALT              10
65 #define CB_CL_CPR_DMA           11
66 #define CB_CL_CPR_POST_USER     12
67 #define CB_CL_UADMIN_PRE_VFS    13
68 #define CB_CL_MDBOOT            CB_CL_UADMIN
69 #define CB_CL_ENTER_DEBUGGER    14
70 #define CB_CL_CPR_POST_KERNEL   15
71 #define NCBCLASS                16 /* CHANGE ME if classes are added/removed */
72
73 /*
74  * CB_CL_CPR_DAEMON class specific definitions are given below:
75  */
76
77 /*
78  * code for CPR callb_execute_class
79  */
80 #define CB_CODE_CPR_CHKPT       0
81 #define CB_CODE_CPR_RESUME      1
82
83 typedef void *          callb_id_t;
84 /*
85  * Per kernel thread structure for CPR daemon callbacks.
86  * Must be protected by either a existing lock in the daemon or
87  * a new lock created for such a purpose.
88  */
89 typedef struct callb_cpr {
90         kmutex_t        *cc_lockp;      /* lock to protect this struct */
91         char            cc_events;      /* various events for CPR */
92         callb_id_t      cc_id;          /* callb id address */
93         kcondvar_t      cc_callb_cv;    /* cv for callback waiting */
94         kcondvar_t      cc_stop_cv;     /* cv to checkpoint block */
95 } callb_cpr_t;
96
97 /*
98  * cc_events definitions
99  */
100 #define CALLB_CPR_START         1       /* a checkpoint request's started */
101 #define CALLB_CPR_SAFE          2       /* thread is safe for CPR */
102 #define CALLB_CPR_ALWAYS_SAFE   4       /* thread is ALWAYS safe for CPR */
103
104 /*
105  * Used when checking that all kernel threads are stopped.
106  */
107 #define CALLB_MAX_RETRY         3       /* when waiting for kthread to sleep */
108 #define CALLB_THREAD_DELAY      10      /* ticks allowed to reach sleep */
109 #define CPR_KTHREAD_TIMEOUT_SEC 90      /* secs before callback times out -- */
110                                         /* due to pwr mgmt of disks, make -- */
111                                         /* big enough for worst spinup time */
112
113 #ifdef  _KERNEL
114 /*
115  *
116  * CALLB_CPR_INIT macro is used by kernel threads to add their entry to
117  * the callback table and perform other initialization.  It automatically
118  * adds the thread as being in the callback class CB_CL_CPR_DAEMON.
119  *
120  *      cp    - ptr to the callb_cpr_t structure for this kernel thread
121  *
122  *      lockp - pointer to mutex protecting the callb_cpr_t stuct
123  *
124  *      func  - pointer to the callback function for this kernel thread.
125  *              It has the prototype boolean_t <func>(void *arg, int code)
126  *              where: arg      - ptr to the callb_cpr_t structure
127  *                     code     - not used for this type of callback
128  *              returns: B_TRUE if successful; B_FALSE if unsuccessful.
129  *
130  *      name  - a string giving the name of the kernel thread
131  *
132  * Note: lockp is the lock to protect the callb_cpr_t (cp) structure
133  * later on.  No lock held is needed for this initialization.
134  */
135 #define CALLB_CPR_INIT(cp, lockp, func, name)   {                       \
136                 strlcpy(curthread->td_name, (name),                     \
137                     sizeof(curthread->td_name));                        \
138                 strlcpy(curthread->td_proc->p_comm, (name),             \
139                     sizeof(curthread->td_proc->p_comm));                \
140                 bzero((caddr_t)(cp), sizeof (callb_cpr_t));             \
141                 (cp)->cc_lockp = lockp;                                 \
142                 (cp)->cc_id = callb_add(func, (void *)(cp),             \
143                         CB_CL_CPR_DAEMON, name);                        \
144                 cv_init(&(cp)->cc_callb_cv, NULL, CV_DEFAULT, NULL);    \
145                 cv_init(&(cp)->cc_stop_cv, NULL, CV_DEFAULT, NULL);     \
146         }
147
148 #ifndef __lock_lint
149 #define CALLB_CPR_ASSERT(cp)    ASSERT(MUTEX_HELD((cp)->cc_lockp));
150 #else
151 #define CALLB_CPR_ASSERT(cp)
152 #endif
153 /*
154  * Some threads (like the idle threads) do not adhere to the callback
155  * protocol and are always considered safe.  Such threads must never exit.
156  * They register their presence by calling this macro during their
157  * initialization.
158  *
159  * Args:
160  *      t       - thread pointer of the client kernel thread
161  *      name    - a string giving the name of the kernel thread
162  */
163 #define CALLB_CPR_INIT_SAFE(t, name) {                                  \
164                 (void) callb_add_thread(callb_generic_cpr_safe,         \
165                 (void *) &callb_cprinfo_safe, CB_CL_CPR_DAEMON,         \
166                     name, t);                                           \
167         }
168 /*
169  * The lock to protect cp's content must be held before
170  * calling the following two macros.
171  *
172  * Any code region between CALLB_CPR_SAFE_BEGIN and CALLB_CPR_SAFE_END
173  * is safe for checkpoint/resume.
174  */
175 #define CALLB_CPR_SAFE_BEGIN(cp) {                      \
176                 CALLB_CPR_ASSERT(cp)                    \
177                 (cp)->cc_events |= CALLB_CPR_SAFE;      \
178                 if ((cp)->cc_events & CALLB_CPR_START)  \
179                         cv_signal(&(cp)->cc_callb_cv);  \
180         }
181 #define CALLB_CPR_SAFE_END(cp, lockp) {                         \
182                 CALLB_CPR_ASSERT(cp)                            \
183                 while ((cp)->cc_events & CALLB_CPR_START)       \
184                         cv_wait(&(cp)->cc_stop_cv, lockp);      \
185                 (cp)->cc_events &= ~CALLB_CPR_SAFE;             \
186         }
187 /*
188  * cv_destroy is nop right now but may be needed in the future.
189  */
190 #define CALLB_CPR_EXIT(cp) {                            \
191                 CALLB_CPR_ASSERT(cp)                    \
192                 (cp)->cc_events |= CALLB_CPR_SAFE;      \
193                 if ((cp)->cc_events & CALLB_CPR_START)  \
194                         cv_signal(&(cp)->cc_callb_cv);  \
195                 mutex_exit((cp)->cc_lockp);             \
196                 (void) callb_delete((cp)->cc_id);       \
197                 cv_destroy(&(cp)->cc_callb_cv);         \
198                 cv_destroy(&(cp)->cc_stop_cv);          \
199         }
200
201 extern callb_cpr_t callb_cprinfo_safe;
202 extern callb_id_t callb_add(boolean_t  (*)(void *, int), void *, int, char *);
203 extern callb_id_t callb_add_thread(boolean_t (*)(void *, int),
204     void *, int, char *, kthread_id_t);
205 extern int      callb_delete(callb_id_t);
206 extern void     callb_execute(callb_id_t, int);
207 extern void     *callb_execute_class(int, int);
208 extern boolean_t callb_generic_cpr(void *, int);
209 extern boolean_t callb_generic_cpr_safe(void *, int);
210 extern boolean_t callb_is_stopped(kthread_id_t, caddr_t *);
211 extern void     callb_lock_table(void);
212 extern void     callb_unlock_table(void);
213 #endif
214
215 #ifdef  __cplusplus
216 }
217 #endif
218
219 #endif  /* _SYS_CALLB_H */