mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Move alerts onto events rather than checking every loop.
This commit is contained in:
		
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,7 +1,8 @@
 | 
			
		||||
# $OpenBSD$
 | 
			
		||||
 | 
			
		||||
PROG=	tmux
 | 
			
		||||
SRCS=	arguments.c \
 | 
			
		||||
SRCS=	alerts.c \
 | 
			
		||||
	arguments.c \
 | 
			
		||||
	attributes.c \
 | 
			
		||||
	cfg.c \
 | 
			
		||||
	client.c \
 | 
			
		||||
@@ -101,7 +102,6 @@ SRCS=	arguments.c \
 | 
			
		||||
	screen.c \
 | 
			
		||||
	server-client.c \
 | 
			
		||||
	server-fn.c \
 | 
			
		||||
	server-window.c \
 | 
			
		||||
	server.c \
 | 
			
		||||
	session.c \
 | 
			
		||||
	signal.c \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/* $OpenBSD$ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
 * Copyright (c) 2015 Nicholas Marriott <nicm@users.sourceforge.net>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
@@ -19,43 +19,133 @@
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <event.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
int	server_window_check_bell(struct session *, struct winlink *);
 | 
			
		||||
int	server_window_check_activity(struct session *, struct winlink *);
 | 
			
		||||
int	server_window_check_silence(struct session *, struct winlink *);
 | 
			
		||||
void	ring_bell(struct session *);
 | 
			
		||||
int	alerts_fired;
 | 
			
		||||
 | 
			
		||||
void	alerts_timer(int, short, void *);
 | 
			
		||||
int	alerts_enabled(struct window *, int);
 | 
			
		||||
void	alerts_callback(int, short, void *);
 | 
			
		||||
void	alerts_reset(struct window *);
 | 
			
		||||
 | 
			
		||||
int	alerts_check_bell(struct session *, struct winlink *);
 | 
			
		||||
int	alerts_check_activity(struct session *, struct winlink *);
 | 
			
		||||
int	alerts_check_silence(struct session *, struct winlink *);
 | 
			
		||||
void	alerts_ring_bell(struct session *);
 | 
			
		||||
 | 
			
		||||
/* Window functions that need to happen every loop. */
 | 
			
		||||
void
 | 
			
		||||
server_window_loop(void)
 | 
			
		||||
alerts_timer(unused int fd, unused short events, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w = arg;
 | 
			
		||||
 | 
			
		||||
	log_debug("@%u alerts timer expired", w->id);
 | 
			
		||||
	alerts_reset(w);
 | 
			
		||||
	alerts_queue(w, WINDOW_SILENCE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
alerts_callback(unused int fd, unused short events, unused void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
	struct winlink	*wl;
 | 
			
		||||
	int		 flags, alerts;
 | 
			
		||||
 | 
			
		||||
	RB_FOREACH(w, windows, &windows) {
 | 
			
		||||
		RB_FOREACH(s, sessions, &sessions) {
 | 
			
		||||
			RB_FOREACH(wl, winlinks, &s->windows) {
 | 
			
		||||
				if (wl->window != w)
 | 
			
		||||
					continue;
 | 
			
		||||
				flags = w->flags;
 | 
			
		||||
 | 
			
		||||
				if (server_window_check_bell(s, wl) ||
 | 
			
		||||
				    server_window_check_activity(s, wl) ||
 | 
			
		||||
				    server_window_check_silence(s, wl))
 | 
			
		||||
				alerts  = alerts_check_bell(s, wl);
 | 
			
		||||
				alerts |= alerts_check_activity(s, wl);
 | 
			
		||||
				alerts |= alerts_check_silence(s, wl);
 | 
			
		||||
				if (alerts != 0)
 | 
			
		||||
					server_status_session(s);
 | 
			
		||||
 | 
			
		||||
				log_debug("%s:%d @%u alerts check, alerts %#x, "
 | 
			
		||||
				    "flags %#x", s->name, wl->idx, w->id,
 | 
			
		||||
				    alerts, flags);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		check_window_name(w);
 | 
			
		||||
	}
 | 
			
		||||
	alerts_fired = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check for bell in window. */
 | 
			
		||||
int
 | 
			
		||||
server_window_check_bell(struct session *s, struct winlink *wl)
 | 
			
		||||
alerts_enabled(struct window *w, int flags)
 | 
			
		||||
{
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
 | 
			
		||||
	if (flags & WINDOW_ACTIVITY) {
 | 
			
		||||
		if (options_get_number(&w->options, "monitor-activity"))
 | 
			
		||||
			return (1);
 | 
			
		||||
	}
 | 
			
		||||
	if (flags & WINDOW_SILENCE) {
 | 
			
		||||
		if (options_get_number(&w->options, "monitor-silence") != 0)
 | 
			
		||||
			return (1);
 | 
			
		||||
	}
 | 
			
		||||
	if (~flags & WINDOW_BELL)
 | 
			
		||||
		return (0);
 | 
			
		||||
	RB_FOREACH(s, sessions, &sessions) {
 | 
			
		||||
		if (!session_has(s, w))
 | 
			
		||||
			continue;
 | 
			
		||||
		if (options_get_number(&s->options, "bell-action") != BELL_NONE)
 | 
			
		||||
			return (1);
 | 
			
		||||
	}
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
alerts_reset_all(void)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
 | 
			
		||||
	RB_FOREACH(w, windows, &windows)
 | 
			
		||||
		alerts_reset(w);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
alerts_reset(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct timeval	tv;
 | 
			
		||||
 | 
			
		||||
	w->flags &= ~WINDOW_SILENCE;
 | 
			
		||||
	event_del(&w->alerts_timer);
 | 
			
		||||
 | 
			
		||||
	timerclear(&tv);
 | 
			
		||||
	tv.tv_sec = options_get_number(&w->options, "monitor-silence");
 | 
			
		||||
 | 
			
		||||
	log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec);
 | 
			
		||||
	if (tv.tv_sec != 0)
 | 
			
		||||
		event_add(&w->alerts_timer, &tv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
alerts_queue(struct window *w, int flags)
 | 
			
		||||
{
 | 
			
		||||
	if (!event_initialized(&w->alerts_timer))
 | 
			
		||||
		evtimer_set(&w->alerts_timer, alerts_timer, w);
 | 
			
		||||
 | 
			
		||||
	if (w->flags & flags)
 | 
			
		||||
		return;
 | 
			
		||||
	w->flags |= flags;
 | 
			
		||||
	log_debug("@%u alerts flags added %#x", w->id, flags);
 | 
			
		||||
 | 
			
		||||
	if (!alerts_fired && alerts_enabled(w, flags)) {
 | 
			
		||||
		log_debug("alerts check queued (by @%u)", w->id);
 | 
			
		||||
		event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
 | 
			
		||||
		alerts_fired = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags & WINDOW_ACTIVITY)
 | 
			
		||||
		alerts_reset(w);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
alerts_check_bell(struct session *s, struct winlink *wl)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	struct window	*w = wl->window;
 | 
			
		||||
@@ -70,10 +160,11 @@ server_window_check_bell(struct session *s, struct winlink *wl)
 | 
			
		||||
	if (s->curw->window == w)
 | 
			
		||||
		w->flags &= ~WINDOW_BELL;
 | 
			
		||||
 | 
			
		||||
	visual = options_get_number(&s->options, "visual-bell");
 | 
			
		||||
	action = options_get_number(&s->options, "bell-action");
 | 
			
		||||
	if (action == BELL_NONE)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	visual = options_get_number(&s->options, "visual-bell");
 | 
			
		||||
	TAILQ_FOREACH(c, &clients, entry) {
 | 
			
		||||
		if (c->session != s || c->flags & CLIENT_CONTROL)
 | 
			
		||||
			continue;
 | 
			
		||||
@@ -93,12 +184,11 @@ server_window_check_bell(struct session *s, struct winlink *wl)
 | 
			
		||||
			status_message_set(c, "Bell in window %d", wl->idx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (1);
 | 
			
		||||
	return (WINDOW_BELL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check for activity in window. */
 | 
			
		||||
int
 | 
			
		||||
server_window_check_activity(struct session *s, struct winlink *wl)
 | 
			
		||||
alerts_check_activity(struct session *s, struct winlink *wl)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	struct window	*w = wl->window;
 | 
			
		||||
@@ -115,7 +205,7 @@ server_window_check_activity(struct session *s, struct winlink *wl)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	if (options_get_number(&s->options, "bell-on-alert"))
 | 
			
		||||
		ring_bell(s);
 | 
			
		||||
		alerts_ring_bell(s);
 | 
			
		||||
	wl->flags |= WINLINK_ACTIVITY;
 | 
			
		||||
 | 
			
		||||
	if (options_get_number(&s->options, "visual-activity")) {
 | 
			
		||||
@@ -126,45 +216,28 @@ server_window_check_activity(struct session *s, struct winlink *wl)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (1);
 | 
			
		||||
	return (WINDOW_ACTIVITY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check for silence in window. */
 | 
			
		||||
int
 | 
			
		||||
server_window_check_silence(struct session *s, struct winlink *wl)
 | 
			
		||||
alerts_check_silence(struct session *s, struct winlink *wl)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	struct window	*w = wl->window;
 | 
			
		||||
	struct timeval	 timer;
 | 
			
		||||
	int		 silence_interval, timer_difference;
 | 
			
		||||
 | 
			
		||||
	if (s->curw->window == w)
 | 
			
		||||
		w->flags &= ~WINDOW_SILENCE;
 | 
			
		||||
 | 
			
		||||
	if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	if (s->curw == wl && !(s->flags & SESSION_UNATTACHED)) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Reset the timer for this window if we've focused it.  We
 | 
			
		||||
		 * don't want the timer tripping as soon as we've switched away
 | 
			
		||||
		 * from this window.
 | 
			
		||||
		 */
 | 
			
		||||
		if (gettimeofday(&w->silence_timer, NULL) != 0)
 | 
			
		||||
			fatal("gettimeofday failed");
 | 
			
		||||
 | 
			
		||||
		return (0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	silence_interval = options_get_number(&w->options, "monitor-silence");
 | 
			
		||||
	if (silence_interval == 0)
 | 
			
		||||
	if (s->curw == wl && !(s->flags & SESSION_UNATTACHED))
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	if (gettimeofday(&timer, NULL) != 0)
 | 
			
		||||
		fatal("gettimeofday");
 | 
			
		||||
	timer_difference = timer.tv_sec - w->silence_timer.tv_sec;
 | 
			
		||||
	if (timer_difference <= silence_interval)
 | 
			
		||||
	if (options_get_number(&w->options, "monitor-silence") == 0)
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	if (options_get_number(&s->options, "bell-on-alert"))
 | 
			
		||||
		ring_bell(s);
 | 
			
		||||
		alerts_ring_bell(s);
 | 
			
		||||
	wl->flags |= WINLINK_SILENCE;
 | 
			
		||||
 | 
			
		||||
	if (options_get_number(&s->options, "visual-silence")) {
 | 
			
		||||
@@ -175,12 +248,11 @@ server_window_check_silence(struct session *s, struct winlink *wl)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (1);
 | 
			
		||||
	return (WINDOW_SILENCE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Ring terminal bell. */
 | 
			
		||||
void
 | 
			
		||||
ring_bell(struct session *s)
 | 
			
		||||
alerts_ring_bell(struct session *s)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
 | 
			
		||||
@@ -186,6 +186,8 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
 | 
			
		||||
	if (strcmp(oe->name, "status") == 0 ||
 | 
			
		||||
	    strcmp(oe->name, "status-interval") == 0)
 | 
			
		||||
		status_timer_start_all();
 | 
			
		||||
	if (strcmp(oe->name, "monitor-silence") == 0)
 | 
			
		||||
		alerts_reset_all();
 | 
			
		||||
 | 
			
		||||
	/* Update sizes and redraw. May not need it but meh. */
 | 
			
		||||
	recalculate_sizes();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								input.c
									
									
									
									
									
								
							@@ -844,14 +844,9 @@ input_parse(struct window_pane *wp)
 | 
			
		||||
	if (EVBUFFER_LENGTH(evb) == 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	window_update_activity(wp->window);
 | 
			
		||||
	wp->flags |= PANE_CHANGED;
 | 
			
		||||
 | 
			
		||||
	wp->window->flags |= WINDOW_ACTIVITY;
 | 
			
		||||
	wp->window->flags &= ~WINDOW_SILENCE;
 | 
			
		||||
 | 
			
		||||
	if (gettimeofday(&wp->window->activity_time, NULL) != 0)
 | 
			
		||||
		fatal("gettimeofday failed");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Open the screen. Use NULL wp if there is a mode set as don't want to
 | 
			
		||||
	 * update the tty.
 | 
			
		||||
@@ -1081,7 +1076,7 @@ input_c0_dispatch(struct input_ctx *ictx)
 | 
			
		||||
	case '\000':	/* NUL */
 | 
			
		||||
		break;
 | 
			
		||||
	case '\007':	/* BEL */
 | 
			
		||||
		wp->window->flags |= WINDOW_BELL;
 | 
			
		||||
		alerts_queue(wp->window, WINDOW_BELL);
 | 
			
		||||
		break;
 | 
			
		||||
	case '\010':	/* BS */
 | 
			
		||||
		screen_write_backspace(sctx);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								server.c
									
									
									
									
									
								
							@@ -249,10 +249,13 @@ server_start(int lockfd, char *lockfile)
 | 
			
		||||
void
 | 
			
		||||
server_loop(void)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w;
 | 
			
		||||
 | 
			
		||||
	while (!server_should_shutdown()) {
 | 
			
		||||
		event_loop(EVLOOP_ONCE);
 | 
			
		||||
 | 
			
		||||
		server_window_loop();
 | 
			
		||||
		RB_FOREACH(w, windows, &windows)
 | 
			
		||||
		    check_window_name(w);
 | 
			
		||||
		server_client_loop();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -519,6 +519,7 @@ session_set_current(struct session *s, struct winlink *wl)
 | 
			
		||||
	winlink_stack_push(&s->lastw, s->curw);
 | 
			
		||||
	s->curw = wl;
 | 
			
		||||
	winlink_clear_flags(wl);
 | 
			
		||||
	window_update_activity(wl->window);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								tmux.h
									
									
									
									
									
								
							@@ -874,7 +874,8 @@ struct window {
 | 
			
		||||
	struct event	 name_event;
 | 
			
		||||
	struct timeval	 name_time;
 | 
			
		||||
 | 
			
		||||
	struct timeval	 silence_timer;
 | 
			
		||||
	struct event	 alerts_timer;
 | 
			
		||||
 | 
			
		||||
	struct timeval	 activity_time;
 | 
			
		||||
 | 
			
		||||
	struct window_pane *active;
 | 
			
		||||
@@ -1829,6 +1830,10 @@ void	 key_bindings_dispatch(struct key_binding *, struct client *,
 | 
			
		||||
int	 key_string_lookup_string(const char *);
 | 
			
		||||
const char *key_string_lookup_key(int);
 | 
			
		||||
 | 
			
		||||
/* alerts.c */
 | 
			
		||||
void	alerts_reset_all(void);
 | 
			
		||||
void	alerts_queue(struct window *, int);
 | 
			
		||||
 | 
			
		||||
/* server.c */
 | 
			
		||||
extern struct clients clients;
 | 
			
		||||
extern struct clients dead_clients;
 | 
			
		||||
@@ -1856,9 +1861,6 @@ void	 server_client_callback(int, short, void *);
 | 
			
		||||
void	 server_client_status_timer(void);
 | 
			
		||||
void	 server_client_loop(void);
 | 
			
		||||
 | 
			
		||||
/* server-window.c */
 | 
			
		||||
void	 server_window_loop(void);
 | 
			
		||||
 | 
			
		||||
/* server-fn.c */
 | 
			
		||||
void	 server_fill_environ(struct session *, struct environ *);
 | 
			
		||||
void	 server_write_ready(struct client *);
 | 
			
		||||
@@ -2084,6 +2086,7 @@ void		 winlink_stack_push(struct winlink_stack *, struct winlink *);
 | 
			
		||||
void		 winlink_stack_remove(struct winlink_stack *, struct winlink *);
 | 
			
		||||
struct window	*window_find_by_id_str(const char *);
 | 
			
		||||
struct window	*window_find_by_id(u_int);
 | 
			
		||||
void		 window_update_activity(struct window *);
 | 
			
		||||
struct window	*window_create1(u_int, u_int);
 | 
			
		||||
struct window	*window_create(const char *, int, char **, const char *,
 | 
			
		||||
		     const char *, int, struct environ *, struct termios *,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								window.c
									
									
									
									
									
								
							@@ -277,6 +277,13 @@ window_find_by_id(u_int id)
 | 
			
		||||
	return (RB_FIND(windows, &windows, &w));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_update_activity(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	gettimeofday(&w->activity_time, NULL);
 | 
			
		||||
	alerts_queue(w, WINDOW_ACTIVITY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct window *
 | 
			
		||||
window_create1(u_int sx, u_int sy)
 | 
			
		||||
{
 | 
			
		||||
@@ -295,9 +302,6 @@ window_create1(u_int sx, u_int sy)
 | 
			
		||||
	w->sx = sx;
 | 
			
		||||
	w->sy = sy;
 | 
			
		||||
 | 
			
		||||
	if (gettimeofday(&w->activity_time, NULL) != 0)
 | 
			
		||||
		fatal("gettimeofday failed");
 | 
			
		||||
 | 
			
		||||
	options_init(&w->options, &global_w_options);
 | 
			
		||||
 | 
			
		||||
	w->references = 0;
 | 
			
		||||
@@ -305,6 +309,8 @@ window_create1(u_int sx, u_int sy)
 | 
			
		||||
	w->id = next_window_id++;
 | 
			
		||||
	RB_INSERT(windows, &windows, w);
 | 
			
		||||
 | 
			
		||||
	window_update_activity(w);
 | 
			
		||||
 | 
			
		||||
	return (w);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -350,6 +356,9 @@ window_destroy(struct window *w)
 | 
			
		||||
	if (event_initialized(&w->name_event))
 | 
			
		||||
		evtimer_del(&w->name_event);
 | 
			
		||||
 | 
			
		||||
	if (event_initialized(&w->alerts_timer))
 | 
			
		||||
		evtimer_del(&w->alerts_timer);
 | 
			
		||||
 | 
			
		||||
	options_free(&w->options);
 | 
			
		||||
 | 
			
		||||
	window_destroy_panes(w);
 | 
			
		||||
@@ -929,14 +938,6 @@ window_pane_read_callback(unused struct bufferevent *bufev, void *data)
 | 
			
		||||
	input_parse(wp);
 | 
			
		||||
 | 
			
		||||
	wp->pipe_off = EVBUFFER_LENGTH(evb);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If we get here, we're not outputting anymore, so set the silence
 | 
			
		||||
	 * flag on the window.
 | 
			
		||||
	 */
 | 
			
		||||
	wp->window->flags |= WINDOW_SILENCE;
 | 
			
		||||
	if (gettimeofday(&wp->window->silence_timer, NULL) != 0)
 | 
			
		||||
		fatal("gettimeofday failed");
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
start_timer:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user