This is probably not a java specific question.
If you meant to ask how Thread.sleep() is implemented, then probably not.
How, in principle, does Thread.sleep work?
If I were to write it naively, I would write
remember time
while (true) {
if (new time - old time > delay)
return;
}
Obviously, this is not how.... Well, how then?
Unfortunately you can easily peek at SUNs implementation of the native
sleep() library call, however if you look how others did it, you might
get the idea (it can be depending on the JVM and the underlying
architecture):
from GNU classpath
------------------
static void sleep(long ms, int ns) throws InterruptedException
{
// Round up
ms += (ns != 0) ? 1 : 0;
// Note: JDK treats a zero length sleep is like Thread.yield(),
// without checking the interrupted status of the thread.
// It's unclear if this is a bug in the implementation or the spec.
// See
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203
if (ms == 0)
{
if (Thread.interrupted())
throw new InterruptedException();
return;
}
// Compute end time, but don't overflow
long now = System.currentTimeMillis();
long end = now + ms;
if (end < now)
end = Long.MAX_VALUE;
// A VM is allowed to return from wait() without notify() having been
// called, so we loop to handle possible spurious wakeups.
VMThread vt = Thread.currentThread().vmThread;
synchronized (vt)
{
while (true)
{
vt.wait(ms);
now = System.currentTimeMillis();
if (now >= end)
break;
ms = end - now;
}
}
}
and System.currentTimeMillis() is directly implemented as:
JNIEXPORT jlong JNICALL
Java_java_lang_VMSystem_currentTimeMillis
(JNIEnv * env __attribute__((__unused__)),
jclass thisClass __attribute__((__unused__)))
{
/* Note: this implementation copied directly from Japhar's, by Chris
Toshok. *
/
jlong result;
struct timeval tp;
if (gettimeofday(&tp, NULL) == -1)
(*env)->FatalError(env, "gettimeofday call failed.");
result = (jlong)tp.tv_sec;
result *= 1000;
result += (tp.tv_usec / 1000);
return result;
}
from JamVM
----------
int monitorWait(Monitor *mon, Thread *self, long long ms, int ns) {
char interrupted = 0;
int old_count;
char timed = (ms != 0) || (ns != 0);
struct timespec ts;
if(mon->owner != self)
return FALSE;
/* We own the monitor */
disableSuspend(self);
old_count = mon->count;
mon->count = 0;
mon->owner = NULL;
mon->waiting++;
if(timed) {
struct timeval tv;
gettimeofday(&tv, 0);
ts.tv_sec = tv.tv_sec + ms/1000;
ts.tv_nsec = (tv.tv_usec + ((ms%1000)*1000))*1000 + ns;
if(ts.tv_nsec > 999999999L) {
ts.tv_sec++;
ts.tv_nsec -= 1000000000L;
}
}
[ ... a lot more code ... ]
It also implements the thread code using the NTPL framework, which is
rather Linux-centric, but fast.
Now in the Kaffe VM:
--------------------
The whole stuff is done with a lot of twists and turns and I'm not sure
if I got it right by browsing the source code ... after going through a
lot of code there is a function being called which listens to the happy
name currentTime():
static jlong currentTime(void) {
struct timeval tm;
gettimeofday(&tm, 0);
return (((jlong)tm.tv_sec * 1000L) + ((jlong)tm.tv_usec / 1000L));
}
So roughly summarise my sparse findings:
sleep() {
grab lock
disable soft interrupts
get time
while (not enough slept) {
schedule other threads
wait a bit
get time
add time
}
enble soft interrupts
release lock
}
If one was restricted to a specific platform only (extremely off-topic
for Java) the Thread.sleep() method could be implemented extremely
efficient and precise (e.g. RDTSC calls, local APIC timer or reading CPU
MSRs).
Take everything with a grain of salt. Cheers,
Roberto Nibali, ratz