LCOV - code coverage report
Current view: top level - lib/tevent - tevent_internal.h (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 138 159 86.8 %
Date: 2024-04-13 12:30:31 Functions: 12 13 92.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    generalised event loop handling
       5             : 
       6             :    INTERNAL STRUCTS. THERE ARE NO API GUARANTEES.
       7             :    External users should only ever have to include this header when
       8             :    implementing new tevent backends.
       9             : 
      10             :    Copyright (C) Stefan Metzmacher 2005-2009
      11             : 
      12             :      ** NOTE! The following LGPL license applies to the tevent
      13             :      ** library. This does NOT imply that all of Samba is released
      14             :      ** under the LGPL
      15             : 
      16             :    This library is free software; you can redistribute it and/or
      17             :    modify it under the terms of the GNU Lesser General Public
      18             :    License as published by the Free Software Foundation; either
      19             :    version 3 of the License, or (at your option) any later version.
      20             : 
      21             :    This library is distributed in the hope that it will be useful,
      22             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      24             :    Lesser General Public License for more details.
      25             : 
      26             :    You should have received a copy of the GNU Lesser General Public
      27             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      28             : */
      29             : 
      30             : struct tevent_req {
      31             :         /**
      32             :          * @brief What to do on completion
      33             :          *
      34             :          * This is used for the user of an async request, fn is called when
      35             :          * the request completes, either successfully or with an error.
      36             :          */
      37             :         struct {
      38             :                 /**
      39             :                  * @brief Completion function
      40             :                  * Completion function, to be filled by the API user
      41             :                  */
      42             :                 tevent_req_fn fn;
      43             :                 /**
      44             :                  * @brief Private data for the completion function
      45             :                  */
      46             :                 void *private_data;
      47             :                 /**
      48             :                  * @brief  The completion function name, for flow tracing.
      49             :                  */
      50             :                 const char *fn_name;
      51             :         } async;
      52             : 
      53             :         /**
      54             :          * @brief Private state pointer for the actual implementation
      55             :          *
      56             :          * The implementation doing the work for the async request needs to
      57             :          * keep around current data like for example a fd event. The user of
      58             :          * an async request should not touch this.
      59             :          */
      60             :         void *data;
      61             : 
      62             :         /**
      63             :          * @brief A function to overwrite the default print function
      64             :          *
      65             :          * The implementation doing the work may want to implement a
      66             :          * custom function to print the text representation of the async
      67             :          * request.
      68             :          */
      69             :         tevent_req_print_fn private_print;
      70             : 
      71             :         /**
      72             :          * @brief A function to cancel the request
      73             :          *
      74             :          * The implementation might want to set a function
      75             :          * that is called when the tevent_req_cancel() function
      76             :          * was called.
      77             :          */
      78             :         struct {
      79             :                 tevent_req_cancel_fn fn;
      80             :                 const char *fn_name;
      81             :         } private_cancel;
      82             : 
      83             :         /**
      84             :          * @brief A function to cleanup the request
      85             :          *
      86             :          * The implementation might want to set a function
      87             :          * that is called before the tevent_req_done() and tevent_req_error()
      88             :          * trigger the callers callback function.
      89             :          */
      90             :         struct {
      91             :                 tevent_req_cleanup_fn fn;
      92             :                 const char *fn_name;
      93             :                 enum tevent_req_state state;
      94             :         } private_cleanup;
      95             : 
      96             :         /**
      97             :          * @brief Internal state of the request
      98             :          *
      99             :          * Callers should only access this via functions and never directly.
     100             :          */
     101             :         struct {
     102             :                 /**
     103             :                  * @brief The talloc type of the data pointer
     104             :                  *
     105             :                  * This is filled by the tevent_req_create() macro.
     106             :                  *
     107             :                  * This for debugging only.
     108             :                  */
     109             :                 const char *private_type;
     110             : 
     111             :                 /**
     112             :                  * @brief The location where the request was created
     113             :                  *
     114             :                  * This uses the __location__ macro via the tevent_req_create()
     115             :                  * macro.
     116             :                  *
     117             :                  * This for debugging only.
     118             :                  */
     119             :                 const char *create_location;
     120             : 
     121             :                 /**
     122             :                  * @brief The location where the request was finished
     123             :                  *
     124             :                  * This uses the __location__ macro via the tevent_req_done(),
     125             :                  * tevent_req_error() or tevent_req_nomem() macro.
     126             :                  *
     127             :                  * This for debugging only.
     128             :                  */
     129             :                 const char *finish_location;
     130             : 
     131             :                 /**
     132             :                  * @brief The location where the request was canceled
     133             :                  *
     134             :                  * This uses the __location__ macro via the
     135             :                  * tevent_req_cancel() macro.
     136             :                  *
     137             :                  * This for debugging only.
     138             :                  */
     139             :                 const char *cancel_location;
     140             : 
     141             :                 /**
     142             :                  * @brief The external state - will be queried by the caller
     143             :                  *
     144             :                  * While the async request is being processed, state will remain in
     145             :                  * TEVENT_REQ_IN_PROGRESS. A request is finished if
     146             :                  * req->state>=TEVENT_REQ_DONE.
     147             :                  */
     148             :                 enum tevent_req_state state;
     149             : 
     150             :                 /**
     151             :                  * @brief status code when finished
     152             :                  *
     153             :                  * This status can be queried in the async completion function. It
     154             :                  * will be set to 0 when everything went fine.
     155             :                  */
     156             :                 uint64_t error;
     157             : 
     158             :                 /**
     159             :                  * @brief the immediate event used by tevent_req_post
     160             :                  *
     161             :                  */
     162             :                 struct tevent_immediate *trigger;
     163             : 
     164             :                 /**
     165             :                  * @brief An event context which will be used to
     166             :                  *        defer the _tevent_req_notify_callback().
     167             :                  */
     168             :                 struct tevent_context *defer_callback_ev;
     169             : 
     170             :                 /**
     171             :                  * @brief the timer event if tevent_req_set_endtime was used
     172             :                  *
     173             :                  */
     174             :                 struct tevent_timer *timer;
     175             : 
     176             :                 /**
     177             :                  * @brief The place where profiling data is kept
     178             :                  */
     179             :                 struct tevent_req_profile *profile;
     180             : 
     181             :                 size_t call_depth;
     182             :         } internal;
     183             : };
     184             : 
     185             : struct tevent_req_profile {
     186             :         struct tevent_req_profile *prev, *next;
     187             :         struct tevent_req_profile *parent;
     188             :         const char *req_name;
     189             :         pid_t pid;
     190             :         const char *start_location;
     191             :         struct timeval start_time;
     192             :         const char *stop_location;
     193             :         struct timeval stop_time;
     194             :         enum tevent_req_state state;
     195             :         uint64_t user_error;
     196             :         struct tevent_req_profile *subprofiles;
     197             : };
     198             : 
     199             : struct tevent_fd {
     200             :         struct tevent_fd *prev, *next;
     201             :         struct tevent_context *event_ctx;
     202             :         struct tevent_wrapper_glue *wrapper;
     203             :         bool busy;
     204             :         bool destroyed;
     205             :         int fd;
     206             :         uint16_t flags; /* see TEVENT_FD_* flags */
     207             :         tevent_fd_handler_t handler;
     208             :         tevent_fd_close_fn_t close_fn;
     209             :         /* this is private for the specific handler */
     210             :         void *private_data;
     211             :         /* this is for debugging only! */
     212             :         const char *handler_name;
     213             :         const char *location;
     214             :         /* this is private for the events_ops implementation */
     215             :         uint64_t additional_flags;
     216             :         void *additional_data;
     217             :         /* custom tag that can be set by caller */
     218             :         uint64_t tag;
     219             :         struct tevent_fd_mpx {
     220             :                 struct tevent_fd_mpx *prev, *next;
     221             :                 struct tevent_fd *fde;
     222             :                 struct tevent_fd *primary;
     223             :                 struct tevent_fd_mpx *list;
     224             :                 uint16_t total_flags;
     225             :                 bool has_mpx;
     226             :         } mpx;
     227             : };
     228             : 
     229             : struct tevent_timer {
     230             :         struct tevent_timer *prev, *next;
     231             :         struct tevent_context *event_ctx;
     232             :         struct tevent_wrapper_glue *wrapper;
     233             :         bool busy;
     234             :         bool destroyed;
     235             :         struct timeval next_event;
     236             :         tevent_timer_handler_t handler;
     237             :         /* this is private for the specific handler */
     238             :         void *private_data;
     239             :         /* this is for debugging only! */
     240             :         const char *handler_name;
     241             :         const char *location;
     242             :         /* this is private for the events_ops implementation */
     243             :         void *additional_data;
     244             :         /* custom tag that can be set by caller */
     245             :         uint64_t tag;
     246             : };
     247             : 
     248             : struct tevent_immediate {
     249             :         struct tevent_immediate *prev, *next;
     250             :         struct tevent_context *event_ctx;
     251             :         struct tevent_wrapper_glue *wrapper;
     252             :         bool busy;
     253             :         bool destroyed;
     254             :         struct tevent_context *detach_ev_ctx;
     255             :         tevent_immediate_handler_t handler;
     256             :         /* this is private for the specific handler */
     257             :         void *private_data;
     258             :         /* this is for debugging only! */
     259             :         const char *handler_name;
     260             :         const char *create_location;
     261             :         const char *schedule_location;
     262             :         /* this is private for the events_ops implementation */
     263             :         void (*cancel_fn)(struct tevent_immediate *im);
     264             :         void *additional_data;
     265             :         /* custom tag that can be set by caller */
     266             :         uint64_t tag;
     267             : };
     268             : 
     269             : struct tevent_signal {
     270             :         struct tevent_signal *prev, *next;
     271             :         struct tevent_context *event_ctx;
     272             :         struct tevent_wrapper_glue *wrapper;
     273             :         bool busy;
     274             :         bool destroyed;
     275             :         int signum;
     276             :         int sa_flags;
     277             :         tevent_signal_handler_t handler;
     278             :         /* this is private for the specific handler */
     279             :         void *private_data;
     280             :         /* this is for debugging only! */
     281             :         const char *handler_name;
     282             :         const char *location;
     283             :         /* this is private for the events_ops implementation */
     284             :         void *additional_data;
     285             :         /* custom tag that can be set by caller */
     286             :         uint64_t tag;
     287             : };
     288             : 
     289             : struct tevent_threaded_context {
     290             :         struct tevent_threaded_context *next, *prev;
     291             : 
     292             : #ifdef HAVE_PTHREAD
     293             :         pthread_mutex_t event_ctx_mutex;
     294             : #endif
     295             :         struct tevent_context *event_ctx;
     296             : };
     297             : 
     298             : struct tevent_debug_ops {
     299             :         enum tevent_debug_level max_level;
     300             :         void (*debug)(void *context, enum tevent_debug_level level,
     301             :                       const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
     302             :         void *context;
     303             : };
     304             : 
     305             : void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level,
     306             :                   const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
     307             : #define TEVENT_DEBUG(__ev, __level, __fmt, ...) do { \
     308             :         if (unlikely((__ev) != NULL && \
     309             :                      (__level) <= (__ev)->debug_ops.max_level)) \
     310             :         { \
     311             :                 tevent_debug((__ev), (__level), (__fmt), __VA_ARGS__); \
     312             :         } \
     313             : } while(0)
     314             : 
     315             : void tevent_abort(struct tevent_context *ev, const char *reason);
     316             : 
     317             : void tevent_common_check_double_free(TALLOC_CTX *ptr, const char *reason);
     318             : 
     319             : struct tevent_context {
     320             :         /* the specific events implementation */
     321             :         const struct tevent_ops *ops;
     322             : 
     323             :         /*
     324             :          * The following three pointers are queried on every loop_once
     325             :          * in the order in which they appear here. Not measured, but
     326             :          * hopefully putting them at the top together with "ops"
     327             :          * should make tevent a *bit* more cache-friendly than before.
     328             :          */
     329             : 
     330             :         /* list of signal events - used by common code */
     331             :         struct tevent_signal *signal_events;
     332             : 
     333             :         /* List of threaded job indicators */
     334             :         struct tevent_threaded_context *threaded_contexts;
     335             : 
     336             :         /* list of immediate events - used by common code */
     337             :         struct tevent_immediate *immediate_events;
     338             : 
     339             :         /* list of fd events - used by common code */
     340             :         struct tevent_fd *fd_events;
     341             : 
     342             :         /* list of timed events - used by common code */
     343             :         struct tevent_timer *timer_events;
     344             : 
     345             :         /* List of scheduled immediates */
     346             :         pthread_mutex_t scheduled_mutex;
     347             :         struct tevent_immediate *scheduled_immediates;
     348             : 
     349             :         /* this is private for the events_ops implementation */
     350             :         void *additional_data;
     351             : 
     352             :         /* pipe hack used with signal handlers */
     353             :         struct tevent_fd *wakeup_fde;
     354             :         int wakeup_fd;          /* fd to write into */
     355             : #ifndef HAVE_EVENT_FD
     356             :         int wakeup_read_fd;
     357             : #endif
     358             : 
     359             :         /* debugging operations */
     360             :         struct tevent_debug_ops debug_ops;
     361             : 
     362             :         /* info about the nesting status */
     363             :         struct {
     364             :                 bool allowed;
     365             :                 uint32_t level;
     366             :                 tevent_nesting_hook hook_fn;
     367             :                 void *hook_private;
     368             :         } nesting;
     369             : 
     370             :         struct {
     371             :                 struct {
     372             :                         tevent_trace_callback_t callback;
     373             :                         void *private_data;
     374             :                 } point;
     375             : 
     376             :                 struct {
     377             :                         tevent_trace_fd_callback_t callback;
     378             :                         void *private_data;
     379             :                 } fde;
     380             : 
     381             :                 struct {
     382             :                         tevent_trace_signal_callback_t callback;
     383             :                         void *private_data;
     384             :                 } se;
     385             : 
     386             :                 struct {
     387             :                         tevent_trace_timer_callback_t callback;
     388             :                         void *private_data;
     389             :                 } te;
     390             : 
     391             :                 struct {
     392             :                         tevent_trace_immediate_callback_t callback;
     393             :                         void *private_data;
     394             :                 } im;
     395             : 
     396             :                 struct {
     397             :                         tevent_trace_queue_callback_t callback;
     398             :                         void *private_data;
     399             :                 } qe;
     400             :         } tracing;
     401             : 
     402             :         struct {
     403             :                 /*
     404             :                  * This is used on the main event context
     405             :                  */
     406             :                 struct tevent_wrapper_glue *list;
     407             : 
     408             :                 /*
     409             :                  * This is used on the wrapper event context
     410             :                  */
     411             :                 struct tevent_wrapper_glue *glue;
     412             :         } wrapper;
     413             : 
     414             :         /*
     415             :          * an optimization pointer into timer_events
     416             :          * used by used by common code via
     417             :          * tevent_common_add_timer_v2()
     418             :          */
     419             :         struct tevent_timer *last_zero_timer;
     420             : 
     421             : #ifdef HAVE_PTHREAD
     422             :         struct tevent_context *prev, *next;
     423             : #endif
     424             : };
     425             : 
     426             : int tevent_common_context_destructor(struct tevent_context *ev);
     427             : int tevent_common_loop_wait(struct tevent_context *ev,
     428             :                             const char *location);
     429             : 
     430             : struct tevent_common_fd_buf {
     431             :         char buf[128];
     432             : };
     433             : 
     434             : const char *tevent_common_fd_str(struct tevent_common_fd_buf *buf,
     435             :                                  const char *description,
     436             :                                  const struct tevent_fd *fde);
     437             : 
     438             : int tevent_common_fd_destructor(struct tevent_fd *fde);
     439             : struct tevent_fd *tevent_common_add_fd(struct tevent_context *ev,
     440             :                                        TALLOC_CTX *mem_ctx,
     441             :                                        int fd,
     442             :                                        uint16_t flags,
     443             :                                        tevent_fd_handler_t handler,
     444             :                                        void *private_data,
     445             :                                        const char *handler_name,
     446             :                                        const char *location);
     447             : void tevent_common_fd_set_close_fn(struct tevent_fd *fde,
     448             :                                    tevent_fd_close_fn_t close_fn);
     449             : uint16_t tevent_common_fd_get_flags(struct tevent_fd *fde);
     450             : void tevent_common_fd_set_flags(struct tevent_fd *fde, uint16_t flags);
     451             : int tevent_common_invoke_fd_handler(struct tevent_fd *fde, uint16_t flags,
     452             :                                     bool *removed);
     453             : 
     454             : struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev,
     455             :                                              TALLOC_CTX *mem_ctx,
     456             :                                              struct timeval next_event,
     457             :                                              tevent_timer_handler_t handler,
     458             :                                              void *private_data,
     459             :                                              const char *handler_name,
     460             :                                              const char *location);
     461             : struct tevent_timer *tevent_common_add_timer_v2(struct tevent_context *ev,
     462             :                                                 TALLOC_CTX *mem_ctx,
     463             :                                                 struct timeval next_event,
     464             :                                                 tevent_timer_handler_t handler,
     465             :                                                 void *private_data,
     466             :                                                 const char *handler_name,
     467             :                                                 const char *location);
     468             : struct timeval tevent_common_loop_timer_delay(struct tevent_context *);
     469             : int tevent_common_invoke_timer_handler(struct tevent_timer *te,
     470             :                                        struct timeval current_time,
     471             :                                        bool *removed);
     472             : 
     473             : void tevent_common_schedule_immediate(struct tevent_immediate *im,
     474             :                                       struct tevent_context *ev,
     475             :                                       tevent_immediate_handler_t handler,
     476             :                                       void *private_data,
     477             :                                       const char *handler_name,
     478             :                                       const char *location);
     479             : int tevent_common_invoke_immediate_handler(struct tevent_immediate *im,
     480             :                                            bool *removed);
     481             : bool tevent_common_loop_immediate(struct tevent_context *ev);
     482             : void tevent_common_threaded_activate_immediate(struct tevent_context *ev);
     483             : 
     484             : bool tevent_common_have_events(struct tevent_context *ev);
     485             : int tevent_common_wakeup_init(struct tevent_context *ev);
     486             : int tevent_common_wakeup_fd(int fd);
     487             : int tevent_common_wakeup(struct tevent_context *ev);
     488             : 
     489             : struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
     490             :                                                TALLOC_CTX *mem_ctx,
     491             :                                                int signum,
     492             :                                                int sa_flags,
     493             :                                                tevent_signal_handler_t handler,
     494             :                                                void *private_data,
     495             :                                                const char *handler_name,
     496             :                                                const char *location);
     497             : int tevent_common_check_signal(struct tevent_context *ev);
     498             : void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se);
     499             : int tevent_common_invoke_signal_handler(struct tevent_signal *se,
     500             :                                         int signum, int count, void *siginfo,
     501             :                                         bool *removed);
     502             : 
     503             : struct tevent_context *tevent_wrapper_main_ev(struct tevent_context *ev);
     504             : 
     505             : struct tevent_wrapper_ops;
     506             : 
     507             : struct tevent_wrapper_glue {
     508             :         struct tevent_wrapper_glue *prev, *next;
     509             :         struct tevent_context *wrap_ev;
     510             :         struct tevent_context *main_ev;
     511             :         bool busy;
     512             :         bool destroyed;
     513             :         const struct tevent_wrapper_ops *ops;
     514             :         void *private_state;
     515             : };
     516             : 
     517             : void tevent_wrapper_push_use_internal(struct tevent_context *ev,
     518             :                                       struct tevent_wrapper_glue *wrapper);
     519             : void tevent_wrapper_pop_use_internal(const struct tevent_context *__ev_ptr,
     520             :                                      struct tevent_wrapper_glue *wrapper);
     521             : 
     522             : bool tevent_standard_init(void);
     523             : bool tevent_poll_init(void);
     524             : bool tevent_poll_event_add_fd_internal(struct tevent_context *ev,
     525             :                                        struct tevent_fd *fde);
     526             : bool tevent_poll_mt_init(void);
     527             : #ifdef HAVE_EPOLL
     528             : bool tevent_epoll_init(void);
     529             : void tevent_epoll_set_panic_fallback(struct tevent_context *ev,
     530             :                         bool (*panic_fallback)(struct tevent_context *ev,
     531             :                                                bool replay));
     532             : #endif
     533             : 
     534  1033941202 : static inline void tevent_thread_call_depth_notify(
     535             :                         enum tevent_thread_call_depth_cmd cmd,
     536             :                         struct tevent_req *req,
     537             :                         size_t depth,
     538             :                         const char *fname)
     539             : {
     540  1033941202 :         if (tevent_thread_call_depth_state_g.cb != NULL) {
     541           0 :                 tevent_thread_call_depth_state_g.cb(
     542             :                         tevent_thread_call_depth_state_g.cb_private,
     543             :                         cmd,
     544             :                         req,
     545             :                         depth,
     546             :                         fname);
     547             :         }
     548   993785391 : }
     549             : 
     550             : void tevent_trace_point_callback(struct tevent_context *ev,
     551             :                                  enum tevent_trace_point);
     552             : 
     553             : void tevent_trace_fd_callback(struct tevent_context *ev,
     554             :                               struct tevent_fd *fde,
     555             :                               enum tevent_event_trace_point);
     556             : 
     557             : void tevent_trace_signal_callback(struct tevent_context *ev,
     558             :                                   struct tevent_signal *se,
     559             :                                   enum tevent_event_trace_point);
     560             : 
     561             : void tevent_trace_timer_callback(struct tevent_context *ev,
     562             :                                  struct tevent_timer *te,
     563             :                                  enum tevent_event_trace_point);
     564             : 
     565             : void tevent_trace_immediate_callback(struct tevent_context *ev,
     566             :                                      struct tevent_immediate *im,
     567             :                                      enum tevent_event_trace_point);
     568             : 
     569             : void tevent_trace_queue_callback(struct tevent_context *ev,
     570             :                                  struct tevent_queue_entry *qe,
     571             :                                  enum tevent_event_trace_point);
     572             : 
     573             : #include "tevent_dlinklist.h"
     574             : 
     575    41680026 : static inline void tevent_common_fd_mpx_reinit(struct tevent_fd *fde)
     576             : {
     577    41630927 :         fde->mpx = (struct tevent_fd_mpx) { .fde = fde, };
     578    41501453 : }
     579             : 
     580     1041746 : static inline void tevent_common_fd_disarm(struct tevent_fd *fde)
     581             : {
     582     1041746 :         if (fde->event_ctx != NULL) {
     583     1041746 :                 tevent_trace_fd_callback(fde->event_ctx, fde,
     584             :                                          TEVENT_EVENT_TRACE_DETACH);
     585     1041746 :                 DLIST_REMOVE(fde->event_ctx->fd_events, fde);
     586     1041746 :                 fde->event_ctx = NULL;
     587             :         }
     588     1041746 :         tevent_common_fd_mpx_reinit(fde);
     589     1041746 :         fde->wrapper = NULL;
     590     1041746 : }
     591             : 
     592             : /*
     593             :  * tevent_common_fd_mpx_primary() returns the fde that is responsible
     594             :  * for the low level state.
     595             :  *
     596             :  * By default (when there's no multiplexing) it just returns 'any_fde'.
     597             :  *
     598             :  * Note it always returns a valid pointer.
     599             :  */
     600             : static inline
     601   385744810 : struct tevent_fd *tevent_common_fd_mpx_primary(struct tevent_fd *any_fde)
     602             : {
     603   385825557 :         struct tevent_fd *primary = NULL;
     604             : 
     605   370084468 :         if (any_fde->mpx.primary != NULL) {
     606       70508 :                 primary = any_fde->mpx.primary;
     607             :         } else {
     608   369716054 :                 primary = any_fde;
     609             :         }
     610             : 
     611   370084468 :         return primary;
     612             : }
     613             : 
     614             : /*
     615             :  * tevent_common_fd_mpx_update_flags() needs to be called
     616             :  * if update_fde->flags has changed. It is needed in
     617             :  * order to let tevent_common_fd_mpx_flags() return a valid
     618             :  * result.
     619             :  */
     620             : static inline
     621    21051763 : void tevent_common_fd_mpx_update_flags(struct tevent_fd *update_fde)
     622             : {
     623    21049877 :         struct tevent_fd *primary = tevent_common_fd_mpx_primary(update_fde);
     624    21051763 :         struct tevent_fd_mpx *mpx = NULL;
     625    21051763 :         uint16_t new_total_flags = 0;
     626             : 
     627    21051763 :         if (!primary->mpx.has_mpx) {
     628    20978565 :                 primary->mpx.total_flags = primary->flags;
     629    20978565 :                 return;
     630             :         }
     631             : 
     632      186004 :         for (mpx = primary->mpx.list; mpx != NULL; mpx = mpx->next) {
     633      112806 :                 struct tevent_fd *mpx_fde = mpx->fde;
     634             :                 /* we don't care that mpx_fde might be == primary */
     635      112806 :                 new_total_flags |= mpx_fde->flags;
     636             :         }
     637             : 
     638       73198 :         primary->mpx.total_flags = new_total_flags;
     639             : }
     640             : 
     641             : /*
     642             :  * tevent_common_fd_mpx_flags() return the effective flags
     643             :  * (TEVEND_FD_*) of the primary fde and all multiplexed fdes.
     644             :  *
     645             :  * Valid after tevent_common_fd_mpx_update_flags() was called
     646             :  */
     647             : static inline
     648   193732347 : uint16_t tevent_common_fd_mpx_flags(struct tevent_fd *any_fde)
     649             : {
     650   193730461 :         struct tevent_fd *primary = tevent_common_fd_mpx_primary(any_fde);
     651             : 
     652   193730325 :         return primary->mpx.total_flags;
     653             : }
     654             : 
     655             : /*
     656             :  * tevent_common_fd_mpx_clear_writeable() clears TEVENT_FD_WRITE
     657             :  * from all fdes belonging together.
     658             :  */
     659             : static inline
     660           0 : void tevent_common_fd_mpx_clear_writeable(struct tevent_fd *any_fde)
     661             : {
     662           0 :         struct tevent_fd *primary = tevent_common_fd_mpx_primary(any_fde);
     663           0 :         struct tevent_fd_mpx *mpx = NULL;
     664             : 
     665           0 :         primary->flags &= ~TEVENT_FD_WRITE;
     666             : 
     667           0 :         for (mpx = primary->mpx.list; mpx != NULL; mpx = mpx->next) {
     668           0 :                 struct tevent_fd *mpx_fde = mpx->fde;
     669             :                 /* we don't care that mpx_fde might be == primary */
     670           0 :                 mpx_fde->flags &= ~TEVENT_FD_WRITE;
     671             :         }
     672             : 
     673           0 :         primary->mpx.total_flags &= ~TEVENT_FD_WRITE;
     674           0 : }
     675             : 
     676             : /*
     677             :  * tevent_common_fd_mpx_additional_flags() modifies
     678             :  * fde->additional_flags for all fdes belonging together.
     679             :  */
     680             : static inline
     681    67371144 : void tevent_common_fd_mpx_additional_flags(struct tevent_fd *any_fde,
     682             :                                            uint64_t clear_flags,
     683             :                                            uint64_t add_flags)
     684             : {
     685    67291323 :         struct tevent_fd *primary = tevent_common_fd_mpx_primary(any_fde);
     686    67371144 :         struct tevent_fd_mpx *mpx = NULL;
     687             : 
     688    67371144 :         primary->additional_flags &= ~clear_flags;
     689    67371144 :         primary->additional_flags |= add_flags;
     690             : 
     691    67730958 :         for (mpx = primary->mpx.list; mpx != NULL; mpx = mpx->next) {
     692      359814 :                 struct tevent_fd *mpx_fde = mpx->fde;
     693             :                 /* we don't care that mpx_fde might be == primary */
     694      359814 :                 mpx_fde->additional_flags &= ~clear_flags;
     695      359814 :                 mpx_fde->additional_flags |= add_flags;
     696             :         }
     697    67169372 : }
     698             : 
     699             : /*
     700             :  * tevent_common_fd_mpx_disarm_all() detaches
     701             :  * all fdes currently belonging together from each other
     702             :  * and also from the tevent_context, which means their
     703             :  * handler will never be called again.
     704             :  */
     705             : static inline
     706           1 : void tevent_common_fd_mpx_disarm_all(struct tevent_fd *any_fde)
     707             : {
     708           1 :         struct tevent_fd *primary = tevent_common_fd_mpx_primary(any_fde);
     709           1 :         struct tevent_fd_mpx *mpx = NULL, *next = NULL;
     710             : 
     711           1 :         for (mpx = primary->mpx.list; mpx != NULL; mpx = next) {
     712           0 :                 struct tevent_fd *mpx_fde = mpx->fde;
     713             : 
     714           0 :                 next = mpx->next;
     715           0 :                 DLIST_REMOVE(primary->mpx.list, mpx);
     716             : 
     717           0 :                 if (mpx_fde == primary) {
     718             :                         /* primary is handled below */
     719           0 :                         continue;
     720             :                 }
     721             : 
     722           0 :                 tevent_common_fd_disarm(mpx_fde);
     723             :         }
     724             : 
     725           1 :         tevent_common_fd_disarm(primary);
     726           1 : }
     727             : 
     728             : /*
     729             :  * tevent_common_fd_mpx_select() selects the handler that
     730             :  * should be called for the given low level event.
     731             :  *
     732             :  * Note it's important to pass the primary fde!
     733             :  */
     734             : static inline
     735   150895998 : struct tevent_fd *tevent_common_fd_mpx_select(struct tevent_fd *primary,
     736             :                                               uint16_t flags,
     737             :                                               bool got_error)
     738             : {
     739   150895998 :         struct tevent_fd_mpx *mpx = NULL;
     740   150895998 :         struct tevent_fd *selected = NULL;
     741             : 
     742             :         /* optimize for the single event case. */
     743   150895998 :         if (!primary->mpx.has_mpx) {
     744             :                 /*
     745             :                  * If we got an error, we won't report it if
     746             :                  * the caller only asked for TEVENT_FD_WRITE.
     747             :                  */
     748   140896732 :                 if (got_error &&
     749     9979146 :                     !(primary->flags & (TEVENT_FD_READ|TEVENT_FD_ERROR)))
     750             :                 {
     751           0 :                         return NULL;
     752             :                 }
     753             : 
     754   140896732 :                 if (flags & primary->flags) {
     755   135049991 :                         return primary;
     756             :                 }
     757             : 
     758           0 :                 return NULL;
     759             :         }
     760             : 
     761    23925701 :         for (mpx = primary->mpx.list; mpx != NULL; mpx = mpx->next) {
     762    23925701 :                 struct tevent_fd *mpx_fde = mpx->fde;
     763             : 
     764             :                 /*
     765             :                  * If we got an error, we won't report it if
     766             :                  * the caller only asked for TEVENT_FD_WRITE.
     767             :                  */
     768    23925701 :                 if (got_error &&
     769        5330 :                     !(mpx_fde->flags & (TEVENT_FD_READ|TEVENT_FD_ERROR)))
     770             :                 {
     771        3552 :                         continue;
     772             :                 }
     773             : 
     774    23922149 :                 if (flags & mpx_fde->flags) {
     775      584807 :                         selected = mpx_fde;
     776      584807 :                         break;
     777             :                 }
     778             :         }
     779             : 
     780     9999266 :         if (selected == NULL) {
     781           0 :                 return NULL;
     782             :         }
     783             : 
     784             :         /*
     785             :          * Maintain fairness and demote the just selected fde
     786             :          */
     787     9999266 :         DLIST_DEMOTE_SHORT(primary->mpx.list, &selected->mpx);
     788      584807 :         return selected;
     789             : }
     790             : 
     791             : /*
     792             :  * tevent_common_fd_mpx_add() searches for an existing (active) fde
     793             :  * for the same low level fd and adds the given 'add_fde'
     794             :  * as multiplexed to the found fde.
     795             :  *
     796             :  * If another fde was found it is returned.
     797             :  * NULL is returned to indicate no match
     798             :  */
     799             : static inline
     800       37950 : struct tevent_fd *tevent_common_fd_mpx_add(struct tevent_fd *add_fde)
     801             : {
     802       37950 :         struct tevent_context *ev = add_fde->event_ctx;
     803       37950 :         struct tevent_fd *add_primary = tevent_common_fd_mpx_primary(add_fde);
     804       37950 :         uint16_t add_flags = tevent_common_fd_mpx_flags(add_primary);
     805       37950 :         struct tevent_fd *mpx_fde = NULL;
     806       37950 :         struct tevent_fd *mpx_primary = NULL;
     807       37950 :         struct tevent_fd_mpx *tmp = NULL;
     808       37950 :         struct tevent_fd_mpx *next = NULL;
     809             : 
     810             :         /* Find the existing fde that caused the EEXIST error. */
     811       76185 :         for (mpx_fde = ev->fd_events; mpx_fde; mpx_fde = mpx_fde->next) {
     812       76185 :                 mpx_primary = tevent_common_fd_mpx_primary(mpx_fde);
     813             : 
     814       76185 :                 if (mpx_primary->fd != add_primary->fd) {
     815         185 :                         mpx_primary = NULL;
     816         185 :                         continue;
     817             :                 }
     818             : 
     819       76000 :                 if (mpx_primary == add_primary) {
     820       37948 :                         mpx_primary = NULL;
     821       37948 :                         continue;
     822             :                 }
     823             : 
     824       75042 :                 if (add_flags != 0 &&
     825       38052 :                     tevent_common_fd_mpx_flags(mpx_primary) == 0)
     826             :                 {
     827             :                         /*
     828             :                          * only active events should match
     829             :                          */
     830         102 :                         mpx_primary = NULL;
     831         102 :                         continue;
     832             :                 }
     833       36990 :                 break;
     834             :         }
     835       37950 :         if (mpx_primary == NULL) {
     836           0 :                 tevent_debug(ev, TEVENT_DEBUG_FATAL,
     837             :                              "can't find multiplex fde for fd[%d]",
     838             :                              add_fde->fd);
     839           0 :                 return NULL;
     840             :         }
     841             : 
     842             :         /*
     843             :          * If add_primary is not in it's own list
     844             :          * we add it in order to simplify the loop below.
     845             :          */
     846             : 
     847       37950 :         if (add_primary->mpx.prev == NULL && add_primary->mpx.next == NULL) {
     848       37950 :                 DLIST_ADD_END(add_primary->mpx.list, &add_primary->mpx);
     849             :         }
     850             : 
     851             :         /*
     852             :          * Add the new mpx_primary to its own list before others,
     853             :          * if it is not already added.
     854             :          */
     855       37950 :         if (mpx_primary->mpx.prev == NULL && mpx_primary->mpx.next == NULL) {
     856       31232 :                 DLIST_ADD_END(mpx_primary->mpx.list, &mpx_primary->mpx);
     857             :         }
     858             : 
     859             :         /*
     860             :          * Now we clear all entries and move them to the
     861             :          * new primary
     862             :          */
     863       75900 :         for (tmp = add_primary->mpx.list; tmp != NULL; tmp = next) {
     864       37950 :                 struct tevent_fd *tmp_fde = tmp->fde;
     865             : 
     866       37950 :                 next = tmp->next;
     867             : 
     868       37950 :                 DLIST_REMOVE(add_primary->mpx.list, tmp);
     869       37950 :                 tevent_common_fd_mpx_reinit(tmp_fde);
     870       37950 :                 DLIST_ADD_END(mpx_primary->mpx.list, tmp);
     871       37950 :                 tmp->primary = mpx_primary;
     872       37950 :                 tmp->has_mpx = true;
     873             :         }
     874             : 
     875       37950 :         mpx_primary->mpx.has_mpx = true;
     876       37950 :         return mpx_primary;
     877             : }
     878             : 
     879             : /*
     880             :  * tevent_common_fd_mpx_update() calls tevent_common_fd_mpx_update_flags()
     881             :  * and compares tevent_common_fd_mpx_flags() before and after.
     882             :  *
     883             :  * When there's a low level update needed the primary fde,
     884             :  * otherwise NULL is returned.
     885             :  */
     886             : static inline
     887       75866 : struct tevent_fd *tevent_common_fd_mpx_update(struct tevent_fd *update_fde)
     888             : {
     889       75866 :         struct tevent_fd *primary = tevent_common_fd_mpx_primary(update_fde);
     890        1886 :         uint16_t old_total_flags;
     891        1886 :         uint16_t new_total_flags;
     892             : 
     893       75866 :         old_total_flags = primary->mpx.total_flags;
     894       75866 :         tevent_common_fd_mpx_update_flags(primary);
     895       75866 :         new_total_flags = primary->mpx.total_flags;
     896             : 
     897       75866 :         if (old_total_flags == new_total_flags) {
     898             :                 /* No update needed */
     899          36 :                 return NULL;
     900             :         }
     901             : 
     902       73980 :         return primary;
     903             : }
     904             : 
     905             : /*
     906             :  * tevent_common_fd_mpx_remove() removes remove_fde from its possible primary,
     907             :  * if remove_fde is a primary itself, a new primary is selected.
     908             :  *
     909             :  * The remaining primary or NULL is returned.
     910             :  */
     911             : static inline
     912    14905569 : struct tevent_fd *tevent_common_fd_mpx_remove(struct tevent_fd *remove_fde)
     913             : {
     914    14905569 :         struct tevent_fd *primary = tevent_common_fd_mpx_primary(remove_fde);
     915    14905569 :         struct tevent_fd_mpx *mpx = NULL, *next = NULL;
     916    14905569 :         struct tevent_fd *new_primary = NULL;
     917             : 
     918    14905569 :         DLIST_REMOVE(primary->mpx.list, &remove_fde->mpx);
     919             : 
     920    14905569 :         if (primary != remove_fde) {
     921       35046 :                 tevent_common_fd_mpx_reinit(remove_fde);
     922       35046 :                 return primary;
     923             :         }
     924             : 
     925    14873411 :         for (mpx = primary->mpx.list; mpx != NULL; mpx = next) {
     926        2888 :                 struct tevent_fd *mpx_fde = mpx->fde;
     927             : 
     928        2888 :                 next = mpx->next;
     929             : 
     930        2888 :                 DLIST_REMOVE(primary->mpx.list, &mpx_fde->mpx);
     931        2888 :                 tevent_common_fd_mpx_reinit(mpx_fde);
     932        2888 :                 mpx->primary = new_primary;
     933        2888 :                 if (new_primary == NULL) {
     934             :                         /*
     935             :                          * Select the first one as the new primary and add
     936             :                          * itself as the first mpx-fde to the mpx list
     937             :                          */
     938        2870 :                         new_primary = mpx_fde;
     939        2870 :                         DLIST_ADD(new_primary->mpx.list, &mpx_fde->mpx);
     940        2870 :                         continue;
     941             :                 }
     942          18 :                 new_primary->mpx.has_mpx = true;
     943          18 :                 mpx->has_mpx = true;
     944          18 :                 DLIST_ADD_END(new_primary->mpx.list, &mpx_fde->mpx);
     945             :         }
     946             : 
     947             :         /* primary == remove_fde */
     948    14870523 :         tevent_common_fd_mpx_reinit(primary);
     949    14870523 :         return new_primary;
     950             : }

Generated by: LCOV version 1.14