Skip to content

Commit

Permalink
Initial checkin commit for lockfree stack.
Browse files Browse the repository at this point in the history
Tests not yet included.
  • Loading branch information
vjpai committed Jul 10, 2015
1 parent a4ae29b commit 005e305
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 0 deletions.
4 changes: 4 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cc_library(
"src/core/support/env.h",
"src/core/support/file.h",
"src/core/support/murmur_hash.h",
"src/core/support/stack_lockfree.h",
"src/core/support/string.h",
"src/core/support/string_win32.h",
"src/core/support/thd_internal.h",
Expand All @@ -73,6 +74,7 @@ cc_library(
"src/core/support/murmur_hash.c",
"src/core/support/slice.c",
"src/core/support/slice_buffer.c",
"src/core/support/stack_lockfree.c",
"src/core/support/string.c",
"src/core/support/string_posix.c",
"src/core/support/string_win32.c",
Expand Down Expand Up @@ -873,6 +875,7 @@ objc_library(
"src/core/support/murmur_hash.c",
"src/core/support/slice.c",
"src/core/support/slice_buffer.c",
"src/core/support/stack_lockfree.c",
"src/core/support/string.c",
"src/core/support/string_posix.c",
"src/core/support/string_win32.c",
Expand Down Expand Up @@ -920,6 +923,7 @@ objc_library(
"src/core/support/env.h",
"src/core/support/file.h",
"src/core/support/murmur_hash.h",
"src/core/support/stack_lockfree.h",
"src/core/support/string.h",
"src/core/support/string_win32.h",
"src/core/support/thd_internal.h",
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3100,6 +3100,7 @@ LIBGPR_SRC = \
src/core/support/murmur_hash.c \
src/core/support/slice.c \
src/core/support/slice_buffer.c \
src/core/support/stack_lockfree.c \
src/core/support/string.c \
src/core/support/string_posix.c \
src/core/support/string_win32.c \
Expand Down
2 changes: 2 additions & 0 deletions build.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"src/core/support/env.h",
"src/core/support/file.h",
"src/core/support/murmur_hash.h",
"src/core/support/stack_lockfree.h",
"src/core/support/string.h",
"src/core/support/string_win32.h",
"src/core/support/thd_internal.h"
Expand Down Expand Up @@ -401,6 +402,7 @@
"src/core/support/murmur_hash.c",
"src/core/support/slice.c",
"src/core/support/slice_buffer.c",
"src/core/support/stack_lockfree.c",
"src/core/support/string.c",
"src/core/support/string_posix.c",
"src/core/support/string_win32.c",
Expand Down
3 changes: 3 additions & 0 deletions gRPC.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Pod::Spec.new do |s|
ss.source_files = 'src/core/support/env.h',
'src/core/support/file.h',
'src/core/support/murmur_hash.h',
'src/core/support/stack_lockfree.h',
'src/core/support/grpc_string.h',
'src/core/support/string_win32.h',
'src/core/support/thd_internal.h',
Expand Down Expand Up @@ -118,6 +119,7 @@ Pod::Spec.new do |s|
'src/core/support/murmur_hash.c',
'src/core/support/slice.c',
'src/core/support/slice_buffer.c',
'src/core/support/stack_lockfree.c',
'src/core/support/string.c',
'src/core/support/string_posix.c',
'src/core/support/string_win32.c',
Expand Down Expand Up @@ -389,6 +391,7 @@ Pod::Spec.new do |s|
ss.private_header_files = 'src/core/support/env.h',
'src/core/support/file.h',
'src/core/support/murmur_hash.h',
'src/core/support/stack_lockfree.h',
'src/core/support/string.h',
'src/core/support/string_win32.h',
'src/core/support/thd_internal.h',
Expand Down
130 changes: 130 additions & 0 deletions src/core/support/stack_lockfree.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#include "src/core/support/stack_lockfree.h"

#include <stdlib.h>
#include <string.h>

#include <grpc/support/port_platform.h>
#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/log.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 */
gpr_uint16 index;
#ifdef GPR_ARCH_64
gpr_uint16 pad;
gpr_uint32 aba_ctr;
#else
#ifdef GPR_ARCH_32
gpr_uint16 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;

#define ENTRY_ALIGNMENT_BITS 3 /* make sure that entries aligned to 8-bytes */
#define INVALID_ENTRY_INDEX ((1<<16)-1) /* reserve this entry as invalid */

struct gpr_stack_lockfree {
lockfree_node *entries;
lockfree_node head; /* An atomic entry describing curr head */
};

gpr_stack_lockfree *gpr_stack_lockfree_create(int entries) {
gpr_stack_lockfree *stack;
stack = 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 = gpr_malloc_aligned(entries * sizeof(stack->entries[0]),
ENTRY_ALIGNMENT_BITS);
/* Clear out all entries */
memset(stack->entries, 0, entries * sizeof(stack->entries[0]));

/* Point the head at reserved dummy entry */
stack->head.contents.index = INVALID_ENTRY_INDEX;
return stack;
}

void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack) {
gpr_free_aligned(stack->entries);
gpr_free(stack);
}

void gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
lockfree_node head;
lockfree_node newhead;

/* First fill in the entry's index and aba ctr for new head */
newhead.contents.index = (gpr_uint16)entry;
/* Also post-increment the aba_ctr */
newhead.contents.aba_ctr = stack->entries[entry].contents.aba_ctr++;

do {
/* Atomically get the existing head value for use */
head.atm = gpr_atm_no_barrier_load(&(stack->head.atm));
/* Point to it */
stack->entries[entry].contents.index = head.contents.index;
} 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 */
}

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.contents.index = stack->entries[head.contents.index].contents.index;

} while (!gpr_atm_no_barrier_cas(&(stack->head.atm),
head.atm,
newhead.atm));
return newhead.contents.index;
}
50 changes: 50 additions & 0 deletions src/core/support/stack_lockfree.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#ifndef GRPC_INTERNAL_CORE_SUPPORT_STACK_LOCKFREE_H
#define GRPC_INTERNAL_CORE_SUPPORT_STACK_LOCKFREE_H

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(int entries);
void gpr_stack_lockfree_destroy(gpr_stack_lockfree *);

/* Pass in a valid entry number for the next stack entry */
void 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 *);

#endif /* GRPC_INTERNAL_CORE_SUPPORT_STACK_LOCKFREE_H */
2 changes: 2 additions & 0 deletions tools/doxygen/Doxyfile.core.internal
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,7 @@ include/grpc/support/useful.h \
src/core/support/env.h \
src/core/support/file.h \
src/core/support/murmur_hash.h \
src/core/support/stack_lockfree.h \
src/core/support/string.h \
src/core/support/string_win32.h \
src/core/support/thd_internal.h \
Expand All @@ -1070,6 +1071,7 @@ src/core/support/log_win32.c \
src/core/support/murmur_hash.c \
src/core/support/slice.c \
src/core/support/slice_buffer.c \
src/core/support/stack_lockfree.c \
src/core/support/string.c \
src/core/support/string_posix.c \
src/core/support/string_win32.c \
Expand Down
3 changes: 3 additions & 0 deletions tools/run_tests/sources_and_headers.json
Original file line number Diff line number Diff line change
Expand Up @@ -8595,6 +8595,7 @@
"src/core/support/env.h",
"src/core/support/file.h",
"src/core/support/murmur_hash.h",
"src/core/support/stack_lockfree.h",
"src/core/support/string.h",
"src/core/support/string_win32.h",
"src/core/support/thd_internal.h"
Expand Down Expand Up @@ -8656,6 +8657,8 @@
"src/core/support/murmur_hash.h",
"src/core/support/slice.c",
"src/core/support/slice_buffer.c",
"src/core/support/stack_lockfree.c",
"src/core/support/stack_lockfree.h",
"src/core/support/string.c",
"src/core/support/string.h",
"src/core/support/string_posix.c",
Expand Down
3 changes: 3 additions & 0 deletions vsprojects/gpr/gpr.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@
<ClInclude Include="..\..\src\core\support\env.h" />
<ClInclude Include="..\..\src\core\support\file.h" />
<ClInclude Include="..\..\src\core\support\murmur_hash.h" />
<ClInclude Include="..\..\src\core\support\stack_lockfree.h" />
<ClInclude Include="..\..\src\core\support\string.h" />
<ClInclude Include="..\..\src\core\support\string_win32.h" />
<ClInclude Include="..\..\src\core\support\thd_internal.h" />
Expand Down Expand Up @@ -230,6 +231,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\support\slice_buffer.c">
</ClCompile>
<ClCompile Include="..\..\src\core\support\stack_lockfree.c">
</ClCompile>
<ClCompile Include="..\..\src\core\support\string.c">
</ClCompile>
<ClCompile Include="..\..\src\core\support\string_posix.c">
Expand Down
6 changes: 6 additions & 0 deletions vsprojects/gpr/gpr.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@
<ClCompile Include="..\..\src\core\support\slice_buffer.c">
<Filter>src\core\support</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\support\stack_lockfree.c">
<Filter>src\core\support</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\support\string.c">
<Filter>src\core\support</Filter>
</ClCompile>
Expand Down Expand Up @@ -209,6 +212,9 @@
<ClInclude Include="..\..\src\core\support\murmur_hash.h">
<Filter>src\core\support</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\support\stack_lockfree.h">
<Filter>src\core\support</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\support\string.h">
<Filter>src\core\support</Filter>
</ClInclude>
Expand Down

0 comments on commit 005e305

Please sign in to comment.