diff --git a/src/backend.cmod b/src/backend.cmod index b798f5e13853c4671535efd3c1a01ae3d18be6b5..af46683a0d9e7de4b54219d017fe63cf7ff384b1 100644 --- a/src/backend.cmod +++ b/src/backend.cmod @@ -11,6 +11,7 @@ #include "global.h" #include "fdlib.h" #include "backend.h" +#include "time_stuff.h" #include <errno.h> #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> @@ -191,6 +192,7 @@ DECLARATIONS struct callback_list do_debug_callbacks; struct timeval current_time; +int current_time_invalid = 1; /* * Stuff to map fds to the proper Backend @@ -725,7 +727,7 @@ PIKECLASS Backend if(num_threads>1) { struct timeval tmp; - GETTIMEOFDAY(&tmp); + ACCURATE_GETTIMEOFDAY(&tmp); my_add_timeval(& new->tv, &tmp); IF_CO (fprintf (stderr, "BACKEND[%d]: Adding call out at %ld.%ld " "(current time is %ld.%ld)\n", me->id, @@ -734,11 +736,13 @@ PIKECLASS Backend }else #endif { - my_add_timeval(& new->tv, ¤t_time); + struct timeval tmp; + INACCURATE_GETTIMEOFDAY(&tmp); + my_add_timeval(& new->tv, &tmp); IF_CO (fprintf (stderr, "BACKEND[%d]: Adding call out at %ld.%ld " "(current_time is %ld.%ld)\n", me->id, new->tv.tv_sec, new->tv.tv_usec, - current_time.tv_sec, current_time.tv_usec)); + tmp.tv_sec, tmp.tv_usec)); } if(Pike_fp && Pike_fp->current_object) @@ -863,15 +867,17 @@ PIKECLASS Backend { int call_count = 0; int args; - struct timeval tmp; + struct timeval tmp, now; backend_verify_call_outs(me); - tmp.tv_sec = current_time.tv_sec; - tmp.tv_usec = current_time.tv_usec; + INACCURATE_GETTIMEOFDAY(&now); + tmp.tv_sec = now.tv_sec; + tmp.tv_usec = now.tv_usec; tmp.tv_sec++; while(me->num_pending_calls && - my_timercmp(&CALL(0)->tv, <= ,¤t_time)) + my_timercmp(&CALL(0)->tv, <= ,&now)) { + struct timeval now; /* unlink call out */ call_out c,*cc; @@ -917,8 +923,8 @@ PIKECLASS Backend } backend_verify_call_outs(me); - GETTIMEOFDAY(¤t_time); - if(my_timercmp(¤t_time, > , &tmp)) break; + ACCURATE_GETTIMEOFDAY(&now); + if(my_timercmp(&now, > , &tmp)) break; } IF_CO ( @@ -928,7 +934,7 @@ PIKECLASS Backend "(current_time %ld.%ld, limit at %ld.%ld)\n", me->id, me->num_pending_calls, CALL(0)->tv.tv_sec, CALL(0)->tv.tv_usec, - current_time.tv_sec, current_time.tv_usec, + now.tv_sec, now.tv_usec, tmp.tv_sec, tmp.tv_usec); else fprintf (stderr, "BACKEND[%d]: backend_do_call_outs: " @@ -1021,7 +1027,7 @@ PIKECLASS Backend */ PIKEFUN int _do_call_outs() { - GETTIMEOFDAY(¤t_time); + INVALIDATE_CURRENT_TIME(); RETURN backend_do_call_outs(THIS); } @@ -1060,7 +1066,9 @@ PIKECLASS Backend SET_SVAL(*Pike_sp, T_INT, NUMBER_UNDEFINED, integer, -1); Pike_sp++; }else{ - push_int(CALL(e)->tv.tv_sec - current_time.tv_sec); + struct timeval now; + INACCURATE_GETTIMEOFDAY(&now); + push_int(CALL(e)->tv.tv_sec - now.tv_sec); } UNPROTECT_CALL_OUTS(); backend_verify_call_outs(me); @@ -1093,12 +1101,14 @@ PIKECLASS Backend backend_verify_call_outs(me); if(e!=-1) { + struct timeval now; + INACCURATE_GETTIMEOFDAY(&now); IF_CO (fprintf (stderr, "BACKEND[%d]: Removing call out at %ld.%ld " "(current_time is %ld.%ld)\n", me->id, CALL(e)->tv.tv_sec, CALL(e)->tv.tv_usec, - current_time.tv_sec, current_time.tv_usec)); + now.tv_sec, now.tv_usec)); pop_n_elems(args); - push_int(CALL(e)->tv.tv_sec - current_time.tv_sec); + push_int(CALL(e)->tv.tv_sec - now.tv_sec); free_array(CALL(e)->args); if(CALL(e)->caller) free_object(CALL(e)->caller); @@ -1127,6 +1137,7 @@ PIKECLASS Backend { int e; struct array *ret; + struct timeval now; ONERROR err; backend_verify_call_outs(me); @@ -1134,11 +1145,12 @@ PIKECLASS Backend ret=allocate_array_no_init(0, me->num_pending_calls); SET_ONERROR(err, do_free_array, ret); ret->type_field = BIT_ARRAY; + if(me->num_pending_calls) INACCURATE_GETTIMEOFDAY(&now); for(e=0;e<me->num_pending_calls;e++) { struct array *v; v=allocate_array_no_init(CALL(e)->args->size+2, 0); - ITEM(v)[0].u.integer=CALL(e)->tv.tv_sec - current_time.tv_sec; + ITEM(v)[0].u.integer=CALL(e)->tv.tv_sec - now.tv_sec; if(CALL(e)->caller) { @@ -1799,7 +1811,7 @@ PIKECLASS Backend #ifdef PIKE_DEBUG struct timeval max_timeout; #endif - struct timeval *next_timeout = &me->next_timeout; + struct timeval *next_timeout = &me->next_timeout, now; alloca(0); /* Do garbage collect */ #ifdef PIKE_DEBUG @@ -1826,12 +1838,14 @@ PIKECLASS Backend me->exec_thread = 1; #endif + #ifndef OWN_GETHRTIME - GETTIMEOFDAY(¤t_time); + ACCURATE_GETTIMEOFDAY(&now); #else /* good place to run the gethrtime-conversion update since we have to run gettimeofday anyway /Mirar */ - own_gethrtime_update(¤t_time); + INACCURATE_GETTIMEOFDAY(&now); + own_gethrtime_update(&now); #endif if (start_time->tv_sec < 0) { next_timeout->tv_sec = -1; @@ -1839,10 +1853,10 @@ PIKECLASS Backend } else { *next_timeout = *start_time; - my_add_timeval(next_timeout, ¤t_time); + my_add_timeval(next_timeout, &now); } - *start_time = current_time; + *start_time = now; /* Call outs */ if(me->num_pending_calls) @@ -1870,9 +1884,9 @@ PIKECLASS Backend next_timeout->tv_sec = 100000000; next_timeout->tv_usec = 0; } - else if(my_timercmp(next_timeout, > , ¤t_time)) + else if(my_timercmp(next_timeout, > , &now)) { - my_subtract_timeval(next_timeout, ¤t_time); + my_subtract_timeval(next_timeout, &now); }else{ next_timeout->tv_usec = 0; next_timeout->tv_sec = 0; @@ -2063,7 +2077,7 @@ PIKECLASS Backend me->backend_callbacks.callbacks=0; me->backend_callbacks.num_calls=0; - GETTIMEOFDAY(¤t_time); /* Why? /mast */ + INVALIDATE_CURRENT_TIME(); /* Why? /mast */ me->num_pending_calls=0; me->call_buffer=0; @@ -3224,7 +3238,7 @@ PIKECLASS PollDeviceBackend THREADS_DISALLOW(); check_threads_etc(); me->may_need_wakeup = 0; - GETTIMEOFDAY(¤t_time); + INVALIDATE_CURRENT_TIME(); } if (TYPEOF(me->after_callback) != T_INT) @@ -3419,7 +3433,7 @@ PIKECLASS PollDeviceBackend CALL_AND_UNSET_ONERROR(free_fd_list); /* Must be up-to-date for backend_do_call_outs. */ - GETTIMEOFDAY(¤t_time); + INVALIDATE_CURRENT_TIME(); }else{ switch(errno) { @@ -3470,8 +3484,10 @@ PIKECLASS PollDeviceBackend if (!done_something) timeout->tv_sec = -1; else { - timeout->tv_sec = current_time.tv_sec; - timeout->tv_usec = current_time.tv_usec; + struct timeval now; + INACCURATE_GETTIMEOFDAY(&now); + timeout->tv_sec = now.tv_sec; + timeout->tv_usec = now.tv_usec; my_subtract_timeval (timeout, &start_time); } @@ -3822,7 +3838,7 @@ PIKECLASS PollBackend THREADS_DISALLOW(); check_threads_etc(); me->may_need_wakeup = 0; - GETTIMEOFDAY(¤t_time); + INVALIDATE_CURRENT_TIME(); } if (TYPEOF(me->after_callback) != T_INT) @@ -3981,7 +3997,7 @@ PIKECLASS PollBackend CALL_AND_UNSET_ONERROR(free_fd_list); /* Must be up-to-date for backend_do_call_outs. */ - GETTIMEOFDAY(¤t_time); + INVALIDATE_CURRENT_TIME(); }else{ switch(errno) { @@ -4032,8 +4048,10 @@ PIKECLASS PollBackend if (!done_something) timeout->tv_sec = -1; else { - timeout->tv_sec = current_time.tv_sec; - timeout->tv_usec = current_time.tv_usec; + struct timeval now; + INACCURATE_GETTIMEOFDAY(&now); + timeout->tv_sec = now.tv_sec; + timeout->tv_usec = now.tv_usec; my_subtract_timeval (timeout, &start_time); } @@ -4377,7 +4395,7 @@ PIKECLASS SelectBackend THREADS_DISALLOW(); check_threads_etc(); me->may_need_wakeup = 0; - GETTIMEOFDAY(¤t_time); + INVALIDATE_CURRENT_TIME(); } if (TYPEOF(me->after_callback) != T_INT) @@ -4462,7 +4480,7 @@ PIKECLASS SelectBackend CALL_AND_UNSET_ONERROR(free_fd_list); /* Must be up-to-date for backend_do_call_outs. */ - GETTIMEOFDAY(¤t_time); + INVALIDATE_CURRENT_TIME(); }else{ switch(errno) { @@ -4586,8 +4604,10 @@ PIKECLASS SelectBackend if (!done_something) timeout->tv_sec = -1; else { - timeout->tv_sec = current_time.tv_sec; - timeout->tv_usec = current_time.tv_usec; + struct timeval now; + INACCURATE_GETTIMEOFDAY(&now); + timeout->tv_sec = now.tv_sec; + timeout->tv_usec = now.tv_usec; my_subtract_timeval (timeout, &start_time); } @@ -4943,7 +4963,7 @@ void wake_up_backend(void) void do_call_outs(void) { if(default_backend) { - GETTIMEOFDAY (¤t_time); + INVALIDATE_CURRENT_TIME(); backend_do_call_outs(default_backend); } } diff --git a/src/backend.h b/src/backend.h index 836db0f8324c42cbf10758649d041d430c91a839..0cfe9de5d2d8aa70df08d564d331624facbfb769 100644 --- a/src/backend.h +++ b/src/backend.h @@ -72,7 +72,6 @@ struct Backend_struct; -PMOD_EXPORT extern struct timeval current_time; PMOD_EXPORT extern struct Backend_struct *default_backend; extern struct callback_list do_debug_callbacks; PMOD_EXPORT extern struct program *Backend_program; diff --git a/src/builtin.cmod b/src/builtin.cmod index c31aefa03018baf56c80c9a3b5a5dff3e94dec88..505680ac53268e69284fae0dca74db5620928011 100644 --- a/src/builtin.cmod +++ b/src/builtin.cmod @@ -3223,22 +3223,26 @@ PIKECLASS Time PIKEFUN int `sec() { - extern struct timeval current_time; + struct timeval now; if( THIS->hard_update ) - GETTIMEOFDAY( ¤t_time ); + ACCURATE_GETTIMEOFDAY( &now ); + else + INACCURATE_GETTIMEOFDAY( &now ); - RETURN current_time.tv_sec; + RETURN now.tv_sec; } PIKEFUN int `usec() { - extern struct timeval current_time; + struct timeval now; if( THIS->hard_update ) - GETTIMEOFDAY( ¤t_time ); + ACCURATE_GETTIMEOFDAY( &now ); + else + INACCURATE_GETTIMEOFDAY( &now ); - RETURN current_time.tv_usec; + RETURN now.tv_usec; } /*! @decl int usec_full @@ -3250,20 +3254,22 @@ PIKECLASS Time PIKEFUN int `usec_full() { - extern struct timeval current_time; + struct timeval now; if( THIS->hard_update ) - GETTIMEOFDAY( ¤t_time ); + ACCURATE_GETTIMEOFDAY( &now ); + else + INACCURATE_GETTIMEOFDAY( &now ); #ifdef AUTO_BIGNUM - push_int( current_time.tv_sec ); + push_int( now.tv_sec ); push_int( 1000000 ); f_multiply( 2 ); - push_int( current_time.tv_usec ); + push_int( now.tv_usec ); f_add( 2 ); return; #else - RETURN (current_time.tv_sec * 1000000 + current_time.tv_usec); + RETURN (now.tv_sec * 1000000 + now.tv_usec); #endif } @@ -3297,12 +3303,14 @@ PIKECLASS Timer */ PIKEFUN float peek( ) { - extern struct timeval current_time; + struct timeval now; FLOAT_TYPE res; if( THIS->hard_update ) - GETTIMEOFDAY( ¤t_time ); - res = current_time.tv_sec-THIS->last_time.tv_sec + - (current_time.tv_usec-THIS->last_time.tv_usec)/(FLOAT_TYPE) 1000000.0; + ACCURATE_GETTIMEOFDAY( &now ); + else + INACCURATE_GETTIMEOFDAY( &now ); + res = now.tv_sec-THIS->last_time.tv_sec + + (now.tv_usec-THIS->last_time.tv_usec)/(FLOAT_TYPE) 1000000.0; RETURN res; } @@ -3313,9 +3321,8 @@ PIKECLASS Timer */ PIKEFUN float get( ) { - extern struct timeval current_time; f_Timer_peek( 0 ); - THIS->last_time = current_time; + INACCURATE_GETTIMEOFDAY(&THIS->last_time); return; } @@ -3332,11 +3339,11 @@ PIKECLASS Timer PIKEFUN void create( int|zero|void fast ) flags ID_PROTECTED; { - extern struct timeval current_time; THIS->hard_update = !fast; if( THIS->hard_update ) - GETTIMEOFDAY( ¤t_time ); - THIS->last_time = current_time; + ACCURATE_GETTIMEOFDAY( &THIS->last_time ); + else + INACCURATE_GETTIMEOFDAY( &THIS->last_time ); } } diff --git a/src/builtin_functions.c b/src/builtin_functions.c index b21748c1eda1f74ef57cf9d6ba4ca4362ea45dc9..0f71e6c1074a1dbf7c685ce836f6ebaac23736e3 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -2930,25 +2930,31 @@ void f__exit(INT32 args) */ PMOD_EXPORT void f_time(INT32 args) { + struct timeval ret; if(!args || (TYPEOF(Pike_sp[-args]) == T_INT && Pike_sp[-args].u.integer == 0)) { - GETTIMEOFDAY(¤t_time); + ACCURATE_GETTIMEOFDAY(&ret); + pop_n_elems(args); + push_int(ret.tv_sec); + + return; }else{ if(TYPEOF(Pike_sp[-args]) == T_INT && Pike_sp[-args].u.integer > 1) { struct timeval tmp; - GETTIMEOFDAY(¤t_time); + ACCURATE_GETTIMEOFDAY(&ret); tmp.tv_sec=Pike_sp[-args].u.integer; tmp.tv_usec=0; - my_subtract_timeval(&tmp,¤t_time); + my_subtract_timeval(&tmp,&ret); pop_n_elems(args); push_float( - (FLOAT_TYPE)tmp.tv_sec-((FLOAT_TYPE)tmp.tv_usec)/1000000 ); return; } } pop_n_elems(args); - push_int(current_time.tv_sec); + INACCURATE_GETTIMEOFDAY(&ret); + push_int(ret.tv_sec); } /*! @decl string crypt(string password) @@ -4662,13 +4668,13 @@ static void delaysleep(double delay, unsigned do_abort_on_signal, if (t0 == -1) { /* Paranoia in case get_real_time fails. */ /* fprintf (stderr, "get_real_time failed in sleep()\n"); */ - GETTIMEOFDAY (>od_t0); + ACCURATE_GETTIMEOFDAY (>od_t0); gtod_tv = gtod_t0; } #define FIX_LEFT() \ if (t0 == -1) { \ - GETTIMEOFDAY (>od_tv); \ + ACCURATE_GETTIMEOFDAY (>od_tv); \ left = delay - ((gtod_tv.tv_sec-gtod_t0.tv_sec) + \ (gtod_tv.tv_usec-gtod_t0.tv_usec)*1e-6); \ } \ @@ -4690,7 +4696,7 @@ static void delaysleep(double delay, unsigned do_abort_on_signal, sysleep(left); THREADS_DISALLOW(); if(do_abort_on_signal) { - GETTIMEOFDAY (¤t_time); + INVALIDATE_CURRENT_TIME(); return; } FIX_LEFT(); @@ -4698,14 +4704,14 @@ static void delaysleep(double delay, unsigned do_abort_on_signal, break; check_threads_etc(); } - GETTIMEOFDAY (¤t_time); + INVALIDATE_CURRENT_TIME(); } if (do_microsleep) { if (t0 == -1) { while (delay> ((gtod_tv.tv_sec-gtod_t0.tv_sec) + (gtod_tv.tv_usec-gtod_t0.tv_usec)*1e-6)) - GETTIMEOFDAY (>od_tv); + ACCURATE_GETTIMEOFDAY (>od_tv); } else { while (delay> (tv - t0) * (1.0 / CPU_TIME_TICKS)) diff --git a/src/modules/files/file.c b/src/modules/files/file.c index 4045e88ee25376e2a2652a412442a00a60d18356..c369bfdd43309193204dd0eeab2d6f540600858b 100644 --- a/src/modules/files/file.c +++ b/src/modules/files/file.c @@ -23,6 +23,7 @@ #include "bignum.h" #include "builtin_functions.h" #include "gc.h" +#include "time_stuff.h" #include "file_machine.h" #include "file.h" @@ -1343,6 +1344,9 @@ static void file_read(INT32 args) push_int(0); } + if (!(THIS->open_mode & FILE_NONBLOCKING)) + INVALIDATE_CURRENT_TIME(); + /* Race: A backend in another thread might have managed to set these * again for something that arrived after the read above. Not that * bad - it will get through in a later backend round. */ @@ -1604,6 +1608,9 @@ static void file_read_oob(INT32 args) push_int(0); } + if (!(THIS->open_mode & FILE_NONBLOCKING)) + INVALIDATE_CURRENT_TIME(); + /* Race: A backend in another thread might have managed to set these * again for something that arrived after the read above. Not that * bad - it will get through in a later backend round. */ @@ -1791,6 +1798,9 @@ static void file_write(INT32 args) struct iovec *iov = iovbase; int iovcnt = a->size; + if (!(THIS->open_mode & FILE_NONBLOCKING)) + INVALIDATE_CURRENT_TIME(); + i = a->size; while(i--) { if (a->item[i].u.string->len) { @@ -1953,6 +1963,9 @@ static void file_write(INT32 args) check_threads_etc(); + if (!(THIS->open_mode & FILE_NONBLOCKING)) + INVALIDATE_CURRENT_TIME(); + if(i<0) { #ifdef HAVE_PIKE_SEND_FD @@ -2123,6 +2136,9 @@ static void file_write_oob(INT32 args) ADD_FD_EVENTS (THIS, PIKE_BIT_FD_WRITE_OOB); ERRNO=0; + if (!(THIS->open_mode & FILE_NONBLOCKING)) + INVALIDATE_CURRENT_TIME(); + pop_n_elems(args); push_int64(written); } @@ -4376,6 +4392,7 @@ static void file_open_socket(INT32 args) addr_len = get_inet_addr(&addr, (char *) STR0(Pike_sp[2-args].u.string), NULL, -1, 0); family = SOCKADDR_FAMILY(addr); + INVALIDATE_CURRENT_TIME(); } if (args && TYPEOF(Pike_sp[-args]) == PIKE_T_INT && @@ -4411,6 +4428,7 @@ static void file_open_socket(INT32 args) Pike_sp[-args].u.string->str : NULL), (TYPEOF(Pike_sp[-args]) == PIKE_T_INT? Pike_sp[-args].u.integer : -1), 0); + INVALIDATE_CURRENT_TIME(); fd=fd_socket((family<0? SOCKADDR_FAMILY(addr):family), SOCK_STREAM, 0); if(fd < 0) @@ -4687,6 +4705,7 @@ static void file_connect(INT32 args) dest_port->u.string->str : NULL), (TYPEOF(*dest_port) == PIKE_T_INT? dest_port->u.integer : -1), 0); + INVALIDATE_CURRENT_TIME(); if(was_closed) { diff --git a/src/modules/files/socket.c b/src/modules/files/socket.c index 16f45f142339321c2a20f91094108d067798f01e..58fc0dc09f4ff4153fe651df047667879afa6984 100644 --- a/src/modules/files/socket.c +++ b/src/modules/files/socket.c @@ -20,6 +20,7 @@ #include "threads.h" #include "program_id.h" #include "module_support.h" +#include "time_stuff.h" #include "file_machine.h" #include "file.h" @@ -75,6 +76,7 @@ struct port { struct fd_callback_box box; /* Must be first. */ int my_errno; + unsigned int immediate_cnt; struct svalue accept_callback; /* Mapped. */ struct svalue id; /* Mapped. */ }; @@ -95,6 +97,7 @@ static int got_port_event (struct fd_callback_box *box, int event) #endif p->my_errno = errno; /* Propagate backend setting. */ + p->immediate_cnt++; push_svalue (&p->id); apply_svalue(& p->accept_callback, 1); pop_stack(); @@ -261,6 +264,7 @@ static void port_bind(INT32 args) Pike_sp[-args].u.string->str : NULL), (TYPEOF(Pike_sp[-args]) == PIKE_T_INT? Pike_sp[-args].u.integer : -1), 0); + INVALIDATE_CURRENT_TIME(); fd=fd_socket(SOCKADDR_FAMILY(addr), SOCK_STREAM, 0); @@ -536,6 +540,7 @@ static void port_accept(INT32 args) err = errno; } while (fd < 0 && err == EINTR); THREADS_DISALLOW(); + INVALIDATE_CURRENT_TIME(); if(fd < 0) { diff --git a/src/modules/files/udp.c b/src/modules/files/udp.c index 51147eff877d6b693c961630095e7e174e07ecab..a43b902f2298e9aeefca79c5ed425215305f892f 100644 --- a/src/modules/files/udp.c +++ b/src/modules/files/udp.c @@ -18,6 +18,7 @@ #include "mapping.h" #include "object.h" #include "backend.h" +#include "time_stuff.h" #include "fd_control.h" #include "pike_error.h" @@ -133,6 +134,8 @@ struct udp_storage { struct fd_callback_box box; /* Must be first. */ int my_errno; + int nonblocking; + int type; int protocol; @@ -215,6 +218,7 @@ static void udp_bind(INT32 args) Pike_sp[-args].u.string->str : NULL), (TYPEOF(Pike_sp[-args]) == PIKE_T_INT? Pike_sp[-args].u.integer : -1), 1); + INVALIDATE_CURRENT_TIME(); fd = fd_socket(SOCKADDR_FAMILY(addr), THIS->type, THIS->protocol); if(fd < 0) @@ -328,6 +332,7 @@ void udp_enable_multicast(INT32 args) get_all_args("enable_multicast", args, "%s", &ip); get_inet_addr(&reply, ip, NULL, -1, 1); + INVALIDATE_CURRENT_TIME(); if(SOCKADDR_FAMILY(reply) != AF_INET) Pike_error("Multicast only supported for IPv4.\n"); @@ -378,6 +383,7 @@ void udp_add_membership(INT32 args) get_all_args("add_membership", args, "%s.%s%d", &group, &address, &face); get_inet_addr(&addr, group, NULL, -1, 1); + INVALIDATE_CURRENT_TIME(); if(SOCKADDR_FAMILY(addr) != AF_INET) Pike_error("Multicast only supported for IPv4.\n"); @@ -388,6 +394,7 @@ void udp_add_membership(INT32 args) sock.imr_interface.s_addr = htonl( INADDR_ANY ); else { get_inet_addr(&addr, address, NULL, -1, 1); + INVALIDATE_CURRENT_TIME(); if(SOCKADDR_FAMILY(addr) != AF_INET) Pike_error("Multicast only supported for IPv4.\n"); @@ -419,6 +426,7 @@ void udp_drop_membership(INT32 args) get_all_args("drop_membership", args, "%s.%s%d", &group, &address, &face); get_inet_addr(&addr, group, NULL, -1, 1); + INVALIDATE_CURRENT_TIME(); if(SOCKADDR_FAMILY(addr) != AF_INET) Pike_error("Multicast only supported for IPv4.\n"); @@ -429,6 +437,7 @@ void udp_drop_membership(INT32 args) sock.imr_interface.s_addr = htonl( INADDR_ANY ); else { get_inet_addr(&addr, address, NULL, -1, 1); + INVALIDATE_CURRENT_TIME(); if(SOCKADDR_FAMILY(addr) != AF_INET) Pike_error("Multicast only supported for IPv4.\n"); @@ -656,6 +665,9 @@ void udp_read(INT32 args) push_constant_text("port"); push_int(ntohs(from.ipv4.sin_port)); f_aggregate_mapping( 6 ); + + if (!THIS->nonblocking) + INVALIDATE_CURRENT_TIME(); } /*! @decl int send(string to, int|string port, string message) @@ -708,6 +720,7 @@ void udp_sendto(INT32 args) Pike_sp[1-args].u.string->str : NULL), (TYPEOF(Pike_sp[1-args]) == PIKE_T_INT? Pike_sp[1-args].u.integer : -1), 1); + INVALIDATE_CURRENT_TIME(); fd = FD; str = Pike_sp[2-args].u.string->str; @@ -752,6 +765,8 @@ void udp_sendto(INT32 args) } pop_n_elems(args); push_int64(res); + if (!THIS->nonblocking) + INVALIDATE_CURRENT_TIME(); } @@ -843,6 +858,7 @@ static void udp_set_nonblocking(INT32 args) pop_stack(); } set_nonblocking(FD,1); + THIS->nonblocking = 1; ref_push_object(THISOBJ); } @@ -854,6 +870,7 @@ static void udp_set_blocking(INT32 args) { if (FD < 0) Pike_error("File not open.\n"); set_nonblocking(FD,0); + THIS->nonblocking = 0; pop_n_elems(args); ref_push_object(THISOBJ); } @@ -897,6 +914,7 @@ static void udp_connect(INT32 args) dest_port->u.string->str : NULL), (TYPEOF(*dest_port) == PIKE_T_INT? dest_port->u.integer : -1), 0); + INVALIDATE_CURRENT_TIME(); if(FD < 0) { @@ -914,6 +932,9 @@ static void udp_connect(INT32 args) tmp=fd_connect(tmp, (struct sockaddr *)&addr, addr_len); THREADS_DISALLOW(); + if (!THIS->nonblocking) + INVALIDATE_CURRENT_TIME(); + if(tmp < 0) { THIS->my_errno=errno; diff --git a/src/modules/system/system.c b/src/modules/system/system.c index a972d438eda6d51923c6fd16f8b444d6fa2ddc1d..b529dbff17e709ff142bf0498fc63c23e836bdc9 100644 --- a/src/modules/system/system.c +++ b/src/modules/system/system.c @@ -36,6 +36,7 @@ #include "mapping.h" #include "builtin_functions.h" #include "constants.h" +#include "time_stuff.h" #include "pike_memory.h" #include "pike_security.h" #include "bignum.h" @@ -2069,6 +2070,7 @@ void f_gethostbyaddr(INT32 args) pop_n_elems(args); CALL_GETHOSTBYADDR((char *)&addr, sizeof (addr), AF_INET); + INVALIDATE_CURRENT_TIME(); if(!ret) { push_int(0); @@ -2108,6 +2110,7 @@ void f_gethostbyname(INT32 args) get_all_args("gethostbyname", args, "%s", &name); CALL_GETHOSTBYNAME(name); + INVALIDATE_CURRENT_TIME(); pop_n_elems(args); diff --git a/src/pike_embed.c b/src/pike_embed.c index 14f9ede693834aefd1776f5b5f48aa7adb43c53d..e0224ab8ed5a1faa28ba097bcc45295cbb2ec7fe 100644 --- a/src/pike_embed.c +++ b/src/pike_embed.c @@ -362,7 +362,7 @@ void init_pike_runtime(void (*exit_cb)(int)) TRACE((stderr, "Init time...\n")); - GETTIMEOFDAY(¤t_time); + UPDATE_CURRENT_TIME(); TRACE((stderr, "Init threads...\n")); diff --git a/src/port.c b/src/port.c index 5ff43f84e95adf4372e63c8b7aec987efc04fa6c..3f55b08e806181028936788c06e057e3b3111f46 100644 --- a/src/port.c +++ b/src/port.c @@ -99,7 +99,7 @@ void GETTIMEOFDAY(struct timeval *t) time_t TIME(time_t *t) { struct timeval tv; - GETTIMEOFDAY(&tv); + ACCURATE_GETTIMEOFDAY(&tv); if(t) *t=tv.tv_sec; return tv.tv_sec; } @@ -824,7 +824,7 @@ void own_gethrtime_init() { int fd; - GETTIMEOFDAY(&hrtime_timeval_zero); + ACCURATE_GETTIMEOFDAY(&hrtime_timeval_zero); hrtime_rtsc_zero=rtsc(); hrtime_rtsc_last = hrtime_rtsc_base = hrtime_rtsc_zero; #ifdef RTSC_DEBUG @@ -893,7 +893,7 @@ void own_gethrtime_update(struct timeval *ptr) static double w_c_c_sum = 0.0; static int count = -COUNT_THRESHOLD; - GETTIMEOFDAY(ptr); + ACCURATE_GETTIMEOFDAY(ptr); now=rtsc(); #ifdef RTSC_DEBUG diff --git a/src/post_modules/GTK1/source/global.pre b/src/post_modules/GTK1/source/global.pre index 35564893290adf0de84f0afba532b180b889698b..72080eb923e7dbe24dcd8a1b42849d05ae95b926 100644 --- a/src/post_modules/GTK1/source/global.pre +++ b/src/post_modules/GTK1/source/global.pre @@ -28,7 +28,8 @@ static void backend_callback(struct callback *_cb, { if(backend) { - struct timeval timeout = current_time; + struct timeval timeout; + INACCURATE_GETTIMEOFDAY(&timeout); timeout.tv_usec += 20000; if(timeout.tv_usec > 1000000) { diff --git a/src/post_modules/GTK2/source/global.pre b/src/post_modules/GTK2/source/global.pre index 4f0fed1cc94e4aa1e78305b101791b1c1be143c4..a290cec814e03773cb23c66918b1566fe642eccc 100644 --- a/src/post_modules/GTK2/source/global.pre +++ b/src/post_modules/GTK2/source/global.pre @@ -58,7 +58,8 @@ static void backend_callback(struct callback *_cb, { if(backend) { - struct timeval timeout = current_time; + struct timeval timeout; + INACCURATE_GETTIMEOFDAY(&timeout); timeout.tv_usec += 20000; if(timeout.tv_usec > 1000000) { diff --git a/src/program.c b/src/program.c index c5b8f318a293d53e3a507abb01ad5885ec5c8abf..5b5ae40c0979be050a2a9f1674aead43b8d308e0 100644 --- a/src/program.c +++ b/src/program.c @@ -2574,7 +2574,7 @@ struct program *low_allocate_program(void) INIT_PIKE_MEMOBJ(p, T_PROGRAM); DOUBLELINK(first_program, p); - GETTIMEOFDAY(& p->timestamp); + ACCURATE_GETTIMEOFDAY(& p->timestamp); return p; } diff --git a/src/rusage.c b/src/rusage.c index ee684f2a2a3adf9285251879f2233cc0e56d2597..064b3dc661a7e16963bf77a99ab0473ffb84f7f1 100644 --- a/src/rusage.c +++ b/src/rusage.c @@ -325,7 +325,11 @@ PMOD_EXPORT int pike_get_rusage(pike_rusage_t rusage_values) /* This is totally wrong, but hey, if you can't do it _right_... */ struct timeval tm; MEMSET(rusage_values, 0, sizeof(pike_rusage_t)); +#ifndef CONFIGURE_TEST + ACCURATE_GETTIMEOFDAY(&tm); +#else GETTIMEOFDAY(&tm); +#endif rusage_values[0]=tm.tv_sec*1000L + tm.tv_usec/1000; return 1; } @@ -814,7 +818,13 @@ PMOD_EXPORT int fallback_grt_is_monotonic = 0; PMOD_EXPORT cpu_time_t fallback_grt(void) { struct timeval tv; + int gtod_rval; +#ifndef CONFIGURE_TEST + ACCURATE_GETTIMEOFDAY_RVAL(&tv, gtod_rval); + if (gtod_rval < 0) return -1; +#else if (GETTIMEOFDAY(&tv) < 0) return -1; +#endif return tv.tv_sec * CPU_TIME_TICKS + USEC_TO_CPU_TIME_T (tv.tv_usec); } diff --git a/src/signal_handler.c b/src/signal_handler.c index 20fbece1f13ebfa937fdb35219ffc7b4383aa146..85242353e6b067783531a17eae19adbaabd1baca 100644 --- a/src/signal_handler.c +++ b/src/signal_handler.c @@ -23,6 +23,7 @@ #include "builtin_functions.h" #include "pike_security.h" #include "main.h" +#include "time_stuff.h" #include <signal.h> #ifdef HAVE_PASSWD_H @@ -1716,6 +1717,8 @@ static void f_pid_status_wait(INT32 args) } } #endif /* __NT__ */ + + INVALIDATE_CURRENT_TIME(); } /*! @decl int(-1..2) status() diff --git a/src/threads.c b/src/threads.c index 4e191b3384d2566d367399fda63a9f7076d54b2e..a0c0be138141eb79142536fb2700e3bb9e6d8cae 100644 --- a/src/threads.c +++ b/src/threads.c @@ -283,6 +283,7 @@ PMOD_EXPORT int co_destroy(COND_T *c) #ifndef CONFIGURE_TEST PMOD_EXPORT int co_wait_timeout(COND_T *c, PIKE_MUTEX_T *m, long s, long nanos) { + struct timeval ct; #ifdef POSIX_THREADS struct timespec timeout; #ifdef HAVE_PTHREAD_COND_RELTIMEDWAIT_NP @@ -292,9 +293,9 @@ PMOD_EXPORT int co_wait_timeout(COND_T *c, PIKE_MUTEX_T *m, long s, long nanos) return pthread_cond_reltimedwait_np(c, m, &timeout); #else /* !HAVE_PTHREAD_COND_RELTIMEDWAIT_NP */ /* Absolute timeout. */ - GETTIMEOFDAY(¤t_time); - timeout.tv_sec = current_time.tv_sec + s; - timeout.tv_nsec = current_time.tv_usec * 1000 + nanos; + ACCURATE_GETTIMEOFDAY(&ct); + timeout.tv_sec = ct.tv_sec + s; + timeout.tv_nsec = ct.tv_usec * 1000 + nanos; return pthread_cond_timedwait(c, m, &timeout); #endif /* HAVE_PTHREAD_COND_RELTIMEDWAIT_NP */ #else /* !POSIX_THREADS */ @@ -1500,7 +1501,7 @@ static void check_threads(struct callback *cb, void *arg, void * arg2) preliminary check that at least 35 ms real time has passed. If not yet true we'll postpone the next check a full interval. */ struct timeval tv; - if (GETTIMEOFDAY(&tv) == 0) { + if (ACCURATE_GETTIMEOFDAY(&tv) == 0) { #ifdef INT64 static INT64 real_time_last_check = 0; INT64 real_time_now = tv.tv_sec * 1000000 + tv.tv_usec; @@ -1588,7 +1589,7 @@ static void check_threads(struct callback *cb, void *arg, void * arg2) #endif #endif - GETTIMEOFDAY (&now); + ACCURATE_GETTIMEOFDAY (&now); if (now.tv_sec > last_time) { fprintf (stderr, "[%d:%f] check_threads: %lu calls, " "%lu clocks, %lu no advs, %lu yields" diff --git a/src/time_stuff.h b/src/time_stuff.h index 23c47292e1f86ce3767d85e1e7db6f3f48f59b4f..5d3e4c3d986e69e251a1619906324e1a73153d89 100644 --- a/src/time_stuff.h +++ b/src/time_stuff.h @@ -77,4 +77,28 @@ struct timeval }; #endif +PMOD_EXPORT extern struct timeval current_time; +PMOD_EXPORT extern int current_time_invalid; + +#define INVALIDATE_CURRENT_TIME() do { current_time_invalid = 1; } while (0) +#define UPDATE_CURRENT_TIME() do { \ + GETTIMEOFDAY(¤t_time); \ + current_time_invalid = 0; \ + } while (0) +#define ACCURATE_GETTIMEOFDAY(X) do { \ + UPDATE_CURRENT_TIME(); \ + *(X) = current_time; \ + } while (0) +#define ACCURATE_GETTIMEOFDAY_RVAL(X, ___rval) do { \ + (___rval) = GETTIMEOFDAY(¤t_time); \ + current_time_invalid = 0; \ + *(X) = current_time; \ + } while (0) +#define INACCURATE_GETTIMEOFDAY(X) do { \ + /* unlikely() not available */ \ + if (!(current_time_invalid)) { } \ + else UPDATE_CURRENT_TIME(); \ + *(X) = current_time; \ + } while (0) + #endif