Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new IP assignment, random init, fifo reuse of IP #405

Merged
merged 2 commits into from
Jun 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions apps/ergw_core/c_src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Based on c_src.mk from erlang.mk by Loic Hoguin <[email protected]>

CURDIR := $(shell pwd)
BASEDIR := $(abspath $(CURDIR)/..)

PROJECT ?= $(notdir $(BASEDIR))
PROJECT := $(strip $(PROJECT))

ERTS_INCLUDE_DIR ?= $(shell erl -noshell -eval "io:format(\"~ts/erts-~ts/include/\", [code:root_dir(), erlang:system_info(version)])." -s init stop)
ERL_INTERFACE_INCLUDE_DIR ?= $(shell erl -noshell -eval "io:format(\"~ts\", [code:lib_dir(erl_interface, include)])." -s init stop)
ERL_INTERFACE_LIB_DIR ?= $(shell erl -noshell -eval "io:format(\"~ts\", [code:lib_dir(erl_interface, lib)])." -s init stop)

C_SRC_DIR = $(CURDIR)
C_SRC_OUTPUT ?= $(CURDIR)/../priv/$(PROJECT).so

# System type and C compiler/flags.

UNAME_SYS := $(shell uname -s)
ifeq ($(UNAME_SYS), Darwin)
CC ?= cc
CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall
LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress
else ifeq ($(UNAME_SYS), FreeBSD)
CC ?= cc
CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -finline-functions -Wall
else ifeq ($(UNAME_SYS), Linux)
CC ?= gcc
CFLAGS ?= -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -finline-functions -Wall
endif

CFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)
CXXFLAGS += -fPIC -I $(ERTS_INCLUDE_DIR) -I $(ERL_INTERFACE_INCLUDE_DIR)

LDLIBS += -L $(ERL_INTERFACE_LIB_DIR) -lei
LDFLAGS += -shared

# Verbosity.

c_verbose_0 = @echo " C " $(?F);
c_verbose = $(c_verbose_$(V))

cpp_verbose_0 = @echo " CPP " $(?F);
cpp_verbose = $(cpp_verbose_$(V))

link_verbose_0 = @echo " LD " $(@F);
link_verbose = $(link_verbose_$(V))

SOURCES := $(shell find $(C_SRC_DIR) -type f \( -name "*.c" -o -name "*.C" -o -name "*.cc" -o -name "*.cpp" \))
OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))

COMPILE_C = $(c_verbose) $(CC) $(CFLAGS) $(CPPFLAGS) -c
COMPILE_CPP = $(cpp_verbose) $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c

$(C_SRC_OUTPUT): $(OBJECTS)
@mkdir -p $(BASEDIR)/priv/
$(link_verbose) $(CC) $(OBJECTS) $(LDFLAGS) $(LDLIBS) -o $(C_SRC_OUTPUT)

%.o: %.c
$(COMPILE_C) $(OUTPUT_OPTION) $<

%.o: %.cc
$(COMPILE_CPP) $(OUTPUT_OPTION) $<

%.o: %.C
$(COMPILE_CPP) $(OUTPUT_OPTION) $<

%.o: %.cpp
$(COMPILE_CPP) $(OUTPUT_OPTION) $<

clean:
@rm -f $(C_SRC_OUTPUT) $(OBJECTS)
202 changes: 202 additions & 0 deletions apps/ergw_core/c_src/uint32_fy_shuffle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/* Copyright 2021, Travelping GmbH <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/

/* Generate a sequence of at most 2^32 unsigned 32bit integers using the
* Fisher-Yates shuffle */

#include <erl_nif.h>
#include <stdint.h>
#include <time.h>

#define STEPCNT (4*1024)

#define min(x,y) ( \
{ __auto_type __x = (x); __auto_type __y = (y); \
__x < __y ? __x : __y; })

static ERL_NIF_TERM
mk_atom(ErlNifEnv* env, const char* atom)
{
ERL_NIF_TERM ret;

if(!enif_make_existing_atom(env, atom, &ret, ERL_NIF_LATIN1))
{
return enif_make_atom(env, atom);
}

return ret;
}

static void swap (unsigned int *a, unsigned int *b)
{
unsigned int temp = *a;
*a = *b;
*b = temp;
}

static ERL_NIF_TERM shuffle_ret(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM new_argv[4];
ERL_NIF_TERM head, tail;
unsigned int i, n, end;
unsigned int *arr;
ErlNifBinary bin;

if (argc != 4 ||
!enif_get_uint(env, argv[0], &n) || n <= 0 ||
!enif_get_uint(env, argv[1], &i) || i > n ||
!enif_inspect_binary(env, argv[2], &bin) ||
!enif_is_list(env, argv[3]))
return enif_make_badarg(env);

/* printf("ret i: %u\n\r", i); */
/* printf("ret n: %u\n\r", n); */

tail = argv[3];
end = min(n, i + STEPCNT);
arr = (unsigned int *)bin.data;

for (; i < end; i++) {
head = enif_make_tuple1(env,
enif_make_tuple2(env,
enif_make_int64(env, INT64_MIN + i),
enif_make_uint(env, arr[i])));
tail = enif_make_list_cell(env, head, tail);
}

if (i >= n) {
enif_release_binary(&bin);
return tail;
} else {
new_argv[0] = argv[0];
new_argv[1] = enif_make_uint(env, i);
new_argv[2] = argv[2];
new_argv[3] = tail;
return enif_schedule_nif(env, "shuffle_ret", 0, shuffle_ret, 4, new_argv);
}
}

static ERL_NIF_TERM shuffle_randomize(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM new_argv[4];
unsigned int i, n, end;
unsigned int *arr;
ErlNifBinary bin;

if (argc != 3 ||
!enif_get_uint(env, argv[0], &n) || n <= 0 ||
!enif_get_uint(env, argv[1], &i) || i > n ||
!enif_inspect_binary(env, argv[2], &bin))
return enif_make_badarg(env);

if (i == n - 1)
srand(time(NULL));

end = (i > STEPCNT) ? i - STEPCNT : 0;
arr = (unsigned int *)bin.data;

for (; i > end; i--) {
unsigned int j = rand() % (i+1);
swap(&arr[i], &arr[j]);
}

new_argv[0] = argv[0];
new_argv[2] = argv[2];

if (i == 0) {
new_argv[1] = enif_make_uint(env, 0);
new_argv[3] = enif_make_list(env, 0);
return enif_schedule_nif(env, "shuffle_ret", 0, shuffle_ret, 4, new_argv);
} else {
new_argv[1] = enif_make_uint(env, i);
return enif_schedule_nif(env, "shuffle_randomize", 0, shuffle_randomize, 3, new_argv);
}
}

static ERL_NIF_TERM shuffle_fill(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM new_argv[3];
unsigned int i, n, end;
unsigned int *arr;
ErlNifBinary bin;

if (argc != 3 ||
!enif_get_uint(env, argv[0], &n) || n <= 0 ||
!enif_get_uint(env, argv[1], &i) || i > n ||
!enif_inspect_binary(env, argv[2], &bin))
return enif_make_badarg(env);

/* printf("fill i: %u\r\n", i); */
/* printf("fill n: %u\r\n", n); */

end = min(n, i + STEPCNT);
arr = (unsigned int *)bin.data;

for (; i < end; i++)
arr[i] = i;

new_argv[0] = argv[0];
new_argv[2] = argv[2];

if (i == n) {
new_argv[1] = enif_make_uint(env, n - 1);
return enif_schedule_nif(env, "shuffle_randomize", 0, shuffle_randomize, 3, new_argv);
} else {
new_argv[1] = enif_make_uint(env, i);
return enif_schedule_nif(env, "shuffle_fill", 0, shuffle_fill, 3, new_argv);
}
}

static ERL_NIF_TERM shuffle(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM new_argv[3];
unsigned int n;

if (!enif_get_uint(env, argv[0], &n) || n <= 0)
return enif_make_badarg(env);

if (!(enif_make_new_binary(env, n * sizeof(unsigned int), &new_argv[2])))
return enif_raise_exception(env, mk_atom(env, "out_of_memory"));

new_argv[0] = argv[0];
new_argv[1] = enif_make_uint(env, 0);
return enif_schedule_nif(env, "shuffle_fill", 0, shuffle_fill, 3, new_argv);
}

#if 0
static ERL_NIF_TERM shuffle(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM head, tail;
unsigned int *arr;
unsigned int i, n;

if (!enif_get_uint(env, argv[0], &n) || n <= 0)
return enif_make_badarg(env);

if (!(arr = enif_alloc(n * sizeof(arr[0]))))
return enif_raise_exception(env, mk_atom(env, "out_of_memory"));

for (i = 0; i < n; i++)
arr[i] = i;
//randomize(arr, n);

tail = enif_make_list(env, 0);
for (i = 0; i < n; i++) {
head = enif_make_uint(env, arr[i]);
tail = enif_make_list_cell(env, head, tail);
}
return tail;
}
#endif

static ErlNifFunc nif_funcs[] =
{
{"shuffle", 1, shuffle}
};

ERL_NIF_INIT(uint32_fy_shuffle, nif_funcs, NULL, NULL, NULL, NULL)
9 changes: 9 additions & 0 deletions apps/ergw_core/rebar.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{erl_opts, [debug_info]}.
{deps, []}.

{pre_hooks,
[{"(linux|darwin|solaris)", compile, "make -C c_src"},
{"(freebsd)", compile, "gmake -C c_src"}]}.
{post_hooks,
[{"(linux|darwin|solaris)", clean, "make -C c_src clean"},
{"(freebsd)", clean, "gmake -C c_src clean"}]}.
Loading