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