blob: d8b1f18065c0a5f05b9e82bd62401b3f42dce44b [file] [log] [blame]
David Garcia Quintasf747bbc2015-10-04 23:09:47 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
David Garcia Quintasf747bbc2015-10-04 23:09:47 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
David Garcia Quintasf747bbc2015-10-04 23:09:47 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070016 *
17 */
Yash Tibrewal15ce1422017-09-25 17:46:32 -070018#include <grpc/support/port_platform.h>
19
20#include <inttypes.h>
21
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070022#include "src/core/lib/surface/alarm_internal.h"
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070023
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070024#include <grpc/grpc.h>
25#include <grpc/support/alloc.h>
yang-g0eaf7de2017-07-05 16:50:51 -070026#include <grpc/support/log.h>
Craig Tiller9533d042016-03-25 17:11:06 -070027#include "src/core/lib/iomgr/timer.h"
28#include "src/core/lib/surface/completion_queue.h"
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070029
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070030#ifndef NDEBUG
Sree Kuchibhotla59beeff2017-07-25 14:08:33 -070031grpc_tracer_flag grpc_trace_alarm_refcount =
32 GRPC_TRACER_INITIALIZER(false, "alarm_refcount");
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070033#endif
34
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070035struct grpc_alarm {
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070036 gpr_refcount refs;
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070037 grpc_timer alarm;
Masood Malekghassemib5b43722017-01-05 15:07:26 -080038 grpc_closure on_alarm;
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070039 grpc_cq_completion completion;
40 /** completion queue where events about this alarm will be posted */
Craig Tillerbaa14a92017-11-03 09:09:36 -070041 grpc_completion_queue* cq;
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070042 /** user supplied tag */
Craig Tillerbaa14a92017-11-03 09:09:36 -070043 void* tag;
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070044};
45
Craig Tillerbaa14a92017-11-03 09:09:36 -070046static void alarm_ref(grpc_alarm* alarm) { gpr_ref(&alarm->refs); }
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070047
Craig Tillerbaa14a92017-11-03 09:09:36 -070048static void alarm_unref(grpc_alarm* alarm) {
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070049 if (gpr_unref(&alarm->refs)) {
50 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tiller4782d922017-11-10 09:53:21 -080051 if (alarm->cq != nullptr) {
Vijay Pai58c33ba2017-09-01 14:08:42 -070052 GRPC_CQ_INTERNAL_UNREF(&exec_ctx, alarm->cq, "alarm");
53 }
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070054 grpc_exec_ctx_finish(&exec_ctx);
55 gpr_free(alarm);
56 }
57}
58
59#ifndef NDEBUG
Craig Tillerbaa14a92017-11-03 09:09:36 -070060static void alarm_ref_dbg(grpc_alarm* alarm, const char* reason,
61 const char* file, int line) {
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070062 if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) {
63 gpr_atm val = gpr_atm_no_barrier_load(&alarm->refs.count);
64 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
65 "Alarm:%p ref %" PRIdPTR " -> %" PRIdPTR " %s", alarm, val,
66 val + 1, reason);
67 }
68
69 alarm_ref(alarm);
70}
71
Craig Tillerbaa14a92017-11-03 09:09:36 -070072static void alarm_unref_dbg(grpc_alarm* alarm, const char* reason,
73 const char* file, int line) {
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070074 if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) {
75 gpr_atm val = gpr_atm_no_barrier_load(&alarm->refs.count);
76 gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
77 "Alarm:%p Unref %" PRIdPTR " -> %" PRIdPTR " %s", alarm, val,
78 val - 1, reason);
79 }
80
81 alarm_unref(alarm);
82}
83#endif
84
Craig Tillerbaa14a92017-11-03 09:09:36 -070085static void alarm_end_completion(grpc_exec_ctx* exec_ctx, void* arg,
86 grpc_cq_completion* c) {
87 grpc_alarm* alarm = (grpc_alarm*)arg;
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070088 GRPC_ALARM_UNREF(alarm, "dequeue-end-op");
89}
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070090
Craig Tillerbaa14a92017-11-03 09:09:36 -070091static void alarm_cb(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
92 grpc_alarm* alarm = (grpc_alarm*)arg;
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -070093
94 /* We are queuing an op on completion queue. This means, the alarm's structure
95 cannot be destroyed until the op is dequeued. Adding an extra ref
96 here and unref'ing when the op is dequeued will achieve this */
97 GRPC_ALARM_REF(alarm, "queue-end-op");
98 grpc_cq_end_op(exec_ctx, alarm->cq, alarm->tag, error, alarm_end_completion,
Craig Tillerbaa14a92017-11-03 09:09:36 -070099 (void*)alarm, &alarm->completion);
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700100}
101
Craig Tillerbaa14a92017-11-03 09:09:36 -0700102grpc_alarm* grpc_alarm_create(void* reserved) {
103 grpc_alarm* alarm = (grpc_alarm*)gpr_malloc(sizeof(grpc_alarm));
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -0700104
105#ifndef NDEBUG
106 if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) {
107 gpr_log(GPR_DEBUG, "Alarm:%p created (ref: 1)", alarm);
108 }
109#endif
110
Vijay Pai58c33ba2017-09-01 14:08:42 -0700111 gpr_ref_init(&alarm->refs, 1);
112 grpc_timer_init_unset(&alarm->alarm);
Craig Tiller4782d922017-11-10 09:53:21 -0800113 alarm->cq = nullptr;
Vijay Pai58c33ba2017-09-01 14:08:42 -0700114 GRPC_CLOSURE_INIT(&alarm->on_alarm, alarm_cb, alarm,
115 grpc_schedule_on_exec_ctx);
116 return alarm;
117}
118
Craig Tillerbaa14a92017-11-03 09:09:36 -0700119void grpc_alarm_set(grpc_alarm* alarm, grpc_completion_queue* cq,
120 gpr_timespec deadline, void* tag, void* reserved) {
Vijay Pai58c33ba2017-09-01 14:08:42 -0700121 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
122
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700123 GRPC_CQ_INTERNAL_REF(cq, "alarm");
124 alarm->cq = cq;
125 alarm->tag = tag;
126
yang-g7d6b9142017-07-13 11:48:56 -0700127 GPR_ASSERT(grpc_cq_begin_op(cq, tag));
Craig Tiller9a8c3f32017-07-21 13:14:14 -0700128 grpc_timer_init(&exec_ctx, &alarm->alarm,
129 grpc_timespec_to_millis_round_up(deadline), &alarm->on_alarm);
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700130 grpc_exec_ctx_finish(&exec_ctx);
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700131}
132
Craig Tillerbaa14a92017-11-03 09:09:36 -0700133void grpc_alarm_cancel(grpc_alarm* alarm, void* reserved) {
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700134 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
135 grpc_timer_cancel(&exec_ctx, &alarm->alarm);
136 grpc_exec_ctx_finish(&exec_ctx);
137}
138
Craig Tillerbaa14a92017-11-03 09:09:36 -0700139void grpc_alarm_destroy(grpc_alarm* alarm, void* reserved) {
Vijay Pai58c33ba2017-09-01 14:08:42 -0700140 grpc_alarm_cancel(alarm, reserved);
Sree Kuchibhotlaa8cf05c2017-06-22 15:08:55 -0700141 GRPC_ALARM_UNREF(alarm, "alarm_destroy");
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700142}