src/timer/unix/SDL_systimer.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 10 Mar 2014 05:44:34 -0700
changeset 8595 c6fc94639f38
parent 8268 3f8410f20405
child 8879 f6e4f24df1ac
permissions -rw-r--r--
Implemented YV12 and IYUV texture support for the D3D11 renderer
slouken@1361
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@1361
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1361
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1361
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1361
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@1361
    22
slouken@1635
    23
#ifdef SDL_TIMER_UNIX
slouken@1635
    24
slouken@1361
    25
#include <stdio.h>
slouken@1361
    26
#include <sys/time.h>
slouken@1361
    27
#include <unistd.h>
slouken@1361
    28
#include <errno.h>
slouken@1361
    29
slouken@1361
    30
#include "SDL_timer.h"
slouken@1361
    31
slouken@1361
    32
/* The clock_gettime provides monotonous time, so we should use it if
slouken@1361
    33
   it's available. The clock_gettime function is behind ifdef
slouken@1361
    34
   for __USE_POSIX199309
slouken@1361
    35
   Tommi Kyntola (tommi.kyntola@ray.fi) 27/09/2005
slouken@1361
    36
*/
urkle@7137
    37
/* Reworked monotonic clock to not assume the current system has one
urkle@7137
    38
   as not all linux kernels provide a monotonic clock (yeah recent ones
urkle@7137
    39
   probably do)
urkle@7137
    40
   Also added OS X Monotonic clock support
urkle@7137
    41
   Based on work in https://github.com/ThomasHabets/monotonic_clock
urkle@7137
    42
 */
slouken@1598
    43
#if HAVE_NANOSLEEP || HAVE_CLOCK_GETTIME
slouken@1361
    44
#include <time.h>
slouken@1361
    45
#endif
urkle@7137
    46
#ifdef __APPLE__
urkle@7137
    47
#include <mach/mach_time.h>
urkle@7137
    48
#endif
slouken@1361
    49
slouken@1361
    50
/* The first ticks value of the application */
urkle@7137
    51
#if HAVE_CLOCK_GETTIME
urkle@7137
    52
static struct timespec start_ts;
urkle@7137
    53
#elif defined(__APPLE__)
urkle@7137
    54
static uint64_t start_mach;
urkle@7137
    55
mach_timebase_info_data_t mach_base_info;
urkle@7137
    56
#endif
urkle@7137
    57
static SDL_bool has_monotonic_time = SDL_FALSE;
urkle@7137
    58
static struct timeval start_tv;
urkle@7649
    59
static SDL_bool ticks_started = SDL_FALSE;
slouken@1361
    60
slouken@1895
    61
void
slouken@8268
    62
SDL_TicksInit(void)
slouken@1361
    63
{
urkle@7649
    64
    if (ticks_started) {
urkle@7649
    65
        return;
urkle@7649
    66
    }
urkle@7649
    67
    ticks_started = SDL_TRUE;
urkle@7649
    68
slouken@1895
    69
    /* Set first ticks value */
slouken@1361
    70
#if HAVE_CLOCK_GETTIME
urkle@7137
    71
    if (clock_gettime(CLOCK_MONOTONIC, &start_ts) == 0) {
urkle@7137
    72
        has_monotonic_time = SDL_TRUE;
urkle@7137
    73
    } else
urkle@7137
    74
#elif defined(__APPLE__)
urkle@7137
    75
    kern_return_t ret = mach_timebase_info(&mach_base_info);
urkle@7137
    76
    if (ret == 0) {
urkle@7137
    77
        has_monotonic_time = SDL_TRUE;
slouken@7316
    78
        start_mach = mach_absolute_time();
urkle@7137
    79
    } else
slouken@1361
    80
#endif
urkle@7137
    81
    {
urkle@7137
    82
        gettimeofday(&start_tv, NULL);
urkle@7137
    83
    }
slouken@1361
    84
}
slouken@1361
    85
slouken@8268
    86
void
slouken@8268
    87
SDL_TicksQuit(void)
slouken@8268
    88
{
slouken@8268
    89
    ticks_started = SDL_FALSE;
slouken@8268
    90
}
slouken@8268
    91
slouken@1895
    92
Uint32
slouken@1895
    93
SDL_GetTicks(void)
slouken@1361
    94
{
gabomdq@7679
    95
    Uint32 ticks;
urkle@7649
    96
    if (!ticks_started) {
slouken@8268
    97
        SDL_TicksInit();
urkle@7649
    98
    }
urkle@7649
    99
urkle@7137
   100
    if (has_monotonic_time) {
slouken@1361
   101
#if HAVE_CLOCK_GETTIME
urkle@7137
   102
        struct timespec now;
urkle@7137
   103
        clock_gettime(CLOCK_MONOTONIC, &now);
slouken@7316
   104
        ticks = (now.tv_sec - start_ts.tv_sec) * 1000 + (now.tv_nsec -
urkle@7137
   105
                                                 start_ts.tv_nsec) / 1000000;
urkle@7137
   106
#elif defined(__APPLE__)
urkle@7137
   107
        uint64_t now = mach_absolute_time();
slouken@7316
   108
        ticks = (((now - start_mach) * mach_base_info.numer) / mach_base_info.denom) / 1000000;
urkle@7137
   109
#endif
urkle@7137
   110
    } else {
urkle@7137
   111
        struct timeval now;
slouken@5514
   112
urkle@7137
   113
        gettimeofday(&now, NULL);
urkle@7137
   114
        ticks =
urkle@7137
   115
            (now.tv_sec - start_tv.tv_sec) * 1000 + (now.tv_usec -
urkle@7137
   116
                                                  start_tv.tv_usec) / 1000;
urkle@7137
   117
    }
slouken@1895
   118
    return (ticks);
slouken@1361
   119
}
slouken@1361
   120
slouken@5514
   121
Uint64
slouken@5514
   122
SDL_GetPerformanceCounter(void)
slouken@5514
   123
{
gabomdq@7679
   124
    Uint64 ticks;
urkle@7649
   125
    if (!ticks_started) {
slouken@8268
   126
        SDL_TicksInit();
urkle@7649
   127
    }
urkle@7649
   128
urkle@7137
   129
    if (has_monotonic_time) {
slouken@5514
   130
#if HAVE_CLOCK_GETTIME
urkle@7137
   131
        struct timespec now;
slouken@5514
   132
urkle@7137
   133
        clock_gettime(CLOCK_MONOTONIC, &now);
urkle@7137
   134
        ticks = now.tv_sec;
urkle@7137
   135
        ticks *= 1000000000;
urkle@7137
   136
        ticks += now.tv_nsec;
urkle@7137
   137
#elif defined(__APPLE__)
urkle@7137
   138
        ticks = mach_absolute_time();
urkle@7137
   139
#endif
urkle@7137
   140
    } else {
urkle@7137
   141
        struct timeval now;
urkle@7137
   142
urkle@7137
   143
        gettimeofday(&now, NULL);
urkle@7137
   144
        ticks = now.tv_sec;
urkle@7137
   145
        ticks *= 1000000;
urkle@7137
   146
        ticks += now.tv_usec;
urkle@7137
   147
    }
slouken@5514
   148
    return (ticks);
slouken@5514
   149
}
slouken@5514
   150
slouken@5514
   151
Uint64
slouken@5514
   152
SDL_GetPerformanceFrequency(void)
slouken@5514
   153
{
urkle@7649
   154
    if (!ticks_started) {
slouken@8268
   155
        SDL_TicksInit();
urkle@7649
   156
    }
urkle@7649
   157
urkle@7137
   158
    if (has_monotonic_time) {
slouken@5514
   159
#if HAVE_CLOCK_GETTIME
urkle@7137
   160
        return 1000000000;
urkle@7137
   161
#elif defined(__APPLE__)
slouken@7628
   162
        Uint64 freq = mach_base_info.denom;
slouken@7316
   163
        freq *= 1000000000;
slouken@7628
   164
        freq /= mach_base_info.numer;
slouken@7316
   165
        return freq;
slouken@5514
   166
#endif
gabomdq@7722
   167
    } 
gabomdq@7722
   168
        
gabomdq@7722
   169
    return 1000000;
slouken@5514
   170
}
slouken@5514
   171
slouken@1895
   172
void
slouken@1895
   173
SDL_Delay(Uint32 ms)
slouken@1361
   174
{
slouken@1895
   175
    int was_error;
slouken@1361
   176
slouken@1361
   177
#if HAVE_NANOSLEEP
slouken@1895
   178
    struct timespec elapsed, tv;
slouken@1361
   179
#else
slouken@1895
   180
    struct timeval tv;
slouken@1895
   181
    Uint32 then, now, elapsed;
slouken@1361
   182
#endif
slouken@1361
   183
slouken@1895
   184
    /* Set the timeout interval */
slouken@1361
   185
#if HAVE_NANOSLEEP
slouken@1895
   186
    elapsed.tv_sec = ms / 1000;
slouken@1895
   187
    elapsed.tv_nsec = (ms % 1000) * 1000000;
slouken@1361
   188
#else
slouken@1895
   189
    then = SDL_GetTicks();
slouken@1361
   190
#endif
slouken@1895
   191
    do {
slouken@1895
   192
        errno = 0;
slouken@1361
   193
slouken@1361
   194
#if HAVE_NANOSLEEP
slouken@1895
   195
        tv.tv_sec = elapsed.tv_sec;
slouken@1895
   196
        tv.tv_nsec = elapsed.tv_nsec;
slouken@1895
   197
        was_error = nanosleep(&tv, &elapsed);
slouken@1361
   198
#else
slouken@1895
   199
        /* Calculate the time interval left (in case of interrupt) */
slouken@1895
   200
        now = SDL_GetTicks();
slouken@1895
   201
        elapsed = (now - then);
slouken@1895
   202
        then = now;
slouken@1895
   203
        if (elapsed >= ms) {
slouken@1895
   204
            break;
slouken@1895
   205
        }
slouken@1895
   206
        ms -= elapsed;
slouken@1895
   207
        tv.tv_sec = ms / 1000;
slouken@1895
   208
        tv.tv_usec = (ms % 1000) * 1000;
slouken@1361
   209
slouken@1895
   210
        was_error = select(0, NULL, NULL, NULL, &tv);
slouken@1361
   211
#endif /* HAVE_NANOSLEEP */
slouken@2735
   212
    } while (was_error && (errno == EINTR));
slouken@1361
   213
}
slouken@1361
   214
slouken@5111
   215
#endif /* SDL_TIMER_UNIX */
slouken@1361
   216
slouken@1895
   217
/* vi: set ts=4 sw=4 expandtab: */