Introduce a clock type field onto gpr_timespec.

Use it to validate that arithmetic on time types makes even some vague
kind of sense.
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index f890f99..10e01eb 100644
--- a/src/core/channel/client_channel.c
+++ b/src/core/channel/client_channel.c
@@ -132,7 +132,7 @@
     mdb.list.head = &calld->status;
     mdb.list.tail = &calld->details;
     mdb.garbage.head = mdb.garbage.tail = NULL;
-    mdb.deadline = gpr_inf_future;
+    mdb.deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
     grpc_sopb_add_metadata(op->recv_ops, mdb);
     *op->recv_state = GRPC_STREAM_CLOSED;
     op->on_done_recv->cb(op->on_done_recv->cb_arg, 1);
@@ -518,7 +518,7 @@
   gpr_mu_init(&calld->mu_state);
   calld->elem = elem;
   calld->state = CALL_CREATED;
-  calld->deadline = gpr_inf_future;
+  calld->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
 }
 
 /* Destructor for call_data */
diff --git a/src/core/iomgr/alarm.c b/src/core/iomgr/alarm.c
index 5860834..5b9a37e 100644
--- a/src/core/iomgr/alarm.c
+++ b/src/core/iomgr/alarm.c
@@ -102,7 +102,8 @@
 
 void grpc_alarm_list_shutdown(void) {
   int i;
-  while (run_some_expired_alarms(NULL, gpr_inf_future, NULL, 0))
+  while (run_some_expired_alarms(NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL,
+                                 0))
     ;
   for (i = 0; i < NUM_SHARDS; i++) {
     shard_type *shard = &g_shards[i];
@@ -127,6 +128,7 @@
   gpr_timespec ts;
   ts.tv_sec = d;
   ts.tv_nsec = 1e9 * (d - ts.tv_sec);
+  ts.clock_type = GPR_TIMESPAN;
   return ts;
 }
 
diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c
index 0c62bfc..ddb1834 100644
--- a/src/core/iomgr/iocp_windows.c
+++ b/src/core/iomgr/iocp_windows.c
@@ -158,7 +158,7 @@
   BOOL success;
   gpr_event_set(&g_shutdown_iocp, (void *)1);
   grpc_iocp_kick();
-  gpr_event_wait(&g_iocp_done, gpr_inf_future);
+  gpr_event_wait(&g_iocp_done, gpr_inf_future(GPR_CLOCK_REALTIME));
   success = CloseHandle(g_iocp);
   GPR_ASSERT(success);
 }
diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c
index cca92d3..2a90b9a 100644
--- a/src/core/iomgr/iomgr.c
+++ b/src/core/iomgr/iomgr.c
@@ -57,7 +57,7 @@
 static void background_callback_executor(void *ignored) {
   gpr_mu_lock(&g_mu);
   while (!g_shutdown) {
-    gpr_timespec deadline = gpr_inf_future;
+    gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
     gpr_timespec short_deadline =
         gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100));
     if (g_cbs_head) {
@@ -145,7 +145,7 @@
       } while (g_cbs_head);
       continue;
     }
-    if (grpc_alarm_check(&g_mu, gpr_inf_future, NULL)) {
+    if (grpc_alarm_check(&g_mu, gpr_inf_future(GPR_CLOCK_REALTIME), NULL)) {
       gpr_log(GPR_DEBUG, "got late alarm");
       continue;
     }
@@ -174,7 +174,8 @@
   gpr_mu_unlock(&g_mu);
 
   grpc_kick_poller();
-  gpr_event_wait(&g_background_callback_executor_done, gpr_inf_future);
+  gpr_event_wait(&g_background_callback_executor_done,
+                 gpr_inf_future(GPR_CLOCK_REALTIME));
 
   grpc_alarm_list_shutdown();
 
diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c
index 8510176..e95d9d1 100644
--- a/src/core/iomgr/pollset_posix.c
+++ b/src/core/iomgr/pollset_posix.c
@@ -191,7 +191,7 @@
                                          gpr_timespec now) {
   gpr_timespec timeout;
   static const int max_spin_polling_us = 10;
-  if (gpr_time_cmp(deadline, gpr_inf_future) == 0) {
+  if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) {
     return -1;
   }
   if (gpr_time_cmp(
diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c
index d70968d..19ded3e 100644
--- a/src/core/iomgr/tcp_server_windows.c
+++ b/src/core/iomgr/tcp_server_windows.c
@@ -115,7 +115,7 @@
   }
   /* This happens asynchronously. Wait while that happens. */
   while (s->active_ports) {
-    gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
+    gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future(GPR_CLOCK_REALTIME));
   }
   gpr_mu_unlock(&s->mu);
 
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 230f0df..5d03b7c 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -324,7 +324,7 @@
     gpr_free(c->cached.service_url);
     c->cached.service_url = NULL;
   }
-  c->cached.jwt_expiration = gpr_inf_past;
+  c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
 }
 
 static void jwt_destroy(grpc_credentials *creds) {
@@ -347,8 +347,8 @@
                                      grpc_credentials_metadata_cb cb,
                                      void *user_data) {
   grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds;
-  gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
-                                    0};
+  gpr_timespec refresh_threshold =
+      gpr_time_from_seconds(GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS);
 
   /* See if we can return a cached jwt. */
   grpc_credentials_md_store *jwt_md = NULL;
@@ -516,6 +516,7 @@
                  access_token->value);
     token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
     token_lifetime->tv_nsec = 0;
+    token_lifetime->clock_type = GPR_TIMESPAN;
     if (*token_md != NULL) grpc_credentials_md_store_unref(*token_md);
     *token_md = grpc_credentials_md_store_create(1);
     grpc_credentials_md_store_add_cstrings(
@@ -552,7 +553,7 @@
     r->cb(r->user_data, c->access_token_md->entries,
           c->access_token_md->num_entries, status);
   } else {
-    c->token_expiration = gpr_inf_past;
+    c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
     r->cb(r->user_data, NULL, 0, status);
   }
   gpr_mu_unlock(&c->mu);
@@ -564,8 +565,8 @@
     grpc_credentials_metadata_cb cb, void *user_data) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
-  gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
-                                    0};
+  gpr_timespec refresh_threshold =
+      gpr_time_from_seconds(GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS);
   grpc_credentials_md_store *cached_access_token_md = NULL;
   {
     gpr_mu_lock(&c->mu);
@@ -596,7 +597,7 @@
   c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
   gpr_ref_init(&c->base.refcount, 1);
   gpr_mu_init(&c->mu);
-  c->token_expiration = gpr_inf_past;
+  c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
   c->fetch_func = fetch_func;
   grpc_httpcli_context_init(&c->httpcli_context);
 }
diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c
index f622def..43f9f62 100644
--- a/src/core/security/google_default_credentials.c
+++ b/src/core/security/google_default_credentials.c
@@ -91,7 +91,7 @@
 
   /* The http call is local. If it takes more than one sec, it is for sure not
      on compute engine. */
-  gpr_timespec max_detection_delay = {1, 0};
+  gpr_timespec max_detection_delay = gpr_time_from_seconds(1);
 
   grpc_pollset_init(&detector.pollset);
   detector.is_done = 0;
@@ -112,7 +112,7 @@
      called once for the lifetime of the process by the default credentials. */
   gpr_mu_lock(GRPC_POLLSET_MU(&detector.pollset));
   while (!detector.is_done) {
-    grpc_pollset_work(&detector.pollset, gpr_inf_future);
+    grpc_pollset_work(&detector.pollset, gpr_inf_future(GPR_CLOCK_REALTIME));
   }
   gpr_mu_unlock(GRPC_POLLSET_MU(&detector.pollset));
 
diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c
index 9b1ea25..021912f 100644
--- a/src/core/security/json_token.c
+++ b/src/core/security/json_token.c
@@ -49,7 +49,7 @@
 /* --- Constants. --- */
 
 /* 1 hour max. */
-const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0};
+const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0, GPR_TIMESPAN};
 
 #define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256"
 #define GRPC_JWT_TYPE "JWT"
diff --git a/src/core/security/jwt_verifier.c b/src/core/security/jwt_verifier.c
index 9140eb2..1276693 100644
--- a/src/core/security/jwt_verifier.c
+++ b/src/core/security/jwt_verifier.c
@@ -109,7 +109,7 @@
 
 static gpr_timespec validate_time_field(const grpc_json *json,
                                         const char *key) {
-  gpr_timespec result = gpr_time_0;
+  gpr_timespec result = gpr_time_0(GPR_CLOCK_REALTIME);
   if (json->type != GRPC_JSON_NUMBER) {
     gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value);
     return result;
@@ -221,17 +221,17 @@
 }
 
 gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return gpr_inf_past;
+  if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME);
   return claims->iat;
 }
 
 gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return gpr_inf_future;
+  if (claims == NULL) return gpr_inf_future(GPR_CLOCK_REALTIME);
   return claims->exp;
 }
 
 gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) {
-  if (claims == NULL) return gpr_inf_past;
+  if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME);
   return claims->nbf;
 }
 
@@ -242,9 +242,9 @@
   memset(claims, 0, sizeof(grpc_jwt_claims));
   claims->json = json;
   claims->buffer = buffer;
-  claims->iat = gpr_inf_past;
-  claims->nbf = gpr_inf_past;
-  claims->exp = gpr_inf_future;
+  claims->iat = gpr_inf_past(GPR_CLOCK_REALTIME);
+  claims->nbf = gpr_inf_past(GPR_CLOCK_REALTIME);
+  claims->exp = gpr_inf_future(GPR_CLOCK_REALTIME);
 
   /* Per the spec, all fields are optional. */
   for (cur = json->child; cur != NULL; cur = cur->next) {
@@ -262,13 +262,16 @@
       if (claims->jti == NULL) goto error;
     } else if (strcmp(cur->key, "iat") == 0) {
       claims->iat = validate_time_field(cur, "iat");
-      if (gpr_time_cmp(claims->iat, gpr_time_0) == 0) goto error;
+      if (gpr_time_cmp(claims->iat, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
+        goto error;
     } else if (strcmp(cur->key, "exp") == 0) {
       claims->exp = validate_time_field(cur, "exp");
-      if (gpr_time_cmp(claims->exp, gpr_time_0) == 0) goto error;
+      if (gpr_time_cmp(claims->exp, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
+        goto error;
     } else if (strcmp(cur->key, "nbf") == 0) {
       claims->nbf = validate_time_field(cur, "nbf");
-      if (gpr_time_cmp(claims->nbf, gpr_time_0) == 0) goto error;
+      if (gpr_time_cmp(claims->nbf, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
+        goto error;
     }
   }
   return claims;
@@ -359,10 +362,10 @@
 /* --- grpc_jwt_verifier object. --- */
 
 /* Clock skew defaults to one minute. */
-gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0};
+gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0, GPR_TIMESPAN};
 
 /* Max delay defaults to one minute. */
-gpr_timespec grpc_jwt_verifier_max_delay = {60, 0};
+gpr_timespec grpc_jwt_verifier_max_delay = {60, 0, GPR_TIMESPAN};
 
 typedef struct {
   char *email_domain;
diff --git a/src/core/support/sync_posix.c b/src/core/support/sync_posix.c
index 0ccbd49..41af8ce 100644
--- a/src/core/support/sync_posix.c
+++ b/src/core/support/sync_posix.c
@@ -63,7 +63,7 @@
 
 int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) {
   int err = 0;
-  if (gpr_time_cmp(abs_deadline, gpr_inf_future) == 0) {
+  if (gpr_time_cmp(abs_deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) {
     err = pthread_cond_wait(cv, mu);
   } else {
     struct timespec abs_deadline_ts;
diff --git a/src/core/support/sync_win32.c b/src/core/support/sync_win32.c
index 29b77fc..63196d1 100644
--- a/src/core/support/sync_win32.c
+++ b/src/core/support/sync_win32.c
@@ -83,7 +83,7 @@
   int timeout = 0;
   DWORD timeout_max_ms;
   mu->locked = 0;
-  if (gpr_time_cmp(abs_deadline, gpr_inf_future) == 0) {
+  if (gpr_time_cmp(abs_deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) {
     SleepConditionVariableCS(cv, &mu->cs, INFINITE);
   } else {
     gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
diff --git a/src/core/support/time.c b/src/core/support/time.c
index d47b08b..aee64c9 100644
--- a/src/core/support/time.c
+++ b/src/core/support/time.c
@@ -41,6 +41,7 @@
 
 int gpr_time_cmp(gpr_timespec a, gpr_timespec b) {
   int cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec);
+  GPR_ASSERT(a.clock_type == b.clock_type);
   if (cmp == 0) {
     cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);
   }
@@ -71,19 +72,40 @@
   ((t)(TYPE_IS_SIGNED(t) ? (TOP_BIT_OF_TYPE(t) - 1) \
                          : ((TOP_BIT_OF_TYPE(t) - 1) << 1) + 1))
 
-const gpr_timespec gpr_time_0 = {0, 0};
-const gpr_timespec gpr_inf_future = {TYPE_MAX(time_t), 0};
-const gpr_timespec gpr_inf_past = {TYPE_MIN(time_t), 0};
+gpr_timespec gpr_time_0(gpr_clock_type type) {
+  gpr_timespec out;
+  out.tv_sec = 0;
+  out.tv_nsec = 0;
+  out.clock_type = type;
+  return out;
+}
+
+gpr_timespec gpr_inf_future(gpr_clock_type type) {
+  gpr_timespec out;
+  out.tv_sec = TYPE_MAX(time_t);
+  out.tv_nsec = 0;
+  out.clock_type = type;
+  return out;
+}
+
+gpr_timespec gpr_inf_past(gpr_clock_type type) {
+  gpr_timespec out;
+  out.tv_sec = TYPE_MIN(time_t);
+  out.tv_nsec = 0;
+  out.clock_type = type;
+  return out;
+}
 
 /* TODO(ctiller): consider merging _nanos, _micros, _millis into a single
    function for maintainability. Similarly for _seconds, _minutes, and _hours */
 
 gpr_timespec gpr_time_from_nanos(long ns) {
   gpr_timespec result;
+  result.clock_type = GPR_TIMESPAN;
   if (ns == LONG_MAX) {
-    result = gpr_inf_future;
+    result = gpr_inf_future(GPR_TIMESPAN);
   } else if (ns == LONG_MIN) {
-    result = gpr_inf_past;
+    result = gpr_inf_past(GPR_TIMESPAN);
   } else if (ns >= 0) {
     result.tv_sec = ns / GPR_NS_PER_SEC;
     result.tv_nsec = (int)(ns - result.tv_sec * GPR_NS_PER_SEC);
@@ -97,10 +119,11 @@
 
 gpr_timespec gpr_time_from_micros(long us) {
   gpr_timespec result;
+  result.clock_type = GPR_TIMESPAN;
   if (us == LONG_MAX) {
-    result = gpr_inf_future;
+    result = gpr_inf_future(GPR_TIMESPAN);
   } else if (us == LONG_MIN) {
-    result = gpr_inf_past;
+    result = gpr_inf_past(GPR_TIMESPAN);
   } else if (us >= 0) {
     result.tv_sec = us / 1000000;
     result.tv_nsec = (int)((us - result.tv_sec * 1000000) * 1000);
@@ -114,10 +137,11 @@
 
 gpr_timespec gpr_time_from_millis(long ms) {
   gpr_timespec result;
+  result.clock_type = GPR_TIMESPAN;
   if (ms == LONG_MAX) {
-    result = gpr_inf_future;
+    result = gpr_inf_future(GPR_TIMESPAN);
   } else if (ms == LONG_MIN) {
-    result = gpr_inf_past;
+    result = gpr_inf_past(GPR_TIMESPAN);
   } else if (ms >= 0) {
     result.tv_sec = ms / 1000;
     result.tv_nsec = (int)((ms - result.tv_sec * 1000) * 1000000);
@@ -131,10 +155,11 @@
 
 gpr_timespec gpr_time_from_seconds(long s) {
   gpr_timespec result;
+  result.clock_type = GPR_TIMESPAN;
   if (s == LONG_MAX) {
-    result = gpr_inf_future;
+    result = gpr_inf_future(GPR_TIMESPAN);
   } else if (s == LONG_MIN) {
-    result = gpr_inf_past;
+    result = gpr_inf_past(GPR_TIMESPAN);
   } else {
     result.tv_sec = s;
     result.tv_nsec = 0;
@@ -144,10 +169,11 @@
 
 gpr_timespec gpr_time_from_minutes(long m) {
   gpr_timespec result;
+  result.clock_type = GPR_TIMESPAN;
   if (m >= LONG_MAX / 60) {
-    result = gpr_inf_future;
+    result = gpr_inf_future(GPR_TIMESPAN);
   } else if (m <= LONG_MIN / 60) {
-    result = gpr_inf_past;
+    result = gpr_inf_past(GPR_TIMESPAN);
   } else {
     result.tv_sec = m * 60;
     result.tv_nsec = 0;
@@ -157,10 +183,11 @@
 
 gpr_timespec gpr_time_from_hours(long h) {
   gpr_timespec result;
+  result.clock_type = GPR_TIMESPAN;
   if (h >= LONG_MAX / 3600) {
-    result = gpr_inf_future;
+    result = gpr_inf_future(GPR_TIMESPAN);
   } else if (h <= LONG_MIN / 3600) {
-    result = gpr_inf_past;
+    result = gpr_inf_past(GPR_TIMESPAN);
   } else {
     result.tv_sec = h * 3600;
     result.tv_nsec = 0;
@@ -171,6 +198,8 @@
 gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) {
   gpr_timespec sum;
   int inc = 0;
+  GPR_ASSERT(b.clock_type == GPR_TIMESPAN);
+  sum.clock_type = a.clock_type;
   sum.tv_nsec = a.tv_nsec + b.tv_nsec;
   if (sum.tv_nsec >= GPR_NS_PER_SEC) {
     sum.tv_nsec -= GPR_NS_PER_SEC;
@@ -180,14 +209,14 @@
     sum = a;
   } else if (b.tv_sec == TYPE_MAX(time_t) ||
              (b.tv_sec >= 0 && a.tv_sec >= TYPE_MAX(time_t) - b.tv_sec)) {
-    sum = gpr_inf_future;
+    sum = gpr_inf_future(sum.clock_type);
   } else if (b.tv_sec == TYPE_MIN(time_t) ||
              (b.tv_sec <= 0 && a.tv_sec <= TYPE_MIN(time_t) - b.tv_sec)) {
-    sum = gpr_inf_past;
+    sum = gpr_inf_past(sum.clock_type);
   } else {
     sum.tv_sec = a.tv_sec + b.tv_sec;
     if (inc != 0 && sum.tv_sec == TYPE_MAX(time_t) - 1) {
-      sum = gpr_inf_future;
+      sum = gpr_inf_future(sum.clock_type);
     } else {
       sum.tv_sec += inc;
     }
@@ -198,6 +227,12 @@
 gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) {
   gpr_timespec diff;
   int dec = 0;
+  if (b.clock_type == GPR_TIMESPAN) {
+    diff.clock_type = a.clock_type;
+  } else {
+    GPR_ASSERT(a.clock_type == b.clock_type);
+    diff.clock_type = GPR_TIMESPAN;
+  }
   diff.tv_nsec = a.tv_nsec - b.tv_nsec;
   if (diff.tv_nsec < 0) {
     diff.tv_nsec += GPR_NS_PER_SEC;
@@ -207,14 +242,14 @@
     diff = a;
   } else if (b.tv_sec == TYPE_MIN(time_t) ||
              (b.tv_sec <= 0 && a.tv_sec >= TYPE_MAX(time_t) + b.tv_sec)) {
-    diff = gpr_inf_future;
+    diff = gpr_inf_future(GPR_CLOCK_REALTIME);
   } else if (b.tv_sec == TYPE_MAX(time_t) ||
              (b.tv_sec >= 0 && a.tv_sec <= TYPE_MIN(time_t) + b.tv_sec)) {
-    diff = gpr_inf_past;
+    diff = gpr_inf_past(GPR_CLOCK_REALTIME);
   } else {
     diff.tv_sec = a.tv_sec - b.tv_sec;
     if (dec != 0 && diff.tv_sec == TYPE_MIN(time_t) + 1) {
-      diff = gpr_inf_past;
+      diff = gpr_inf_past(GPR_CLOCK_REALTIME);
     } else {
       diff.tv_sec -= dec;
     }
@@ -225,6 +260,9 @@
 int gpr_time_similar(gpr_timespec a, gpr_timespec b, gpr_timespec threshold) {
   int cmp_ab;
 
+  GPR_ASSERT(a.clock_type == b.clock_type);
+  GPR_ASSERT(threshold.clock_type == GPR_TIMESPAN);
+
   cmp_ab = gpr_time_cmp(a, b);
   if (cmp_ab == 0) return 1;
   if (cmp_ab < 0) {
diff --git a/src/core/support/time_posix.c b/src/core/support/time_posix.c
index f9b7958..f28c2d7 100644
--- a/src/core/support/time_posix.c
+++ b/src/core/support/time_posix.c
@@ -38,6 +38,7 @@
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
+#include <grpc/support/log.h>
 #include <grpc/support/time.h>
 
 static struct timespec timespec_from_gpr(gpr_timespec gts) {
@@ -48,10 +49,12 @@
 }
 
 #if _POSIX_TIMERS > 0
-static gpr_timespec gpr_from_timespec(struct timespec ts) {
+static gpr_timespec gpr_from_timespec(struct timespec ts,
+                                      gpr_clock_type clock) {
   gpr_timespec rv;
   rv.tv_sec = ts.tv_sec;
   rv.tv_nsec = (int)ts.tv_nsec;
+  rv.clock_type = clock;
   return rv;
 }
 
@@ -62,8 +65,9 @@
 
 gpr_timespec gpr_now(gpr_clock_type clock) {
   struct timespec now;
+  GPR_ASSERT(clock != GPR_TIMESPAN);
   clock_gettime(clockid_for_gpr_clock[clock], &now);
-  return gpr_from_timespec(now);
+  return gpr_from_timespec(now, clock);
 }
 #else
 /* For some reason Apple's OSes haven't implemented clock_gettime. */
@@ -99,6 +103,8 @@
       now.tv_sec = now_dbl * 1e-9;
       now.tv_nsec = now_dbl - now.tv_sec * 1e9;
       break;
+    case GPR_TIMESPAN:
+      abort();
   }
 
   return now;
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 8e6047d..a663577 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -329,7 +329,7 @@
   }
   grpc_call_stack_init(channel_stack, server_transport_data, initial_op_ptr,
                        CALL_STACK_FROM_CALL(call));
-  if (gpr_time_cmp(send_deadline, gpr_inf_future) != 0) {
+  if (gpr_time_cmp(send_deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) != 0) {
     set_deadline_alarm(call, send_deadline);
   }
   return call;
@@ -930,7 +930,7 @@
           mdb.list = chain_metadata_from_app(call, data.send_metadata.count,
                                              data.send_metadata.metadata);
           mdb.garbage.head = mdb.garbage.tail = NULL;
-          mdb.deadline = gpr_inf_future;
+          mdb.deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
           /* send status */
           /* TODO(ctiller): cache common status values */
           data = call->request_data[GRPC_IOREQ_SEND_STATUS];
@@ -1283,7 +1283,7 @@
       l->md = 0;
     }
   }
-  if (gpr_time_cmp(md->deadline, gpr_inf_future) != 0) {
+  if (gpr_time_cmp(md->deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) != 0) {
     set_deadline_alarm(call, md->deadline);
   }
   if (!is_trailing) {
diff --git a/src/core/surface/lame_client.c b/src/core/surface/lame_client.c
index 3dd56fe..3f2bb5c 100644
--- a/src/core/surface/lame_client.c
+++ b/src/core/surface/lame_client.c
@@ -72,7 +72,7 @@
     mdb.list.head = &calld->status;
     mdb.list.tail = &calld->details;
     mdb.garbage.head = mdb.garbage.tail = NULL;
-    mdb.deadline = gpr_inf_future;
+    mdb.deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
     grpc_sopb_add_metadata(op->recv_ops, mdb);
     *op->recv_state = GRPC_STREAM_CLOSED;
     op->on_done_recv->cb(op->on_done_recv->cb_arg, 1);
diff --git a/src/core/surface/server.c b/src/core/surface/server.c
index 4f868c5..026ba70 100644
--- a/src/core/surface/server.c
+++ b/src/core/surface/server.c
@@ -549,7 +549,8 @@
       grpc_stream_op *op = &ops[i];
       if (op->type != GRPC_OP_METADATA) continue;
       grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
-      if (0 != gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future)) {
+      if (0 != gpr_time_cmp(op->data.metadata.deadline,
+                            gpr_inf_future(GPR_CLOCK_REALTIME))) {
         calld->deadline = op->data.metadata.deadline;
       }
       calld->got_initial_metadata = 1;
@@ -623,7 +624,7 @@
   channel_data *chand = cd;
   /* create a call */
   grpc_call_create(chand->channel, NULL, transport_server_data, NULL, 0,
-                   gpr_inf_future);
+                   gpr_inf_future(GPR_CLOCK_REALTIME));
 }
 
 static void channel_connectivity_changed(void *cd, int iomgr_status_ignored) {
@@ -651,7 +652,7 @@
   call_data *calld = elem->call_data;
   channel_data *chand = elem->channel_data;
   memset(calld, 0, sizeof(call_data));
-  calld->deadline = gpr_inf_future;
+  calld->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
   calld->call = grpc_call_from_top_element(elem);
   gpr_mu_init(&calld->mu_state);
 
diff --git a/src/core/transport/chttp2/incoming_metadata.c b/src/core/transport/chttp2/incoming_metadata.c
index 77162a6..974b864 100644
--- a/src/core/transport/chttp2/incoming_metadata.c
+++ b/src/core/transport/chttp2/incoming_metadata.c
@@ -42,7 +42,7 @@
 
 void grpc_chttp2_incoming_metadata_buffer_init(
     grpc_chttp2_incoming_metadata_buffer *buffer) {
-  buffer->deadline = gpr_inf_future;
+  buffer->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
 }
 
 void grpc_chttp2_incoming_metadata_buffer_destroy(
@@ -87,7 +87,7 @@
   b.list.tail = (void *)(gpr_intptr)buffer->count;
   b.garbage.head = b.garbage.tail = NULL;
   b.deadline = buffer->deadline;
-  buffer->deadline = gpr_inf_future;
+  buffer->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
 
   grpc_sopb_add_metadata(sopb, b);
 }
diff --git a/src/core/transport/chttp2/parsing.c b/src/core/transport/chttp2/parsing.c
index 9597395..14c2461 100644
--- a/src/core/transport/chttp2/parsing.c
+++ b/src/core/transport/chttp2/parsing.c
@@ -594,7 +594,7 @@
                                       cached_timeout)) {
         gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
                 grpc_mdstr_as_c_string(md->value));
-        *cached_timeout = gpr_inf_future;
+        *cached_timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
       }
       grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
     }
diff --git a/src/core/transport/chttp2/stream_encoder.c b/src/core/transport/chttp2/stream_encoder.c
index d553d80..d7fc2da 100644
--- a/src/core/transport/chttp2/stream_encoder.c
+++ b/src/core/transport/chttp2/stream_encoder.c
@@ -585,7 +585,8 @@
           l->md = hpack_enc(compressor, l->md, &st);
           need_unref |= l->md != NULL;
         }
-        if (gpr_time_cmp(op->data.metadata.deadline, gpr_inf_future) != 0) {
+        if (gpr_time_cmp(op->data.metadata.deadline,
+                         gpr_inf_future(GPR_CLOCK_REALTIME)) != 0) {
           deadline_enc(compressor, op->data.metadata.deadline, &st);
         }
         curop++;
diff --git a/src/core/transport/chttp2/timeout_encoding.c b/src/core/transport/chttp2/timeout_encoding.c
index 33915c4..7b19712 100644
--- a/src/core/transport/chttp2/timeout_encoding.c
+++ b/src/core/transport/chttp2/timeout_encoding.c
@@ -147,7 +147,7 @@
     gpr_uint32 xp = x * 10 + *p - '0';
     have_digit = 1;
     if (xp < x) {
-      *timeout = gpr_inf_future;
+      *timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
       return 1;
     }
     x = xp;
diff --git a/src/core/transport/stream_op.c b/src/core/transport/stream_op.c
index fdb50c6..71061fe 100644
--- a/src/core/transport/stream_op.c
+++ b/src/core/transport/stream_op.c
@@ -205,7 +205,7 @@
 void grpc_metadata_batch_init(grpc_metadata_batch *batch) {
   batch->list.head = batch->list.tail = batch->garbage.head = batch->garbage.tail =
       NULL;
-  batch->deadline = gpr_inf_future;
+  batch->deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
 }
 
 void grpc_metadata_batch_destroy(grpc_metadata_batch *batch) {
diff --git a/src/core/transport/transport_op_string.c b/src/core/transport/transport_op_string.c
index 0da396a..eebba14 100644
--- a/src/core/transport/transport_op_string.c
+++ b/src/core/transport/transport_op_string.c
@@ -61,7 +61,7 @@
     if (m != md.list.head) gpr_strvec_add(b, gpr_strdup(", "));
     put_metadata(b, m->md);
   }
-  if (gpr_time_cmp(md.deadline, gpr_inf_future) != 0) {
+  if (gpr_time_cmp(md.deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) != 0) {
     char *tmp;
     gpr_asprintf(&tmp, " deadline=%d.%09d", md.deadline.tv_sec,
                  md.deadline.tv_nsec);
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index c68f6dd..372f3e2 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -44,7 +44,7 @@
     : initial_metadata_received_(false),
       call_(nullptr),
       cq_(nullptr),
-      deadline_(gpr_inf_future) {}
+      deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)) {}
 
 ClientContext::~ClientContext() {
   if (call_) {
@@ -53,8 +53,8 @@
   if (cq_) {
     // Drain cq_.
     grpc_completion_queue_shutdown(cq_);
-    while (grpc_completion_queue_next(cq_, gpr_inf_future).type !=
-           GRPC_QUEUE_SHUTDOWN)
+    while (grpc_completion_queue_next(cq_, gpr_inf_future(GPR_CLOCK_REALTIME))
+               .type != GRPC_QUEUE_SHUTDOWN)
       ;
     grpc_completion_queue_destroy(cq_);
   }
diff --git a/src/cpp/common/completion_queue.cc b/src/cpp/common/completion_queue.cc
index b2dd1ac..593963f 100644
--- a/src/cpp/common/completion_queue.cc
+++ b/src/cpp/common/completion_queue.cc
@@ -70,7 +70,8 @@
 }
 
 bool CompletionQueue::Pluck(CompletionQueueTag* tag) {
-  auto ev = grpc_completion_queue_pluck(cq_, tag, gpr_inf_future);
+  auto ev =
+      grpc_completion_queue_pluck(cq_, tag, gpr_inf_future(GPR_CLOCK_REALTIME));
   bool ok = ev.success != 0;
   void* ignored = tag;
   GPR_ASSERT(tag->FinalizeResult(&ignored, &ok));
@@ -80,7 +81,8 @@
 }
 
 void CompletionQueue::TryPluck(CompletionQueueTag* tag) {
-  auto ev = grpc_completion_queue_pluck(cq_, tag, gpr_time_0);
+  auto ev =
+      grpc_completion_queue_pluck(cq_, tag, gpr_time_0(GPR_CLOCK_REALTIME));
   if (ev.type == GRPC_QUEUE_TIMEOUT) return;
   bool ok = ev.success != 0;
   void* ignored = tag;
diff --git a/src/cpp/util/time.cc b/src/cpp/util/time.cc
index fd94d00..99b857a 100644
--- a/src/cpp/util/time.cc
+++ b/src/cpp/util/time.cc
@@ -51,8 +51,9 @@
   system_clock::duration deadline = from.time_since_epoch();
   seconds secs = duration_cast<seconds>(deadline);
   if (from == system_clock::time_point::max() ||
-      secs.count() >= gpr_inf_future.tv_sec || secs.count() < 0) {
-    *to = gpr_inf_future;
+      secs.count() >= gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec ||
+      secs.count() < 0) {
+    *to = gpr_inf_future(GPR_CLOCK_REALTIME);
     return;
   }
   nanoseconds nsecs = duration_cast<nanoseconds>(deadline - secs);
@@ -65,8 +66,9 @@
   high_resolution_clock::duration deadline = from.time_since_epoch();
   seconds secs = duration_cast<seconds>(deadline);
   if (from == high_resolution_clock::time_point::max() ||
-      secs.count() >= gpr_inf_future.tv_sec || secs.count() < 0) {
-    *to = gpr_inf_future;
+      secs.count() >= gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec ||
+      secs.count() < 0) {
+    *to = gpr_inf_future(GPR_CLOCK_REALTIME);
     return;
   }
   nanoseconds nsecs = duration_cast<nanoseconds>(deadline - secs);
@@ -75,7 +77,7 @@
 }
 
 system_clock::time_point Timespec2Timepoint(gpr_timespec t) {
-  if (gpr_time_cmp(t, gpr_inf_future) == 0) {
+  if (gpr_time_cmp(t, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) {
     return system_clock::time_point::max();
   }
   system_clock::time_point tp;
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index a55cc9e..7dd1959 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -302,12 +302,13 @@
 
 GPR_EXPORT grpc_event GPR_CALLTYPE
 grpcsharp_completion_queue_next(grpc_completion_queue *cq) {
-  return grpc_completion_queue_next(cq, gpr_inf_future);
+  return grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME));
 }
 
 GPR_EXPORT grpc_event GPR_CALLTYPE
 grpcsharp_completion_queue_pluck(grpc_completion_queue *cq, void *tag) {
-  return grpc_completion_queue_pluck(cq, tag, gpr_inf_future);
+  return grpc_completion_queue_pluck(cq, tag,
+                                     gpr_inf_future(GPR_CLOCK_REALTIME));
 }
 
 /* Channel */
@@ -382,7 +383,7 @@
 GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(void) { return gpr_now(GPR_CLOCK_REALTIME); }
 
 GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_future(void) {
-  return gpr_inf_future;
+  return gpr_inf_future(GPR_CLOCK_REALTIME);
 }
 
 GPR_EXPORT gpr_int32 GPR_CALLTYPE gprsharp_sizeof_timespec(void) {
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index 10a4946..b67bae7 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -408,7 +408,7 @@
     goto cleanup;
   }
   event = grpc_completion_queue_pluck(completion_queue, call->wrapped,
-                                      gpr_inf_future);
+                                      gpr_inf_future(GPR_CLOCK_REALTIME));
   if (!event.success) {
     zend_throw_exception(spl_ce_LogicException,
                          "The batch failed for some reason",
diff --git a/src/php/ext/grpc/completion_queue.c b/src/php/ext/grpc/completion_queue.c
index b24c837..c653a59 100644
--- a/src/php/ext/grpc/completion_queue.c
+++ b/src/php/ext/grpc/completion_queue.c
@@ -43,8 +43,9 @@
 
 void grpc_php_shutdown_completion_queue(TSRMLS_D) {
   grpc_completion_queue_shutdown(completion_queue);
-  while (grpc_completion_queue_next(completion_queue, gpr_inf_future).type !=
-         GRPC_QUEUE_SHUTDOWN)
+  while (grpc_completion_queue_next(completion_queue,
+                                    gpr_inf_future(GPR_CLOCK_REALTIME))
+             .type != GRPC_QUEUE_SHUTDOWN)
     ;
   grpc_completion_queue_destroy(completion_queue);
 }
diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c
index 02c886c..c319526 100644
--- a/src/php/ext/grpc/server.c
+++ b/src/php/ext/grpc/server.c
@@ -64,7 +64,8 @@
   wrapped_grpc_server *server = (wrapped_grpc_server *)object;
   if (server->wrapped != NULL) {
     grpc_server_shutdown_and_notify(server->wrapped, completion_queue, NULL);
-    grpc_completion_queue_pluck(completion_queue, NULL, gpr_inf_future);
+    grpc_completion_queue_pluck(completion_queue, NULL,
+                                gpr_inf_future(GPR_CLOCK_REALTIME));
     grpc_server_destroy(server->wrapped);
   }
   efree(server);
@@ -143,7 +144,8 @@
                          (long)error_code TSRMLS_CC);
     goto cleanup;
   }
-  event = grpc_completion_queue_pluck(completion_queue, NULL, gpr_inf_future);
+  event = grpc_completion_queue_pluck(completion_queue, NULL,
+                                      gpr_inf_future(GPR_CLOCK_REALTIME));
   if (!event.success) {
     zend_throw_exception(spl_ce_LogicException,
                          "Failed to request a call for some reason",
diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c
index ccf7f0f..d753048 100644
--- a/src/php/ext/grpc/timeval.c
+++ b/src/php/ext/grpc/timeval.c
@@ -228,7 +228,8 @@
  * @return Timeval Infinite future time value
  */
 PHP_METHOD(Timeval, infFuture) {
-  zval *grpc_php_timeval_inf_future = grpc_php_wrap_timeval(gpr_inf_future);
+  zval *grpc_php_timeval_inf_future =
+      grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME));
   RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future);
 }
 
@@ -237,7 +238,8 @@
  * @return Timeval Infinite past time value
  */
 PHP_METHOD(Timeval, infPast) {
-  zval *grpc_php_timeval_inf_past = grpc_php_wrap_timeval(gpr_inf_past);
+  zval *grpc_php_timeval_inf_past =
+      grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME));
   RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past);
 }
 
diff --git a/src/python/src/grpc/_adapter/_c/utility.c b/src/python/src/grpc/_adapter/_c/utility.c
index 480a720..b82b042 100644
--- a/src/python/src/grpc/_adapter/_c/utility.c
+++ b/src/python/src/grpc/_adapter/_c/utility.c
@@ -385,7 +385,8 @@
 gpr_timespec pygrpc_cast_double_to_gpr_timespec(double seconds) {
   gpr_timespec result;
   if (pygrpc_isinf(seconds)) {
-    result = seconds > 0.0 ? gpr_inf_future : gpr_inf_past;
+    result = seconds > 0.0 ? gpr_inf_future(GPR_CLOCK_REALTIME)
+                           : gpr_inf_past(GPR_CLOCK_REALTIME);
   } else {
     result.tv_sec = (time_t)seconds;
     result.tv_nsec = ((seconds - result.tv_sec) * 1e9);
diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c
index 2d52d96..8a98e16 100644
--- a/src/ruby/ext/grpc/rb_completion_queue.c
+++ b/src/ruby/ext/grpc/rb_completion_queue.c
@@ -82,7 +82,7 @@
   next_call.cq = cq;
   next_call.event.type = GRPC_QUEUE_TIMEOUT;
   /* TODO: the timeout should be a module level constant that defaults
-   * to gpr_inf_future.
+   * to gpr_inf_future(GPR_CLOCK_REALTIME).
    *
    * - at the moment this does not work, it stalls.  Using a small timeout like
    *   this one works, and leads to fast test run times; a longer timeout was
@@ -143,7 +143,7 @@
   TypedData_Get_Struct(self, grpc_completion_queue,
                        &grpc_rb_completion_queue_data_type, next_call.cq);
   if (TYPE(timeout) == T_NIL) {
-    next_call.timeout = gpr_inf_future;
+    next_call.timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
   } else {
     next_call.timeout = grpc_rb_time_timeval(timeout, /* absolute time*/ 0);
   }
diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c
index 699548b..706a2a7 100644
--- a/src/ruby/ext/grpc/rb_grpc.c
+++ b/src/ruby/ext/grpc/rb_grpc.c
@@ -235,11 +235,11 @@
   rb_define_const(
       grpc_rb_mTimeConsts, "INFINITE_FUTURE",
       TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
-                            (void *)&gpr_inf_future));
+                            (void *)&gpr_inf_future(GPR_CLOCK_REALTIME)));
   rb_define_const(
       grpc_rb_mTimeConsts, "INFINITE_PAST",
       TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
-                            (void *)&gpr_inf_past));
+                            (void *)&gpr_inf_past(GPR_CLOCK_REALTIME)));
   rb_define_method(grpc_rb_cTimeVal, "to_time", grpc_rb_time_val_to_time, 0);
   rb_define_method(grpc_rb_cTimeVal, "inspect", grpc_rb_time_val_inspect, 0);
   rb_define_method(grpc_rb_cTimeVal, "to_s", grpc_rb_time_val_to_s, 0);