aboutsummaryrefslogtreecommitdiff
path: root/src/os/time.c
blob: 0f7c990e23cae6ec2a1a198aebf7278b874a3a17 (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
#include <stdint.h>
#include <stdbool.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);
}