home | help
gensio_os_funcs(3)	    Library Functions Manual	      gensio_os_funcs(3)

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 *time-
     out);

     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  func-
     tions:

     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 li-
     brary 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  with-
     out 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 dep-
     recated 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 dif-
     ferent  OS  handlers in threads of different priority to run different gen-
     sios 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  multi-
     ple 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 sig-
     nal  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  differ-
     ent  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 gen-
     erally use this instead of gensio_os_proc_setup().  If you have signal han-
     dling 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 appli-
     cation, 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    gen-
     sio_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  gen-
     sio_os_proc_cleanup inbetween, it will return GE_INUSE.

     The  gensio_os_proc_cleanup  function   undoes   all   the   changes   gen-
     sio_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  han-
     dlers.

     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 han-
     dler 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 ex-
     cept 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 sup-
     ply  the  new size parameters.  Set handler and console_iod to NULL to dis-
     able.  Note that the handler will be called with current window size  para-
     meters 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 gen-
     sio 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 allo-
     cated 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 stan-
     dard 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 gen-
     sio library, this log function will be called to report the issue.

     Timers are allocated with gensio_os_funcs_alloc_timer.  When the timer  ex-
     pires,  the  handlers will be called with the given cb_data.  This will re-
     turn NULL if the timer cannot be allocated.  Timers are  not  running  when
     allocated,  the  must  be started with gensio_os_funcs_start_timer, or gen-
     sio_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  gen-
     sio_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 han-
     dler 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  gen-
     sio_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 immedi-
     ately.  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 allo-
     cated.  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 gen-
     sio_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 up-
     dated 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 oc-
     curs, 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   gen-
     sio_os_funcs_wait	except	if an signal is received (Unix only) it will re-
     turn  GE_INTERRUPTED.   gensio_os_funcs_wait_intr_sigmask	is   like   gen-
     sio_os_funcs_wait_intr  but  allows  a user-specified signal mask to be in-
     stalled (Unix only).  See gensio_os_proc_setup for details.  To send a sin-
     gle 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)

home | help