diff options
author | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-03-22 20:30:35 +0000 |
---|---|---|
committer | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-03-22 20:30:35 +0000 |
commit | b5b1aca92b2793175d3662071fd288d84c6f18c8 (patch) | |
tree | c12f1dc0e2891099557a830c4e681939d7e020ed | |
parent | 667bf1e48f1af4e9bba3d6d2805ec2fbb1b145c6 (diff) | |
download | edk2-b5b1aca92b2793175d3662071fd288d84c6f18c8.zip edk2-b5b1aca92b2793175d3662071fd288d84c6f18c8.tar.gz edk2-b5b1aca92b2793175d3662071fd288d84c6f18c8.tar.bz2 |
Fix gBS->Stall bug. The current code would only stall for a single timer tick. Fixing this issue exposed another issue with time slip in the stall that was also fixed.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11414 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r-- | UnixPkg/Sec/UnixThunk.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/UnixPkg/Sec/UnixThunk.c b/UnixPkg/Sec/UnixThunk.c index f65acab..eb9e536 100644 --- a/UnixPkg/Sec/UnixThunk.c +++ b/UnixPkg/Sec/UnixThunk.c @@ -142,17 +142,36 @@ void msSleep (unsigned long Milliseconds) { struct timespec rq, rm; - + struct timeval start, end; + unsigned long MicroSec; + rq.tv_sec = Milliseconds / 1000; rq.tv_nsec = (Milliseconds % 1000) * 1000000; - while (nanosleep (&rq, &rm) != -1) { + // + // nanosleep gets interrupted by our timer tic. + // we need to track wall clock time or we will stall for way too long + // + gettimeofday (&start, NULL); + end.tv_sec = start.tv_sec + rq.tv_sec; + MicroSec = (start.tv_usec + rq.tv_nsec/1000); + end.tv_usec = MicroSec % 1000000; + if (MicroSec > 1000000) { + end.tv_sec++; + } + + while (nanosleep (&rq, &rm) == -1) { if (errno != EINTR) { break; } + gettimeofday (&start, NULL); + if (start.tv_sec > end.tv_sec) { + break; + } if ((start.tv_sec == end.tv_sec) && (start.tv_usec > end.tv_usec)) { + break; + } rq = rm; } - } void |