Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
timeout.c
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kirill Smelkov
timeout.c
Commits
ed7d5b92
Commit
ed7d5b92
authored
Dec 14, 2013
by
william
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor API, moving struct timeout to header, renaming some routines, and adding others
parent
917958e3
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
206 additions
and
75 deletions
+206
-75
timer.c
timer.c
+113
-57
timer.h
timer.h
+93
-18
No files found.
timer.c
View file @
ed7d5b92
...
...
@@ -33,11 +33,10 @@
#include <sys/queue.h>
#include "timer.h"
#include "debug.h"
#define abstime_t timeout_t
/* for documentation purposes */
#define reltime_t timeout_t
/* "" */
#if TIMER_DEBUG - 0 || TIMER_MAIN - 0
#include "debug.h"
#endif
/*
...
...
@@ -45,6 +44,9 @@
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define abstime_t timeout_t
/* for documentation purposes */
#define reltime_t timeout_t
/* "" */
#if !defined countof
#define countof(a) (sizeof (a) / sizeof *(a))
#endif
...
...
@@ -181,39 +183,12 @@ static inline wheel_t rotr(const wheel_t v, int c) {
/*
* T I M E
O U T
R O U T I N E S
* T I M E
R
R O U T I N E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
TAILQ_HEAD
(
timeout_list
,
timeout
);
#define TIMEOUT_INITIALIZER { 0, 0, { 0, 0 } }
struct
timeout
{
int
flags
;
timeout_t
expires
;
struct
timeout_list
*
pending
;
TAILQ_ENTRY
(
timeout
)
tqe
;
};
/* struct timeout */
struct
timeout
*
timeout_init
(
struct
timeout
*
to
,
int
flags
)
{
memset
(
to
,
0
,
sizeof
*
to
);
to
->
flags
=
flags
;
return
to
;
}
/* timeout_init() */
/*
* T I M E R R O U T I N E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct
timeouts
{
struct
timeout_list
wheel
[
WHEEL_NUM
][
WHEEL_LEN
],
expired
;
...
...
@@ -258,6 +233,7 @@ void timeouts_del(struct timeouts *T, struct timeout *to) {
TAILQ_REMOVE
(
to
->
pending
,
to
,
tqe
);
to
->
pending
=
NULL
;
to
->
timeouts
=
NULL
;
}
}
/* timeouts_del() */
...
...
@@ -277,7 +253,7 @@ static inline int timeout_slot(int wheel, timeout_t expires) {
}
/* timeout_slot() */
void
timeouts_ad
d
(
struct
timeouts
*
T
,
struct
timeout
*
to
,
timeout_t
expires
)
{
static
void
timeouts_sche
d
(
struct
timeouts
*
T
,
struct
timeout
*
to
,
timeout_t
expires
)
{
timeout_t
rem
;
int
wheel
,
slot
;
...
...
@@ -285,6 +261,8 @@ void timeouts_add(struct timeouts *T, struct timeout *to, timeout_t expires) {
to
->
expires
=
expires
;
to
->
timeouts
=
T
;
if
(
expires
>
T
->
curtime
)
{
rem
=
timeout_rem
(
T
,
to
);
...
...
@@ -299,10 +277,48 @@ void timeouts_add(struct timeouts *T, struct timeout *to, timeout_t expires) {
to
->
pending
=
&
T
->
expired
;
TAILQ_INSERT_TAIL
(
to
->
pending
,
to
,
tqe
);
}
}
/* timeouts_sched() */
static
void
timeouts_readd
(
struct
timeouts
*
T
,
struct
timeout
*
to
)
{
to
->
expires
+=
to
->
interval
;
if
(
to
->
expires
<=
T
->
curtime
)
{
if
(
to
->
expires
<
T
->
curtime
)
{
timeout_t
n
=
T
->
curtime
-
to
->
expires
;
timeout_t
q
=
n
/
to
->
interval
;
timeout_t
r
=
n
%
to
->
interval
;
if
(
r
)
to
->
expires
+=
(
to
->
interval
*
q
)
+
(
to
->
interval
-
r
);
else
to
->
expires
+=
(
to
->
interval
*
q
);
}
else
{
to
->
expires
+=
to
->
interval
;
}
}
timeouts_sched
(
T
,
to
,
to
->
expires
);
}
/* timeouts_readd() */
void
timeouts_add
(
struct
timeouts
*
T
,
struct
timeout
*
to
,
timeout_t
timeout
)
{
if
(
to
->
flags
&
TIMEOUT_INT
)
to
->
interval
=
MAX
(
1
,
timeout
);
if
(
to
->
flags
&
TIMEOUT_ABS
)
timeouts_sched
(
T
,
to
,
timeout
);
else
timeouts_sched
(
T
,
to
,
T
->
curtime
+
timeout
);
}
/* timeouts_add() */
void
timeouts_step
(
struct
timeouts
*
T
,
abstime_t
curtime
)
{
void
timeouts_addf
(
struct
timeouts
*
T
,
struct
timeout
*
to
,
double
timeout
)
{
timeouts_add
(
T
,
to
,
timeout
*
T
->
hertz
);
}
/* timeouts_addf() */
void
timeouts_update
(
struct
timeouts
*
T
,
abstime_t
curtime
)
{
timeout_t
elapsed
=
curtime
-
T
->
curtime
;
struct
timeout_list
todo
;
int
wheel
;
...
...
@@ -360,10 +376,15 @@ void timeouts_step(struct timeouts *T, abstime_t curtime) {
TAILQ_REMOVE
(
&
todo
,
to
,
tqe
);
to
->
pending
=
0
;
timeouts_
ad
d
(
T
,
to
,
to
->
expires
);
timeouts_
sche
d
(
T
,
to
,
to
->
expires
);
}
return
;
}
/* timeouts_update() */
void
timeouts_step
(
struct
timeouts
*
T
,
reltime_t
elapsed
)
{
timeouts_update
(
T
,
T
->
curtime
+
elapsed
);
}
/* timeouts_step() */
...
...
@@ -385,7 +406,8 @@ bool timeouts_expired(struct timeouts *T) {
/*
* Calculate a minimum timeout value for timeouts pending on our wheels.
* Calculate the interval before needing to process any timeouts pending on
* any wheel.
*
* (This is separated from the public API routine so we can evaluate our
* wheel invariant assertions irrespective of the expired queue.)
...
...
@@ -399,7 +421,7 @@ bool timeouts_expired(struct timeouts *T) {
*
* We should never return a timeout larger than the lowest actual timeout.
*/
static
timeout_t
t
ms__timeou
t
(
struct
timeouts
*
T
)
{
static
timeout_t
t
imeouts_in
t
(
struct
timeouts
*
T
)
{
timeout_t
timeout
=
~
TIMEOUT_C
(
0
),
_timeout
;
timeout_t
relmask
;
int
wheel
,
slot
;
...
...
@@ -424,22 +446,21 @@ static timeout_t tms__timeout(struct timeouts *T) {
}
return
timeout
;
}
/* t
ms__timeou
t() */
}
/* t
imeouts_in
t() */
/*
* Calculate
a timeout that our caller can wait before updating and
*
processing the wheel
.
* Calculate
the interval our caller can wait before needing to process
*
events
.
*/
timeout_t
timeouts_timeout
(
struct
timeouts
*
T
)
{
if
(
!
TAILQ_EMPTY
(
&
T
->
expired
))
return
0
;
return
t
ms__timeou
t
(
T
);
return
t
imeouts_in
t
(
T
);
}
/* timeouts_timeout() */
struct
timeout
*
timeouts_get
(
struct
timeouts
*
T
)
{
if
(
!
TAILQ_EMPTY
(
&
T
->
expired
))
{
struct
timeout
*
to
=
TAILQ_FIRST
(
&
T
->
expired
);
...
...
@@ -447,6 +468,12 @@ struct timeout *timeouts_get(struct timeouts *T) {
TAILQ_REMOVE
(
&
T
->
expired
,
to
,
tqe
);
to
->
pending
=
0
;
if
((
to
->
flags
&
TIMEOUT_INT
)
&&
to
->
interval
>
0
)
{
timeouts_readd
(
T
,
to
);
}
else
{
to
->
timeouts
=
0
;
}
return
to
;
}
else
{
return
0
;
...
...
@@ -458,7 +485,7 @@ struct timeout *timeouts_get(struct timeouts *T) {
* Use dumb looping to locate the earliest timeout pending on the wheel so
* our invariant assertions can check the result of our optimized code.
*/
static
struct
timeout
*
t
ms_
_min
(
struct
timeouts
*
T
)
{
static
struct
timeout
*
t
imeouts
_min
(
struct
timeouts
*
T
)
{
struct
timeout
*
to
,
*
min
=
NULL
;
unsigned
i
,
j
;
...
...
@@ -472,7 +499,7 @@ static struct timeout *tms__min(struct timeouts *T) {
}
return
min
;
}
/* t
ms_
_min() */
}
/* t
imeouts
_min() */
/*
...
...
@@ -495,10 +522,10 @@ bool timeouts_check(struct timeouts *T, FILE *fp) {
timeout_t
timeout
;
struct
timeout
*
to
;
if
((
to
=
t
ms_
_min
(
T
)))
{
if
((
to
=
t
imeouts
_min
(
T
)))
{
check
(
to
->
expires
>
T
->
curtime
,
"missed timeout (expires:%"
TIMEOUT_PRIu
" <= curtime:%"
TIMEOUT_PRIu
")
\n
"
,
to
->
expires
,
T
->
curtime
);
timeout
=
t
ms__timeou
t
(
T
);
timeout
=
t
imeouts_in
t
(
T
);
check
(
timeout
<=
to
->
expires
-
T
->
curtime
,
"wrong soft timeout (soft:%"
TIMEOUT_PRIu
" > hard:%"
TIMEOUT_PRIu
") (expires:%"
TIMEOUT_PRIu
"; curtime:%"
TIMEOUT_PRIu
")
\n
"
,
timeout
,
(
to
->
expires
-
T
->
curtime
),
to
->
expires
,
T
->
curtime
);
timeout
=
timeouts_timeout
(
T
);
...
...
@@ -516,6 +543,35 @@ bool timeouts_check(struct timeouts *T, FILE *fp) {
}
/* timeouts_check() */
/*
* T I M E O U T R O U T I N E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct
timeout
*
timeout_init
(
struct
timeout
*
to
,
int
flags
)
{
memset
(
to
,
0
,
sizeof
*
to
);
to
->
flags
=
flags
;
return
to
;
}
/* timeout_init() */
bool
timeout_pending
(
struct
timeout
*
to
)
{
return
to
->
pending
&&
to
->
pending
!=
&
to
->
timeouts
->
expired
;
}
/* timeout_pending() */
bool
timeout_expired
(
struct
timeout
*
to
)
{
return
to
->
pending
&&
to
->
pending
==
&
to
->
timeouts
->
expired
;
}
/* timeout_expired() */
void
timeout_del
(
struct
timeout
*
to
)
{
timeouts_del
(
to
->
timeouts
,
to
);
}
/* timeout_del() */
#if TIMER_MAIN - 0
#include <stdio.h>
...
...
@@ -524,7 +580,7 @@ bool timeouts_check(struct timeouts *T, FILE *fp) {
static
timeout_t
slow_timeout
(
struct
timeouts
*
T
)
{
struct
timeout
*
to
=
t
ms_
_min
(
T
);
struct
timeout
*
to
=
t
imeouts
_min
(
T
);
return
(
to
)
?
to
->
expires
-
T
->
curtime
:
0
;
}
/* slow_timeout() */
...
...
@@ -569,15 +625,15 @@ int main(int argc, char **argv) {
argv
+=
optind
;
timeouts_init
(
&
T
,
TIMEOUT_mHZ
);
timeouts_
step
(
&
T
,
time
);
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
0
],
0
),
time
+
62
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
1
],
0
),
time
+
63
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
2
],
0
),
time
+
64
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
3
],
0
),
time
+
65
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
5
],
0
),
time
+
192
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
6
],
0
),
time
+
6
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
7
],
0
),
time
+
7
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
8
],
0
),
time
+
8
);
count
++
;
timeouts_
update
(
&
T
,
time
);
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
0
],
0
),
62
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
1
],
0
),
63
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
2
],
0
),
64
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
3
],
0
),
65
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
5
],
0
),
192
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
6
],
0
),
6
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
7
],
0
),
7
);
count
++
;
timeouts_add
(
&
T
,
timeout_init
(
&
to
[
8
],
0
),
8
);
count
++
;
while
(
count
>
0
&&
time
<=
stop
-
1
)
{
time
+=
step
;
...
...
@@ -585,7 +641,7 @@ int main(int argc, char **argv) {
SAY
(
"timeout -> %"
TIMEOUT_PRIu
" (actual:%"
TIMEOUT_PRIu
" curtime:%"
TIMEOUT_PRIu
")"
,
timeouts_timeout
(
&
T
),
slow_timeout
(
&
T
),
T
.
curtime
);
timeouts_check
(
&
T
,
stderr
);
timeouts_
step
(
&
T
,
time
);
timeouts_
update
(
&
T
,
time
);
timeouts_check
(
&
T
,
stderr
);
while
((
expired
=
timeouts_get
(
&
T
)))
{
...
...
timer.h
View file @
ed7d5b92
...
...
@@ -27,11 +27,15 @@
#define TIMER_H
#include <stdbool.h>
/* bool */
#include <stdio.h>
/* FILE */
#include <inttypes.h>
/* PRIu64 PRIx64 PRIX64 uint64_t */
#include <sys/queue.h>
/* TAILQ(3) */
/*
*
T I M I N G W H E E L
I N T E R F A C E S
*
I N T E G E R T Y P E
I N T E R F A C E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
...
...
@@ -46,36 +50,107 @@
typedef
uint64_t
timeout_t
;
struct
timeouts
;
struct
timeout
;
struct
timeouts
*
timeouts_open
(
timeout_t
);
/*
* C A L L B A C K I N T E R F A C E
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void
timeouts_close
(
struct
timeouts
*
);
struct
timeout_cb
{
void
(
*
fn
)();
void
*
arg
;
};
/* struct timeout_cb */
void
timeouts_add
(
struct
timeouts
*
,
struct
timeout
*
,
timeout_t
);
void
timeouts_del
(
struct
timeouts
*
,
struct
timeout
*
);
/*
* T I M E O U T I N T E R F A C E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool
timeouts_pending
(
struct
timeouts
*
);
#define TIMEOUT_INT 0x01
/* interval (repeating) timeout */
#define TIMEOUT_ABS 0x02
/* treat timeout values as absolute */
timeout_t
timeouts_timeout
(
struct
timeouts
*
);
#define TIMEOUT_INITIALIZER(flags) { (flags), 0, 0, 0, { 0, 0 } }
#define timeout_setcb(to, fn, arg) do { \
(to)->callback.fn = (fn); \
(to)->callback.arg = (arg); \
} while (0)
/*
* T I M E O U T C O N T E X T I N T E R F A C E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct
timeout
{
int
flags
;
timeout_t
interval
;
/* timeout interval if periodic */
timeout_t
expires
;
/* absolute expiration time */
struct
timeouts
*
timeouts
;
/* timeouts collection if member of */
struct
timeout_list
*
pending
;
/* timeout list if pending on wheel or expiry queue */
struct
timeout_cb
callback
;
/* optional callback information */
TAILQ_ENTRY
(
timeout
)
tqe
;
};
/* struct timeout */
#define TIMEOUT_PERIODIC 0x01
#define TIMEOUT_ABSTIME 0x02
struct
timeout
*
timeout_init
(
struct
timeout
*
,
int
);
/* initialize timeout structure (same as TIMEOUT_INITIALIZER) */
bool
timeout_pending
(
struct
timeout
*
);
/* true if on timing wheel
or expired queue
, false otherwise */
/* true if on timing wheel, false otherwise */
bool
timeout_expired
(
struct
timeout
*
);
/* true if on expired queue, false otherwise */
void
timeout_del
(
struct
timeout
*
);
/* remove timeout from any timing wheel (okay if not member of any) */
/*
* T I M I N G W H E E L I N T E R F A C E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct
timeouts
;
struct
timeouts
*
timeouts_open
(
timeout_t
);
/* open a new timing wheel, setting optional HZ */
void
timeouts_close
(
struct
timeouts
*
);
/* destroy timing wheel */
void
timeouts_update
(
struct
timeouts
*
,
timeout_t
);
/* update timing wheel with current absolute time */
void
timeouts_step
(
struct
timeouts
*
,
timeout_t
);
/* step timing wheel by relative time */
timeout_t
timeouts_timeout
(
struct
timeouts
*
);
/* return interval to next required update */
void
timeouts_add
(
struct
timeouts
*
,
struct
timeout
*
,
timeout_t
);
/* add timeout to timing wheel */
void
timeouts_addf
(
struct
timeouts
*
,
struct
timeout
*
,
double
);
/* add timeout to timing wheel, translating floating point timeout */
void
timeouts_del
(
struct
timeouts
*
,
struct
timeout
*
);
/* remove timeout from any timing wheel or expired queue (okay if on neither) */
bool
timeouts_pending
(
struct
timeouts
*
);
/* return true if any timeouts pending on timing wheel */
bool
timeouts_expired
(
struct
timeouts
*
);
/* return true if any timeouts on expired queue */
bool
timeouts_check
(
struct
timeouts
*
,
FILE
*
);
/* return true if invariants hold. describes failures to optional file handle. */
#endif
/* TIMER_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment