2005-02-15 13:36:59 +03:00
/*
Unix SMB / CIFS implementation .
generalised event loop handling
Internal structs
Copyright ( C ) Stefan Metzmacher 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-02-15 13:36:59 +03:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-02-15 13:36:59 +03:00
*/
struct event_ops {
/* conntext init */
2007-01-05 12:35:49 +03:00
int ( * context_init ) ( struct event_context * ev ) ;
2005-02-15 13:36:59 +03:00
/* fd_event functions */
struct fd_event * ( * add_fd ) ( struct event_context * ev ,
TALLOC_CTX * mem_ctx ,
int fd , uint16_t flags ,
event_fd_handler_t handler ,
void * private_data ) ;
uint16_t ( * get_fd_flags ) ( struct fd_event * fde ) ;
void ( * set_fd_flags ) ( struct fd_event * fde , uint16_t flags ) ;
/* timed_event functions */
struct timed_event * ( * add_timed ) ( struct event_context * ev ,
TALLOC_CTX * mem_ctx ,
struct timeval next_event ,
event_timed_handler_t handler ,
void * private_data ) ;
2007-01-05 12:35:49 +03:00
/* disk aio event functions */
struct aio_event * ( * add_aio ) ( struct event_context * ev ,
TALLOC_CTX * mem_ctx ,
struct iocb * iocb ,
event_aio_handler_t handler ,
void * private_data ) ;
2007-01-21 11:23:14 +03:00
/* signal functions */
struct signal_event * ( * add_signal ) ( struct event_context * ev ,
TALLOC_CTX * mem_ctx ,
2007-01-21 13:32:39 +03:00
int signum , int sa_flags ,
2007-01-21 11:23:14 +03:00
event_signal_handler_t handler ,
void * private_data ) ;
2005-02-15 13:36:59 +03:00
/* loop functions */
int ( * loop_once ) ( struct event_context * ev ) ;
int ( * loop_wait ) ( struct event_context * ev ) ;
} ;
struct fd_event {
struct fd_event * prev , * next ;
struct event_context * event_ctx ;
int fd ;
uint16_t flags ; /* see EVENT_FD_* flags */
event_fd_handler_t handler ;
/* this is private for the specific handler */
void * private_data ;
/* this is private for the events_ops implementation */
2005-12-09 19:43:19 +03:00
uint16_t additional_flags ;
2005-02-15 13:36:59 +03:00
void * additional_data ;
} ;
struct timed_event {
struct timed_event * prev , * next ;
struct event_context * event_ctx ;
struct timeval next_event ;
event_timed_handler_t handler ;
/* this is private for the specific handler */
void * private_data ;
/* this is private for the events_ops implementation */
void * additional_data ;
} ;
2007-01-21 11:23:14 +03:00
struct signal_event {
struct signal_event * prev , * next ;
struct event_context * event_ctx ;
event_signal_handler_t handler ;
void * private_data ;
int signum ;
2007-01-21 13:32:39 +03:00
int sa_flags ;
2007-01-21 11:23:14 +03:00
} ;
2008-06-14 19:23:31 +04:00
/* DEBUG */
enum ev_debug_level { EV_DEBUG_FATAL , EV_DEBUG_ERROR ,
EV_DEBUG_WARNING , EV_DEBUG_TRACE } ;
struct ev_debug_ops {
void ( * debug ) ( void * context , enum ev_debug_level level ,
const char * fmt , va_list ap ) PRINTF_ATTRIBUTE ( 3 , 0 ) ;
void * context ;
} ;
int ev_set_debug ( struct event_context * ev ,
void ( * debug ) ( void * context , enum ev_debug_level level ,
const char * fmt , va_list ap ) ,
void * context ) ;
int ev_set_debug_stderr ( struct event_context * ev ) ;
void ev_debug ( struct event_context * ev , enum ev_debug_level level , const char * fmt , . . . ) ;
2007-01-05 12:35:49 +03:00
/* aio event is private to the aio backend */
struct aio_event ;
2008-06-14 19:23:31 +04:00
struct event_context {
2005-02-15 13:36:59 +03:00
/* the specific events implementation */
const struct event_ops * ops ;
2007-01-05 12:35:49 +03:00
/* list of timed events - used by common code */
struct timed_event * timed_events ;
2005-02-15 13:36:59 +03:00
/* this is private for the events_ops implementation */
void * additional_data ;
2007-01-21 11:23:14 +03:00
/* number of signal event handlers */
int num_signal_handlers ;
/* pipe hack used with signal handlers */
struct fd_event * pipe_fde ;
2008-06-14 19:23:31 +04:00
/* debugging operations */
struct ev_debug_ops debug_ops ;
2005-02-15 13:36:59 +03:00
} ;
2007-01-05 12:35:49 +03:00
2007-05-02 01:29:42 +04:00
bool event_register_backend ( const char * name , const struct event_ops * ops ) ;
2007-01-05 12:35:49 +03:00
2008-06-14 19:23:31 +04:00
bool ev_timeval_is_zero ( const struct timeval * tv ) ;
2007-01-05 12:35:49 +03:00
struct timed_event * common_event_add_timed ( struct event_context * , TALLOC_CTX * ,
struct timeval , event_timed_handler_t , void * ) ;
r22661: optimize the handling of directly triggered timed events:
- if someone adds a timed_event with a zero timeval
we now avoid serval gettimeofday() calls and the
event handler doesn't get the current time when it's
called, instead we also pass a zero timeval
- this also makes sure multiple timed events with a zero timeval
are processed in the order there're added.
the little benchmark shows that processing 2000000 directly timed events
is now much faster, while avoiding syscalls at all!
> time ./evtest (with the old code)
real 0m6.388s
user 0m1.740s
sys 0m4.632s
> time ./evtest (with the new code)
real 0m1.498s
user 0m1.496s
sys 0m0.004s
metze@SERNOX:~/devel/samba/4.0/samba4-ci/source> cat evtest.c
#include <stdio.h>
#include <stdint.h>
#include <sys/time.h>
#include <talloc.h>
#include <events.h>
static void dummy_fde_handler(struct event_context *ev_ctx, struct fd_event *fde,
uint16_t flags, void *private_data)
{
}
static void timeout_handler(struct event_context *ev, struct timed_event *te,
struct timeval tval, void *private_data)
{
uint32_t *countp = (uint32_t *)private_data;
(*countp)++;
if (*countp > 2000000) exit(0);
event_add_timed(ev, ev, tval, timeout_handler, countp);
}
int main(void)
{
struct event_context *ev;
struct timeval tval = { 0, 0 };
uint32_t count = 0;
ev = event_context_init(NULL);
event_add_fd(ev, ev, 0, 0, dummy_fde_handler, NULL);
event_add_timed(ev, ev, tval, timeout_handler, &count);
return event_loop_wait(ev);
}
(This used to be commit 4db64b4ce2320b88d648078cbf86385f6fb44f1f)
2007-05-04 13:22:52 +04:00
struct timeval common_event_loop_timer_delay ( struct event_context * ) ;
2007-01-21 11:23:14 +03:00
struct signal_event * common_event_add_signal ( struct event_context * ev ,
TALLOC_CTX * mem_ctx ,
int signum ,
2007-01-21 13:32:39 +03:00
int sa_flags ,
2007-01-21 11:23:14 +03:00
event_signal_handler_t handler ,
void * private_data ) ;
int common_event_check_signal ( struct event_context * ev ) ;
2008-06-14 19:23:31 +04:00
bool events_standard_init ( void ) ;
bool events_select_init ( void ) ;
# if HAVE_EVENTS_EPOLL
bool events_epoll_init ( void ) ;
# endif
# if HAVE_LINUX_AIO
bool events_aio_init ( void ) ;
# endif