From b0768b35fb515b7c0a15c3c7d8c1227497c59786 Mon Sep 17 00:00:00 2001 From: Alberto Compagno Date: Mon, 27 Jan 2020 16:04:33 +0100 Subject: [HICN-488] Adding lock to vapi calls and manage vapi_connect in order to connect only once. - Added library to hicn-plugin called safe_vapi that takes care of handling concurrent calls to the vapi. - Removed dependency of libhicnctrl from libtransport and added dependency to safe_vapi. - Added dependency to safe_vapi on libhicnctrl Change-Id: Ie49e8319f64a50e7ed6a56e041db977c3b184cc5 Signed-off-by: Alberto Compagno --- hicn-plugin/vapi/CMakeLists.txt | 70 +++++++++++++++++++++++++++++ hicn-plugin/vapi/include/vapi/vapi_safe.h | 19 ++++++++ hicn-plugin/vapi/vapi_safe.c | 75 +++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 hicn-plugin/vapi/CMakeLists.txt create mode 100644 hicn-plugin/vapi/include/vapi/vapi_safe.h create mode 100644 hicn-plugin/vapi/vapi_safe.c (limited to 'hicn-plugin/vapi') diff --git a/hicn-plugin/vapi/CMakeLists.txt b/hicn-plugin/vapi/CMakeLists.txt new file mode 100644 index 000000000..00bcaf49f --- /dev/null +++ b/hicn-plugin/vapi/CMakeLists.txt @@ -0,0 +1,70 @@ +# Copyright (c) 2019 Cisco and/or its affiliates. +# 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. +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +set(SAFE_VAPI safe_vapi CACHE INTERNAL "" FORCE) +set(SAFE_VAPI_SHARED ${SAFE_VAPI}.shared CACHE INTERNAL "" FORCE) +set(SAFE_VAPI_STATIC ${SAFE_VAPI}.static CACHE INTERNAL "" FORCE) + +project(${SAFE_VAPI}) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules/" + "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules/" +) + +include (Packaging) +include (BuildMacros) + +# Dependencies + +find_package(Vpp REQUIRED) + +list(APPEND HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/include/vapi/vapi_safe.h +) + +list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/vapi_safe.c +) + +set (LIBRARIES + ${VPP_LIBRARIES}) + +list (APPEND INCLUDE_DIRS + ${VPP_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include) + +build_library(${SAFE_VAPI} + SHARED STATIC + SOURCES ${SOURCE_FILES} ${HEADER_FILES} + INSTALL_HEADERS ${HEADER_FILES} + LINK_LIBRARIES ${LIBRARIES} + COMPONENT ${HICN_PLUGIN} + INCLUDE_DIRS ${INCLUDE_DIRS} + INSTALL_ROOT_DIR / + DEFINITIONS ${COMPILER_DEFINITIONS} + ) + +set(SAFE_VAPI_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/include + "" CACHE INTERNAL + "" FORCE +) + +set(SAFE_VAPI_LIBRARIES + ${SAFE_VAPI_SHARED} + "" CACHE INTERNAL + "" FORCE +) + diff --git a/hicn-plugin/vapi/include/vapi/vapi_safe.h b/hicn-plugin/vapi/include/vapi/vapi_safe.h new file mode 100644 index 000000000..df1114cde --- /dev/null +++ b/hicn-plugin/vapi/include/vapi/vapi_safe.h @@ -0,0 +1,19 @@ +#ifndef VAPI_SAFE +#include +#include + +extern pthread_mutex_t *mutex; + +vapi_error_e vapi_connect_safe(vapi_ctx_t * vapi_ctx_ret, int async); + +vapi_error_e vapi_disconnect_safe(); +void vapi_lock(); + +void vapi_unlock(); + +#define VAPI_SAFE (NAME, res, ...) \ + vapi_lock(); \ + res = ## NAME (__ARGS__); \ + vapi_unlock(); + +#endif //VAPI_SAFE diff --git a/hicn-plugin/vapi/vapi_safe.c b/hicn-plugin/vapi/vapi_safe.c new file mode 100644 index 000000000..c1d66c0ac --- /dev/null +++ b/hicn-plugin/vapi/vapi_safe.c @@ -0,0 +1,75 @@ +#include +#include +#include + +#define APP_NAME "hicn_plugin" +#define MAX_OUTSTANDING_REQUESTS 4 +#define RESPONSE_QUEUE_SIZE 2 + +pthread_mutex_t *mutex = NULL; +vapi_ctx_t g_vapi_ctx_instance = NULL; +u32 count = 0; +int lock = 0; + +vapi_error_e vapi_connect_safe(vapi_ctx_t *vapi_ctx_ret, int async) { + vapi_error_e rv = VAPI_OK; + + while (!__sync_bool_compare_and_swap(&lock, 0, 1)); + + if (!g_vapi_ctx_instance && !mutex) + { + rv = vapi_ctx_alloc(&g_vapi_ctx_instance); + if (rv != VAPI_OK) + goto err; + + mutex = malloc(sizeof(pthread_mutex_t)); + if (!mutex) + goto err_mutex_alloc; + + if (pthread_mutex_init(mutex, NULL) != 0) { + printf("Mutex init failed\n"); + goto err_mutex_init; + } + } + + if (!count) + { + rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL, + MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE, + async ? VAPI_MODE_NONBLOCKING : VAPI_MODE_BLOCKING, true); + + if (rv != VAPI_OK) + goto err_vapi; + + count++; + } + + *vapi_ctx_ret = g_vapi_ctx_instance; + + while (!__sync_bool_compare_and_swap(&lock, 1, 0)); + return rv; + + err_vapi: + vapi_ctx_free(g_vapi_ctx_instance); + err_mutex_init: + free(mutex); + err_mutex_alloc: + err: + while (!__sync_bool_compare_and_swap(&lock, 1, 0)); + return VAPI_ENOMEM; +} + +vapi_error_e vapi_disconnect_safe() { + pthread_mutex_lock(mutex); + vapi_error_e rv = VAPI_OK; + pthread_mutex_unlock(mutex); + return rv; +} + +void vapi_lock() { + pthread_mutex_lock(mutex); +} + +void vapi_unlock() { + pthread_mutex_unlock(mutex); +} -- cgit 1.2.3-korg