1 /* 2 * os_handler.h 3 * 4 * MontaVista IPMI os handler interface. 5 * 6 * Author: MontaVista Software, Inc. 7 * Corey Minyard <minyard@mvista.com> 8 * source@mvista.com 9 * 10 * Copyright 2002,2003,2004,2005 MontaVista Software Inc. 11 * 12 * This software is available to you under a choice of one of two 13 * licenses. You may choose to be licensed under the terms of the GNU 14 * Lesser General Public License (GPL) Version 2 or the modified BSD 15 * license below. The following disclamer applies to both licenses: 16 * 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 26 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * GNU Lesser General Public Licence 29 * 30 * This program is free software; you can redistribute it and/or 31 * modify it under the terms of the GNU Lesser General Public License 32 * as published by the Free Software Foundation; either version 2 of 33 * the License, or (at your option) any later version. 34 * 35 * You should have received a copy of the GNU Lesser General Public 36 * License along with this program; if not, write to the Free 37 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 38 * 39 * Modified BSD Licence 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above 48 * copyright notice, this list of conditions and the following 49 * disclaimer in the documentation and/or other materials provided 50 * with the distribution. 51 * 3. The name of the author may not be used to endorse or promote 52 * products derived from this software without specific prior 53 * written permission. 54 */ 55 56 #ifndef OS_HANDLER_H 57 #define OS_HANDLER_H 58 59 #include <stdarg.h> 60 #include <sys/time.h> 61 #include <OpenIPMI/ipmi_log.h> 62 63 /************************************************************************ 64 * WARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNINGWARNING 65 * 66 * In order to make this data structure extensible, you should never 67 * declare a static version of the OS handler. You should *always* 68 * allocate it with the allocation routine at the end of this file, 69 * and free it with the free routine found there. That way, if new 70 * items are added to the end of this data structure, you are ok. You 71 * have been warned! Note that if you use the standard OS handlers, 72 * then you are ok. 73 * 74 ************************************************************************/ 75 76 #ifdef __cplusplus 77 extern "C" { 78 #endif 79 80 /* An os-independent normal lock. */ 81 typedef struct os_hnd_lock_s os_hnd_lock_t; 82 83 /* An os-independent read/write lock. */ 84 typedef struct os_hnd_rwlock_s os_hnd_rwlock_t; 85 86 /* An os-independent condition variable. */ 87 typedef struct os_hnd_cond_s os_hnd_cond_t; 88 89 /* An os-independent file descriptor holder. */ 90 typedef struct os_hnd_fd_id_s os_hnd_fd_id_t; 91 92 /* An os-independent timer. */ 93 typedef struct os_hnd_timer_id_s os_hnd_timer_id_t; 94 95 /* This is a structure that defined the os-dependent stuff required by 96 threaded code. In general, return values of these should be zero 97 on success, or an errno value on failure. The errno values will be 98 propigated back up to the commands that caused these to be called, 99 if possible. */ 100 typedef void (*os_data_ready_t)(int fd, void *cb_data, os_hnd_fd_id_t *id); 101 typedef void (*os_timed_out_t)(void *cb_data, os_hnd_timer_id_t *id); 102 103 /* This can be registered with add_fd_to_wait_for, it will be called 104 if the fd handler is freed or replaced. This can be used to avoid 105 free race conditions, handlers may be in callbacks when you remove 106 an fd to wait for, this will be called when all handlers are 107 done. */ 108 typedef void (*os_fd_data_freed_t)(int fd, void *data); 109 110 /* This can be registered with free_timer, it will be called if the 111 time free actually occurs. This can be used to avoid free race 112 conditions, handlers may be in callbacks when you free the timer, 113 this will be called when all handlers are done. */ 114 typedef void (*os_timer_freed_t)(void *data); 115 116 typedef struct os_handler_s os_handler_t; 117 118 /* A function to output logs, used to override the default functions. */ 119 typedef void (*os_vlog_t)(os_handler_t *handler, 120 const char *format, 121 enum ipmi_log_type_e log_type, 122 va_list ap); 123 124 struct os_handler_s 125 { 126 /* Allocate and free data, like malloc() and free(). These are 127 only used in the "main" os handler, too, not in the oned 128 registered for domains. */ 129 void *(*mem_alloc)(int size); 130 void (*mem_free)(void *data); 131 132 /* This is called by the user code to register a callback handler 133 to be called when data is ready to be read on the given file 134 descriptor. I know, it's kind of wierd, a callback to register 135 a callback, but it's the best way I could think of to do this. 136 This call will return an id that can then be used to cancel 137 the wait. The called code should register that whenever data 138 is ready to be read from the given file descriptor, data_ready 139 should be called with the given cb_data. If this is NULL, you 140 may only call the commands ending in "_wait", the event-driven 141 code will return errors. You also may not receive commands or 142 events. Note that these calls may NOT block. */ 143 int (*add_fd_to_wait_for)(os_handler_t *handler, 144 int fd, 145 os_data_ready_t data_ready, 146 void *cb_data, 147 os_fd_data_freed_t freed, 148 os_hnd_fd_id_t **id); 149 int (*remove_fd_to_wait_for)(os_handler_t *handler, 150 os_hnd_fd_id_t *id); 151 152 /* Create a timer. This will allocate all the data required for 153 the timer, so no other timer operations should fail due to lack 154 of memory. */ 155 int (*alloc_timer)(os_handler_t *handler, 156 os_hnd_timer_id_t **id); 157 /* Free the memory for the given timer. If the timer is running, 158 stop it first. */ 159 int (*free_timer)(os_handler_t *handler, 160 os_hnd_timer_id_t *id); 161 /* This is called to register a callback handler to be called 162 after the given amount of time (relative). After the given 163 time has passed, the "timed_out" will be called with the given 164 cb_data. The identifier in "id" just be one previously 165 allocated with alloc_timer(). Note that timed_out may NOT 166 block. */ 167 int (*start_timer)(os_handler_t *handler, 168 os_hnd_timer_id_t *id, 169 struct timeval *timeout, 170 os_timed_out_t timed_out, 171 void *cb_data); 172 /* Cancel the given timer. If the timer has already been called 173 (or is in the process of being called) this should return 174 ESRCH, and it may not return ESRCH for any other reason. In 175 other words, if ESRCH is returned, the timer is valid and the 176 timeout handler has or will be called. */ 177 int (*stop_timer)(os_handler_t *handler, 178 os_hnd_timer_id_t *id); 179 180 /* Used to implement locking primitives for multi-threaded access. 181 If these are NULL, then the code will assume that the system is 182 single-threaded and doesn't need locking. Note that these no 183 longer have to be recursive locks, they may be normal 184 non-recursive locks. */ 185 int (*create_lock)(os_handler_t *handler, 186 os_hnd_lock_t **id); 187 int (*destroy_lock)(os_handler_t *handler, 188 os_hnd_lock_t *id); 189 int (*lock)(os_handler_t *handler, 190 os_hnd_lock_t *id); 191 int (*unlock)(os_handler_t *handler, 192 os_hnd_lock_t *id); 193 194 /* Return "len" bytes of random data into "data". */ 195 int (*get_random)(os_handler_t *handler, 196 void *data, 197 unsigned int len); 198 199 /* Log reports some through here. They will not end in newlines. 200 See the log types defined in ipmiif.h for more information on 201 handling these. */ 202 void (*log)(os_handler_t *handler, 203 enum ipmi_log_type_e log_type, 204 const char *format, 205 ...); 206 void (*vlog)(os_handler_t *handler, 207 enum ipmi_log_type_e log_type, 208 const char *format, 209 va_list ap); 210 211 /* The user may use this for whatever they like. */ 212 void *user_data; 213 214 215 /* The rest of these are not used by OpenIPMI proper, but are here 216 for upper layers if they need them. If your upper layer 217 doesn't use theses, you don't have to provide them. */ 218 219 /* Condition variables, like in POSIX Threads. */ 220 int (*create_cond)(os_handler_t *handler, 221 os_hnd_cond_t **cond); 222 int (*destroy_cond)(os_handler_t *handler, 223 os_hnd_cond_t *cond); 224 int (*cond_wait)(os_handler_t *handler, 225 os_hnd_cond_t *cond, 226 os_hnd_lock_t *lock); 227 /* The timeout here is relative, not absolute. */ 228 int (*cond_timedwait)(os_handler_t *handler, 229 os_hnd_cond_t *cond, 230 os_hnd_lock_t *lock, 231 struct timeval *timeout); 232 int (*cond_wake)(os_handler_t *handler, 233 os_hnd_cond_t *cond); 234 int (*cond_broadcast)(os_handler_t *handler, 235 os_hnd_cond_t *cond); 236 237 /* Thread management */ 238 int (*create_thread)(os_handler_t *handler, 239 int priority, 240 void (*startup)(void *data), 241 void *data); 242 /* Terminate the running thread. */ 243 int (*thread_exit)(os_handler_t *handler); 244 245 /* Should *NOT* be used by the user, this is for the OS handler's 246 internal use. */ 247 void *internal_data; 248 249 /***************************************************************/ 250 251 /* These are basic function on the OS handler that are here for 252 convenience to the user. These are not used by OpenIPMI 253 proper. Depending on the specific OS handler, these may or may 254 not be implemented. If you are not sure, check for NULL. */ 255 256 /* Free the OS handler passed in. After this call, the OS handler 257 may not be used any more. May sure that nothing is using it 258 before this is called. */ 259 void (*free_os_handler)(os_handler_t *handler); 260 261 /* Wait up to the amount of time specified in timeout (relative 262 time) to perform one operation (a timeout, file operation, 263 etc.) then return. This return a standard errno. If timeout 264 is NULL, then this will wait forever. */ 265 int (*perform_one_op)(os_handler_t *handler, 266 struct timeval *timeout); 267 268 /* Loop continuously handling operations. This function does not 269 return. */ 270 void (*operation_loop)(os_handler_t *handler); 271 272 273 /* The following are no longer implemented because they are 274 race-prone, unneeded, and/or difficult to implement. You may 275 safely set these to NULL, but they are here for backwards 276 compatability with old os handlers. */ 277 int (*is_locked)(os_handler_t *handler, 278 os_hnd_lock_t *id); 279 int (*create_rwlock)(os_handler_t *handler, 280 os_hnd_rwlock_t **id); 281 int (*destroy_rwlock)(os_handler_t *handler, 282 os_hnd_rwlock_t *id); 283 int (*read_lock)(os_handler_t *handler, 284 os_hnd_rwlock_t *id); 285 int (*read_unlock)(os_handler_t *handler, 286 os_hnd_rwlock_t *id); 287 int (*write_lock)(os_handler_t *handler, 288 os_hnd_rwlock_t *id); 289 int (*write_unlock)(os_handler_t *handler, 290 os_hnd_rwlock_t *id); 291 int (*is_readlocked)(os_handler_t *handler, 292 os_hnd_rwlock_t *id); 293 int (*is_writelocked)(os_handler_t *handler, 294 os_hnd_rwlock_t *id); 295 296 /* Database storage and retrieval routines. These are used by 297 things in OpenIPMI to speed up various operations by caching 298 data locally instead of going to the actual system to get them. 299 The key is a arbitrary length character string. The find 300 routine returns an error on failure. Otherwise, if it can 301 fetch the data without delay, it allocates a block of data and 302 returns it in data (with the length in data_len) and sets 303 fetch_completed to true. Otherwise, if it cannot fetch the 304 data without delay, it will set fetch_completed to false and 305 start the database operation, calling got_data() when it is 306 done. 307 308 The data returned should be freed by database_free. Note that 309 these routines are optional and do not need to be here, they 310 simply speed up operation when working correctly. Also, if 311 these routines fail for some reason it is not fatal to the 312 operation of OpenIPMI. It is not a big deal. */ 313 int (*database_store)(os_handler_t *handler, 314 char *key, 315 unsigned char *data, 316 unsigned int data_len); 317 int (*database_find)(os_handler_t *handler, 318 char *key, 319 unsigned int *fetch_completed, 320 unsigned char **data, 321 unsigned int *data_len, 322 void (*got_data)(void *cb_data, 323 int err, 324 unsigned char *data, 325 unsigned int data_len), 326 void *cb_data); 327 void (*database_free)(os_handler_t *handler, 328 unsigned char *data); 329 /* Sets the filename to use for the database to the one specified. 330 The meaning is system-dependent. On *nix systems it defaults 331 to $HOME/.OpenIPMI_db. This is for use by the user, OpenIPMI 332 proper does not use this. */ 333 int (*database_set_filename)(os_handler_t *handler, 334 char *name); 335 336 /* Set the function to send logs to. */ 337 void (*set_log_handler)(os_handler_t *handler, 338 os_vlog_t log_handler); 339 340 /* For fd handlers, allow write and except handling to be done, 341 and allow any of the I/O types to be enabled and disabled. */ 342 void (*set_fd_handlers)(os_handler_t *handler, os_hnd_fd_id_t *id, 343 os_data_ready_t write_ready, 344 os_data_ready_t except_ready); 345 int (*set_fd_enables)(os_handler_t *handler, os_hnd_fd_id_t *id, 346 int read, int write, int except); 347 348 int (*get_monotonic_time)(os_handler_t *handler, struct timeval *tv); 349 int (*get_real_time)(os_handler_t *handler, struct timeval *tv); 350 }; 351 352 /* Only use these to allocate/free OS handlers. */ 353 os_handler_t *ipmi_alloc_os_handler(void); 354 void ipmi_free_os_handler(os_handler_t *handler); 355 356 /********************************************************************** 357 * 358 * Tools to use OS handlers to wait. 359 * 360 * Well, you shouldn't have to wait for OpenIPMI to do things, you 361 * should use callbacks and event-drive your programs. However, it's 362 * not always that simple. Broken APIs that require blocking exist, 363 * and it makes things ugly. 364 * 365 * The tools below help you with this. They provide a way with an OS 366 * handler to do blocking operations more easily. They handle all the 367 * nastiness of threading, single-threaded, and whatnot. 368 * 369 * To use this, allocate a waiter factory. Then when you need to 370 * wait, allocate a waiter from the factory. It is allocated with a 371 * usecount of 1. For every operation you start, "use" the waiter. 372 * When you are done starting operations, do one "release" of the 373 * waiter and then wait on the waiter. When operations complete, they 374 * "release" the waiter. When the last operation is done the wait 375 * operation will return. Then free the waiter. You cannot reuse 376 * waiters, you must allocate new ones. 377 * 378 * This interface has three basic modes. If you have a 379 * single-threaded OS handler (no threads support in the handler) then 380 * you must set num_threads = 0 and it runs single-threaded. The code 381 * will run an event loop while waiting for the operations to complete. 382 * 383 * If you have multiple thread support in the OS handler and set 384 * num_threads > 0, it will allocate num_threads event loop threads. 385 * The event loop will not be run from the waiting thread (there are 386 * race conditions with this) but condition variable are used to wake 387 * the waiting thread. 388 * 389 * If you have multiple thread support in the OS handler and set 390 * num_threads = 0, things are more complex. This allows a 391 * single-threaded application, but permits a multi-threaded 392 * application. Another thread is allocated to run the event loop. 393 * It will *only* run when a thread is waiting. Thus it preserved 394 * single-threaded operation for single-threaded programs, but does 395 * not have races in multi-threaded programs. 396 * 397 * Be careful using the timeout. You want to be *sure* that you don't 398 * free the waiter before anything else that might wake up and release 399 * it. 400 * 401 *********************************************************************/ 402 403 typedef struct os_handler_waiter_factory_s os_handler_waiter_factory_t; 404 typedef struct os_handler_waiter_s os_handler_waiter_t; 405 406 /* Allocate a factory to get waiters from. This is the thing that 407 owns the event loop threads (if you have them). The event loop 408 threads are allocated with thread_priority. */ 409 int os_handler_alloc_waiter_factory(os_handler_t *os_hnd, 410 unsigned int num_threads, 411 int thread_priority, 412 os_handler_waiter_factory_t **factory); 413 414 /* Free a waiter factory. This will fail with EAGAIN if there are any 415 waiters allocated from it that have not been freed. */ 416 int os_handler_free_waiter_factory(os_handler_waiter_factory_t *factory); 417 418 /* Allocate a waiter from the factory. Returns NULL on failure. It is 419 allocated with a use count of 1. */ 420 os_handler_waiter_t *os_handler_alloc_waiter 421 (os_handler_waiter_factory_t *factory); 422 423 /* Free a waiter. It cannot be waiting or an error is returned (EAGAIN). */ 424 int os_handler_free_waiter(os_handler_waiter_t *waiter); 425 426 /* Increment the use count of the waiter. */ 427 void os_handler_waiter_use(os_handler_waiter_t *waiter); 428 429 /* Decrement the use count of the waiter. When the usecount reaches 430 zero the waiter will return. */ 431 void os_handler_waiter_release(os_handler_waiter_t *waiter); 432 433 /* Wait for the waiter's use count to reach zero. If timeout is 434 non-NULL, it will wait up to that amount of time. */ 435 int os_handler_waiter_wait(os_handler_waiter_t *waiter, 436 struct timeval *timeout); 437 438 /* 439 * This is for shutting down to a level that you can restart the 440 * system again. It basically removes the built-in OS handler 441 * used for memory allocation so it can be re-assigned. 442 */ 443 void os_handler_global_shutdown(void); 444 445 #ifdef __cplusplus 446 } 447 #endif 448 449 #endif /* OS_HANDLER_H */ 450