Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
d44da7ef
Commit
d44da7ef
authored
Feb 11, 2003
by
David Mosberger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ia64: Fix do_gettimeoffset() to not update last_nsec_offset with (potentially)
invalid values.
parent
aa34464e
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
39 additions
and
19 deletions
+39
-19
arch/ia64/kernel/time.c
arch/ia64/kernel/time.c
+39
-19
No files found.
arch/ia64/kernel/time.c
View file @
d44da7ef
...
...
@@ -115,33 +115,53 @@ do_settimeofday (struct timeval *tv)
void
do_gettimeofday
(
struct
timeval
*
tv
)
{
unsigned
long
seq
,
nsec
,
usec
,
sec
,
old
;
unsigned
long
seq
,
nsec
,
usec
,
sec
,
old
,
offset
;
while
(
1
)
{
seq
=
read_seqbegin
(
&
xtime_lock
);
nsec
=
gettimeoffset
();
/*
* Ensure time never goes backwards, even when ITC on different CPUs are
* not perfectly synchronized.
*/
{
old
=
last_nsec_offset
;
if
(
unlikely
(
nsec
<=
old
))
/* someone else has seen a newer time-offset; use that one instead */
nsec
=
old
;
else
if
(
unlikely
(
cmpxchg
(
&
last_nsec_offset
,
old
,
nsec
)
!=
old
))
/* someone else beat us to updating last_nsec_offset; try again */
continue
;
offset
=
gettimeoffset
();
sec
=
xtime
.
tv_sec
;
nsec
+=
xtime
.
tv_nsec
;
if
(
likely
(
!
read_seqretry
(
&
xtime_lock
,
seq
)))
nsec
=
xtime
.
tv_nsec
;
}
if
(
unlikely
(
read_seqretry
(
&
xtime_lock
,
seq
)))
continue
;
/*
* Ensure that for any pair of causally ordered gettimeofday() calls, time
* never goes backwards (even when ITC on different CPUs are not perfectly
* synchronized). (A pair of concurrent calls to gettimeofday() is by
* definition non-causal and hence it makes no sense to talk about
* time-continuity for such calls.)
*
* Doing this in a lock-free and race-free manner is tricky. Here is why
* it works (most of the time): read_seqretry() just succeeded, which
* implies we calculated a consistent (valid) value for "offset". If the
* cmpxchg() below succeeds, we further know that last_nsec_offset still
* has the same value as at the beginning of the loop, so there was
* presumably no timer-tick or other updates to last_nsec_offset in the
* meantime. This isn't 100% true though: there _is_ a possibility of a
* timer-tick occurring right right after read_seqretry() and then getting
* zero or more other readers which will set last_nsec_offset to the same
* value as the one we read at the beginning of the loop. If this
* happens, we'll end up returning a slightly newer time than we ought to
* (the jump forward is at most "offset" nano-seconds). There is no
* danger of causing time to go backwards, though, so we are safe in that
* sense. We could make the probability of this unlucky case occurring
* arbitrarily small by encoding a version number in last_nsec_offset, but
* even without versioning, the probability of this unlucky case should be
* so small that we won't worry about it.
*/
if
(
offset
<=
old
)
{
offset
=
old
;
break
;
}
else
if
(
likely
(
cmpxchg
(
&
last_nsec_offset
,
old
,
offset
)
==
old
))
break
;
/* someone else beat us to updating last_nsec_offset; try again */
}
usec
=
nsec
/
1000
;
usec
=
(
nsec
+
offset
)
/
1000
;
while
(
unlikely
(
usec
>=
1000000
))
{
usec
-=
1000000
;
...
...
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