aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/time.c
blob: 1dc7ca68d4783315893d12b2c9816f3212130fa5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <stdint.h>
#include <stdbool.h>
#include <sys/time.h>

#include <uv.h>

#include "os/time.h"
#include "vim.h"
#include "term.h"

static uv_mutex_t delay_mutex;
static uv_cond_t delay_cond;

static void microdelay(uint64_t ms);

void time_init()
{
  uv_mutex_init(&delay_mutex);
  uv_cond_init(&delay_cond);
}

void os_delay(uint64_t milliseconds, bool ignoreinput)
{
  os_microdelay(milliseconds * 1000, ignoreinput);
}

void os_microdelay(uint64_t microseconds, bool ignoreinput)
{
  int old_tmode;

  if (ignoreinput) {
    // Go to cooked mode without echo, to allow SIGINT interrupting us
    // here
    old_tmode = curr_tmode;

    if (curr_tmode == TMODE_RAW)
      settmode(TMODE_SLEEP);

    microdelay(microseconds);

    settmode(old_tmode);
  } else {
    microdelay(microseconds);
  }
}

static void microdelay(uint64_t microseconds)
{
  uint64_t hrtime;
  int64_t ns = microseconds * 1000;  // convert to nanoseconds

  uv_mutex_lock(&delay_mutex);

  while (ns > 0) {
    hrtime =  uv_hrtime();
    if (uv_cond_timedwait(&delay_cond, &delay_mutex, ns) == UV_ETIMEDOUT)
      break;
    ns -= uv_hrtime() - hrtime;
  }

  uv_mutex_unlock(&delay_mutex);
}

struct tm *os_localtime_r(const time_t *clock, struct tm *result)
{
#ifdef UNIX
  // POSIX provides localtime_r() as a thread-safe version of localtime().
  return localtime_r(clock, result);
#else
  // Windows version of localtime() is thread-safe.
  // See http://msdn.microsoft.com/en-us/library/bf12f0hc%28VS.80%29.aspx
  struct tm *local_time = localtime(clock);  // NOLINT
  *result = *local_time;
return result;
#endif
}

struct tm *os_get_localtime(struct tm *result)
{
  struct timeval tv;
  if (gettimeofday(&tv, NULL) < 0) {
    return NULL;
  }

  return os_localtime_r(&tv.tv_sec, result);
}