aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Nicolas "Pixel" Noble <pixel@nobis-crew.org>2017-11-29 19:31:42 +0100
committerGravatar Nicolas "Pixel" Noble <pixel@nobis-crew.org>2017-11-29 19:31:42 +0100
commit361f8108e41497c53f174c0ad6ea0ffcc97022a9 (patch)
tree2fa08b8f0b047f627481c07ccdffd603c0edc42c /src/core
parent18a6837bb0bec8b62c566b4a49adc179f0450c1d (diff)
parentf836c7e941beb003289dc6e9a58a6e47f5caa5f0 (diff)
Merge branch 'master' of https://github.com/grpc/grpc into upmerge-from-v1.7
Diffstat (limited to 'src/core')
-rw-r--r--src/core/ext/filters/client_channel/subchannel_index.cc2
-rw-r--r--src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc2
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.cc9
-rw-r--r--src/core/ext/transport/chttp2/transport/flow_control.h1
-rw-r--r--src/core/lib/channel/channel_stack.h1
-rw-r--r--src/core/lib/debug/trace.cc4
-rw-r--r--src/core/lib/iomgr/ev_epoll1_linux.cc10
-rw-r--r--src/core/lib/iomgr/ev_epollex_linux.cc10
-rw-r--r--src/core/lib/iomgr/ev_epollsig_linux.cc10
-rw-r--r--src/core/lib/iomgr/lockfree_event.cc6
-rw-r--r--src/core/lib/iomgr/lockfree_event.h7
-rw-r--r--src/core/lib/iomgr/sockaddr_utils.cc2
-rw-r--r--src/core/lib/support/abstract.h29
-rw-r--r--src/core/lib/support/cpu_posix.cc30
-rw-r--r--src/core/lib/support/manual_constructor.h135
-rw-r--r--src/core/lib/support/murmur_hash.cc19
-rw-r--r--src/core/lib/support/stack_lockfree.cc137
-rw-r--r--src/core/lib/support/stack_lockfree.h46
-rw-r--r--src/core/lib/surface/call.cc34
-rw-r--r--src/core/lib/surface/version.cc4
-rw-r--r--src/core/lib/transport/error_utils.cc9
-rw-r--r--src/core/lib/transport/error_utils.h8
22 files changed, 272 insertions, 243 deletions
diff --git a/src/core/ext/filters/client_channel/subchannel_index.cc b/src/core/ext/filters/client_channel/subchannel_index.cc
index ae39ca394e..1624643d0b 100644
--- a/src/core/ext/filters/client_channel/subchannel_index.cc
+++ b/src/core/ext/filters/client_channel/subchannel_index.cc
@@ -163,7 +163,7 @@ grpc_subchannel* grpc_subchannel_index_register(grpc_exec_ctx* exec_ctx,
grpc_subchannel_key* key,
grpc_subchannel* constructed) {
grpc_subchannel* c = nullptr;
- bool need_to_unref_constructed;
+ bool need_to_unref_constructed = false;
while (c == nullptr) {
need_to_unref_constructed = false;
diff --git a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
index 6bbb4d5739..390da52e2f 100644
--- a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
+++ b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
@@ -139,7 +139,7 @@ static bool parse_user_agent(grpc_mdelem md) {
bool grpc_objc_specifier_seen = false;
bool cronet_specifier_seen = false;
char *major_version_str = user_agent_str, *minor_version_str;
- long major_version, minor_version;
+ long major_version = 0, minor_version = 0;
char* head = strtok(user_agent_str, " ");
while (head != nullptr) {
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index 5bd647885f..01a16955d9 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -1758,7 +1758,7 @@ static void send_goaway(grpc_exec_ctx* exec_ctx, grpc_chttp2_transport* t,
grpc_http2_error_code http_error;
grpc_slice slice;
grpc_error_get_status(exec_ctx, error, GRPC_MILLIS_INF_FUTURE, nullptr,
- &slice, &http_error);
+ &slice, &http_error, nullptr);
grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error,
grpc_slice_ref_internal(slice), &t->qbuf);
grpc_chttp2_initiate_write(exec_ctx, t,
@@ -2061,7 +2061,7 @@ void grpc_chttp2_cancel_stream(grpc_exec_ctx* exec_ctx,
if (s->id != 0) {
grpc_http2_error_code http_error;
grpc_error_get_status(exec_ctx, due_to_error, s->deadline, nullptr,
- nullptr, &http_error);
+ nullptr, &http_error, nullptr);
grpc_slice_buffer_add(
&t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
&s->stats.outgoing));
@@ -2079,7 +2079,8 @@ void grpc_chttp2_fake_status(grpc_exec_ctx* exec_ctx, grpc_chttp2_transport* t,
grpc_chttp2_stream* s, grpc_error* error) {
grpc_status_code status;
grpc_slice slice;
- grpc_error_get_status(exec_ctx, error, s->deadline, &status, &slice, nullptr);
+ grpc_error_get_status(exec_ctx, error, s->deadline, &status, &slice, nullptr,
+ nullptr);
if (status != GRPC_STATUS_OK) {
s->seen_error = true;
}
@@ -2244,7 +2245,7 @@ static void close_from_api(grpc_exec_ctx* exec_ctx, grpc_chttp2_transport* t,
grpc_status_code grpc_status;
grpc_slice slice;
grpc_error_get_status(exec_ctx, error, s->deadline, &grpc_status, &slice,
- nullptr);
+ nullptr, nullptr);
GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
diff --git a/src/core/ext/transport/chttp2/transport/flow_control.h b/src/core/ext/transport/chttp2/transport/flow_control.h
index bb710fef83..2515c94309 100644
--- a/src/core/ext/transport/chttp2/transport/flow_control.h
+++ b/src/core/ext/transport/chttp2/transport/flow_control.h
@@ -19,6 +19,7 @@
#ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FLOW_CONTROL_H
#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FLOW_CONTROL_H
+#include <grpc/support/port_platform.h>
#include <stdint.h>
#include <grpc/support/useful.h>
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index 6b41ad105a..830c1123d0 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -84,6 +84,7 @@ typedef struct {
typedef struct {
grpc_call_stats stats;
grpc_status_code final_status;
+ const char** error_string;
} grpc_call_final_info;
/* Channel filters specify:
diff --git a/src/core/lib/debug/trace.cc b/src/core/lib/debug/trace.cc
index 4c63983bdc..a76c1afb4c 100644
--- a/src/core/lib/debug/trace.cc
+++ b/src/core/lib/debug/trace.cc
@@ -75,8 +75,8 @@ void TraceFlagList::LogAllTracers() {
}
// Flags register themselves on the list during construction
-TraceFlag::TraceFlag(bool default_enabled, const char* name)
- : name_(name), value_(default_enabled) {
+TraceFlag::TraceFlag(bool default_enabled, const char* name) : name_(name) {
+ set_enabled(default_enabled);
TraceFlagList::Add(this);
}
diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc
index 60446f7dd5..0dda1d924c 100644
--- a/src/core/lib/iomgr/ev_epoll1_linux.cc
+++ b/src/core/lib/iomgr/ev_epoll1_linux.cc
@@ -263,11 +263,13 @@ static grpc_fd* fd_create(int fd, const char* name) {
if (new_fd == nullptr) {
new_fd = (grpc_fd*)gpr_malloc(sizeof(grpc_fd));
+ new_fd->read_closure.Init();
+ new_fd->write_closure.Init();
}
new_fd->fd = fd;
- new_fd->read_closure.Init();
- new_fd->write_closure.Init();
+ new_fd->read_closure->InitEvent();
+ new_fd->write_closure->InitEvent();
gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
new_fd->freelist_next = nullptr;
@@ -336,8 +338,8 @@ static void fd_orphan(grpc_exec_ctx* exec_ctx, grpc_fd* fd,
GRPC_CLOSURE_SCHED(exec_ctx, on_done, GRPC_ERROR_REF(error));
grpc_iomgr_unregister_object(&fd->iomgr_object);
- fd->read_closure.Destroy();
- fd->write_closure.Destroy();
+ fd->read_closure->DestroyEvent();
+ fd->write_closure->DestroyEvent();
gpr_mu_lock(&fd_freelist_mu);
fd->freelist_next = fd_freelist;
diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc
index 10b84401fa..62643df697 100644
--- a/src/core/lib/iomgr/ev_epollex_linux.cc
+++ b/src/core/lib/iomgr/ev_epollex_linux.cc
@@ -286,8 +286,8 @@ static void fd_destroy(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
fd->freelist_next = fd_freelist;
fd_freelist = fd;
- fd->read_closure.Destroy();
- fd->write_closure.Destroy();
+ fd->read_closure->DestroyEvent();
+ fd->write_closure->DestroyEvent();
gpr_mu_unlock(&fd_freelist_mu);
}
@@ -340,6 +340,8 @@ static grpc_fd* fd_create(int fd, const char* name) {
if (new_fd == nullptr) {
new_fd = (grpc_fd*)gpr_malloc(sizeof(grpc_fd));
+ new_fd->read_closure.Init();
+ new_fd->write_closure.Init();
}
gpr_mu_init(&new_fd->pollable_mu);
@@ -347,8 +349,8 @@ static grpc_fd* fd_create(int fd, const char* name) {
new_fd->pollable_obj = nullptr;
gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
new_fd->fd = fd;
- new_fd->read_closure.Init();
- new_fd->write_closure.Init();
+ new_fd->read_closure->InitEvent();
+ new_fd->write_closure->InitEvent();
gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
new_fd->freelist_next = nullptr;
diff --git a/src/core/lib/iomgr/ev_epollsig_linux.cc b/src/core/lib/iomgr/ev_epollsig_linux.cc
index 689c0d4573..12c8483b8e 100644
--- a/src/core/lib/iomgr/ev_epollsig_linux.cc
+++ b/src/core/lib/iomgr/ev_epollsig_linux.cc
@@ -767,8 +767,8 @@ static void unref_by(grpc_fd* fd, int n) {
fd_freelist = fd;
grpc_iomgr_unregister_object(&fd->iomgr_object);
- fd->read_closure.Destroy();
- fd->write_closure.Destroy();
+ fd->read_closure->DestroyEvent();
+ fd->write_closure->DestroyEvent();
gpr_mu_unlock(&fd_freelist_mu);
} else {
@@ -819,6 +819,8 @@ static grpc_fd* fd_create(int fd, const char* name) {
if (new_fd == nullptr) {
new_fd = (grpc_fd*)gpr_malloc(sizeof(grpc_fd));
gpr_mu_init(&new_fd->po.mu);
+ new_fd->read_closure.Init();
+ new_fd->write_closure.Init();
}
/* Note: It is not really needed to get the new_fd->po.mu lock here. If this
@@ -833,8 +835,8 @@ static grpc_fd* fd_create(int fd, const char* name) {
gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
new_fd->fd = fd;
new_fd->orphaned = false;
- new_fd->read_closure.Init();
- new_fd->write_closure.Init();
+ new_fd->read_closure->InitEvent();
+ new_fd->write_closure->InitEvent();
gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
new_fd->freelist_next = nullptr;
diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc
index d477f64ba5..f0e798e8d8 100644
--- a/src/core/lib/iomgr/lockfree_event.cc
+++ b/src/core/lib/iomgr/lockfree_event.cc
@@ -57,7 +57,9 @@ extern grpc_core::TraceFlag grpc_polling_trace;
namespace grpc_core {
-LockfreeEvent::LockfreeEvent() {
+LockfreeEvent::LockfreeEvent() { InitEvent(); }
+
+void LockfreeEvent::InitEvent() {
/* Perform an atomic store to start the state machine.
Note carefully that LockfreeEvent *MAY* be used whilst in a destroyed
@@ -67,7 +69,7 @@ LockfreeEvent::LockfreeEvent() {
gpr_atm_no_barrier_store(&state_, kClosureNotReady);
}
-LockfreeEvent::~LockfreeEvent() {
+void LockfreeEvent::DestroyEvent() {
gpr_atm curr;
do {
curr = gpr_atm_no_barrier_load(&state_);
diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h
index c667dcd3bc..aec67a3399 100644
--- a/src/core/lib/iomgr/lockfree_event.h
+++ b/src/core/lib/iomgr/lockfree_event.h
@@ -30,11 +30,16 @@ namespace grpc_core {
class LockfreeEvent {
public:
LockfreeEvent();
- ~LockfreeEvent();
LockfreeEvent(const LockfreeEvent&) = delete;
LockfreeEvent& operator=(const LockfreeEvent&) = delete;
+ // These methods are used to initialize and destroy the internal state. These
+ // cannot be done in constructor and destructor because SetReady may be called
+ // when the event is destroyed and put in a freelist.
+ void InitEvent();
+ void DestroyEvent();
+
bool IsShutdown() const {
return (gpr_atm_no_barrier_load(&state_) & kShutdownBit) != 0;
}
diff --git a/src/core/lib/iomgr/sockaddr_utils.cc b/src/core/lib/iomgr/sockaddr_utils.cc
index 3477fb52cd..0c0a2fe5b2 100644
--- a/src/core/lib/iomgr/sockaddr_utils.cc
+++ b/src/core/lib/iomgr/sockaddr_utils.cc
@@ -148,7 +148,7 @@ int grpc_sockaddr_to_string(char** out,
grpc_resolved_address addr_normalized;
char ntop_buf[INET6_ADDRSTRLEN];
const void* ip = nullptr;
- int port;
+ int port = 0;
uint32_t sin6_scope_id = 0;
int ret;
diff --git a/src/core/lib/support/abstract.h b/src/core/lib/support/abstract.h
new file mode 100644
index 0000000000..5498769a7d
--- /dev/null
+++ b/src/core/lib/support/abstract.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SUPPORT_ABSTRACT_H
+#define GRPC_CORE_LIB_SUPPORT_ABSTRACT_H
+
+// This is needed to support abstract base classes in the c core. Since gRPC
+// doesn't have a c++ runtime, it will hit a linker error on delete unless
+// we define a virtual operator delete. See this blog for more info:
+// https://eli.thegreenplace.net/2015/c-deleting-destructors-and-virtual-operator-delete/
+#define GRPC_ABSTRACT_BASE_CLASS \
+ static void operator delete(void* p) { abort(); }
+
+#endif /* GRPC_CORE_LIB_SUPPORT_ABSTRACT_H */
diff --git a/src/core/lib/support/cpu_posix.cc b/src/core/lib/support/cpu_posix.cc
index 503a96b4c8..bca14a0c12 100644
--- a/src/core/lib/support/cpu_posix.cc
+++ b/src/core/lib/support/cpu_posix.cc
@@ -18,21 +18,23 @@
#include <grpc/support/port_platform.h>
-#ifdef GPR_CPU_POSIX
+#if defined(GPR_CPU_POSIX)
#include <errno.h>
+#include <pthread.h>
#include <string.h>
#include <unistd.h>
+#include <grpc/support/alloc.h>
#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/useful.h>
-static __thread char magic_thread_local;
-
static long ncpus = 0;
+static pthread_key_t thread_id_key;
+
static void init_ncpus() {
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
if (ncpus < 1 || ncpus > INT32_MAX) {
@@ -47,12 +49,32 @@ unsigned gpr_cpu_num_cores(void) {
return (unsigned)ncpus;
}
+static void delete_thread_id(void* value) {
+ if (value) {
+ gpr_free(value);
+ }
+}
+
+static void init_thread_id_key(void) {
+ pthread_key_create(&thread_id_key, delete_thread_id);
+}
+
unsigned gpr_cpu_current_cpu(void) {
/* NOTE: there's no way I know to return the actual cpu index portably...
most code that's using this is using it to shard across work queues though,
so here we use thread identity instead to achieve a similar though not
identical effect */
- return (unsigned)GPR_HASH_POINTER(&magic_thread_local, gpr_cpu_num_cores());
+ static gpr_once once = GPR_ONCE_INIT;
+ gpr_once_init(&once, init_thread_id_key);
+
+ unsigned int* thread_id =
+ static_cast<unsigned int*>(pthread_getspecific(thread_id_key));
+ if (thread_id == nullptr) {
+ thread_id = static_cast<unsigned int*>(gpr_malloc(sizeof(unsigned int)));
+ pthread_setspecific(thread_id_key, thread_id);
+ }
+
+ return (unsigned)GPR_HASH_POINTER(thread_id, gpr_cpu_num_cores());
}
#endif /* GPR_CPU_POSIX */
diff --git a/src/core/lib/support/manual_constructor.h b/src/core/lib/support/manual_constructor.h
index d753cf98a0..fda7653dbc 100644
--- a/src/core/lib/support/manual_constructor.h
+++ b/src/core/lib/support/manual_constructor.h
@@ -22,12 +22,147 @@
// manually construct a region of memory with some type
#include <stddef.h>
+#include <stdlib.h>
#include <new>
#include <type_traits>
#include <utility>
+#include <grpc/support/log.h>
+
namespace grpc_core {
+// this contains templated helpers needed to implement the ManualConstructors
+// in this file.
+namespace manual_ctor_impl {
+
+// is_one_of returns true it a class, Member, is present in a variadic list of
+// classes, List.
+template <class Member, class... List>
+class is_one_of;
+
+template <class Member, class... List>
+class is_one_of<Member, Member, List...> {
+ public:
+ static constexpr const bool value = true;
+};
+
+template <class Member, class A, class... List>
+class is_one_of<Member, A, List...> {
+ public:
+ static constexpr const bool value = is_one_of<Member, List...>::value;
+};
+
+template <class Member>
+class is_one_of<Member> {
+ public:
+ static constexpr const bool value = false;
+};
+
+// max_size_of returns sizeof(Type) for the largest type in the variadic list
+// of classes, Types.
+template <class... Types>
+class max_size_of;
+
+template <class A>
+class max_size_of<A> {
+ public:
+ static constexpr const size_t value = sizeof(A);
+};
+
+template <class A, class... B>
+class max_size_of<A, B...> {
+ public:
+ static constexpr const size_t value = sizeof(A) > max_size_of<B...>::value
+ ? sizeof(A)
+ : max_size_of<B...>::value;
+};
+
+// max_size_of returns alignof(Type) for the largest type in the variadic list
+// of classes, Types.
+template <class... Types>
+class max_align_of;
+
+template <class A>
+class max_align_of<A> {
+ public:
+ static constexpr const size_t value = alignof(A);
+};
+
+template <class A, class... B>
+class max_align_of<A, B...> {
+ public:
+ static constexpr const size_t value = alignof(A) > max_align_of<B...>::value
+ ? alignof(A)
+ : max_align_of<B...>::value;
+};
+
+} // namespace manual_ctor_impl
+
+template <class BaseType, class... DerivedTypes>
+class PolymorphicManualConstructor {
+ public:
+ // No constructor or destructor because one of the most useful uses of
+ // this class is as part of a union, and members of a union could not have
+ // constructors or destructors till C++11. And, anyway, the whole point of
+ // this class is to bypass constructor and destructor.
+
+ BaseType* get() { return reinterpret_cast<BaseType*>(&space_); }
+ const BaseType* get() const {
+ return reinterpret_cast<const BaseType*>(&space_);
+ }
+
+ BaseType* operator->() { return get(); }
+ const BaseType* operator->() const { return get(); }
+
+ BaseType& operator*() { return *get(); }
+ const BaseType& operator*() const { return *get(); }
+
+ template <class DerivedType>
+ void Init() {
+ FinishInit(new (&space_) DerivedType);
+ }
+
+ // Init() constructs the Type instance using the given arguments
+ // (which are forwarded to Type's constructor).
+ //
+ // Note that Init() with no arguments performs default-initialization,
+ // not zero-initialization (i.e it behaves the same as "new Type;", not
+ // "new Type();"), so it will leave non-class types uninitialized.
+ template <class DerivedType, typename... Ts>
+ void Init(Ts&&... args) {
+ FinishInit(new (&space_) DerivedType(std::forward<Ts>(args)...));
+ }
+
+ // Init() that is equivalent to copy and move construction.
+ // Enables usage like this:
+ // ManualConstructor<std::vector<int>> v;
+ // v.Init({1, 2, 3});
+ template <class DerivedType>
+ void Init(const DerivedType& x) {
+ FinishInit(new (&space_) DerivedType(x));
+ }
+ template <class DerivedType>
+ void Init(DerivedType&& x) {
+ FinishInit(new (&space_) DerivedType(std::move(x)));
+ }
+
+ void Destroy() { get()->~BaseType(); }
+
+ private:
+ template <class DerivedType>
+ void FinishInit(DerivedType* p) {
+ static_assert(
+ manual_ctor_impl::is_one_of<DerivedType, DerivedTypes...>::value,
+ "DerivedType must be one of the predeclared DerivedTypes");
+ GPR_ASSERT(reinterpret_cast<BaseType*>(static_cast<DerivedType*>(p)) == p);
+ }
+
+ typename std::aligned_storage<
+ grpc_core::manual_ctor_impl::max_size_of<DerivedTypes...>::value,
+ grpc_core::manual_ctor_impl::max_align_of<DerivedTypes...>::value>::type
+ space_;
+};
+
template <typename Type>
class ManualConstructor {
public:
diff --git a/src/core/lib/support/murmur_hash.cc b/src/core/lib/support/murmur_hash.cc
index 4e08579a1d..2f0e71a53c 100644
--- a/src/core/lib/support/murmur_hash.cc
+++ b/src/core/lib/support/murmur_hash.cc
@@ -30,22 +30,19 @@
(h) ^= (h) >> 16;
uint32_t gpr_murmur_hash3(const void* key, size_t len, uint32_t seed) {
- const uint8_t* data = (const uint8_t*)key;
- const size_t nblocks = len / 4;
- int i;
-
uint32_t h1 = seed;
uint32_t k1;
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
- const uint32_t* blocks = ((const uint32_t*)key) + nblocks;
- const uint8_t* tail = (const uint8_t*)(data + nblocks * 4);
+ const uint8_t* keyptr = (const uint8_t*)key;
+ const size_t bsize = sizeof(k1);
+ const size_t nblocks = len / bsize;
/* body */
- for (i = -(int)nblocks; i; i++) {
- memcpy(&k1, blocks + i, sizeof(uint32_t));
+ for (size_t i = 0; i < nblocks; i++, keyptr += bsize) {
+ memcpy(&k1, keyptr, bsize);
k1 *= c1;
k1 = ROTL32(k1, 15);
@@ -61,13 +58,13 @@ uint32_t gpr_murmur_hash3(const void* key, size_t len, uint32_t seed) {
/* tail */
switch (len & 3) {
case 3:
- k1 ^= ((uint32_t)tail[2]) << 16;
+ k1 ^= ((uint32_t)keyptr[2]) << 16;
/* fallthrough */
case 2:
- k1 ^= ((uint32_t)tail[1]) << 8;
+ k1 ^= ((uint32_t)keyptr[1]) << 8;
/* fallthrough */
case 1:
- k1 ^= tail[0];
+ k1 ^= keyptr[0];
k1 *= c1;
k1 = ROTL32(k1, 15);
k1 *= c2;
diff --git a/src/core/lib/support/stack_lockfree.cc b/src/core/lib/support/stack_lockfree.cc
deleted file mode 100644
index 7a4ede3b92..0000000000
--- a/src/core/lib/support/stack_lockfree.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "src/core/lib/support/stack_lockfree.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/atm.h>
-#include <grpc/support/log.h>
-#include <grpc/support/port_platform.h>
-
-/* The lockfree node structure is a single architecture-level
- word that allows for an atomic CAS to set it up. */
-struct lockfree_node_contents {
- /* next thing to look at. Actual index for head, next index otherwise */
- uint16_t index;
-#ifdef GPR_ARCH_64
- uint16_t pad;
- uint32_t aba_ctr;
-#else
-#ifdef GPR_ARCH_32
- uint16_t aba_ctr;
-#else
-#error Unsupported bit width architecture
-#endif
-#endif
-};
-
-/* Use a union to make sure that these are in the same bits as an atm word */
-typedef union lockfree_node {
- gpr_atm atm;
- struct lockfree_node_contents contents;
-} lockfree_node;
-
-/* make sure that entries aligned to 8-bytes */
-#define ENTRY_ALIGNMENT_BITS 3
-/* reserve this entry as invalid */
-#define INVALID_ENTRY_INDEX ((1 << 16) - 1)
-
-struct gpr_stack_lockfree {
- lockfree_node* entries;
- lockfree_node head; /* An atomic entry describing curr head */
-};
-
-gpr_stack_lockfree* gpr_stack_lockfree_create(size_t entries) {
- gpr_stack_lockfree* stack;
- stack = (gpr_stack_lockfree*)gpr_malloc(sizeof(*stack));
- /* Since we only allocate 16 bits to represent an entry number,
- * make sure that we are within the desired range */
- /* Reserve the highest entry number as a dummy */
- GPR_ASSERT(entries < INVALID_ENTRY_INDEX);
- stack->entries = (lockfree_node*)gpr_malloc_aligned(
- entries * sizeof(stack->entries[0]), ENTRY_ALIGNMENT_BITS);
- /* Clear out all entries */
- memset(stack->entries, 0, entries * sizeof(stack->entries[0]));
- memset(&stack->head, 0, sizeof(stack->head));
-
- GPR_ASSERT(sizeof(stack->entries->atm) == sizeof(stack->entries->contents));
-
- /* Point the head at reserved dummy entry */
- stack->head.contents.index = INVALID_ENTRY_INDEX;
-/* Fill in the pad and aba_ctr to avoid confusing memcheck tools */
-#ifdef GPR_ARCH_64
- stack->head.contents.pad = 0;
-#endif
- stack->head.contents.aba_ctr = 0;
- return stack;
-}
-
-void gpr_stack_lockfree_destroy(gpr_stack_lockfree* stack) {
- gpr_free_aligned(stack->entries);
- gpr_free(stack);
-}
-
-int gpr_stack_lockfree_push(gpr_stack_lockfree* stack, int entry) {
- lockfree_node head;
- lockfree_node newhead;
- lockfree_node curent;
- lockfree_node newent;
-
- /* First fill in the entry's index and aba ctr for new head */
- newhead.contents.index = (uint16_t)entry;
-#ifdef GPR_ARCH_64
- /* Fill in the pad to avoid confusing memcheck tools */
- newhead.contents.pad = 0;
-#endif
-
- /* Also post-increment the aba_ctr */
- curent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
- newhead.contents.aba_ctr = ++curent.contents.aba_ctr;
- gpr_atm_no_barrier_store(&stack->entries[entry].atm, curent.atm);
-
- do {
- /* Atomically get the existing head value for use */
- head.atm = gpr_atm_no_barrier_load(&(stack->head.atm));
- /* Point to it */
- newent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
- newent.contents.index = head.contents.index;
- gpr_atm_no_barrier_store(&stack->entries[entry].atm, newent.atm);
- } while (!gpr_atm_rel_cas(&(stack->head.atm), head.atm, newhead.atm));
- /* Use rel_cas above to make sure that entry index is set properly */
- return head.contents.index == INVALID_ENTRY_INDEX;
-}
-
-int gpr_stack_lockfree_pop(gpr_stack_lockfree* stack) {
- lockfree_node head;
- lockfree_node newhead;
-
- do {
- head.atm = gpr_atm_acq_load(&(stack->head.atm));
- if (head.contents.index == INVALID_ENTRY_INDEX) {
- return -1;
- }
- newhead.atm =
- gpr_atm_no_barrier_load(&(stack->entries[head.contents.index].atm));
-
- } while (!gpr_atm_no_barrier_cas(&(stack->head.atm), head.atm, newhead.atm));
-
- return head.contents.index;
-}
diff --git a/src/core/lib/support/stack_lockfree.h b/src/core/lib/support/stack_lockfree.h
deleted file mode 100644
index 337ecc2b17..0000000000
--- a/src/core/lib/support/stack_lockfree.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H
-#define GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct gpr_stack_lockfree gpr_stack_lockfree;
-
-/* This stack must specify the maximum number of entries to track.
- The current implementation only allows up to 65534 entries */
-gpr_stack_lockfree* gpr_stack_lockfree_create(size_t entries);
-void gpr_stack_lockfree_destroy(gpr_stack_lockfree* stack);
-
-/* Pass in a valid entry number for the next stack entry */
-/* Returns 1 if this is the first element on the stack, 0 otherwise */
-int gpr_stack_lockfree_push(gpr_stack_lockfree*, int entry);
-
-/* Returns -1 on empty or the actual entry number */
-int gpr_stack_lockfree_pop(gpr_stack_lockfree* stack);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRPC_CORE_LIB_SUPPORT_STACK_LOCKFREE_H */
diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc
index a83c95c8dc..a2eb02bd85 100644
--- a/src/core/lib/surface/call.cc
+++ b/src/core/lib/surface/call.cc
@@ -234,6 +234,7 @@ struct grpc_call {
struct {
grpc_status_code* status;
grpc_slice* status_details;
+ const char** error_string;
} client;
struct {
int* cancelled;
@@ -284,7 +285,8 @@ static void receiving_slice_ready(grpc_exec_ctx* exec_ctx, void* bctlp,
static void get_final_status(grpc_exec_ctx* exec_ctx, grpc_call* call,
void (*set_value)(grpc_status_code code,
void* user_data),
- void* set_value_user_data, grpc_slice* details);
+ void* set_value_user_data, grpc_slice* details,
+ const char** error_string);
static void set_status_value_directly(grpc_status_code status, void* dest);
static void set_status_from_error(grpc_exec_ctx* exec_ctx, grpc_call* call,
status_source source, grpc_error* error);
@@ -546,7 +548,8 @@ static void destroy_call(grpc_exec_ctx* exec_ctx, void* call,
}
get_final_status(exec_ctx, c, set_status_value_directly,
- &c->final_info.final_status, nullptr);
+ &c->final_info.final_status, nullptr,
+ c->final_info.error_string);
c->final_info.stats.latency =
gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
@@ -733,16 +736,15 @@ static void cancel_with_status(grpc_exec_ctx* exec_ctx, grpc_call* c,
* FINAL STATUS CODE MANIPULATION
*/
-static bool get_final_status_from(grpc_exec_ctx* exec_ctx, grpc_call* call,
- grpc_error* error, bool allow_ok_status,
- void (*set_value)(grpc_status_code code,
- void* user_data),
- void* set_value_user_data,
- grpc_slice* details) {
+static bool get_final_status_from(
+ grpc_exec_ctx* exec_ctx, grpc_call* call, grpc_error* error,
+ bool allow_ok_status,
+ void (*set_value)(grpc_status_code code, void* user_data),
+ void* set_value_user_data, grpc_slice* details, const char** error_string) {
grpc_status_code code;
grpc_slice slice = grpc_empty_slice();
grpc_error_get_status(exec_ctx, error, call->send_deadline, &code, &slice,
- nullptr);
+ nullptr, error_string);
if (code == GRPC_STATUS_OK && !allow_ok_status) {
return false;
}
@@ -757,7 +759,8 @@ static bool get_final_status_from(grpc_exec_ctx* exec_ctx, grpc_call* call,
static void get_final_status(grpc_exec_ctx* exec_ctx, grpc_call* call,
void (*set_value)(grpc_status_code code,
void* user_data),
- void* set_value_user_data, grpc_slice* details) {
+ void* set_value_user_data, grpc_slice* details,
+ const char** error_string) {
int i;
received_status status[STATUS_SOURCE_COUNT];
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
@@ -781,7 +784,7 @@ static void get_final_status(grpc_exec_ctx* exec_ctx, grpc_call* call,
grpc_error_has_clear_grpc_status(status[i].error)) {
if (get_final_status_from(exec_ctx, call, status[i].error,
allow_ok_status != 0, set_value,
- set_value_user_data, details)) {
+ set_value_user_data, details, error_string)) {
return;
}
}
@@ -791,7 +794,7 @@ static void get_final_status(grpc_exec_ctx* exec_ctx, grpc_call* call,
if (status[i].is_set) {
if (get_final_status_from(exec_ctx, call, status[i].error,
allow_ok_status != 0, set_value,
- set_value_user_data, details)) {
+ set_value_user_data, details, error_string)) {
return;
}
}
@@ -1332,10 +1335,11 @@ static void post_batch_completion(grpc_exec_ctx* exec_ctx,
if (call->is_client) {
get_final_status(exec_ctx, call, set_status_value_directly,
call->final_op.client.status,
- call->final_op.client.status_details);
+ call->final_op.client.status_details,
+ call->final_op.client.error_string);
} else {
get_final_status(exec_ctx, call, set_cancelled_value,
- call->final_op.server.cancelled, nullptr);
+ call->final_op.server.cancelled, nullptr, nullptr);
}
GRPC_ERROR_UNREF(error);
@@ -1992,6 +1996,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx* exec_ctx,
call->final_op.client.status = op->data.recv_status_on_client.status;
call->final_op.client.status_details =
op->data.recv_status_on_client.status_details;
+ call->final_op.client.error_string =
+ op->data.recv_status_on_client.error_string;
stream_op->recv_trailing_metadata = true;
stream_op->collect_stats = true;
stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
diff --git a/src/core/lib/surface/version.cc b/src/core/lib/surface/version.cc
index 5c06c66d0c..7d36c6c9e1 100644
--- a/src/core/lib/surface/version.cc
+++ b/src/core/lib/surface/version.cc
@@ -21,6 +21,6 @@
#include <grpc/grpc.h>
-const char* grpc_version_string(void) { return "5.0.0"; }
+const char* grpc_version_string(void) { return "5.0.0-dev"; }
-const char* grpc_g_stands_for(void) { return "gambit"; }
+const char* grpc_g_stands_for(void) { return "glossy"; }
diff --git a/src/core/lib/transport/error_utils.cc b/src/core/lib/transport/error_utils.cc
index 19510b4c8d..69c8ae6de3 100644
--- a/src/core/lib/transport/error_utils.cc
+++ b/src/core/lib/transport/error_utils.cc
@@ -18,6 +18,7 @@
#include "src/core/lib/transport/error_utils.h"
+#include <grpc/support/string_util.h>
#include "src/core/lib/iomgr/error_internal.h"
#include "src/core/lib/transport/status_conversion.h"
@@ -41,8 +42,8 @@ static grpc_error* recursively_find_error_with_field(grpc_error* error,
void grpc_error_get_status(grpc_exec_ctx* exec_ctx, grpc_error* error,
grpc_millis deadline, grpc_status_code* code,
- grpc_slice* slice,
- grpc_http2_error_code* http_error) {
+ grpc_slice* slice, grpc_http2_error_code* http_error,
+ const char** error_string) {
// Start with the parent error and recurse through the tree of children
// until we find the first one that has a status code.
grpc_error* found_error =
@@ -69,6 +70,10 @@ void grpc_error_get_status(grpc_exec_ctx* exec_ctx, grpc_error* error,
}
if (code != nullptr) *code = status;
+ if (error_string != NULL && status != GRPC_STATUS_OK) {
+ *error_string = gpr_strdup(grpc_error_string(error));
+ }
+
if (http_error != nullptr) {
if (grpc_error_get_int(found_error, GRPC_ERROR_INT_HTTP2_ERROR, &integer)) {
*http_error = (grpc_http2_error_code)integer;
diff --git a/src/core/lib/transport/error_utils.h b/src/core/lib/transport/error_utils.h
index 690e42058a..6f21f484e5 100644
--- a/src/core/lib/transport/error_utils.h
+++ b/src/core/lib/transport/error_utils.h
@@ -30,13 +30,15 @@ extern "C" {
/// A utility function to get the status code and message to be returned
/// to the application. If not set in the top-level message, looks
/// through child errors until it finds the first one with these attributes.
-/// All attributes are pulled from the same child error. If any of the
-/// attributes (code, msg, http_status) are unneeded, they can be passed as
+/// All attributes are pulled from the same child error. error_string will
+/// be populated with the entire error string. If any of the attributes (code,
+/// msg, http_status, error_string) are unneeded, they can be passed as
/// NULL.
void grpc_error_get_status(grpc_exec_ctx* exec_ctx, grpc_error* error,
grpc_millis deadline, grpc_status_code* code,
grpc_slice* slice,
- grpc_http2_error_code* http_status);
+ grpc_http2_error_code* http_status,
+ const char** error_string);
/// A utility function to check whether there is a clear status code that
/// doesn't need to be guessed in \a error. This means that \a error or some