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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _LIBFMEVENT_H 28 #define _LIBFMEVENT_H 29 30 /* 31 * FMA event library. 32 * 33 * A. Protocol event subscription interfaces (Committed). 34 */ 35 36 #ifdef __cplusplus 37 extern "C" { 38 #endif 39 40 #include <sys/types.h> 41 #include <libnvpair.h> 42 #include <stdlib.h> 43 #include <door.h> 44 #include <sys/time.h> 45 #include <sys/fm/protocol.h> 46 47 /* 48 * Library ABI interface version. Quote the version you are using 49 * to fmev_shdl_init. Only interfaces introduced in or prior to the 50 * quoted version will be available. Once introduced an interface 51 * only ever changes compatibly. 52 */ 53 #define LIBFMEVENT_VERSION_1 1 54 55 #define LIBFMEVENT_VERSION_LATEST LIBFMEVENT_VERSION_1 56 57 /* 58 * Success and error return values. The descriptive comment for each 59 * FMEVERR_* becomes the string that is returned by fmev_strerror for that 60 * error type. 61 */ 62 typedef enum { 63 FMEV_SUCCESS = 0, 64 FMEV_OK = FMEV_SUCCESS, /* alias for FMEV_SUCCESS */ 65 FMEVERR_UNKNOWN = 0xe000, /* Error details unknown */ 66 FMEVERR_VERSION_MISMATCH, /* Library ABI version incompatible with caller */ 67 FMEVERR_API, /* Library API usage violation */ 68 FMEVERR_ALLOC, /* Failed to allocate additional resources */ 69 FMEVERR_MALFORMED_EVENT, /* Event contents are inconsistent or corrupt */ 70 FMEVERR_OVERFLOW, /* Operation would overflow result type */ 71 FMEVERR_INTERNAL, /* Internal library error */ 72 FMEVERR_NOPRIV, /* Insufficient permissions or privilege */ 73 FMEVERR_BUSY, /* Resource is busy */ 74 FMEVERR_DUPLICATE, /* Duplicate request */ 75 FMEVERR_BADCLASS, /* Bad event class or class pattern */ 76 FMEVERR_NOMATCH, /* No match to criteria provided */ 77 FMEVERR_MAX_SUBSCRIBERS, /* Exceeds maximum subscribers per handle */ 78 FMEVERR_INVALIDARG /* Argument is invalid */ 79 } fmev_err_t; 80 81 /* 82 * Some interfaces return an fmev_err_t - FMEV_SUCCESS on success, otherwise 83 * failure of the indicated type. You can use fmev_strerror to render an 84 * fmev_err_t into a string. 85 * 86 * Other interfaces do not return an fmev_err_t directly. For example 87 * where we return a pointer an error is indicated by a NULL return. 88 * In these cases you can retrieve the fmev_err_t describing the reason 89 * for the failure using fmev_errno or get a string with 90 * fmev_strerr(fmev_errno). Note that fmev_errno is per-thread and holds 91 * the error value for any error that occured during the last libfmevent 92 * API call made by the current thread. Use fmev_errno as you would 93 * regular errno, but you should not assign to fmev_errno. 94 */ 95 extern const fmev_err_t *__fmev_errno(void); /* do not use this directly */ 96 #define fmev_errno (*(__fmev_errno())) 97 extern const char *fmev_strerror(fmev_err_t); 98 99 /* 100 * Part A - Protocol Event Subscription 101 * ====== 102 * 103 * Subscribe to FMA protocol events published by the fault management 104 * daemon, receiving a callback for each matching event. 105 * 106 * This is a Committed interface (see attributes(5) for a definition). 107 */ 108 109 /* 110 * Opaque subscription handle and event types. 111 */ 112 typedef struct fmev_shdl *fmev_shdl_t; 113 typedef struct fmev *fmev_t; 114 115 /* 116 * Subscription callback function type for fmev_shdl_subscribe. 117 */ 118 typedef void fmev_cbfunc_t(fmev_t, const char *, nvlist_t *, void *); 119 120 /* 121 * Initialize a new handle using fmev_shdl_init and quoting interface 122 * version number along with alloc, zalloc and free function pointers (all 123 * NULL to use the defaults. 124 * 125 * Close the handle and release resources with fmev_shdl_fini. 126 */ 127 128 extern fmev_shdl_t fmev_shdl_init(uint32_t, 129 void *(*)(size_t), /* alloc */ 130 void *(*)(size_t), /* zalloc */ 131 void (*)(void *, size_t)); /* free */ 132 133 extern fmev_err_t fmev_shdl_fini(fmev_shdl_t); 134 135 /* 136 * Having created a handle you may optionally configure various properties 137 * for this handle using fmev_shdlctl_*. In most cases accepting the defaults 138 * (that are obtained through fmev_shdl_init alone) will provide adequate 139 * semantics - the controls below are provided for applications 140 * that require fine-grained control over event delivery semantics and, in 141 * particular, the service threads used to perform delivery callbacks. 142 * 143 * These controls may only be applied to a subscription handle 144 * that has no current subscriptions in place. You therefore cannot 145 * change the properties once subscriptions are established, and the 146 * handle properties apply uniformly to all subscriptions on that handle. 147 * If you require different properties per subscription then use multiple 148 * handles. 149 * 150 * fmev_shdlctl_serialize() will serialize all callbacks arising from all 151 * subscriptions on a handle. Event deliveries are normally single-threaded 152 * on a per-subscribtion bases, that is a call to fmev_shdl_subscribe 153 * will have deliveries arising from that subscription delivered 154 * in a serialized fashion on a single thread dedicated to the subscription. 155 * If multiple subscriptions are established then each has a dedicated 156 * delivery thread - fmev_shdlctl_serialize arranges that only one of these 157 * threads services a callback at any one time. 158 * 159 * fmev_shdlctl_thrattr() allows you to provide thread attributes for use 160 * in pthread_create() when server threads are created. The attributes 161 * are not copied - the pthread_attr_t object passed must exist for 162 * the duration of all subscriptions on the handle. These attributes only 163 * apply if fmev_shdlctl_thrcreate() is not in use on this handle. 164 * 165 * fmev_shdlctl_sigmask() allows you to provide a sigset_t signal mask 166 * of signals to block in server threads. The pthread_sigmask is set 167 * to this immediately before pthread_create, and restored immediately 168 * after pthread_create. This mask only applies if fmev_shdlctl_thrcreate() 169 * is not in use on this handle. 170 * 171 * fmev_shdlctl_thrsetup() allows you to install a custom door server thread 172 * setup function - see door_xcreate(3C). This will be used with the 173 * default thread creation semantics or with any custom thread creation 174 * function appointed with fmev_shdlctl_thrcreate(). 175 * 176 * fmev_shdlctl_thrcreate() allows you to install a custom door server thread 177 * creation function - see door_xcreate(3C). This option excludes 178 * fmev_shdlctl_{thrattr,sigmask} but the remaining options 179 * of fmev_shdlctl_{serialize,thrsetup} are still available. 180 */ 181 182 extern fmev_err_t fmev_shdlctl_serialize(fmev_shdl_t); 183 extern fmev_err_t fmev_shdlctl_thrattr(fmev_shdl_t, pthread_attr_t *); 184 extern fmev_err_t fmev_shdlctl_sigmask(fmev_shdl_t, sigset_t *); 185 extern fmev_err_t fmev_shdlctl_thrsetup(fmev_shdl_t, 186 door_xcreate_thrsetup_func_t *, void *); 187 extern fmev_err_t fmev_shdlctl_thrcreate(fmev_shdl_t, 188 door_xcreate_server_func_t *, void *); 189 190 /* 191 * Specify subscription choices on a handle using fmev_shdl_subscribe as 192 * many times as needed to describe the full event set. The event class 193 * pattern can be wildcarded using simple '*' wildcarding. When an event 194 * matching a subscription is received a callback is performed to the 195 * nominated function passing a fmev_t handle on the event and the 196 * requested cookie argument. 197 * 198 * See the fault management event protocol specification for a description 199 * of event classes. 200 * 201 * Drop a subscription using fmev_shdl_unsubscribe (which must match an 202 * earlier subscription). 203 */ 204 205 #define FMEV_MAX_CLASS 64 /* Longest class string for subscription */ 206 207 extern fmev_err_t fmev_shdl_subscribe(fmev_shdl_t, const char *, fmev_cbfunc_t, 208 void *); 209 extern fmev_err_t fmev_shdl_unsubscribe(fmev_shdl_t, const char *); 210 211 /* 212 * Event access. In the common case that the event is processed to 213 * completion in the context of the event callback you need only 214 * use fmev_attr_list to access the nvlist of event attributes, 215 * with no responsibility for freeing the event or the nvlist; for 216 * convenience, fmev_class and fmev_timestamp can both be used to 217 * look inside an event without having to work with the attribute list (and 218 * the callback receives the class as an argument). 219 * 220 * See libnvpair(3LIB) for interfaces to access an nvlist_t. 221 * 222 * The remaining interfaces apply in the case that event handling will 223 * continue beyond the context of the event callback in which it is received. 224 * 225 * The fmev_t handle received in a callback is reference-counted; 226 * the initial reference count on entry to the callback is 1, and the 227 * count is always decremented when the callback completes. To continue 228 * to operate on a received event outside of the context of the callback 229 * in which it is first received, take an fmev_hold during the callback 230 * and later fmev_rele to release your hold (and free the event if the count 231 * drops to 0). 232 * 233 * To access attributes of an event use fmev_attr_list to receive 234 * an nvlist_t pointer valid for the same lifetime as the event itself (i.e., 235 * until its reference count drops to zero). 236 * 237 * If changes are made to a received fmev_t (discouraged) then all who 238 * have a hold on the event share the change. To obtain an independent 239 * copy of an fmev_t, with a reference count of 1, use fmev_dup. When 240 * finished with the copy decrement the reference count 241 * using fmev_rele - the event will be freed if the count reaches 0. 242 * 243 * For convenience you can retrieve the class of an event using fmev_class 244 * (it's also available as an argument to a callback, and within the 245 * event attribute list). The string returned by fmev_class is valid for 246 * the same lifetime as the event itself. 247 * 248 * The time at which a protocol event was generated is available via 249 * fmev_timespec; tv_sec has seconds since the epoch, and tv_nsec nanoseconds 250 * past that second. This can fail with FMEVERR_OVERFLOW if the seconds 251 * value does not fit within a time_t; you can retrieve the 64-bit second 252 * and nanosecond values with fmev_time_sec and fmev_time_nsec. 253 */ 254 255 extern nvlist_t *fmev_attr_list(fmev_t); 256 extern const char *fmev_class(fmev_t); 257 258 extern fmev_err_t fmev_timespec(fmev_t, struct timespec *); 259 extern uint64_t fmev_time_sec(fmev_t); 260 extern uint64_t fmev_time_nsec(fmev_t); 261 extern struct tm *fmev_localtime(fmev_t, struct tm *); 262 263 extern void fmev_hold(fmev_t); 264 extern void fmev_rele(fmev_t); 265 extern fmev_t fmev_dup(fmev_t); 266 267 /* 268 * The following will allocate and free memory based on the choices made 269 * at fmev_shdl_init. 270 */ 271 void *fmev_shdl_alloc(fmev_shdl_t, size_t); 272 void *fmev_shdl_zalloc(fmev_shdl_t, size_t); 273 void fmev_shdl_free(fmev_shdl_t, void *, size_t); 274 275 #ifdef __cplusplus 276 } 277 #endif 278 279 #endif /* _LIBFMEVENT_H */ 280