diff options
author | deischen <deischen@FreeBSD.org> | 2003-04-18 05:04:16 +0000 |
---|---|---|
committer | deischen <deischen@FreeBSD.org> | 2003-04-18 05:04:16 +0000 |
commit | 5d56aa9cb2bdbe0a18bafbdbb6eb8cf6a46beb79 (patch) | |
tree | 46bc1e113ddc7c1ed88e4fa724039df8664c963a /lib/libkse/thread/thr_nanosleep.c | |
parent | e68f624d876da04bfb6860b450593c77d80368bd (diff) | |
download | FreeBSD-src-5d56aa9cb2bdbe0a18bafbdbb6eb8cf6a46beb79.zip FreeBSD-src-5d56aa9cb2bdbe0a18bafbdbb6eb8cf6a46beb79.tar.gz |
Revamp libpthread so that it has a chance of working in an SMP
environment. This includes support for multiple KSEs and KSEGs.
The ability to create more than 1 KSE via pthread_setconcurrency()
is in the works as well as support for PTHREAD_SCOPE_SYSTEM threads.
Those should come shortly.
There are still some known issues which davidxu and I are working
on, but it'll make it easier for us by committing what we have.
This library now passes all of the ACE tests that libc_r passes
with the exception of one. It also seems to work OK with KDE
including konqueror, kwrite, etc. I haven't been able to get
mozilla to run due to lack of java plugin, so I'd be interested
to see how it works with that.
Reviewed by: davidxu
Diffstat (limited to 'lib/libkse/thread/thr_nanosleep.c')
-rw-r--r-- | lib/libkse/thread/thr_nanosleep.c | 67 |
1 files changed, 26 insertions, 41 deletions
diff --git a/lib/libkse/thread/thr_nanosleep.c b/lib/libkse/thread/thr_nanosleep.c index 6cccb87..bec3b66 100644 --- a/lib/libkse/thread/thr_nanosleep.c +++ b/lib/libkse/thread/thr_nanosleep.c @@ -39,57 +39,42 @@ __weak_reference(__nanosleep, nanosleep); int -_nanosleep(const struct timespec * time_to_sleep, - struct timespec * time_remaining) +_nanosleep(const struct timespec *time_to_sleep, + struct timespec *time_remaining) { struct pthread *curthread = _get_curthread(); int ret = 0; - struct timespec current_time; - struct timespec current_time1; + struct timespec ts, ts1; struct timespec remaining_time; - struct timeval tv; /* Check if the time to sleep is legal: */ - if (time_to_sleep == NULL || time_to_sleep->tv_sec < 0 || - time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec >= 1000000000) { + if ((time_to_sleep == NULL) || (time_to_sleep->tv_sec < 0) || + (time_to_sleep->tv_nsec < 0) || + (time_to_sleep->tv_nsec >= 1000000000)) { /* Return an EINVAL error : */ errno = EINVAL; ret = -1; } else { - /* - * As long as we're going to get the time of day, we - * might as well store it in the global time of day: - */ - gettimeofday((struct timeval *) &_sched_tod, NULL); - GET_CURRENT_TOD(tv); - TIMEVAL_TO_TIMESPEC(&tv, ¤t_time); + KSE_GET_TOD(curthread->kse, &ts); /* Calculate the time for the current thread to wake up: */ - curthread->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec; - curthread->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec; + TIMESPEC_ADD(&curthread->wakeup_time, &ts, time_to_sleep); - /* Check if the nanosecond field has overflowed: */ - if (curthread->wakeup_time.tv_nsec >= 1000000000) { - /* Wrap the nanosecond field: */ - curthread->wakeup_time.tv_sec += 1; - curthread->wakeup_time.tv_nsec -= 1000000000; - } + THR_SCHED_LOCK(curthread, curthread); curthread->interrupted = 0; - /* Reschedule the current thread to sleep: */ - _thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__); + THR_SET_STATE(curthread, PS_SLEEP_WAIT); + THR_SCHED_UNLOCK(curthread, curthread); - /* - * As long as we're going to get the time of day, we - * might as well store it in the global time of day: - */ - gettimeofday((struct timeval *) &_sched_tod, NULL); - GET_CURRENT_TOD(tv); - TIMEVAL_TO_TIMESPEC(&tv, ¤t_time1); + /* Reschedule the current thread to sleep: */ + _thr_sched_switch(curthread); /* Calculate the remaining time to sleep: */ - remaining_time.tv_sec = time_to_sleep->tv_sec + current_time.tv_sec - current_time1.tv_sec; - remaining_time.tv_nsec = time_to_sleep->tv_nsec + current_time.tv_nsec - current_time1.tv_nsec; + KSE_GET_TOD(curthread->kse, &ts1); + remaining_time.tv_sec = time_to_sleep->tv_sec + + ts.tv_sec - ts1.tv_sec; + remaining_time.tv_nsec = time_to_sleep->tv_nsec + + ts.tv_nsec - ts1.tv_nsec; /* Check if the nanosecond field has underflowed: */ if (remaining_time.tv_nsec < 0) { @@ -97,9 +82,8 @@ _nanosleep(const struct timespec * time_to_sleep, remaining_time.tv_sec -= 1; remaining_time.tv_nsec += 1000000000; } - /* Check if the nanosecond field has overflowed: */ - if (remaining_time.tv_nsec >= 1000000000) { + else if (remaining_time.tv_nsec >= 1000000000) { /* Handle the overflow: */ remaining_time.tv_sec += 1; remaining_time.tv_nsec -= 1000000000; @@ -130,14 +114,15 @@ _nanosleep(const struct timespec * time_to_sleep, } int -__nanosleep(const struct timespec * time_to_sleep, struct timespec * - time_remaining) +__nanosleep(const struct timespec *time_to_sleep, + struct timespec *time_remaining) { - int ret; + struct pthread *curthread = _get_curthread(); + int ret; - _thread_enter_cancellation_point(); + _thr_enter_cancellation_point(curthread); ret = _nanosleep(time_to_sleep, time_remaining); - _thread_leave_cancellation_point(); + _thr_leave_cancellation_point(curthread); - return ret; + return (ret); } |