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