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)