Provided by: libgensio-dev_2.8.2-6.1build1_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_alloc_os_funcs(int wake_sig, struct gensio_os_funcs **o,
                       unsigned int flags, ...)

       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);

       int gensio_os_thread_setup(struct gensio_os_funcs *o);

       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 (Deprecated) provides a way to get the 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.  Use  of
       this  is now discouraged in general.  Having two independent parts of a system share an OS
       funcs without knowing about it is likely to lead to issues.  If a program knows it is  the
       only  thing  using  it,  then  this is ok for now, but it's going to be deprecated at some
       point.

       gensio_alloc_os_funcs allocates a new OS function handler for the platform,  for  Unix  or
       Windows.   Multiple  OS  handlers  can  be  used  to  handle  different  I/O  at different
       priorities.  When you create a gensio, all I/O callbacks  will  be  handled  from  the  OS
       handler  used  to create it.  So you can run different OS handlers in threads of different
       priority to run different gensios at different priority.   Otherwise  there  is  not  much
       reason for more than one of these.

       The  wake_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  you  pass in anything but zero, it will set up that signal by removing it
       from the sigmask and installing a handler for it.

       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.

       You can pass in GENSIO_OS_FUNCS_DEFAULT_THREAD_SIGNAL to take the default signal  handler,
       which is SIGUSR1.

       On  unix,  gensio_os_proc_setup  function handles all the above mentioned signal setup for
       you (blocking signals, setting signal handler), for the wake signal as above and also  for
       some  other signals like SIGTERM, SIGCHILD, SIGPIPE, and others.  You should generally use
       that unless you have special needs.  It also does neccessary setup on Windows.

       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_os_thread_setup is much like gensio_os_proc_setup, but it only sets up  the  signal
       handlers and blocking signals for the wakeup signal, it doesn't do any of the other setup.
       It allows you to bring a thread in to gensio that wasn't created by gensio.  It also  does
       some necessary setup on Windows for the thread.  If you have no signal handling needs, you
       can generally use this instead of gensio_os_proc_setup().  If  you  have  signal  handling
       needs,  one  thread  should  call gensio_os_proc_setup() and all other threads should call
       this function if they were not created by gensio.

       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.

       Note that  if  you  call  this  more  than  once  without  calling  gensio_os_proc_cleanup
       inbetween, it will return GE_INUSE.

       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.  This must be called from a thread that is already set up.

       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.  Call this before
       starting any other threads so they inherit the proper sigmask.

       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.  Call
       this before starting any other threads so they inherit the proper sigmask.

       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, through
       the console interface on Windows).  It will supply the new size parameters.   Set  handler
       and  console_iod  to  NULL  to disable.  Note that the handler will be called with current
       window size parameters after this is  called.   This  may  be  called  after  threads  are
       started,  the  SIGWINCH  signal  mask is set up by default in gensio_os_proc_setup on *nix
       systems.

       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)