Vendor patch that adds a microsecond timer function.

This commit is contained in:
Hartmut Brandt 2006-12-08 14:45:15 +00:00
parent 5ae1be8157
commit ca77a23f23
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/libbegemot/dist/; revision=165009
3 changed files with 100 additions and 49 deletions

View file

@ -101,16 +101,16 @@
# endif # endif
typedef signed long long tval_t; typedef int64_t tval_t;
static inline tval_t GETMSECS(void); static inline tval_t GETUSECS(void);
static inline tval_t static inline tval_t
GETMSECS(void) { GETUSECS(void) {
struct timeval tval; struct timeval tval;
(void)gettimeofday(&tval, NULL); (void)gettimeofday(&tval, NULL);
return (tval_t)tval.tv_sec*1000+tval.tv_usec/1000; return (tval_t)tval.tv_sec * 1000000 + tval.tv_usec;
} }
/* /*
@ -170,11 +170,11 @@ typedef struct {
* Now for timers * Now for timers
*/ */
typedef struct { typedef struct {
u_int msecs; /* millisecond value of the timer */ uint64_t usecs; /* microsecond value of the timer */
int repeat; /* one shot or repeat? */ int repeat; /* one shot or repeat? */
void *arg; /* client arg */ void *arg; /* client arg */
timer_f func; /* handler, 0 means disfunct */ timer_f func; /* handler, 0 means disfunct */
tval_t when; /* next time to trigger in msecs! */ tval_t when; /* next time to trigger in usecs! */
} PollTim_t; } PollTim_t;
/* how many records should our table grow at once? */ /* how many records should our table grow at once? */
@ -296,8 +296,8 @@ poll_register(int fd, poll_f func, void *arg, int mask)
poll_unblocksig(); poll_unblocksig();
if(rpoll_trace) if(rpoll_trace)
fprintf(stderr, "poll_register(%d, %#lx, %#lx, %#x)->%d", fprintf(stderr, "poll_register(%d, %p, %p, %#x)->%tu",
fd, (u_long)func, (u_long)arg, mask, p - regs); fd, (void *)func, (void *)arg, mask, p - regs);
return p - regs; return p - regs;
} }
@ -372,6 +372,13 @@ poll_build(void)
int int
poll_start_timer(u_int msecs, int repeat, timer_f func, void *arg) poll_start_timer(u_int msecs, int repeat, timer_f func, void *arg)
{
return (poll_start_utimer((unsigned long long)msecs * 1000,
repeat, func, arg));
}
int
poll_start_utimer(unsigned long long usecs, int repeat, timer_f func, void *arg)
{ {
PollTim_t *p; PollTim_t *p;
@ -392,19 +399,19 @@ poll_start_timer(u_int msecs, int repeat, timer_f func, void *arg)
} }
/* create entry */ /* create entry */
p->msecs = msecs; p->usecs = usecs;
p->repeat = repeat; p->repeat = repeat;
p->arg = arg; p->arg = arg;
p->func = func; p->func = func;
p->when = GETMSECS() + msecs; p->when = GETUSECS() + usecs;
tims_used++; tims_used++;
resort = 1; resort = 1;
if(rpoll_trace) if(rpoll_trace)
fprintf(stderr, "poll_start_timer(%u, %d, %#lx, %#lx)->%u", fprintf(stderr, "poll_start_utimer(%llu, %d, %p, %p)->%tu",
msecs, repeat, (u_long)func, (u_long)arg, p - tims); usecs, repeat, (void *)func, (void *)arg, p - tims);
return p - tims; return p - tims;
} }
@ -497,7 +504,7 @@ poll_dispatch(int wait)
u_int i, idx; u_int i, idx;
int ret; int ret;
tval_t now; tval_t now;
int tout; tval_t tout;
static u_int last_index; static u_int last_index;
# ifdef USE_SELECT # ifdef USE_SELECT
@ -519,12 +526,13 @@ poll_dispatch(int wait)
/* in wait mode - compute the timeout */ /* in wait mode - compute the timeout */
if(wait) { if(wait) {
if(tfd_used) { if(tfd_used) {
now = GETMSECS(); now = GETUSECS();
# ifdef DEBUG # ifdef DEBUG
{ {
fprintf(stderr, "now=%"QUADFMT"u", now); fprintf(stderr, "now=%llu", now);
for(i = 0; i < tims_used; i++) for(i = 0; i < tims_used; i++)
fprintf(stderr, "timers[%2d] = %"QUADFMT"d", i, tfd[i]->when - now); fprintf(stderr, "timers[%2d] = %lld",
i, tfd[i]->when - now);
} }
# endif # endif
if((tout = tims[tfd[0]].when - now) < 0) if((tout = tims[tfd[0]].when - now) < 0)
@ -539,7 +547,7 @@ poll_dispatch(int wait)
# endif # endif
# ifdef USE_POLL # ifdef USE_POLL
ret = poll(pfd, regs_used, tout); ret = poll(pfd, regs_used, tout == INFTIM ? INFTIM : (tout / 1000));
# endif # endif
# ifdef USE_SELECT # ifdef USE_SELECT
@ -547,13 +555,13 @@ poll_dispatch(int wait)
nwset = wset; nwset = wset;
nxset = xset; nxset = xset;
if(tout != INFTIM) { if(tout != INFTIM) {
tv.tv_sec = tout / 1000; tv.tv_sec = tout / 1000000;
tv.tv_usec = (tout % 1000) * 1000; tv.tv_usec = tout % 1000000;
} }
ret = select(maxfd+1, ret = select(maxfd+1,
SELECT_CAST(&nrset), SELECT_CAST(&nrset),
SELECT_CAST(&nwset), SELECT_CAST(&nwset),
SELECT_CAST(&nxset), (tout==INFTIM) ? 0 : &tv); SELECT_CAST(&nxset), (tout==INFTIM) ? NULL : &tv);
# endif # endif
if(ret == -1) { if(ret == -1) {
@ -574,20 +582,26 @@ poll_dispatch(int wait)
# ifdef USE_POLL # ifdef USE_POLL
if(regs[idx].pfd) { if(regs[idx].pfd) {
if(regs[idx].pfd->revents & poll_in) if ((regs[idx].mask & POLL_IN) &&
(regs[idx].pfd->revents & poll_in))
mask |= POLL_IN; mask |= POLL_IN;
if(regs[idx].pfd->revents & poll_out) if ((regs[idx].mask & POLL_OUT) &&
(regs[idx].pfd->revents & poll_out))
mask |= POLL_OUT; mask |= POLL_OUT;
if(regs[idx].pfd->revents & poll_except) if((regs[idx].mask & POLL_EXCEPT) &&
(regs[idx].pfd->revents & poll_except))
mask |= POLL_EXCEPT; mask |= POLL_EXCEPT;
} }
# endif # endif
# ifdef USE_SELECT # ifdef USE_SELECT
if(FD_ISSET(regs[idx].fd, &nrset)) if ((regs[idx].mask & POLL_IN) &&
FD_ISSET(regs[idx].fd, &nrset))
mask |= POLL_IN; mask |= POLL_IN;
if(FD_ISSET(regs[idx].fd, &nwset)) if ((regs[idx].mask & POLL_OUT) &&
FD_ISSET(regs[idx].fd, &nwset))
mask |= POLL_OUT; mask |= POLL_OUT;
if(FD_ISSET(regs[idx].fd, &nxset)) if ((regs[idx].mask & POLL_EXCEPT) &&
FD_ISSET(regs[idx].fd, &nxset))
mask |= POLL_EXCEPT; mask |= POLL_EXCEPT;
# endif # endif
assert(idx < regs_alloc); assert(idx < regs_alloc);
@ -595,8 +609,8 @@ poll_dispatch(int wait)
if(mask) { if(mask) {
if(rpoll_trace) if(rpoll_trace)
fprintf(stderr, "poll_dispatch() -- " fprintf(stderr, "poll_dispatch() -- "
"file %d/%d", "file %d/%d %x",
regs[idx].fd, idx); regs[idx].fd, idx, mask);
(*regs[idx].func)(regs[idx].fd, mask, regs[idx].arg); (*regs[idx].func)(regs[idx].fd, mask, regs[idx].arg);
} }
} }
@ -607,7 +621,7 @@ poll_dispatch(int wait)
/* dispatch timeouts */ /* dispatch timeouts */
if(tfd_used) { if(tfd_used) {
now = GETMSECS(); now = GETUSECS();
for(i = 0; i < tfd_used; i++) { for(i = 0; i < tfd_used; i++) {
if(tfd[i] < 0) if(tfd[i] < 0)
continue; continue;
@ -619,7 +633,7 @@ poll_dispatch(int wait)
if(tfd[i] < 0) if(tfd[i] < 0)
continue; continue;
if(tims[tfd[i]].repeat) if(tims[tfd[i]].repeat)
tims[tfd[i]].when = now + tims[tfd[i]].msecs; tims[tfd[i]].when = now + tims[tfd[i]].usecs;
else { else {
tims[tfd[i]].func = NULL; tims[tfd[i]].func = NULL;
tims_used--; tims_used--;
@ -644,8 +658,8 @@ elaps(void)
{ {
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
return (double)(10 * now.tv_sec + now.tv_usec / 100000 - 10 * start.tv_sec - start.tv_usec / 100000) return (double)(10 * now.tv_sec + now.tv_usec / 100000 -
/ 10; 10 * start.tv_sec - start.tv_usec / 100000) / 10;
} }
void void
@ -675,6 +689,14 @@ tfunc1(int tid, void *arg)
{ {
printf("%4.1f -- %d: %s\n", elaps(), tid, (char *)arg); printf("%4.1f -- %d: %s\n", elaps(), tid, (char *)arg);
} }
void
tfunc2(int tid, void *arg)
{
static u_int count = 0;
if (++count % 10000 == 0)
printf("%4.1f -- %d\n", elaps(), tid);
}
void first(int tid, void *arg); void first(int tid, void *arg);
void second(int tid, void *arg); void second(int tid, void *arg);
@ -683,7 +705,7 @@ void
second(int tid, void *arg) second(int tid, void *arg)
{ {
printf("%4.1f -- %d: %s\n", elaps(), tid, (char *)arg); printf("%4.1f -- %d: %s\n", elaps(), tid, (char *)arg);
poll_start_timer(5500, 0, first, "first"); poll_start_utimer(5500000, 0, first, "first");
poll_stop_timer(t1); poll_stop_timer(t1);
t0 = poll_start_timer(1000, 1, tfunc0, "1 second"); t0 = poll_start_timer(1000, 1, tfunc0, "1 second");
} }
@ -699,12 +721,16 @@ first(int tid, void *arg)
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
argc = argc;
argv = argv; argv = argv;
gettimeofday(&start, NULL); gettimeofday(&start, NULL);
poll_register(0, infunc, NULL, POLL_IN); poll_register(0, infunc, NULL, POLL_IN);
t0 = poll_start_timer(1000, 1, tfunc0, "1 second");
poll_start_timer(2500, 0, first, "first"); if (argc < 2) {
t0 = poll_start_timer(1000, 1, tfunc0, "1 second");
poll_start_timer(2500, 0, first, "first");
} else {
t0 = poll_start_utimer(300, 1, tfunc2, NULL);
}
while(1) while(1)
poll_dispatch(1); poll_dispatch(1);

View file

@ -43,6 +43,8 @@ int poll_register(int fd, poll_f func, void *arg, int mask);
void poll_unregister(int); void poll_unregister(int);
void poll_dispatch(int wait); void poll_dispatch(int wait);
int poll_start_timer(u_int msecs, int repeat, timer_f func, void *arg); int poll_start_timer(u_int msecs, int repeat, timer_f func, void *arg);
int poll_start_utimer(unsigned long long usecs, int repeat, timer_f func,
void *arg);
void poll_stop_timer(int); void poll_stop_timer(int);
# if defined(POLL_IN) # if defined(POLL_IN)

View file

@ -1,8 +1,8 @@
'\" '\"
'\" Copyright (c)1996-2002 by Hartmut Brandt '\" Copyright (c)1996-2006 by Hartmut Brandt
'\" All rights reserved. '\" All rights reserved.
'\" '\"
'\" Author: Hartmut Brandt '\" Author: harti@freebsd.org <Hartmut Brandt>
'\" '\"
'\" Redistribution of this software and documentation and use in source and '\" Redistribution of this software and documentation and use in source and
'\" binary forms, with or without modification, are permitted provided that '\" binary forms, with or without modification, are permitted provided that
@ -28,28 +28,32 @@
'\" '\"
'\" $Begemot: libbegemot/rpoll.man,v 1.4 2004/09/21 15:59:00 brandt Exp $ '\" $Begemot: libbegemot/rpoll.man,v 1.4 2004/09/21 15:59:00 brandt Exp $
'\" '\"
.TH rpoll 3 "21 Oct 1996" "BEGEMOT" "BEGEMOT Library" .TH rpoll 3 "8 Dec 2006" "BEGEMOT" "BEGEMOT Library"
.SH NAME .SH NAME
rpoll - callback functions for file descriptors and timers rpoll - callback functions for file descriptors and timers
.SH SYNOPSIS .SH SYNOPSIS
.LP .LP
.B "# include <rpoll.h>" .B "# include <rpoll.h>"
.LP .LP
.BR "typedef void (*poll_f)(int " "fd" ", int " "mask" ", void *" "arg);" .BR "typedef void (*poll_f)(int " "fd" ", int " "mask" ", void *" "arg" ");"
.br .br
.BR "typedef void (*timer_f)(int " "tid" ", void *" "arg);" .BR "typedef void (*timer_f)(int " "tid" ", void *" "arg" ");"
.LP .LP
.BR "int poll_register(int " "fd" ", poll_f " .BR "int poll_register(int " "fd" ", poll_f "
.RB "func" ", void *" "arg" ", int " "mask" ");" .RB "func" ", void *" "arg" ", int " "mask" ");"
.LP .LP
.BR "void poll_unregister(int " "handle" ");" .BR "void poll_unregister(int " "handle" ");"
.LP .LP
.BR "int poll_start_timer(u_int " "msecs" ", int " "repeat" ", timer_f " "func," .BR "int poll_start_timer(u_int " "msecs" ", int " "repeat" ", timer_f " "func" ","
.if n .ti +.5i .if n .ti +.5i
.BR "void *" "arg);" .BR "void *" "arg" ");"
.LP .LP
.BR "void poll_stop_timer(int " "handle" ");" .BR "void poll_stop_timer(int " "handle" ");"
.LP .LP
.BR "int poll_start_utimer(unsigned long long " "usecs" ", int " "repeat" ",
.if n .ti +.5i
.BR "timer_f " "func" ", void *" "arg" ");"
.LP
.BR "void poll_dispatch(int " "wait" ");" .BR "void poll_dispatch(int " "wait" ");"
.SH DESCRIPTION .SH DESCRIPTION
Many programs need to read from several file descriptors at the same time. Many programs need to read from several file descriptors at the same time.
@ -113,9 +117,24 @@ with the handle returned by
.BR poll_register . .BR poll_register .
.LP .LP
A timer is created with A timer is created with
.BR poll_start_timer . .BR poll_start_timer
or
.BR poll_start_utimer .
.I msecs .I msecs
is the number of milliseconds, after which the timer event will be generated. is the number of milliseconds in
.BR poll_start_timer
while
.I usecs
is the number of microseconds in
.BR poll_start_utimer ,
after which the timer event will be generated.
If the functions use the
.BR poll (2)
system call, then
.I usecs
is rounded to milliseconds and
.BR poll_start_timer
is called.
.I repeat .I repeat
selects one-short behavior (if 0) or a repeatable timer (if not 0). A one-short timer selects one-short behavior (if 0) or a repeatable timer (if not 0). A one-short timer
will automatically unregistered after expiry. will automatically unregistered after expiry.
@ -123,7 +142,9 @@ will automatically unregistered after expiry.
is the user function which will be called with a timer id and the user supplied is the user function which will be called with a timer id and the user supplied
.IR arg . .IR arg .
.B poll_start_timer .B poll_start_timer
returnes a timer id, which may be used to cancel the timer with and
.B poll_start_utimer
return a timer id, which may be used to cancel the timer with
.BR poll_stop_timer . .BR poll_stop_timer .
A one-short timer should be canceled only if it has not yet fired. A one-short timer should be canceled only if it has not yet fired.
.LP .LP
@ -151,10 +172,12 @@ while(1)
.SH "SEE ALSO" .SH "SEE ALSO"
.BR poll (2), select (3C) .BR poll (2), select (3C)
.SH "RETURN VALUES" .SH "RETURN VALUES"
.B poll_register .B poll_register ,
and
.B poll_start_timer .B poll_start_timer
return a handle which may be used to unregister the file descriptor or cancel the timer. and
.B poll_start_utimer
return a handle which may be used to unregister the file descriptor or
cancel the timer.
.LP .LP
Both functions and Both functions and
.B poll_dispatch .B poll_dispatch