-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsleep.c
executable file
·152 lines (124 loc) · 3.35 KB
/
sleep.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
* UAE - The Un*x Amiga Emulator
*
* Sleeping for *nix systems
*
* Copyright 2003-2005 Richard Drummond
*/
#if 1 //ndef _WIN32
#include "sysconfig.h"
#include "sysdeps.h"
#include "uae.h"
#include "custom.h"
#include "options.h"
#include "events.h"
#include "hrtimer.h"
#include "sleep.h"
/* Define me to always sleep no matter what the latency
* of the sleep function */
//#define SLEEP_DONT_BUSY_WAIT
/* Busy sleep threshhold in ms. If busy-waiting is enabled, sleeps for periods
* shorter than this will always be done with a busy loop
*
* We should probably determine the threshhold at run-time, but a constant value
* works well enough
*/
#define SLEEP_BUSY_THRESHOLD 5
/*
* Sleep for ms milliseconds either using an appropriate sleep routine on the
* target system or, if the target's routine has too much latency to
* accurately sleep for that period, then busy wait.
*
* Busy-waiting requires a high-resolution timer for accuracy. We use
* the machine-dependent read_processor_time ()
*/
void sleep_millis (int ms)
{
frame_time_t start = uae_gethrtime ();
frame_time_t sleep_time;
#ifndef SLEEP_DONT_BUSY_WAIT
if (ms < SLEEP_BUSY_THRESHOLD) {
/* Typical sleep routines can't sleep for less than 10ms. If we want
* to sleep for a period shorter than the threshold, we'll have to busy wait . . .
*/
frame_time_t end = start + ms * uae_gethrtimebase () / 1000;
frame_time_t v;
do {
v = uae_gethrtime ();
} while (v < end && v > -end);
} else
#endif
uae_msleep (ms);
sleep_time = uae_gethrtime () - start;
idletime += sleep_time;
}
/*
* Sleep for ms milliseconds if and only busy-waiting would not be required
* to do so.
*/
void sleep_millis_busy (int ms)
{
#ifndef SLEEP_DONT_BUSY_WAIT
if (ms >= SLEEP_BUSY_THRESHOLD)
#endif
sleep_millis (ms);
}
/*
* Measure how long it takes to do a ms millisecond sleep. Timing is performed
* with a machine-specific high-resolution timer.
*/
static int do_sleep_test (int ms)
{
frame_time_t t;
frame_time_t t2;
t = uae_gethrtime ();
uae_msleep (ms);
t2 = uae_gethrtime () - t;
if (t2 < 0)
t2 = -t2;
return t2;
}
/*
* Test the target system's sleep routine to decide whether we should busy wait
* by default for sleeps shorter in duration than SLEEP_BUSY_THRESHOLD
*/
void sleep_test (void)
{
static int done = 0;
int result;
#ifndef SLEEP_DONT_BUSY_WAIT
if (!done) {
uae_u64 total = 0;
int result;
int num_tests;
int i;
currprefs.dont_busy_wait = 1;
done = 1;
//write_log ("Testing system sleep function"); flush_log ();
/* Do a few tests to get a rough idea how fast we can do it */
num_tests = 16;
for (i=0; i < num_tests; i++)
total += do_sleep_test (1);
/* How many for 2 seconds worth of tests . . . */
num_tests = 2 * uae_gethrtimebase () * num_tests / total;
total = 0;
/* Now the test proper */
for (i = 0; i < num_tests; i++) {
total += do_sleep_test (1);
if (i - (i % 100) == i) {
write_log (".");
flush_log ();
}
}
result = (1000 * total / uae_gethrtimebase ()) / num_tests;
write_log ("\nAverage duration of a 1ms sleep: %d ms\n", result);
if (result > SLEEP_BUSY_THRESHOLD) {
currprefs.dont_busy_wait = 0;
write_log ("Enabling busy-waiting for sub-%dms sleeps\n", SLEEP_BUSY_THRESHOLD);
}
}
#else
currprefs.dont_busy_wait = 1;
#endif
}
#endif /* !_WIN32 */