Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-gpu
Commits
0f9a94f2
Commit
0f9a94f2
authored
Jul 12, 2011
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split mdate(), mwait(), msleep() to POSIX and Win32 files
Also implement correct run-time POSIX clock selection.
parent
78a752b6
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
281 additions
and
366 deletions
+281
-366
configure.ac
configure.ac
+10
-35
include/vlc_mtime.h
include/vlc_mtime.h
+0
-60
include/vlc_threads.h
include/vlc_threads.h
+61
-0
src/misc/mtime.c
src/misc/mtime.c
+17
-263
src/posix/thread.c
src/posix/thread.c
+154
-8
src/win32/thread.c
src/win32/thread.c
+39
-0
No files found.
configure.ac
View file @
0f9a94f2
...
@@ -566,6 +566,7 @@ dnl Check for system libs needed
...
@@ -566,6 +566,7 @@ dnl Check for system libs needed
need_libc=false
need_libc=false
dnl Check for usual libc functions
dnl Check for usual libc functions
AC_CHECK_DECLS([nanosleep],,,[#include <time.h>])
AC_CHECK_FUNCS([daemon fcntl fdopendir fstatvfs fork getenv getpwuid_r gettimeofday if_nameindex if_nametoindex isatty lstat memalign mmap openat pread posix_fadvise posix_madvise posix_memalign setlocale stricmp strnicmp uselocale])
AC_CHECK_FUNCS([daemon fcntl fdopendir fstatvfs fork getenv getpwuid_r gettimeofday if_nameindex if_nametoindex isatty lstat memalign mmap openat pread posix_fadvise posix_madvise posix_memalign setlocale stricmp strnicmp uselocale])
AC_REPLACE_FUNCS([asprintf atof atoll dirfd flockfile fsync getdelim getpid gmtime_r lldiv localtime_r nrand48 rewind setenv strcasecmp strcasestr strdup strlcpy strncasecmp strndup strnlen strsep strtof strtok_r strtoll swab tdestroy vasprintf])
AC_REPLACE_FUNCS([asprintf atof atoll dirfd flockfile fsync getdelim getpid gmtime_r lldiv localtime_r nrand48 rewind setenv strcasecmp strcasestr strdup strlcpy strncasecmp strndup strnlen strsep strtof strtok_r strtoll swab tdestroy vasprintf])
AC_CHECK_FUNCS(fdatasync,,
AC_CHECK_FUNCS(fdatasync,,
...
@@ -772,23 +773,19 @@ if test "${SYS}" != "mingw32" -a "${SYS}" != "mingwce"; then
...
@@ -772,23 +773,19 @@ if test "${SYS}" != "mingw32" -a "${SYS}" != "mingwce"; then
AC_CHECK_LIB(rt, clock_nanosleep, [
AC_CHECK_LIB(rt, clock_nanosleep, [
VLC_ADD_LIBS([libvlccore],[-lrt])
VLC_ADD_LIBS([libvlccore],[-lrt])
AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1, [Define to 1 if you have clock_nanosleep.])
], [
], [
AC_CHECK_FUNC(nanosleep,,[
AC_CHECK_LIB(rt,nanosleep, [
VLC_ADD_LIBS([libvlccore],[-lrt])
], [
AC_CHECK_LIB(posix4,nanosleep, [
VLC_ADD_LIBS([libvlccore],[-lposix4])
])
])
])
dnl HP/UX port
dnl HP/UX port
AC_CHECK_LIB(rt,sem_init, [VLC_ADD_LIBS([libvlccore],[-lrt])])
AC_CHECK_LIB(rt,sem_init, [VLC_ADD_LIBS([libvlccore],[-lrt])])
])
])
have_nanosleep=false
AC_CHECK_FUNCS(nanosleep,have_nanosleep=:,[
AC_CHECK_LIB(rt,nanosleep,
[VLC_ADD_LIBS([libvlccore],[-lrt]) have_nanosleep=:],
[AC_CHECK_LIB(posix4,nanosleep,
[VLC_ADD_LIBS([libvlccore],[-lposix4]) have_nanosleep=:])]
)
])
if ${have_nanosleep}; then
AC_DEFINE(HAVE_NANOSLEEP, 1, [Define if nanosleep is available.])
fi
fi # end "${SYS}" != "mingw32" -a "${SYS}" != "mingwce"
fi # end "${SYS}" != "mingw32" -a "${SYS}" != "mingwce"
dnl Check for misc headers
dnl Check for misc headers
...
@@ -834,28 +831,6 @@ then
...
@@ -834,28 +831,6 @@ then
fi
fi
])
])
dnl Mac OS X and other OSes don't have declaration for nanosleep
if test "${SYS}" != "mingw32" -a "${SYS}" != "mingwce"; then
AC_MSG_CHECKING(for nanosleep in time.h)
AC_EGREP_HEADER(nanosleep,time.h,[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_DECL_NANOSLEEP, 1,
Define if <time.h> defines nanosleep.)
],[
AC_MSG_RESULT(no)
])
fi # end "${SYS}" != "mingw32" -a "${SYS}" != "mingwce"
dnl Make sure we have timespecs
AC_MSG_CHECKING(for timespec in sys/time.h)
AC_EGREP_HEADER(timespec,sys/time.h,[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_STRUCT_TIMESPEC, 1,
Define if <sys/time.h> defines struct timespec.)
],[
AC_MSG_RESULT(no)
])
dnl Check for threads library
dnl Check for threads library
if test "${SYS}" != "mingw32" -a "${SYS}" != "mingwce"; then
if test "${SYS}" != "mingw32" -a "${SYS}" != "mingwce"; then
AC_CHECK_HEADERS(pthread.h)
AC_CHECK_HEADERS(pthread.h)
...
...
include/vlc_mtime.h
View file @
0f9a94f2
...
@@ -55,68 +55,8 @@
...
@@ -55,68 +55,8 @@
* Prototypes
* Prototypes
*****************************************************************************/
*****************************************************************************/
VLC_API
char
*
mstrtime
(
char
*
psz_buffer
,
mtime_t
date
);
VLC_API
char
*
mstrtime
(
char
*
psz_buffer
,
mtime_t
date
);
VLC_API
mtime_t
mdate
(
void
);
VLC_API
void
mwait
(
mtime_t
date
);
VLC_API
void
msleep
(
mtime_t
delay
);
VLC_API
char
*
secstotimestr
(
char
*
psz_buffer
,
int32_t
secs
);
VLC_API
char
*
secstotimestr
(
char
*
psz_buffer
,
int32_t
secs
);
# define VLC_HARD_MIN_SLEEP 10000
/* 10 milliseconds = 1 tick at 100Hz */
#if defined (__GNUC__) \
&& ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
/* Linux has 100, 250, 300 or 1000Hz
*
* HZ=100 by default on FreeBSD, but some architectures use a 1000Hz timer
*/
# define VLC_SOFT_MIN_SLEEP 9000000
/* 9 seconds */
static
__attribute__
((
unused
))
__attribute__
((
noinline
))
__attribute__
((
error
(
"sorry, cannot sleep for such short a time"
)))
mtime_t
impossible_delay
(
mtime_t
delay
)
{
(
void
)
delay
;
return
VLC_HARD_MIN_SLEEP
;
}
static
__attribute__
((
unused
))
__attribute__
((
noinline
))
__attribute__
((
warning
(
"use proper event handling instead of short delay"
)))
mtime_t
harmful_delay
(
mtime_t
delay
)
{
return
delay
;
}
# define check_delay( d ) \
((__builtin_constant_p(d < VLC_HARD_MIN_SLEEP) \
&& (d < VLC_HARD_MIN_SLEEP)) \
? impossible_delay(d) \
: ((__builtin_constant_p(d < VLC_SOFT_MIN_SLEEP) \
&& (d < VLC_SOFT_MIN_SLEEP)) \
? harmful_delay(d) \
: d))
static
__attribute__
((
unused
))
__attribute__
((
noinline
))
__attribute__
((
error
(
"deadlines can not be constant"
)))
mtime_t
impossible_deadline
(
mtime_t
deadline
)
{
return
deadline
;
}
# define check_deadline( d ) \
(__builtin_constant_p(d) ? impossible_deadline(d) : d)
#else
# define check_delay(d) (d)
# define check_deadline(d) (d)
#endif
#define msleep(d) msleep(check_delay(d))
#define mwait(d) mwait(check_deadline(d))
/*****************************************************************************
/*****************************************************************************
* date_t: date incrementation without long-term rounding errors
* date_t: date incrementation without long-term rounding errors
*****************************************************************************/
*****************************************************************************/
...
...
include/vlc_threads.h
View file @
0f9a94f2
...
@@ -200,6 +200,67 @@ VLC_API void vlc_cancel(vlc_thread_t);
...
@@ -200,6 +200,67 @@ VLC_API void vlc_cancel(vlc_thread_t);
VLC_API
void
vlc_join
(
vlc_thread_t
,
void
**
);
VLC_API
void
vlc_join
(
vlc_thread_t
,
void
**
);
VLC_API
void
vlc_control_cancel
(
int
cmd
,
...);
VLC_API
void
vlc_control_cancel
(
int
cmd
,
...);
VLC_API
mtime_t
mdate
(
void
);
VLC_API
void
mwait
(
mtime_t
deadline
);
VLC_API
void
msleep
(
mtime_t
delay
);
#define VLC_HARD_MIN_SLEEP 10000
/* 10 milliseconds = 1 tick at 100Hz */
#define VLC_SOFT_MIN_SLEEP 9000000
/* 9 seconds */
#if defined (__GNUC__) \
&& ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
/* Linux has 100, 250, 300 or 1000Hz
*
* HZ=100 by default on FreeBSD, but some architectures use a 1000Hz timer
*/
static
__attribute__
((
unused
))
__attribute__
((
noinline
))
__attribute__
((
error
(
"sorry, cannot sleep for such short a time"
)))
mtime_t
impossible_delay
(
mtime_t
delay
)
{
(
void
)
delay
;
return
VLC_HARD_MIN_SLEEP
;
}
static
__attribute__
((
unused
))
__attribute__
((
noinline
))
__attribute__
((
warning
(
"use proper event handling instead of short delay"
)))
mtime_t
harmful_delay
(
mtime_t
delay
)
{
return
delay
;
}
# define check_delay( d ) \
((__builtin_constant_p(d < VLC_HARD_MIN_SLEEP) \
&& (d < VLC_HARD_MIN_SLEEP)) \
? impossible_delay(d) \
: ((__builtin_constant_p(d < VLC_SOFT_MIN_SLEEP) \
&& (d < VLC_SOFT_MIN_SLEEP)) \
? harmful_delay(d) \
: d))
static
__attribute__
((
unused
))
__attribute__
((
noinline
))
__attribute__
((
error
(
"deadlines can not be constant"
)))
mtime_t
impossible_deadline
(
mtime_t
deadline
)
{
return
deadline
;
}
# define check_deadline( d ) \
(__builtin_constant_p(d) ? impossible_deadline(d) : d)
#else
# define check_delay(d) (d)
# define check_deadline(d) (d)
#endif
#define msleep(d) msleep(check_delay(d))
#define mwait(d) mwait(check_deadline(d))
VLC_API
int
vlc_timer_create
(
vlc_timer_t
*
,
void
(
*
)
(
void
*
),
void
*
)
VLC_USED
;
VLC_API
int
vlc_timer_create
(
vlc_timer_t
*
,
void
(
*
)
(
void
*
),
void
*
)
VLC_USED
;
VLC_API
void
vlc_timer_destroy
(
vlc_timer_t
);
VLC_API
void
vlc_timer_destroy
(
vlc_timer_t
);
VLC_API
void
vlc_timer_schedule
(
vlc_timer_t
,
bool
,
mtime_t
,
mtime_t
);
VLC_API
void
vlc_timer_schedule
(
vlc_timer_t
,
bool
,
mtime_t
,
mtime_t
);
...
...
src/misc/mtime.c
View file @
0f9a94f2
...
@@ -34,62 +34,16 @@
...
@@ -34,62 +34,16 @@
#endif
#endif
#include <vlc_common.h>
#include <vlc_common.h>
#include <time.h>
/* clock_gettime(), clock_nanosleep() */
#include <assert.h>
#include <assert.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
# include <unistd.h>
/* select() */
# include <unistd.h>
#endif
#ifdef HAVE_KERNEL_OS_H
# include <kernel/OS.h>
#endif
#endif
#if !defined (_POSIX_TIMERS)
#if defined( WIN32 ) || defined( UNDER_CE )
# define _POSIX_TIMERS (-1)
# include <windows.h>
# include <mmsystem.h>
#endif
#if defined(HAVE_SYS_TIME_H)
# include <sys/time.h>
# include <sys/time.h>
#endif
#else
# include <time.h>
/* clock_gettime() */
#if defined(__APPLE__) && !defined(__powerpc__) && !defined(__ppc__) && !defined(__ppc64__)
#define USE_APPLE_MACH 1
# include <mach/mach.h>
# include <mach/mach_time.h>
#endif
#if !defined(HAVE_STRUCT_TIMESPEC)
struct
timespec
{
time_t
tv_sec
;
int32_t
tv_nsec
;
};
#endif
#if defined(HAVE_NANOSLEEP) && !defined(HAVE_DECL_NANOSLEEP)
int
nanosleep
(
struct
timespec
*
,
struct
timespec
*
);
#endif
#if !defined (_POSIX_CLOCK_SELECTION)
# define _POSIX_CLOCK_SELECTION (-1)
#endif
# if (_POSIX_CLOCK_SELECTION < 0)
/*
* We cannot use the monotonic clock if clock selection is not available,
* as it would screw vlc_cond_timedwait() completely. Instead, we have to
* stick to the realtime clock. Nevermind it screws everything up when ntpdate
* warps the wall clock.
*/
# undef CLOCK_MONOTONIC
# define CLOCK_MONOTONIC CLOCK_REALTIME
#elif !defined (HAVE_CLOCK_NANOSLEEP)
/* Clock selection without clock in the first place, I don't think so. */
# error We have quite a situation here! Fix me if it ever happens.
#endif
#endif
/**
/**
...
@@ -149,211 +103,6 @@ char *secstotimestr( char *psz_buffer, int32_t i_seconds )
...
@@ -149,211 +103,6 @@ char *secstotimestr( char *psz_buffer, int32_t i_seconds )
return
psz_buffer
;
return
psz_buffer
;
}
}
#if defined (HAVE_CLOCK_NANOSLEEP)
static
unsigned
prec
=
0
;
static
void
mprec_once
(
void
)
{
struct
timespec
ts
;
if
(
clock_getres
(
CLOCK_MONOTONIC
,
&
ts
))
clock_getres
(
CLOCK_REALTIME
,
&
ts
);
prec
=
ts
.
tv_nsec
/
1000
;
}
#endif
/**
* Return a value that is no bigger than the clock precision
* (possibly zero).
*/
static
inline
unsigned
mprec
(
void
)
{
#if defined (HAVE_CLOCK_NANOSLEEP)
static
pthread_once_t
once
=
PTHREAD_ONCE_INIT
;
pthread_once
(
&
once
,
mprec_once
);
return
prec
;
#else
return
0
;
#endif
}
#ifdef USE_APPLE_MACH
static
mach_timebase_info_data_t
mtime_timebase_info
;
static
pthread_once_t
mtime_timebase_info_once
=
PTHREAD_ONCE_INIT
;
static
void
mtime_init_timebase
(
void
)
{
mach_timebase_info
(
&
mtime_timebase_info
);
}
#endif
/**
* Return high precision date
*
* Use a 1 MHz clock when possible, or 1 kHz
*
* Beware ! It doesn't reflect the actual date (since epoch), but can be the machine's uptime or anything (when monotonic clock is used)
*/
mtime_t
mdate
(
void
)
{
mtime_t
res
;
#if defined (HAVE_CLOCK_NANOSLEEP)
struct
timespec
ts
;
/* Try to use POSIX monotonic clock if available */
if
(
clock_gettime
(
CLOCK_MONOTONIC
,
&
ts
)
==
EINVAL
)
/* Run-time fallback to real-time clock (always available) */
(
void
)
clock_gettime
(
CLOCK_REALTIME
,
&
ts
);
res
=
((
mtime_t
)
ts
.
tv_sec
*
(
mtime_t
)
1000000
)
+
(
mtime_t
)(
ts
.
tv_nsec
/
1000
);
#elif defined( HAVE_KERNEL_OS_H )
res
=
real_time_clock_usecs
();
#elif defined( USE_APPLE_MACH )
pthread_once
(
&
mtime_timebase_info_once
,
mtime_init_timebase
);
uint64_t
date
=
mach_absolute_time
();
mach_timebase_info_data_t
tb
=
mtime_timebase_info
;
/* tb.denom is uint32_t, switch to 64 bits to prevent overflow. */
uint64_t
denom
=
tb
.
denom
;
/* Switch to microsecs */
denom
*=
1000LL
;
/* Split the division to prevent overflow */
lldiv_t
d
=
lldiv
(
tb
.
numer
,
denom
);
res
=
(
d
.
quot
*
date
)
+
((
d
.
rem
*
date
)
/
denom
);
#elif defined( WIN32 ) || defined( UNDER_CE )
/* We don't need the real date, just the value of a high precision timer */
LARGE_INTEGER
counter
,
freq
;
if
(
!
QueryPerformanceCounter
(
&
counter
)
||
!
QueryPerformanceFrequency
(
&
freq
))
abort
();
/* Convert to from (1/freq) to microsecond resolution */
/* We need to split the division to avoid 63-bits overflow */
lldiv_t
d
=
lldiv
(
counter
.
QuadPart
,
freq
.
QuadPart
);
res
=
(
d
.
quot
*
1000000
)
+
((
d
.
rem
*
1000000
)
/
freq
.
QuadPart
);
#else
struct
timeval
tv_date
;
/* gettimeofday() cannot fail given &tv_date is a valid address */
(
void
)
gettimeofday
(
&
tv_date
,
NULL
);
res
=
(
mtime_t
)
tv_date
.
tv_sec
*
1000000
+
(
mtime_t
)
tv_date
.
tv_usec
;
#endif
return
res
;
}
#undef mwait
/**
* Wait for a date
*
* This function uses select() and an system date function to wake up at a
* precise date. It should be used for process synchronization. If current date
* is posterior to wished date, the function returns immediately.
* \param date The date to wake up at
*/
void
mwait
(
mtime_t
date
)
{
/* If the deadline is already elapsed, or within the clock precision,
* do not even bother the system timer. */
date
-=
mprec
();
#if defined (HAVE_CLOCK_NANOSLEEP)
lldiv_t
d
=
lldiv
(
date
,
1000000
);
struct
timespec
ts
=
{
d
.
quot
,
d
.
rem
*
1000
};
int
val
;
while
(
(
val
=
clock_nanosleep
(
CLOCK_MONOTONIC
,
TIMER_ABSTIME
,
&
ts
,
NULL
)
)
==
EINTR
);
if
(
val
==
EINVAL
)
{
ts
.
tv_sec
=
d
.
quot
;
ts
.
tv_nsec
=
d
.
rem
*
1000
;
while
(
clock_nanosleep
(
CLOCK_REALTIME
,
0
,
&
ts
,
NULL
)
==
EINTR
);
}
#elif defined (WIN32)
mtime_t
i_total
;
while
(
(
i_total
=
(
date
-
mdate
()))
>
0
)
{
const
mtime_t
i_sleep
=
i_total
/
1000
;
DWORD
i_delay
=
(
i_sleep
>
0x7fffffff
)
?
0x7fffffff
:
i_sleep
;
vlc_testcancel
();
SleepEx
(
i_delay
,
TRUE
);
}
vlc_testcancel
();
#else
mtime_t
delay
=
date
-
mdate
();
if
(
delay
>
0
)
msleep
(
delay
);
#endif
}
#include "libvlc.h"
/* vlc_backtrace() */
#undef msleep
/**
* Portable usleep(). Cancellation point.
*
* \param delay the amount of time to sleep
*/
void
msleep
(
mtime_t
delay
)
{
#if defined( HAVE_CLOCK_NANOSLEEP )
lldiv_t
d
=
lldiv
(
delay
,
1000000
);
struct
timespec
ts
=
{
d
.
quot
,
d
.
rem
*
1000
};
int
val
;
while
(
(
val
=
clock_nanosleep
(
CLOCK_MONOTONIC
,
0
,
&
ts
,
&
ts
)
)
==
EINTR
);
if
(
val
==
EINVAL
)
{
ts
.
tv_sec
=
d
.
quot
;
ts
.
tv_nsec
=
d
.
rem
*
1000
;
while
(
clock_nanosleep
(
CLOCK_REALTIME
,
0
,
&
ts
,
&
ts
)
==
EINTR
);
}
#elif defined( HAVE_KERNEL_OS_H )
snooze
(
delay
);
#elif defined( WIN32 ) || defined( UNDER_CE )
mwait
(
mdate
()
+
delay
);
#elif defined( HAVE_NANOSLEEP )
struct
timespec
ts_delay
;
ts_delay
.
tv_sec
=
delay
/
1000000
;
ts_delay
.
tv_nsec
=
(
delay
%
1000000
)
*
1000
;
while
(
nanosleep
(
&
ts_delay
,
&
ts_delay
)
&&
(
errno
==
EINTR
)
);
#elif defined (USE_APPLE_MACH)
/* The version that should be used, if it was cancelable */
pthread_once
(
&
mtime_timebase_info_once
,
mtime_init_timebase
);
uint64_t
mach_time
=
delay
*
1000
*
mtime_timebase_info
.
denom
/
mtime_timebase_info
.
numer
;
mach_wait_until
(
mach_time
+
mach_absolute_time
());
#else
struct
timeval
tv_delay
;
tv_delay
.
tv_sec
=
delay
/
1000000
;
tv_delay
.
tv_usec
=
delay
%
1000000
;
/* If a signal is caught, you are screwed. Update your OS to nanosleep()
* or clock_nanosleep() if this is an issue. */
select
(
0
,
NULL
,
NULL
,
NULL
,
&
tv_delay
);
#endif
}
/*
/*
* Date management (internal and external)
* Date management (internal and external)
*/
*/
...
@@ -528,16 +277,21 @@ static int gettimeofday (struct timeval *tv, void *tz )
...
@@ -528,16 +277,21 @@ static int gettimeofday (struct timeval *tv, void *tz )
*/
*/
uint64_t
NTPtime64
(
void
)
uint64_t
NTPtime64
(
void
)
{
{
#if (_POSIX_TIMERS > 0)
struct
timespec
ts
;
struct
timespec
ts
;
#if defined (CLOCK_REALTIME) && !defined (__OS2__)
clock_gettime
(
CLOCK_REALTIME
,
&
ts
);
clock_gettime
(
CLOCK_REALTIME
,
&
ts
);
#else
#else
{
struct
timeval
tv
;
struct
timeval
tv
;
struct
{
uint32_t
tv_sec
;
uint32_t
tv_nsec
;
}
ts
;
gettimeofday
(
&
tv
,
NULL
);
gettimeofday
(
&
tv
,
NULL
);
ts
.
tv_sec
=
tv
.
tv_sec
;
ts
.
tv_sec
=
tv
.
tv_sec
;
ts
.
tv_nsec
=
tv
.
tv_usec
*
1000
;
ts
.
tv_nsec
=
tv
.
tv_usec
*
1000
;
}
#endif
#endif
/* Convert nanoseconds to 32-bits fraction (232 picosecond units) */
/* Convert nanoseconds to 32-bits fraction (232 picosecond units) */
...
...
src/posix/thread.c
View file @
0f9a94f2
...
@@ -37,6 +37,7 @@
...
@@ -37,6 +37,7 @@
#include <unistd.h>
/* fsync() */
#include <unistd.h>
/* fsync() */
#include <signal.h>
#include <signal.h>
#include <errno.h>
#include <errno.h>
#include <time.h>
#include <sched.h>
#include <sched.h>
#ifdef __linux__
#ifdef __linux__
...
@@ -66,6 +67,74 @@
...
@@ -66,6 +67,74 @@
# include <sys/pset.h>
# include <sys/pset.h>
#endif
#endif
#if !defined (_POSIX_TIMERS)
# define _POSIX_TIMERS (-1)
#endif
#if !defined (_POSIX_CLOCK_SELECTION)
/* Clock selection was defined in 2001 and became mandatory in 2008. */
# define _POSIX_CLOCK_SELECTION (-1)
#endif
#if !defined (_POSIX_MONOTONIC_CLOCK)
# define _POSIX_MONOTONIC_CLOCK (-1)
#endif
#if (_POSIX_TIMERS > 0)
static
unsigned
vlc_clock_prec
;
# if (_POSIX_CLOCK_SELECTION > 0)
/* POSIX clock selection is needed so that vlc_cond_timewait() is consistent
* with mdate() and mwait(). Otherwise, the monotonic clock cannot be used.
* Fortunately, clock selection has become mandatory as of 2008 so that really
* only broken old systems still lack it. */
# if (_POSIX_MONOTONIC_CLOCK > 0)
/* Compile-time POSIX monotonic clock support */
# define vlc_clock_id (CLOCK_MONOTONIC)
# elif (_POSIX_MONOTONIC_CLOCK == 0)
/* Run-time POSIX monotonic clock support (see clock_setup() below) */
static
clockid_t
vlc_clock_id
;
# else
/* No POSIX monotonic clock support */
# define vlc_clock_id (CLOCK_REALTIME)
# warning Monotonic clock not available. Expect timing issues.
# endif
/* _POSIX_MONOTONIC_CLOKC */
# else
/* No POSIX clock selection. */
# define pthread_condattr_setclock(attr, clock) (attr, clock, 0)
# warning Clock selection not available. Expect timing issues.
# endif
/* _POSIX_CLOCK_SELECTION */
static
void
vlc_clock_setup_once
(
void
)
{
# if (_POSIX_MONOTONIC_CLOCK == 0)
long
val
=
sysconf
(
_SC_MONOTONIC_CLOCK
);
assert
(
val
!=
0
);
vlc_clock_id
=
(
val
<
0
)
?
CLOCK_REALTIME
:
CLOCK_MONOTONIC
;
# endif
struct
timespec
res
;
if
(
unlikely
(
clock_getres
(
vlc_clock_id
,
&
res
)
!=
0
||
res
.
tv_sec
!=
0
))
abort
();
vlc_clock_prec
=
(
res
.
tv_nsec
+
500
)
/
1000
;
}
static
pthread_once_t
vlc_clock_once
=
PTHREAD_ONCE_INIT
;
# define vlc_clock_setup() \
pthread_once(&vlc_clock_once, vlc_clock_setup_once)
#else
/* _POSIX_TIMERS */
# include <sys/time.h>
/* gettimeofday() */
# if defined (HAVE_DECL_NANOSLEEP) && !HAVE_DECL_NANOSLEEP
int
nanosleep
(
struct
timespec
*
,
struct
timespec
*
);
# endif
#endif
/* _POSIX_TIMERS */
/**
/**
* Print a backtrace to the standard error for debugging purpose.
* Print a backtrace to the standard error for debugging purpose.
...
@@ -280,16 +349,10 @@ void vlc_cond_init (vlc_cond_t *p_condvar)
...
@@ -280,16 +349,10 @@ void vlc_cond_init (vlc_cond_t *p_condvar)
{
{
pthread_condattr_t
attr
;
pthread_condattr_t
attr
;
vlc_clock_setup
();
if
(
unlikely
(
pthread_condattr_init
(
&
attr
)))
if
(
unlikely
(
pthread_condattr_init
(
&
attr
)))
abort
();
abort
();
#if !defined (_POSIX_CLOCK_SELECTION)
pthread_condattr_setclock
(
&
attr
,
vlc_clock_id
);
/* Fairly outdated POSIX support (that was defined in 2001) */
# define _POSIX_CLOCK_SELECTION (-1)
#endif
#if (_POSIX_CLOCK_SELECTION >= 0)
/* NOTE: This must be the same clock as the one in mtime.c */
pthread_condattr_setclock
(
&
attr
,
CLOCK_MONOTONIC
);
#endif
if
(
unlikely
(
pthread_cond_init
(
p_condvar
,
&
attr
)))
if
(
unlikely
(
pthread_cond_init
(
p_condvar
,
&
attr
)))
abort
();
abort
();
...
@@ -863,6 +926,89 @@ void vlc_control_cancel (int cmd, ...)
...
@@ -863,6 +926,89 @@ void vlc_control_cancel (int cmd, ...)
assert
(
0
);
assert
(
0
);
}
}
/**
* Precision monotonic clock.
*
* In principles, the clock has a precision of 1 MHz. But the actual resolution
* may be much lower, especially when it comes to sleeping with mwait() or
* msleep(). Most general-purpose operating systems provide a resolution of
* only 100 to 1000 Hz.
*
* @warning The origin date (time value "zero") is not specified. It is
* typically the time the kernel started, but this is platform-dependent.
* If you need wall clock time, use gettimeofday() instead.
*
* @return a timestamp in microseconds.
*/
mtime_t
mdate
(
void
)
{
#if (_POSIX_TIMERS > 0)
struct
timespec
ts
;
vlc_clock_setup
();
if
(
unlikely
(
clock_gettime
(
vlc_clock_id
,
&
ts
)
!=
0
))
abort
();
return
(
INT64_C
(
1000000
)
*
ts
.
tv_sec
)
+
(
ts
.
tv_nsec
/
1000
);
#else
struct
timeval
tv
;
if
(
unlikely
(
gettimeofday
(
&
tv
,
NULL
)
!=
0
))
abort
();
return
(
INT64_C
(
1000000
)
*
tv
.
tv_sec
)
+
tv
.
tv_nsec
;
#endif
}
#undef mwait
/**
* Waits until a deadline (possibly later due to OS scheduling).
* @param deadline timestamp to wait for (see mdate())
*/
void
mwait
(
mtime_t
deadline
)
{
#if (_POSIX_TIMERS > 0)
vlc_clock_setup
();
/* If the deadline is already elapsed, or within the clock precision,
* do not even bother the system timer. */
deadline
-=
vlc_clock_prec
;
lldiv_t
d
=
lldiv
(
deadline
,
1000000
);
struct
timespec
ts
=
{
d
.
quot
,
d
.
rem
*
1000
};
while
(
clock_nanosleep
(
vlc_clock_id
,
TIMER_ABSTIME
,
&
ts
,
NULL
)
==
EINTR
);
#else
deadline
-=
mdate
();
if
(
deadline
>
0
)
msleep
(
deadline
);
#endif
}
#undef msleep
/**
* Waits for an interval of time.
* @param delay how long to wait (in microseconds)
*/
void
msleep
(
mtime_t
delay
)
{
vlc_clock_setup
();
lldiv_t
d
=
lldiv
(
delay
,
1000000
);
struct
timespec
ts
=
{
d
.
quot
,
d
.
rem
*
1000
};
#if (_POSIX_TIMERS > 0)
while
(
clock_nanosleep
(
vlc_clock_id
,
0
,
&
ts
,
&
ts
)
==
EINTR
);
#else
while
(
nanosleep
(
&
ts
,
&
ts
)
==
-
1
)
assert
(
errno
==
EINTR
);
#endif
}
struct
vlc_timer
struct
vlc_timer
{
{
...
...
src/win32/thread.c
View file @
0f9a94f2
...
@@ -778,6 +778,45 @@ void vlc_control_cancel (int cmd, ...)
...
@@ -778,6 +778,45 @@ void vlc_control_cancel (int cmd, ...)
}
}
/*** Clock ***/
mtime_t
mdate
(
void
)
{
/* We don't need the real date, just the value of a high precision timer */
LARGE_INTEGER
counter
,
freq
;
if
(
!
QueryPerformanceCounter
(
&
counter
)
||
!
QueryPerformanceFrequency
(
&
freq
))
abort
();
/* Convert to from (1/freq) to microsecond resolution */
/* We need to split the division to avoid 63-bits overflow */
lldiv_t
d
=
lldiv
(
counter
.
QuadPart
,
freq
.
QuadPart
);
return
(
d
.
quot
*
1000000
)
+
((
d
.
rem
*
1000000
)
/
freq
.
QuadPart
);
}
#undef mwait
void
mwait
(
mtime_t
deadline
)
{
mtime_t
delay
;
vlc_testcancel
();
while
((
delay
=
(
deadline
-
mdate
()))
>
0
)
{
delay
/=
1000
;
if
(
unlikely
(
delay
>
0x7fffffff
))
delay
=
0x7fffffff
;
SleepEx
(
delay
,
TRUE
);
vlc_testcancel
();
}
}
#undef msleep
void
msleep
(
mtime_t
delay
)
{
mwait
(
mdate
()
+
delay
);
}
/*** Timers ***/
/*** Timers ***/
struct
vlc_timer
struct
vlc_timer
{
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment