Provided by: libgensio-dev_2.6.2-3ubuntu1_amd64 bug

NAME

       gensio_os_funcs  -  Abstraction  for  some  operating  system functions used by the gensio
       library

SYNOPSIS

       #include <gensio/gensio_os_funcs_public.h>

       struct gensio_os_funcs {}

       int gensio_default_os_hnd(int wake_sig, struct gensio_os_funcs **o)

       int gensio_unix_funcs_alloc(struct selector_s *sel, int wake_sig,
                 struct gensio_os_funcs **o)

       int gensio_win_funcs_alloc(struct gensio_os_funcs **o)

       void gensio_os_funcs_free(struct gensio_os_funcs *o);

       int gensio_os_proc_setup(struct gensio_os_funcs *o,
                       struct gensio_os_proc_data **data)

       void gensio_os_proc_cleanup(struct gensio_os_proc_data *data);

       sigset_t *gensio_os_proc_unix_get_wait_sigset(
                                struct gensio_os_proc_data *data);

       int gensio_os_new_thread(struct gensio_os_funcs *o,
                       void (*start_func)(void *data), void *data,
                       struct gensio_thread **thread_id);

       int gensio_os_wait_thread(struct gensio_thread *thread_id);

       int gensio_os_proc_register_term_handler(struct gensio_os_proc_data *data,
                                 void (*handler)(void *handler_data),
                                 void *handler_data);

       int gensio_os_proc_register_reload_handler(struct gensio_os_proc_data *data,
                                   void (*handler)(void *handler_data),
                                   void *handler_data);

       int gensio_os_proc_register_winsize_handler(struct gensio_os_proc_data *data,
                                struct gensio_iod *console_iod,
                                void (*handler)(int x_chrs, int y_chrs,
                                          int x_bits, int y_bits,
                                          void *handler_data),
                                void *handler_data);

       void *gensio_os_funcs_zalloc(struct gensio_os_funcs *o, gensiods len);

       void gensio_os_funcs_zfree(struct gensio_os_funcs *o, void *data);

       struct gensio_lock *gensio_os_funcs_alloc_lock(struct gensio_os_funcs *o);

       void gensio_os_funcs_free_lock(struct gensio_os_funcs *o,
                             struct gensio_lock *lock);

       void gensio_os_funcs_lock(struct gensio_os_funcs *o,
                        struct gensio_lock *lock);

       void gensio_os_funcs_unlock(struct gensio_os_funcs *o,
                          struct gensio_lock *lock);

       void gensio_os_funcs_get_monotonic_time(struct gensio_os_funcs *o,
                                gensio_time *time);

       struct gensio_timer *gensio_os_funcs_alloc_timer(struct gensio_os_funcs *o,
                               void (*handler)(struct gensio_timer *t,
                                         void *cb_data),
                               void *cb_data);

       void gensio_os_funcs_free_timer(struct gensio_os_funcs *o,
                           struct gensio_timer *timer);

       int gensio_os_funcs_start_timer(struct gensio_os_funcs *o,
                           struct gensio_timer *timer,
                           gensio_time *timeout);

       int gensio_os_funcs_start_timer_abs(struct gensio_os_funcs *o,
                               struct gensio_timer *timer,
                               gensio_time *timeout);

       int gensio_os_funcs_stop_timer(struct gensio_os_funcs *o,
                             struct gensio_timer *timer);

       int gensio_os_funcs_stop_timer_with_done(struct gensio_os_funcs *o,
                          struct gensio_timer *timer,
                          void (*done_handler)(struct gensio_timer *t,
                                      void *cb_data),
                          void *cb_data);

       struct gensio_runner *gensio_os_funcs_alloc_runner(struct gensio_os_funcs *o,
                                 void (*handler)(struct gensio_runner *r,
                                           void *cb_data),
                                 void *cb_data);

       void gensio_os_funcs_free_runner(struct gensio_os_funcs *o,
                            struct gensio_runner *runner);

       int gensio_os_funcs_run(struct gensio_os_funcs *o,
                      struct gensio_runner *runner);

       typedef void (gensio_vlog_func)(struct gensio_os_funcs *o,
                           enum gensio_log_levels level,
                           const char *log, va_list args);

       void gensio_os_funcs_set_vlog(struct gensio_os_funcs *o,
                                     gensio_vlog_func func);

       int gensio_os_funcs_service(struct gensio_os_funcs *o, gensio_time *timeout);

       int gensio_os_funcs_handle_fork(struct gensio_os_funcs *o);

       struct gensio_waiter *gensio_os_funcs_alloc_waiter(struct gensio_os_funcs *o);

       void gensio_os_funcs_free_waiter(struct gensio_os_funcs *o,
                            struct gensio_waiter *waiter);

       int gensio_os_funcs_wait(struct gensio_os_funcs *o,
                       struct gensio_waiter *waiter, unsigned int count,
                       gensio_time *timeout);

       int gensio_os_funcs_wait_intr(struct gensio_os_funcs *o,
                            struct gensio_waiter *waiter, unsigned int count,
                            gensio_time *timeout);

       int gensio_os_funcs_wait_intr_sigmask(struct gensio_os_funcs *o,
                                 struct gensio_waiter *waiter,
                                 unsigned int count,
                                 gensio_time *timeout,
                                 struct gensio_os_proc_data *proc_data);

       void gensio_os_funcs_wake(struct gensio_os_funcs *o,
                        struct gensio_waiter *waiter);

       void gensio_os_funcs_set_data(struct gensio_os_funcs *o, void *data);

       void *gensio_os_funcs_get_data(struct gensio_os_funcs *o);

DESCRIPTION

       This structure provides an abstraction for the gensio  library  that  lets  it  work  with
       various event libraries.  It provides the following basic functions:

       memory allocation - Allocate and free memory.

       mutexes - Provide mutual exclusion.

       file handler callbacks - Allows file descriptors to be monitored
              and report when I/O is ready on them.

       timers - Call callbacks after a certain amount of time has elapsed.

       runners - Run a function in a new execution context.  Calling callbacks
              straight  from  user functions can result in deadlocks, this provides a way to call
              callbacks from a separate context.

       waiters - Wait for operations to occur while running timers, runners
              and watching for file descriptors.

       logging - Allow the gensio library to generate logs to report issues.

       This document describes the public functions that users can use.  An os handler  has  many
       other functions for use by gensios, these are documented in the os funcs include file.

       The  basic  issue  is that there are various event handling libraries (Tcl/Tk, glib, Xlib,
       custom ones, etc.) and you may want to integrate the gensio library  with  one  of  these.
       Even  though  it's  a  bit  of  a pain to have to pass one of these around, it adds needed
       flexibility.

       gensio_default_os_hnd provides a way to allocate a default OS  function  handler  for  the
       platform.   The  same  value  will be returned each time, only one is created.  You should
       generally use this one unless you have a special need as documented above.

       The wait_sig parameter usage on Windows is unused.  For Unix systems, this signal is  used
       to  signal other processes that may be waiting that they need to wake up.  This is used to
       wake up a process waiting on a waiter, and it's used to signal all waiting processes if  a
       timer is added that is sooner than any other timer so they can adjust their waits.

       If  you  are  running  your program in a single thread, you can safely pass zero into this
       parameter.

       If your app is multi-threaded (or, more accurately, if your app has multiple threads  that
       are  making  gensio  calls) you must pass a valid signal into this, and you must set up an
       empty handler for this signal, and the signal must be blocked in all threads that  call  a
       wait  function.   You  should  not  use  this signal for anything else.  The function that
       allocates a signal handler will block the signal in the calling thread, and  that  sigmask
       is  passed  on  to  other  threads  it  creates.  But if you have allocated threads before
       allocating the os funcs, you must make sure those other threads have this signal blocked.

       Also, if you pass in a different value to gensio_default_os_hnd than  the  first  one  you
       passed   in,   it   will   return   GE_INVAL.    You  can  pass  in  different  values  to
       gensio_unix_funcs_alloc calls, and it will use them, but there's not much value  in  this.
       The  os funcs for Unix can share a signal handler.  And there's not much value is multiple
       OS funcs, anyway.

       gensio_unix_funcs_alloc and gensio_win_funcs_alloc allocate the normal os funcs  for  Unix
       and Windows based systems, respectively.

       The  sel  parameter  for Unix allows you to create your own selector object and pass it to
       the OS handler.  Passing in NULL will cause it to allocate it's own selector object.   See
       the selector.h include file for details.

       The  wake_sig  value  is  a  signal for use by the OS functions for internal communication
       between threads.  If you are running a multi-threaded  application,  you  must  provide  a
       valid  signal that you don't use for any other purpose, generally SIGUSR1 or SIGUSR2.  You
       can use GENSIO_DEF_WAKE_SIG which is zero on Windows and SIGUSR1 on Unix.

       The gensio_os_proc_setup function does all the standard setup for a process.   You  should
       almost  certainly  use  this  function.   On  Windows  this  sets  up some basic things so
       termination registering will work, but on Unix it does all the signal handling  setup,  so
       you  don't  have  to  do all the things mentioned above.  This will block SIGPIPE (because
       those come in when connections die and most applications don't care), SIGCHLD (those  come
       in  for  stdio  and pty gensios), and the wake_sig if that is set.  It also install signal
       handlers for SIGCHLD and the wake_sig (if set) and sets up a signal mask.

       For Unix this is generally what you want, you don't want  SIGPIPE  doing  bad  things  and
       having SIGCHLD wake up a wait can speed things up a bit when waiting for subprograms.

       If  you use the gensio_os_funcs_wait_intr_sigmask OS function, you must pass the proc_data
       value returned by gensio_os_proc_setup into that.  If you want to modify the  wait  signal
       mask,  you can use gensio_os_proc_unix_get_wait_sigset to fetch a pointer to it and modify
       it.

       The gensio_os_proc_cleanup function undoes  all  the  changes  gensio_os_proc_setup  does,
       along  with unregistering any signal handlers done by register calls.  On Unix it restores
       the signal mask and signal handlers it sets to  their  previous  values.   On  Windows  it
       remove registered handlers.

       The  gensio_os_new_thread  function starts a new thread at start_func passing in the given
       data value.  It returns a thread_id that you must pass into the wait  function.   This  is
       just  basic  generic  threads, you can use your OS functions if you need more control over
       the threads.  If you use threads, make sure to see the notes above about  setting  up  for
       them properly.

       The  gensio_os_wait_thread  waits  for  a thread to stop.  Note that it does not cause the
       thread to stop, it waits for it to stop.  You have to cause the thread to stop yourself.

       The  gensio_os_proc_register_term_handler  function  passes  a  handler  to  call  when  a
       termination  (SIGINT,  SIGQUIT,  SIGTERM  on  Unix, console control handler or WM_CLOSE on
       windows) is received by the process.  Set handler to NULL to disable.  If you do  this  on
       Unix, the signals will be blocked except when in a wait or service call.

       The  gensio_os_proc_register_reload_handler  sets  the  function  to call when a reload is
       requested by the operating system (SIGHUP on Unix).  Set handler to NULL to  disable.   On
       Unix, this will cause SIGHUP to be blocked except when in a wait or service call.

       The  gensio_os_proc_register_winsize_handler  function  sets  the  function to call when a
       console window size change is requested by the operating system (SIGWINCH  on  Unix).   It
       will  supply  the  new  size  parameters.   Set handler to NULL to disable.  Note that the
       handler will be called with current window size parameters after this is called.

       gensio_os_funcs_zalloc allocates a block of memory and zeroes it.  The gensio library  has
       it's  own allocator/deallocator that is using in testing to track if all allocated data is
       freed when the tests shut down, and to catch memory overruns,  underruns,  and  use  after
       free  errors.   Returns NULL if the memory cannot be allocated.  Use gensio_os_funcs_zfree
       to free the allocated memory.

       gensio_os_funcs_alloc_lock allocates a mutex that can be used for  locking  by  the  user.
       Use  gensio_os_funcs_lock  and  gensio_os_funcs_unlock  to  lock/unlock  the  mutex.   The
       gensio_os_funcs_free_lock will make sure  the  lock  is  not  locked  and  free  the  data
       associated  with  the  lock.  Note that even for os funcs that don't implement locks, this
       will implement a counter to make sure that all locks are balanced.

       gensio_os_funcs_get_monotonic_time returns a time value from the monotonic clock used  for
       gensio_os_start_timer_abs.   It can also be used as a standard monotonic clock, but is not
       a wall clock of any kind.

       gensio_os_funcs_set_vlog must be called by the user to set a log handling function for the
       os  funcs.   If  something  goes wrong internally in the gensio library, this log function
       will be called to report the issue.

       Timers are allocated  with  gensio_os_funcs_alloc_timer.   When  the  timer  expires,  the
       handlers will be called with the given cb_data.  This will return NULL if the timer cannot
       be  allocated.   Timers  are  not  running  when  allocated,  the  must  be  started  with
       gensio_os_funcs_start_timer, or gensio_os_funcs_start_timer_abs.  The first starts a timer
       relative to the current time.  The second starts a timer based upon a monotonic clock, see
       gensio_os_funcs_get_monotonic_time  for  details.  These will return GE_INUSE if the timer
       was  already  running.   To  stop  a  timer,  call  either  gensio_os_funcs_stop_timer  or
       gensio_os_funcs_stop_timer_with_done.   These  both return GE_TIMEDOUT if the timer is not
       running.  The first has no way to assure that the timer is finished running its  handlers;
       the  timer  handler  may still be active when it returns.  If it does not return an error,
       the second will call the done_handler function when the timer is  completely  stopped  and
       all  the handlers are finished.  The second also returns GE_INUSE if the timer has already
       been stopped but the done handler hasn't been called yet.  Note that you cannot start  the
       timer  again  until  the  done  handler  is  called.   And  finally,  to free a timer, use
       gensio_os_funcs_free_timer.  The timer should not be running when calling this.

       Runners are sort of like zero-time timers, they will just be called immediately.  They are
       useful  for  escaping  from  deep locking situations where you want to do something at the
       base context.  Use gensio_os_funcs_alloc_runner to allocate one of these.  It returns NULL
       if  the  runner cannot be allocated.  gensio_os_funcs_run causes the handler to be called.
       It returns GE_INUSE if  the  runner  is  currently  already  scheduled  to  be  run.   And
       gensio_os_funcs_free_runner  frees  the  runner.   It should not be currently scheduled to
       run.

       gensio_os_funcs_service provides the main service function to  run  timers,  runners,  I/O
       handling, etc.  If it is interrupted by a signal (on Unix), it returns GE_INTERRUPTED.  If
       timeout is non-NULL, it is a relative  amount  of  time  to  wait  and  this  will  return
       GE_TIMEDOUT  if  the  timeout expires.  Note that for long timeouts (days) this may return
       early on some os funcs, so don't rely on this for timing.  When this returns, the  timeout
       will  be updated to any remaining time, even on an early timeout.  Generally you don't use
       this function, you use waiters instead.

       Call gensio_os_funcs_handle_fork in the child function after a  fork  (Unix  only).   This
       cleans  up various things and readies the gensio library to be used after a fork.  If this
       returns an error, it is likely that the gensio library is unusable on the child.

       Waiters are used to wait for things to happen.  When the thing happens occurs,  that  code
       should  call  wake  to wake the waiter.  Normal servicing of tiers, runners, I/O, etc. are
       done while waiting.  Waiters and wakes are count based, if you call the  wake  before  the
       wait that's ok, the wake will be waiting when the wait happens.  If you call wake 3 times,
       there are 3 wakes pending.  To allocate a waiter, call  gensio_os_funcs_alloc_waiter.   It
       returns  NULL  if  it  cannot  allocate  the waiter.  gensio_os_funcs_wait waits for count
       wakeups to be done and then returns zero.  If timeout is NULL it waits forever.  Otherwise
       if  the timeout expires it returns GE_TIMEDOUT and the timeout is updated to the remaining
       time.  If this times out, no wakeups are "used" by the function, if only some are  pending
       those are still pending.  gensio_os_funcs_wait_intr is like gensio_os_funcs_wait except if
       an   signal    is    received    (Unix    only)    it    will    return    GE_INTERRUPTED.
       gensio_os_funcs_wait_intr_sigmask  is  like  gensio_os_funcs_wait_intr  but allows a user-
       specified signal mask to be installed (Unix only).  See gensio_os_proc_setup for  details.
       To  send  a  single  wakeup  to  a waiter, use gensio_os_funcs_wake.  And, of course, call
       gensio_os_funcs_free_waiter to free a waiter.

       An os funcs has a single void pointer that the user may install some data in for their own
       use.   Use  gensio_os_funcs_set_data  to  set  this  data  and gensio_os_funcs_get_data to
       retrieve it.

RETURN VALUES

       Return values are documented in the text above.

SEE ALSO

       gensio_set_log_mask(3),  gensio_get_log_mask(3),  gensio_log_level_to_str(3),   gensio(5),
       gensio_err(3)

                                           23 Feb 2019                         gensio_os_funcs(3)