Add clock_nanosleep(2).
This commit is contained in:
parent
1e2550c0d5
commit
71a2fef5f6
|
@ -354,8 +354,10 @@ tfork.o \
|
||||||
time/clock_getres.o \
|
time/clock_getres.o \
|
||||||
time/clock_gettime.o \
|
time/clock_gettime.o \
|
||||||
time/clock_gettimeres.o \
|
time/clock_gettimeres.o \
|
||||||
|
time/clock_nanosleep.o \
|
||||||
time/clock_settime.o \
|
time/clock_settime.o \
|
||||||
time/clock_settimeres.o \
|
time/clock_settimeres.o \
|
||||||
|
time/nanosleep.o \
|
||||||
time/time.o \
|
time/time.o \
|
||||||
time/timer_create.o \
|
time/timer_create.o \
|
||||||
time/timer_delete.o \
|
time/timer_delete.o \
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2013.
|
||||||
|
|
||||||
This file is part of the Sortix C Library.
|
This file is part of the Sortix C Library.
|
||||||
|
|
||||||
|
@ -22,13 +22,15 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <sys/syscall.h>
|
#include <time.h>
|
||||||
|
#include <timespec.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
DEFN_SYSCALL1(int, SysSleep, SYSCALL_SLEEP, long);
|
|
||||||
|
|
||||||
extern "C" unsigned sleep(unsigned secs)
|
extern "C" unsigned sleep(unsigned secs)
|
||||||
{
|
{
|
||||||
SysSleep(secs);
|
struct timespec delay = timespec_make(secs, 0);
|
||||||
|
struct timespec left;
|
||||||
|
if ( nanosleep(&delay, &left) < 0 )
|
||||||
|
return left.tv_sec + (left.tv_nsec ? 1 : 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2013.
|
||||||
|
|
||||||
|
This file is part of the Sortix C Library.
|
||||||
|
|
||||||
|
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
time/clock_nanosleep.cpp
|
||||||
|
Sleep for a duration on a clock.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
DEFN_SYSCALL4(int, sys_clock_nanosleep, SYSCALL_CLOCK_NANOSLEEP, clockid_t,
|
||||||
|
int, const struct timespec*, struct timespec*);
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
int clock_nanosleep(clockid_t clockid, int flags,
|
||||||
|
const struct timespec* duration, struct timespec* remainder)
|
||||||
|
{
|
||||||
|
return sys_clock_nanosleep(clockid, flags, duration, remainder);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2013.
|
||||||
|
|
||||||
|
This file is part of the Sortix C Library.
|
||||||
|
|
||||||
|
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
time/nanosleep.cpp
|
||||||
|
Sleep for a duration.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
extern "C" int nanosleep(const struct timespec* delay, struct timespec* left)
|
||||||
|
{
|
||||||
|
// NOTE: POSIX specifies that we should nanosleep on CLOCK_REALTIME, but it
|
||||||
|
// makes more sense to sleep on the monotonic system clock. Futhermore
|
||||||
|
// Linux does this as well and users probably won't notice.
|
||||||
|
return clock_nanosleep(CLOCK_MONOTONIC, 0, delay, left);
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2013.
|
||||||
|
|
||||||
This file is part of the Sortix C Library.
|
This file is part of the Sortix C Library.
|
||||||
|
|
||||||
|
@ -18,17 +18,16 @@
|
||||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
usleep.cpp
|
usleep.cpp
|
||||||
Blocks the current thread for for at least N micro seconds.
|
Blocks the current thread for for at least N microseconds.
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <sys/syscall.h>
|
#include <time.h>
|
||||||
|
#include <timespec.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
DEFN_SYSCALL1(int, SysUSleep, SYSCALL_USLEEP, long);
|
|
||||||
|
|
||||||
extern "C" int usleep(useconds_t usecs)
|
extern "C" int usleep(useconds_t usecs)
|
||||||
{
|
{
|
||||||
SysUSleep(usecs);
|
struct timespec delay = timespec_canonalize(timespec_make(0, usecs * 1000));
|
||||||
return 0;
|
return nanosleep(&delay, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include <sortix/kernel/timer.h>
|
#include <sortix/kernel/timer.h>
|
||||||
#include <sortix/kernel/worker.h>
|
#include <sortix/kernel/worker.h>
|
||||||
|
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
|
||||||
Clock::Clock()
|
Clock::Clock()
|
||||||
|
@ -39,6 +41,7 @@ Clock::Clock()
|
||||||
delay_timer = NULL;
|
delay_timer = NULL;
|
||||||
absolute_timer = NULL;
|
absolute_timer = NULL;
|
||||||
current_time = timespec_nul();
|
current_time = timespec_nul();
|
||||||
|
current_advancement = timespec_nul();
|
||||||
resolution = timespec_nul();
|
resolution = timespec_nul();
|
||||||
clock_mutex = KTHREAD_MUTEX_INITIALIZER;
|
clock_mutex = KTHREAD_MUTEX_INITIALIZER;
|
||||||
clock_callable_from_interrupt = false;
|
clock_callable_from_interrupt = false;
|
||||||
|
@ -233,11 +236,66 @@ void Clock::Cancel(Timer* timer)
|
||||||
UnlockClock();
|
UnlockClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: We need some method for threads to sleep for real but still be
|
||||||
|
// interrupted by signals.
|
||||||
|
struct timespec Clock::SleepDelay(struct timespec duration)
|
||||||
|
{
|
||||||
|
struct timespec start_advancement;
|
||||||
|
struct timespec elapsed = timespec_nul();
|
||||||
|
bool start_advancement_set = false;
|
||||||
|
|
||||||
|
while ( timespec_lt(elapsed, duration) )
|
||||||
|
{
|
||||||
|
if ( start_advancement_set )
|
||||||
|
{
|
||||||
|
if ( Signal::IsPending() )
|
||||||
|
return duration;
|
||||||
|
|
||||||
|
kthread_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
LockClock();
|
||||||
|
|
||||||
|
if ( !start_advancement_set )
|
||||||
|
start_advancement = current_advancement,
|
||||||
|
start_advancement_set = true;
|
||||||
|
|
||||||
|
elapsed = timespec_sub(current_advancement, start_advancement);
|
||||||
|
|
||||||
|
UnlockClock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return timespec_nul();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: We need some method for threads to sleep for real but still be
|
||||||
|
// interrupted by signals.
|
||||||
|
struct timespec Clock::SleepUntil(struct timespec expiration)
|
||||||
|
{
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
LockClock();
|
||||||
|
struct timespec now = current_time;
|
||||||
|
UnlockClock();
|
||||||
|
|
||||||
|
if ( timespec_le(now, expiration) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( Signal::IsPending() )
|
||||||
|
return timespec_sub(expiration, now);
|
||||||
|
|
||||||
|
kthread_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
return timespec_nul();
|
||||||
|
}
|
||||||
|
|
||||||
void Clock::Advance(struct timespec duration)
|
void Clock::Advance(struct timespec duration)
|
||||||
{
|
{
|
||||||
LockClock();
|
LockClock();
|
||||||
|
|
||||||
current_time = timespec_add(current_time, duration);
|
current_time = timespec_add(current_time, duration);
|
||||||
|
current_advancement = timespec_add(current_advancement, duration);
|
||||||
TriggerDelay(duration);
|
TriggerDelay(duration);
|
||||||
TriggerAbsolute();
|
TriggerAbsolute();
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
Timer* delay_timer;
|
Timer* delay_timer;
|
||||||
Timer* absolute_timer;
|
Timer* absolute_timer;
|
||||||
struct timespec current_time;
|
struct timespec current_time;
|
||||||
|
struct timespec current_advancement;
|
||||||
struct timespec resolution;
|
struct timespec resolution;
|
||||||
kthread_mutex_t clock_mutex;
|
kthread_mutex_t clock_mutex;
|
||||||
bool clock_callable_from_interrupt;
|
bool clock_callable_from_interrupt;
|
||||||
|
@ -61,6 +62,8 @@ public:
|
||||||
void Cancel(Timer* timer);
|
void Cancel(Timer* timer);
|
||||||
void LockClock();
|
void LockClock();
|
||||||
void UnlockClock();
|
void UnlockClock();
|
||||||
|
struct timespec SleepDelay(struct timespec duration);
|
||||||
|
struct timespec SleepUntil(struct timespec expiration);
|
||||||
|
|
||||||
public: // These should only be called if the clock is locked.
|
public: // These should only be called if the clock is locked.
|
||||||
void RegisterAbsolute(Timer* timer);
|
void RegisterAbsolute(Timer* timer);
|
||||||
|
|
|
@ -126,6 +126,7 @@
|
||||||
#define SYSCALL_ALARMNS 102
|
#define SYSCALL_ALARMNS 102
|
||||||
#define SYSCALL_CLOCK_GETTIMERES 103
|
#define SYSCALL_CLOCK_GETTIMERES 103
|
||||||
#define SYSCALL_CLOCK_SETTIMERES 104
|
#define SYSCALL_CLOCK_SETTIMERES 104
|
||||||
#define SYSCALL_MAX_NUM 105 /* index of highest constant + 1 */
|
#define SYSCALL_CLOCK_NANOSLEEP 105
|
||||||
|
#define SYSCALL_MAX_NUM 106 /* index of highest constant + 1 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -278,6 +278,7 @@ static void SleepUntil(struct timespec wakeat)
|
||||||
Yield();
|
Yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This function has been obsoleted by the clock_nanosleep system call.
|
||||||
int sys_sleep(size_t secs)
|
int sys_sleep(size_t secs)
|
||||||
{
|
{
|
||||||
struct timespec delay = timespec_make(secs, 0);
|
struct timespec delay = timespec_make(secs, 0);
|
||||||
|
@ -286,6 +287,7 @@ int sys_sleep(size_t secs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This function has been obsoleted by the clock_nanosleep system call.
|
||||||
int sys_usleep(size_t usecs)
|
int sys_usleep(size_t usecs)
|
||||||
{
|
{
|
||||||
size_t secs = usecs / 1000000;
|
size_t secs = usecs / 1000000;
|
||||||
|
|
|
@ -242,6 +242,28 @@ static int sys_clock_settimeres(clockid_t clockid, const struct timespec* time,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sys_clock_nanosleep(clockid_t clockid, int flags,
|
||||||
|
const struct timespec* user_duration,
|
||||||
|
struct timespec* user_remainder)
|
||||||
|
{
|
||||||
|
struct timespec time;
|
||||||
|
|
||||||
|
Clock* clock = Time::GetClock(clockid);
|
||||||
|
if ( !clock )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ( !CopyFromUser(&time, user_duration, sizeof(time)) )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
time = flags & TIMER_ABSTIME ? clock->SleepUntil(time) :
|
||||||
|
clock->SleepDelay(time);
|
||||||
|
|
||||||
|
if ( user_remainder && !CopyToUser(user_remainder, &time, sizeof(time)) )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return timespec_eq(time, timespec_nul()) ? 0 : (errno = EINTR, -1);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Made obsolete by cloc_gettimeres.
|
// TODO: Made obsolete by cloc_gettimeres.
|
||||||
static int sys_uptime(uintmax_t* usecssinceboot)
|
static int sys_uptime(uintmax_t* usecssinceboot)
|
||||||
{
|
{
|
||||||
|
@ -260,6 +282,7 @@ void UserTimer::Init()
|
||||||
{
|
{
|
||||||
Syscall::Register(SYSCALL_CLOCK_GETTIMERES, (void*) sys_clock_gettimeres);
|
Syscall::Register(SYSCALL_CLOCK_GETTIMERES, (void*) sys_clock_gettimeres);
|
||||||
Syscall::Register(SYSCALL_CLOCK_SETTIMERES, (void*) sys_clock_settimeres);
|
Syscall::Register(SYSCALL_CLOCK_SETTIMERES, (void*) sys_clock_settimeres);
|
||||||
|
Syscall::Register(SYSCALL_CLOCK_NANOSLEEP, (void*) sys_clock_nanosleep);
|
||||||
Syscall::Register(SYSCALL_TIMER_CREATE, (void*) sys_timer_create);
|
Syscall::Register(SYSCALL_TIMER_CREATE, (void*) sys_timer_create);
|
||||||
Syscall::Register(SYSCALL_TIMER_DELETE, (void*) sys_timer_delete);
|
Syscall::Register(SYSCALL_TIMER_DELETE, (void*) sys_timer_delete);
|
||||||
Syscall::Register(SYSCALL_TIMER_GETOVERRUN, (void*) sys_timer_getoverrun);
|
Syscall::Register(SYSCALL_TIMER_GETOVERRUN, (void*) sys_timer_getoverrun);
|
||||||
|
|
Loading…
Reference in New Issue