From b63ec47559ad7b90f348dd733b805d78d156893d Mon Sep 17 00:00:00 2001 From: nanger Date: Mon, 20 Aug 2018 11:14:15 +0800 Subject: Feat: add new share memory module Change-Id: I25e6ca1bd3d2acc0031926e3f46d4501e8d78f1a Signed-off-by: nanger --- src/CMakeLists.txt | 6 +- src/framework/CMakeLists.txt | 7 +- src/framework/common/include/arch/x86/dmm_atomic.h | 21 + .../common/include/arch/x86/dmm_barrier.h | 21 + src/framework/common/include/arch/x86/dmm_pause.h | 30 ++ src/framework/common/include/arch/x86/dmm_rwlock.h | 21 + .../common/include/arch/x86/dmm_spinlock.h | 21 + src/framework/common/include/dmm_fs.h | 32 ++ src/framework/common/include/generic/dmm_atomic.h | 177 +++++++ src/framework/common/include/generic/dmm_barrier.h | 25 + src/framework/common/include/generic/dmm_pause.h | 30 ++ src/framework/common/include/generic/dmm_rwlock.h | 76 +++ .../common/include/generic/dmm_spinlock.h | 53 ++ src/framework/include/dmm_config.h | 43 ++ src/framework/mem/dmm_fshm.c | 144 ++++++ src/framework/mem/dmm_group.c | 185 +++++++ src/framework/mem/dmm_group.h | 36 ++ src/framework/mem/dmm_heap.c | 83 ++++ src/framework/mem/dmm_huge.c | 53 ++ src/framework/mem/dmm_memory.c | 133 +++++ src/framework/mem/dmm_memory.h | 78 +++ src/framework/mem/dmm_segment.c | 543 +++++++++++++++++++++ src/framework/mem/dmm_segment.h | 35 ++ src/framework/mem/dmm_share.h | 114 +++++ 24 files changed, 1963 insertions(+), 4 deletions(-) create mode 100644 src/framework/common/include/arch/x86/dmm_atomic.h create mode 100644 src/framework/common/include/arch/x86/dmm_barrier.h create mode 100644 src/framework/common/include/arch/x86/dmm_pause.h create mode 100644 src/framework/common/include/arch/x86/dmm_rwlock.h create mode 100644 src/framework/common/include/arch/x86/dmm_spinlock.h create mode 100644 src/framework/common/include/dmm_fs.h create mode 100644 src/framework/common/include/generic/dmm_atomic.h create mode 100644 src/framework/common/include/generic/dmm_barrier.h create mode 100644 src/framework/common/include/generic/dmm_pause.h create mode 100644 src/framework/common/include/generic/dmm_rwlock.h create mode 100644 src/framework/common/include/generic/dmm_spinlock.h create mode 100644 src/framework/include/dmm_config.h create mode 100644 src/framework/mem/dmm_fshm.c create mode 100644 src/framework/mem/dmm_group.c create mode 100644 src/framework/mem/dmm_group.h create mode 100644 src/framework/mem/dmm_heap.c create mode 100644 src/framework/mem/dmm_huge.c create mode 100644 src/framework/mem/dmm_memory.c create mode 100644 src/framework/mem/dmm_memory.h create mode 100644 src/framework/mem/dmm_segment.c create mode 100644 src/framework/mem/dmm_segment.h create mode 100644 src/framework/mem/dmm_share.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1a7f63f..c71659c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,11 +22,13 @@ endif() INCLUDE_DIRECTORIES( framework/log/ + framework/mem framework/include/ framework/common/include/ + framework/common/include/arch/${DMM_ARCH} framework/common/base/include/ - framework/common/base/include/common/ - ${PRI_DIRECTORIES} + framework/common/base/include/common/ + ${PRI_DIRECTORIES} ../platform/SecureC/include/ ../thirdparty/glog/glog-0.3.4/src/ ) diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index b76e1ce..6b22e51 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -29,10 +29,13 @@ FILE(GLOB STARTUP startup/*.c) FILE(GLOB MAINTAIN maintain/*.c) FILE(GLOB HAL hal/*.c) FILE(GLOB DMM_ADPT ../adapt/*.c) +FILE(GLOB MEM mem/*.c) +ADD_LIBRARY(dmm_api SHARED + ${COMMON} ${INIT} ${IPC} ${LOG} ${SNAPSHOT} + ${STARTUP} ${MAINTAIN} ${TRACEING} ${HAL} + ${DMM_ADPT} ${LIBCOMM} ${MEM}) - -ADD_LIBRARY(dmm_api SHARED ${COMMON} ${INIT} ${IPC} ${LOG} ${SNAPSHOT} ${STARTUP} ${MAINTAIN} ${TRACEING} ${HAL} ${DMM_ADPT} ${LIBCOMM}) if(WITH_SECUREC_LIB) ADD_DEPENDENCIES(dmm_api SECUREC JSON GLOG) else() diff --git a/src/framework/common/include/arch/x86/dmm_atomic.h b/src/framework/common/include/arch/x86/dmm_atomic.h new file mode 100644 index 0000000..fae99c2 --- /dev/null +++ b/src/framework/common/include/arch/x86/dmm_atomic.h @@ -0,0 +1,21 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_ATOMIC_H__ARCH_X86_ +#define _DMM_ATOMIC_H__ARCH_X86_ + +#include "generic/dmm_atomic.h" + +#endif /* #ifndef _DMM_ATOMIC_H__ARCH_X86_ */ diff --git a/src/framework/common/include/arch/x86/dmm_barrier.h b/src/framework/common/include/arch/x86/dmm_barrier.h new file mode 100644 index 0000000..bf53650 --- /dev/null +++ b/src/framework/common/include/arch/x86/dmm_barrier.h @@ -0,0 +1,21 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_BARRIER_H__ARCH_X86_ +#define _DMM_BARRIER_H__ARCH_X86_ + +#include "generic/dmm_barrier.h" + +#endif /* #ifndef _DMM_BARRIER_H__ARCH_X86_ */ diff --git a/src/framework/common/include/arch/x86/dmm_pause.h b/src/framework/common/include/arch/x86/dmm_pause.h new file mode 100644 index 0000000..56c60f0 --- /dev/null +++ b/src/framework/common/include/arch/x86/dmm_pause.h @@ -0,0 +1,30 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_PAUSE_H_ +#define _DMM_PAUSE_H_ + +#include + +inline static void +dmm_pause (void) +{ + _mm_pause (); +} + +#define DMM_PAUSE_WHILE(cond) do { dmm_pause(); } while (!!(cond)) +#define DMM_WHILE_PAUSE(cond) do { while (!!(cond)) dmm_pause(); } while (0) + +#endif /* #ifndef _DMM_PAUSE_H_ */ diff --git a/src/framework/common/include/arch/x86/dmm_rwlock.h b/src/framework/common/include/arch/x86/dmm_rwlock.h new file mode 100644 index 0000000..0c31329 --- /dev/null +++ b/src/framework/common/include/arch/x86/dmm_rwlock.h @@ -0,0 +1,21 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_RWLOCK_H__ARCH_X86_ +#define _DMM_RWLOCK_H__ARCH_X86_ + +#include "generic/dmm_rwlock.h" + +#endif /* #ifndef _DMM_RWLOCK_H__ARCH_X86_ */ diff --git a/src/framework/common/include/arch/x86/dmm_spinlock.h b/src/framework/common/include/arch/x86/dmm_spinlock.h new file mode 100644 index 0000000..69ed9a6 --- /dev/null +++ b/src/framework/common/include/arch/x86/dmm_spinlock.h @@ -0,0 +1,21 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_SPINLOCK_H__ARCH_X86_ +#define _DMM_SPINLOCK_H__ARCH_X86_ + +#include "generic/dmm_spinlock.h" + +#endif /* #ifndef _DMM_SPINLOCK_H__ARCH_X86_ */ diff --git a/src/framework/common/include/dmm_fs.h b/src/framework/common/include/dmm_fs.h new file mode 100644 index 0000000..8fd9cd0 --- /dev/null +++ b/src/framework/common/include/dmm_fs.h @@ -0,0 +1,32 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_FS_H_ +#define _DMM_FS_H_ + +#include +#include +#include + +static size_t +dmm_file_size (int fd) +{ + struct stat st; + if (fstat (fd, &st) < 0) + return 0; + return st.st_size; +} + +#endif /* _DMM_FS_H_ */ diff --git a/src/framework/common/include/generic/dmm_atomic.h b/src/framework/common/include/generic/dmm_atomic.h new file mode 100644 index 0000000..637306b --- /dev/null +++ b/src/framework/common/include/generic/dmm_atomic.h @@ -0,0 +1,177 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_ATOMIC_H_ +#define _DMM_ATOMIC_H_ + +/* atomic 32 bit operation */ + +typedef struct +{ + volatile int cnt; +} dmm_atomic_t; + +inline static int +dmm_atomic_get (dmm_atomic_t * a) +{ + return a->cnt; +} + +inline static int +dmm_atomic_add (dmm_atomic_t * a, int n) +{ + return __sync_fetch_and_add (&a->cnt, n); +} + +inline static int +dmm_atomic_sub (dmm_atomic_t * a, int n) +{ + return __sync_fetch_and_sub (&a->cnt, n); +} + +inline static int +dmm_atomic_and (dmm_atomic_t * a, int n) +{ + return __sync_fetch_and_and (&a->cnt, n); +} + +inline static int +dmm_atomic_or (dmm_atomic_t * a, int n) +{ + return __sync_fetch_and_or (&a->cnt, n); +} + +inline static int +dmm_atomic_xor (dmm_atomic_t * a, int n) +{ + return __sync_fetch_and_xor (&a->cnt, n); +} + +inline static int +dmm_atomic_swap (dmm_atomic_t * a, int o, int n) +{ + return __sync_val_compare_and_swap (&a->cnt, o, n); +} + +inline static int +dmm_atomic_add_return (dmm_atomic_t * a, int n) +{ + return __sync_add_and_fetch (&a->cnt, n); +} + +inline static int +dmm_atomic_sub_return (dmm_atomic_t * a, int n) +{ + return __sync_sub_and_fetch (&a->cnt, n); +} + +inline static int +dmm_atomic_and_return (dmm_atomic_t * a, int n) +{ + return __sync_and_and_fetch (&a->cnt, n); +} + +inline static int +dmm_atomic_or_return (dmm_atomic_t * a, int n) +{ + return __sync_or_and_fetch (&a->cnt, n); +} + +inline static int +dmm_atomic_xor_return (dmm_atomic_t * a, int n) +{ + return __sync_xor_and_fetch (&a->cnt, n); +} + +/* atomit 64bit operation */ + +typedef struct +{ + volatile long long int cnt; +} dmm_atomic64_t; + +inline static long long int +dmm_atomic64_get (dmm_atomic64_t * a) +{ + return a->cnt; +} + +inline static long long int +dmm_atomic64_add (dmm_atomic64_t * a, int n) +{ + return __sync_fetch_and_add (&a->cnt, n); +} + +inline static long long int +dmm_atomic64_sub (dmm_atomic64_t * a, int n) +{ + return __sync_fetch_and_sub (&a->cnt, n); +} + +inline static long long int +dmm_atomic64_and (dmm_atomic64_t * a, int n) +{ + return __sync_fetch_and_and (&a->cnt, n); +} + +inline static long long int +dmm_atomic64_or (dmm_atomic64_t * a, int n) +{ + return __sync_fetch_and_or (&a->cnt, n); +} + +inline static long long int +dmm_atomic64_xor (dmm_atomic64_t * a, int n) +{ + return __sync_fetch_and_xor (&a->cnt, n); +} + +inline static long long int +dmm_atomic64_swap (dmm_atomic_t * a, int o, int n) +{ + return __sync_val_compare_and_swap (&a->cnt, o, n); +} + +inline static long long int +dmm_atomic64_add_return (dmm_atomic64_t * a, int n) +{ + return __sync_add_and_fetch (&a->cnt, n); +} + +inline static long long int +dmm_atomic64_sub_return (dmm_atomic64_t * a, int n) +{ + return __sync_sub_and_fetch (&a->cnt, n); +} + +inline static long long int +dmm_atomic64_and_return (dmm_atomic64_t * a, int n) +{ + return __sync_and_and_fetch (&a->cnt, n); +} + +inline static long long int +dmm_atomic64_or_return (dmm_atomic64_t * a, int n) +{ + return __sync_or_and_fetch (&a->cnt, n); +} + +inline static long long int +dmm_atomic64_xor_return (dmm_atomic64_t * a, int n) +{ + return __sync_xor_and_fetch (&a->cnt, n); +} + +#endif /* #ifndef _DMM_ATOMIC_H_ */ diff --git a/src/framework/common/include/generic/dmm_barrier.h b/src/framework/common/include/generic/dmm_barrier.h new file mode 100644 index 0000000..b70fe85 --- /dev/null +++ b/src/framework/common/include/generic/dmm_barrier.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_BARRIER_H_ +#define _DMM_BARRIER_H_ + +inline static void +dmm_barrier (void) +{ + __sync_synchronize (); +} + +#endif /* #ifndef _DMM_BARRIER_H_ */ diff --git a/src/framework/common/include/generic/dmm_pause.h b/src/framework/common/include/generic/dmm_pause.h new file mode 100644 index 0000000..56c60f0 --- /dev/null +++ b/src/framework/common/include/generic/dmm_pause.h @@ -0,0 +1,30 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_PAUSE_H_ +#define _DMM_PAUSE_H_ + +#include + +inline static void +dmm_pause (void) +{ + _mm_pause (); +} + +#define DMM_PAUSE_WHILE(cond) do { dmm_pause(); } while (!!(cond)) +#define DMM_WHILE_PAUSE(cond) do { while (!!(cond)) dmm_pause(); } while (0) + +#endif /* #ifndef _DMM_PAUSE_H_ */ diff --git a/src/framework/common/include/generic/dmm_rwlock.h b/src/framework/common/include/generic/dmm_rwlock.h new file mode 100644 index 0000000..93570f1 --- /dev/null +++ b/src/framework/common/include/generic/dmm_rwlock.h @@ -0,0 +1,76 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_RWLOCK_H_ +#define _DMM_RWLOCK_H_ + +#include "dmm_pause.h" + +typedef struct +{ + volatile int lock; +} dmm_rwlock_t; + +#define DMM_RWLOCK_INIT { 0 } + +inline static void +dmm_rwlock_init (dmm_rwlock_t * rwlock) +{ + rwlock->lock = 0; +} + +inline static void +dmm_read_lock (dmm_rwlock_t * rwlock) +{ + int val; + + do + { + if ((val = rwlock->lock) < 0) + { + dmm_pause (); + continue; + } + } + while (!__sync_bool_compare_and_swap (&rwlock->lock, val, val + 1)); +} + +inline static void +dmm_read_unlock (dmm_rwlock_t * rwlock) +{ + __sync_sub_and_fetch (&rwlock->lock, 1); +} + +inline static void +dmm_write_lock (dmm_rwlock_t * rwlock) +{ + do + { + if (rwlock->lock != 0) + { + dmm_pause (); + continue; + } + } + while (!__sync_bool_compare_and_swap (&rwlock->lock, 0, -1)); +} + +inline static void +dmm_write_unlock (dmm_rwlock_t * rwlock) +{ + rwlock->lock = 0; +} + +#endif /* #ifndef _DMM_RWLOCK_H_ */ diff --git a/src/framework/common/include/generic/dmm_spinlock.h b/src/framework/common/include/generic/dmm_spinlock.h new file mode 100644 index 0000000..be183a6 --- /dev/null +++ b/src/framework/common/include/generic/dmm_spinlock.h @@ -0,0 +1,53 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_SPINLOCK_H_ +#define _DMM_SPINLOCK_H_ + +#include "dmm_pause.h" + +typedef struct +{ + volatile int lock; +} dmm_spinlock_t; + +inline static void +dmm_spin_init (dmm_spinlock_t * spinlock) +{ + spinlock->lock = 0; +} + +inline static void +dmm_spin_lock (dmm_spinlock_t * spinlock) +{ + while (0 != __sync_lock_test_and_set (&spinlock->lock, 1)) + { + DMM_PAUSE_WHILE (spinlock->lock); + } +} + +inline static int +dmm_spin_trylock (dmm_spinlock_t * spinlock) +{ + return 0 == __sync_lock_test_and_set (&spinlock->lock, 1); +} + +inline static void +dmm_spin_unlock (dmm_spinlock_t * spinlock) +{ + spinlock->lock = 0; +} + +#endif /* #ifndef _DMM_SPINLOCK_H_ */ diff --git a/src/framework/include/dmm_config.h b/src/framework/include/dmm_config.h new file mode 100644 index 0000000..43a06ab --- /dev/null +++ b/src/framework/include/dmm_config.h @@ -0,0 +1,43 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_CONFIG_H_ +#define _DMM_CONFIG_H_ + +#ifndef DMM_VAR_DIR +#define DMM_VAR_DIR "/var/run" +#endif + +#ifndef DMM_MAIN_SHARE_TYPE +#define DMM_MAIN_SHARE_TYPE DMM_SHARE_FSHM /* 1 */ +#endif + +#ifndef DMM_MAIN_SHARE_SIZE +#define DMM_MAIN_SHARE_SIZE 1024 /* Megabyte */ +#endif + +#ifndef DMM_SHARE_TYPE +#define DMM_SHARE_TYPE DMM_SHARE_FSHM /* 1 */ +#endif + +#ifndef DMM_SHARE_SIZE +#define DMM_SHARE_SIZE 16 /* Megabyte */ +#endif + +#ifndef DMM_HUGE_DIR +#define DMM_HUGE_DIR "/mnt/dmm-huge" +#endif + +#endif /* _DMM_CONFIG_H_ */ diff --git a/src/framework/mem/dmm_fshm.c b/src/framework/mem/dmm_fshm.c new file mode 100644 index 0000000..605c728 --- /dev/null +++ b/src/framework/mem/dmm_fshm.c @@ -0,0 +1,144 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 +#include +#include +#include +#include +#include + +#include "dmm_config.h" +#include "dmm_share.h" +#include "dmm_fs.h" + +#define DMM_FSHM_FMT "%s/dmm-fshm-%d" /* VAR_DIR pid */ + +inline static void +set_fshm_path (struct dmm_share *share) +{ + (void) snprintf (share->path, sizeof (share->path), DMM_FSHM_FMT, + DMM_VAR_DIR, share->pid); +} + +/* +input: share->path, share->size, share->pid +output: share->base +*/ +int +dmm_fshm_create (struct dmm_share *share) +{ + int fd, ret; + void *base; + + set_fshm_path (share); + + fd = open (share->path, O_RDWR | O_CREAT, 0666); + if (fd < 0) + { + return -1; + } + + ret = ftruncate (fd, share->size); + if (ret < 0) + { + (void) close (fd); + return -1; + } + + base = mmap (NULL, share->size, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, 0); + if (base == MAP_FAILED) + { + (void) close (fd); + return -1; + } + + share->base = base; + + (void) close (fd); + return 0; +} + +int +dmm_fshm_delete (struct dmm_share *share) +{ + (void) munmap (share->base, share->size); + (void) unlink (share->path); + + return 0; +} + +/* +input: share->path, share->size, share->base(OPT) +output: share->base(if-null) +*/ +int +dmm_fshm_attach (struct dmm_share *share) +{ + int fd; + void *base; + + if (share->type != DMM_SHARE_FSHM) + { + return -1; + } + + fd = open (share->path, O_RDWR); + if (fd < 0) + { + return -1; + } + + if (share->size <= 0) + { + share->size = dmm_file_size (fd); + if (share->size == 0) + { + (void) close (fd); + return -1; + } + } + + base = mmap (share->base, share->size, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, 0); + if (base == MAP_FAILED) + { + (void) close (fd); + return -1; + } + + if (NULL == share->base) + { + share->base = base; + } + else if (base != share->base) + { + (void) munmap (base, share->size); + (void) close (fd); + return -1; + } + + (void) close (fd); + return 0; +} + +int +dmm_fshm_detach (struct dmm_share *share) +{ + (void) munmap (share->base, share->size); + + return 0; +} diff --git a/src/framework/mem/dmm_group.c b/src/framework/mem/dmm_group.c new file mode 100644 index 0000000..35e6100 --- /dev/null +++ b/src/framework/mem/dmm_group.c @@ -0,0 +1,185 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 +#include +#include +#include +#include +#include +#include +#include + +//#include "dmm_memory.h" +#include "dmm_config.h" +#include "dmm_group.h" +#include "dmm_pause.h" + +#define DMM_GROUP_ACTIVE 0x55D5551 +#define DMM_GROUP_GLOBAL "global" +#define DMM_GROUP_ENV "DMM_GROUP" +#define DMM_GROUP_FMT "%s/dmm-group-%s" /* VAR_DIR group-name */ + +static struct flock group_lock = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = sizeof (struct dmm_group), +}; + +static int group_fd = -1; +struct dmm_group *main_group = NULL; + +inline static const char * +get_group_path () +{ + static char group_path[PATH_MAX] = ""; + + if (!group_path[0]) + { + const char *group = getenv (DMM_GROUP_ENV); + + if (!group || !group[0]) + group = DMM_GROUP_GLOBAL; + + (void) snprintf (group_path, sizeof (group_path), DMM_GROUP_FMT, + DMM_VAR_DIR, group); + group_path[sizeof (group_path) - 1] = 0; + } + + return group_path; +} + +void +dmm_group_active () +{ + main_group->group_init = DMM_GROUP_ACTIVE; +} + +int +dmm_group_create_main () +{ + int ret; + const char *path = get_group_path (); + + group_fd = open (path, O_RDWR | O_CREAT, 0664); + if (group_fd < 0) + { + return -1; + } + + ret = ftruncate (group_fd, sizeof (struct dmm_group)); + if (ret < 0) + { + (void) close (group_fd); + group_fd = -1; + return -1; + } + + ret = fcntl (group_fd, F_SETLK, &group_lock); + if (ret < 0) + { + (void) close (group_fd); + group_fd = -1; + return -1; + } + + main_group = (struct dmm_group *) mmap (NULL, sizeof (struct dmm_group), + PROT_READ | PROT_WRITE, MAP_SHARED, + group_fd, 0); + + if (main_group == MAP_FAILED) + { + (void) close (group_fd); + group_fd = -1; + return -1; + } + + return 0; +} + +int +dmm_group_delete_main () +{ + if (main_group) + { + (void) munmap (main_group, sizeof (struct dmm_group)); + main_group = NULL; + } + + if (group_fd >= 0) + { + (void) close (group_fd); + group_fd = -1; + } + + (void) unlink (get_group_path ()); + + return 0; +} + +int +dmm_group_attach_main () +{ + const char *path = get_group_path (); + + group_fd = open (path, O_RDONLY); + if (group_fd < 0) + { + return -1; + } + + main_group = (struct dmm_group *) mmap (NULL, sizeof (struct dmm_group *), + PROT_READ, MAP_SHARED, group_fd, 0); + if (main_group == MAP_FAILED) + { + (void) close (group_fd); + group_fd = -1; + return -1; + } + + while (main_group->group_init != DMM_GROUP_ACTIVE) + { + dmm_pause (); + } + + if (kill (main_group->share.pid, 0)) + { + (void) munmap (main_group->share.base, main_group->share.size); + (void) close (group_fd); + group_fd = -1; + return -1; + } + + return 0; +} + +int +dmm_group_detach_main () +{ + if (main_group) + { + (void) munmap (main_group, sizeof (struct dmm_group)); + main_group = NULL; + } + + if (group_fd >= 0) + { + (void) close (group_fd); + group_fd = -1; + } + + return 0; +} diff --git a/src/framework/mem/dmm_group.h b/src/framework/mem/dmm_group.h new file mode 100644 index 0000000..b11a22b --- /dev/null +++ b/src/framework/mem/dmm_group.h @@ -0,0 +1,36 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_GROUP_H_ +#define _DMM_GROUP_H_ + +#include "dmm_share.h" + +struct dmm_group +{ + volatile int group_init; + struct dmm_share share; +}; + +extern struct dmm_group *main_group; + +void dmm_group_active (); +int dmm_group_create_main (); +int dmm_group_delete_main (); +int dmm_group_attach_main (); +int dmm_group_detach_main (); + +#endif /* _DMM_GROUP_H_ */ diff --git a/src/framework/mem/dmm_heap.c b/src/framework/mem/dmm_heap.c new file mode 100644 index 0000000..bc966ef --- /dev/null +++ b/src/framework/mem/dmm_heap.c @@ -0,0 +1,83 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 +#include + +#include "dmm_config.h" +#include "dmm_share.h" + +struct heap_path +{ + void *base; + size_t size; +}; + +int +dmm_heap_create (struct dmm_share *share) +{ + share->base = malloc (share->size); + + if (share->base) + { + struct heap_path *hp = (struct heap_path *) share->path; + hp->base = share->base; + hp->size = share->size; + return 0; + } + + return -1; +} + +int +dmm_heap_delete (struct dmm_share *share) +{ + free (share->base); + return 0; +} + +int +dmm_heap_attach (struct dmm_share *share) +{ + struct heap_path *hp = (struct heap_path *) share->path; + + if (share->base) + { + if (hp->base != share->base) + return -1; + } + else + { + share->base = hp->base; + } + + if (share->size) + { + if (share->size != hp->size) + return -1; + } + else + { + share->size = hp->size; + } + + return 0; +} + +int +dmm_heap_detach (struct dmm_share *share) +{ + return 0; +} diff --git a/src/framework/mem/dmm_huge.c b/src/framework/mem/dmm_huge.c new file mode 100644 index 0000000..735c507 --- /dev/null +++ b/src/framework/mem/dmm_huge.c @@ -0,0 +1,53 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 +#include + +#include "dmm_config.h" +#include "dmm_share.h" + +#define DMM_HUGE_FMT "%s/dmm-%d-%d" /* HUGE_DIR pid index */ + +inline static void +huge_set_path (struct dmm_share *share, int index) +{ + (void) snprintf (share->path, sizeof (share->path), DMM_HUGE_FMT, + DMM_HUGE_DIR, share->pid, index); +} + +int +dmm_huge_create (struct dmm_share *share) +{ + return -1; +} + +int +dmm_huge_delete (struct dmm_share *share) +{ + return -1; +} + +int +dmm_huge_attach (struct dmm_share *share) +{ + return -1; +} + +int +dmm_huge_detach (struct dmm_share *share) +{ + return -1; +} diff --git a/src/framework/mem/dmm_memory.c b/src/framework/mem/dmm_memory.c new file mode 100644 index 0000000..0352432 --- /dev/null +++ b/src/framework/mem/dmm_memory.c @@ -0,0 +1,133 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 +#include + +#include "dmm_config.h" +#include "dmm_memory.h" +#include "dmm_group.h" + +#define DMM_MEGABYTE (1024 * 1024) + +/* shared from main process */ +static struct dmm_share *main_share = NULL; +struct dmm_segment *main_seg = NULL; + +/* shared by process tree */ +static struct dmm_share base_share = { 0 }; + +struct dmm_segment *base_seg = NULL; + +int +dmm_mem_main_init () +{ + int ret; + + ret = dmm_group_create_main (); + if (ret) + { + return -1; + } + + main_share = &main_group->share; + main_share->type = DMM_MAIN_SHARE_TYPE; + main_share->size = DMM_MAIN_SHARE_SIZE * DMM_MEGABYTE; + main_share->base = NULL; + main_share->pid = getpid (); + ret = dmm_share_create (main_share); + if (ret) + { + return -1; + } + + main_seg = dmm_seg_create (main_share->base, main_share->size); + if (!main_seg) + { + return -1; + } + + dmm_group_active (); + + return 0; +} + +int +dmm_mem_main_exit () +{ + dmm_group_delete_main (); + return 0; +} + +int +dmm_mem_app_init () +{ + int ret; + + ret = dmm_group_attach_main (); + if (0 == ret) + { + main_share = &main_group->share; + ret = dmm_share_attach (main_share); + if (ret) + { + return -1; + } + + main_seg = dmm_seg_attach (main_share->base, main_share->size); + if (!main_seg) + { + return -1; + } + + /* now share main process share-memory */ + base_seg = main_seg; + } + else + { + base_share.type = DMM_SHARE_TYPE; + base_share.size = DMM_SHARE_SIZE * DMM_MEGABYTE; + base_share.base = NULL; + base_share.pid = getpid (); + ret = dmm_share_create (&base_share); + if (ret) + { + return -1; + } + + base_seg = dmm_seg_create (base_share.base, base_share.size); + if (!base_seg) + { + return -1; + } + } + + return 0; +} + +int +dmm_mem_app_exit () +{ + dmm_group_detach_main (); + + if (base_share.base) + dmm_share_delete (&base_share); + + base_share.base = NULL; + base_seg = NULL; + main_seg = NULL; + + return 0; +} diff --git a/src/framework/mem/dmm_memory.h b/src/framework/mem/dmm_memory.h new file mode 100644 index 0000000..2fac118 --- /dev/null +++ b/src/framework/mem/dmm_memory.h @@ -0,0 +1,78 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_MEMORY_H_ +#define _DMM_MEMORY_H_ +#include +#include +#include "dmm_share.h" +#include "dmm_segment.h" + +int dmm_mem_main_init (); +int dmm_mem_main_exit (); + +int dmm_mem_app_init (); +int dmm_mem_app_exit (); + +extern struct dmm_segment *main_seg; +extern struct dmm_segment *base_seg; + +inline static void * +dmm_map (size_t size, const char name[DMM_MEM_NAME_SIZE]) +{ + return dmm_mem_map (base_seg, size, name); +} + +inline static void * +dmm_mapv (size_t size, const char *name_fmt, ...) +{ + int len; + char name[DMM_MEM_NAME_SIZE]; + va_list ap; + + va_start (ap, name_fmt); + len = vsnprintf (name, DMM_MEM_NAME_SIZE, name_fmt, ap); + va_end (ap); + + if (len >= DMM_MEM_NAME_SIZE) + return NULL; + + return dmm_map (size, name); +} + +inline static void * +dmm_lookup (const char name[DMM_MEM_NAME_SIZE]) +{ + return dmm_mem_lookup (base_seg, name); +} + +inline static void * +dmm_lookupv (const char *name_fmt, ...) +{ + int len; + char name[DMM_MEM_NAME_SIZE]; + va_list ap; + + va_start (ap, name_fmt); + len = vsnprintf (name, DMM_MEM_NAME_SIZE, name_fmt, ap); + va_end (ap); + + if (len >= DMM_MEM_NAME_SIZE) + return NULL; + + return dmm_mem_lookup (base_seg, name); +} + +#endif /* _DMM_MEMORY_H_ */ diff --git a/src/framework/mem/dmm_segment.c b/src/framework/mem/dmm_segment.c new file mode 100644 index 0000000..6358506 --- /dev/null +++ b/src/framework/mem/dmm_segment.c @@ -0,0 +1,543 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 +#include +#include "dmm_rwlock.h" +#include "dmm_segment.h" +#include "nstack_log.h" + +#define SECTION_SIZE 64 /* cache line size */ + +#define FIRST_NAME "FIRST SECTION FOR SEGMENT" +#define LAST_NAME "LAST SECTION FOR FREE HEAD" + +#define MEM_ERR(fmt, ...) \ + NS_LOGPID(LOGFW, "DMM-MEM", NSLOG_ERR, fmt, ##__VA_ARGS__) + +/* +init create: + \--total number + /--head no align \ can be used \--tail no align + / ___________________/\___________________ \ +/\/ \/\ +__{S}[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]__ +^ \ /\ /\____________ ________________/\ / +| | | \ / | +| | +--the segment | +--last section(free:0 used:0) +| +--first section(prev_rel:0 used:2 free:11 req_size:sizeof(dmm_segment)) ++--base address + +init: {S}[ ] +alloc A: {S}[ ]######### +alloc B: {S}[ ]################## +free A: {S}[ ]#########[ ] +alloc C: {S}[ ]############[ ] +*/ + +typedef struct dmm_section +{ + int prev_rel; + int used_num; + int free_num; + int __flags; /* reserved */ + size_t req_size; /* in bytes */ + int less_rel; /* for free list */ + int more_rel; /* for free list */ + char name[DMM_MEM_NAME_SIZE]; +} __attribute__ ((__aligned__ (SECTION_SIZE))) section_t; +SIZE_OF_TYPE_EQUAL_TO (section_t, SECTION_SIZE); + +struct dmm_segment +{ + void *base; /* base address(maybe not align) */ + size_t size; /* full size */ + section_t *first; /* aligned 64 */ + section_t *last; /* last section used to handle free list */ + dmm_rwlock_t lock; + int total_num; /* MAX:2147483647 ==> MAX size: 128M-64 */ + int used_num; + int sec_num; + size_t used_size; /* real alloc size bytes */ +}; + +/* calculate segment number, auto align 64, include 1 section_t */ +inline static int +CALC_NUM (size_t size) +{ + if (size) + { + const size_t MASK = SECTION_SIZE - 1; + return (size + MASK) / SECTION_SIZE + 1; + } + + return 2; /* if size is 0, then alloc 1 block */ +} + +inline static int +SEC_REL (const section_t * base, const section_t * sec) +{ + return sec - base; +} + +section_t * +REL_SEC (section_t * base, int rel) +{ + return base + rel; +} + +inline static int +SEC_INDEX (struct dmm_segment *seg, section_t * sec) +{ + return SEC_REL (seg->first, sec); +} + +inline static section_t * +LESS_SEC (section_t * sec) +{ + return sec + sec->less_rel; +} + +inline static section_t * +MORE_SEC (section_t * sec) +{ + return sec + sec->more_rel; +} + +inline static section_t * +PREV_SEC (section_t * sec) +{ + return sec + sec->prev_rel; +} + +inline static section_t * +NEXT_SEC (section_t * sec) +{ + return sec + (sec->free_num + sec->used_num); +} + +inline static int +CHECK_ADDR (struct dmm_segment *seg, void *mem) +{ + if (mem < (void *) seg->first) + return -1; + if (mem > (void *) seg->last) + return -1; + if ((long) mem & (SECTION_SIZE - 1)) + return -1; + + return 0; +} + +inline static section_t * +mem_lookup (struct dmm_segment *seg, const char name[DMM_MEM_NAME_SIZE]) +{ + section_t *sec; + + /* caller ensures the validity of the name */ + + for (sec = seg->last; sec != seg->first; sec = PREV_SEC (sec)) + { + if (sec->name[0] == 0) + continue; + if (0 == strcmp (sec->name, name)) + return sec; + } + + return NULL; +} + +static section_t * +mem_alloc (struct dmm_segment *seg, size_t size) +{ + const int num = CALC_NUM (size); + section_t *sec, *pos, *next, *less, *more; + + if (num > seg->total_num - seg->used_num) + { + /* no enough memory */ + return NULL; + } + + /* find enough free space */ + pos = seg->last; + do + { + pos = MORE_SEC (pos); + if (pos == seg->last) + { + /* no enough memory */ + return NULL; + } + } + while (num > pos->free_num); + + /* allocate pos pos section tail */ + + /* change next section's prev possion */ + next = NEXT_SEC (pos); + next->prev_rel = -num; + + /* create new section */ + sec = PREV_SEC (next); + sec->prev_rel = SEC_REL (sec, pos); + sec->used_num = num; + sec->req_size = size; + sec->free_num = 0; /* no free space */ + sec->less_rel = 0; + sec->more_rel = 0; + sec->name[0] = 0; + + /* adjust pos */ + pos->free_num -= num; + + less = LESS_SEC (pos); + more = MORE_SEC (pos); + + /* remove pos free list */ + less->more_rel = SEC_REL (less, more); + more->less_rel = SEC_REL (more, less); + pos->more_rel = 0; + pos->less_rel = 0; + + /* find position */ + while (less != seg->last) + { + if (pos->free_num >= less->free_num) + break; + less = LESS_SEC (less); + } + + /* insert into free list */ + more = MORE_SEC (less); + less->more_rel = SEC_REL (less, pos); + more->less_rel = SEC_REL (more, pos); + pos->more_rel = SEC_REL (pos, more); + pos->less_rel = SEC_REL (pos, less); + + /* adjust segment */ + seg->used_size += size; + seg->used_num += num; + seg->sec_num++; + + /* victory */ + return sec; +} + +static void +mem_free (struct dmm_segment *seg, section_t * sec) +{ + const int num = sec->used_num + sec->free_num; + section_t *next = NEXT_SEC (sec); + section_t *prev = PREV_SEC (sec); + section_t *more, *less; + + /* adjust next section's prev */ + next->prev_rel = SEC_REL (next, prev); + + if (sec->free_num) + { + /* remove from free list */ + more = MORE_SEC (sec); + less = LESS_SEC (sec); + more->less_rel = SEC_REL (more, less); + less->more_rel = SEC_REL (less, more); + } + + if (prev->free_num) + { + /* remove from free list */ + more = MORE_SEC (prev); + less = LESS_SEC (prev); + more->less_rel = SEC_REL (more, less); + less->more_rel = SEC_REL (less, more); + } + else + { + more = MORE_SEC (seg->last); + } + + /* put the space to prev's free space */ + prev->free_num += num; + + while (more != seg->last) + { + if (prev->free_num <= more->free_num) + break; + more = MORE_SEC (more); + } + less = LESS_SEC (more); + + /* insert */ + less->more_rel = SEC_REL (less, prev); + more->less_rel = SEC_REL (more, prev); + prev->more_rel = SEC_REL (prev, more); + prev->less_rel = SEC_REL (prev, less); + + /* adjust segment */ + seg->used_size -= sec->req_size; + seg->used_num -= sec->used_num; + seg->sec_num--; +} + +void +dmm_seg_dump (struct dmm_segment *seg) +{ + section_t *sec; + + dmm_read_lock (&seg->lock); + + (void) printf ("---- segment:%p base:%p size:%lu --------------\n" + " first[%d]:%p last[%d]:%p total_num:%d used_num:%d\n" + " sec_num:%d used_size:%lu use%%:%lu%% free%%:%lu%%\n", + seg, seg->base, seg->size, + SEC_INDEX (seg, seg->first), seg->first, + SEC_INDEX (seg, seg->last), seg->last, + seg->total_num, seg->used_num, + seg->sec_num, seg->used_size, + seg->used_size * 100 / seg->size, + (seg->total_num - + seg->used_num) * SECTION_SIZE * 100 / seg->size); + + (void) printf ("----------------------------------------\n" + "%18s %9s %9s %9s %9s %10s %9s %9s %s\n", + "PHYSICAL-ORDER", "section", "prev_rel", "used_num", + "free_num", "req_size", "less_rel", "more_rel", "name"); + + sec = seg->first; + while (1) + { + (void) printf ("%18p %9d %9d %9d %9d %10lu %9d %9d '%s'\n", + sec, SEC_INDEX (seg, sec), + sec->prev_rel, sec->used_num, sec->free_num, + sec->req_size, sec->less_rel, sec->more_rel, sec->name); + if (sec == seg->last) + break; + sec = NEXT_SEC (sec); + } + + (void) printf ("----------------------------------------\n" + "%18s %9s %9s\n", "FREE-ORDER", "section", "free_num"); + for (sec = MORE_SEC (seg->last); sec != seg->last; sec = MORE_SEC (sec)) + { + (void) printf ("%18p %9d %9d\n", + sec, SEC_INDEX (seg, sec), sec->free_num); + } + + (void) printf ("----------------------------------------\n"); + + dmm_read_unlock (&seg->lock); +} + +inline static int +align_section (void *base, size_t size, section_t ** first) +{ + const long MASK = ((long) SECTION_SIZE - 1); + const int SEG_NUM = CALC_NUM (sizeof (struct dmm_segment)); + + const long align = (long) base; + const long addr = (align + MASK) & (~MASK); + const size_t total = (size - (addr - align)) / SECTION_SIZE; + + if (total > 0x7fffFFFF) + return -1; + if (total < SEG_NUM + 1) /* first+segment + last */ + return -1; + + *first = (section_t *) addr; + return (int) total; +} + +struct dmm_segment * +dmm_seg_create (void *base, size_t size) +{ + const int SEG_NUM = CALC_NUM (sizeof (struct dmm_segment)); + section_t *first, *last; + struct dmm_segment *seg; + int total = align_section (base, size, &first); + + if (total <= 0) + return NULL; + + last = first + (total - 1); + + /* first section */ + first->prev_rel = 0; + first->used_num = SEG_NUM; + first->req_size = sizeof (struct dmm_segment); + first->free_num = total - (SEG_NUM + 1); + first->less_rel = SEC_REL (first, last); + first->more_rel = SEC_REL (first, last); + first->name[0] = 0; + (void) strncpy (&first->name[1], FIRST_NAME, sizeof (first->name) - 1); + + /* last section */ + last->prev_rel = SEC_REL (last, first); + last->used_num = 0; + last->req_size = 0; + last->free_num = 0; + last->less_rel = SEC_REL (last, first); + last->more_rel = SEC_REL (last, first); + last->name[0] = 0; + (void) strncpy (&last->name[1], LAST_NAME, sizeof (first->name) - 1); + + /* segment */ + seg = (struct dmm_segment *) (first + 1); + dmm_rwlock_init (&seg->lock); + seg->base = base; + seg->size = size; + seg->first = first; + seg->last = last; + seg->total_num = total; + seg->sec_num = 2; + seg->used_size = sizeof (struct dmm_segment); + seg->used_num = first->used_num; + + return seg; +} + +struct dmm_segment * +dmm_seg_attach (void *base, size_t size) +{ + section_t *first, *last; + struct dmm_segment *seg; + int total = align_section (base, size, &first); + + if (total <= 0) + return NULL; + + last = first + (total - 1); + seg = (struct dmm_segment *) (first + 1); + + if (seg->base != base) + return NULL; + if (seg->size != size) + return NULL; + if (seg->total_num != total) + return NULL; + + if (seg->first != first) + return NULL; + if (first->name[0] != 0) + return NULL; + if (strncmp (&first->name[1], FIRST_NAME, sizeof (first->name) - 1)) + return NULL; + + if (seg->last != last) + return NULL; + if (last->name[0] != 0) + return NULL; + if (strncmp (&last->name[1], LAST_NAME, sizeof (last->name) - 1)) + return NULL; + + return seg; +} + +void * +dmm_mem_alloc (struct dmm_segment *seg, size_t size) +{ + section_t *sec; + + dmm_write_lock (&seg->lock); + sec = mem_alloc (seg, size); + dmm_write_unlock (&seg->lock); + + return sec ? sec + 1 : NULL; +} + +int +dmm_mem_free (struct dmm_segment *seg, void *mem) +{ + if (CHECK_ADDR (seg, mem)) + { + MEM_ERR ("Invalid address:%p", mem); + return -1; + } + + dmm_write_lock (&seg->lock); + mem_free (seg, ((section_t *) mem) - 1); + dmm_write_unlock (&seg->lock); + + return 0; +} + +void * +dmm_mem_lookup (struct dmm_segment *seg, const char name[DMM_MEM_NAME_SIZE]) +{ + section_t *sec; + + if (!name || !name[0]) + return NULL; + + dmm_read_lock (&seg->lock); + sec = mem_lookup (seg, name); + dmm_read_unlock (&seg->lock); + + return sec ? sec + 1 : NULL; +} + +void * +dmm_mem_map (struct dmm_segment *seg, size_t size, + const char name[DMM_MEM_NAME_SIZE]) +{ + void *mem; + section_t *sec; + + if (!name || !name[0] || strlen (name) >= DMM_MEM_NAME_SIZE) + return NULL; + + dmm_write_lock (&seg->lock); + + sec = mem_lookup (seg, name); + if (sec) + { + MEM_ERR ("Map '%s' exist", name); + mem = NULL; + } + else if (!(sec = mem_alloc (seg, size))) + { + MEM_ERR ("alloc '%s' failed for size %lu", name, size); + mem = NULL; + } + else + { + (void) strncpy (sec->name, name, sizeof (sec->name)); + mem = sec + 1; + } + + dmm_write_unlock (&seg->lock); + + return mem; +} + +int +dmm_mem_unmap (struct dmm_segment *seg, const char name[DMM_MEM_NAME_SIZE]) +{ + section_t *sec; + + if (!name || !name[0]) + return -1; + + dmm_write_lock (&seg->lock); + + sec = mem_lookup (seg, name); + if (sec) + mem_free (seg, sec); + + dmm_write_unlock (&seg->lock); + + return sec != NULL ? 0 : -1; +} diff --git a/src/framework/mem/dmm_segment.h b/src/framework/mem/dmm_segment.h new file mode 100644 index 0000000..135f347 --- /dev/null +++ b/src/framework/mem/dmm_segment.h @@ -0,0 +1,35 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_SEGMENT_H_ +#define _DMM_SEGMENT_H_ + +#define DMM_MEM_NAME_SIZE 32 + +struct dmm_segment *dmm_seg_create (void *base, size_t size); +struct dmm_segment *dmm_seg_attach (void *base, size_t size); +void dmm_seg_dump (struct dmm_segment *seg); + +void *dmm_mem_alloc (struct dmm_segment *seg, size_t size); +int dmm_mem_free (struct dmm_segment *seg, void *mem); + +void *dmm_mem_lookup (struct dmm_segment *seg, + const char name[DMM_MEM_NAME_SIZE]); +void *dmm_mem_map (struct dmm_segment *seg, size_t size, + const char name[DMM_MEM_NAME_SIZE]); +int dmm_mem_unmap (struct dmm_segment *seg, + const char name[DMM_MEM_NAME_SIZE]); + +#endif /* #ifndef _DMM_SEGMENT_H_ */ diff --git a/src/framework/mem/dmm_share.h b/src/framework/mem/dmm_share.h new file mode 100644 index 0000000..0d0ff8f --- /dev/null +++ b/src/framework/mem/dmm_share.h @@ -0,0 +1,114 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 _DMM_SHARE_H_ +#define _DMM_SHARE_H_ + +#define DMM_SHARE_PATH_MAX 100 + +enum dmm_share_type +{ + DMM_SHARE_HEAP, + DMM_SHARE_FSHM, + DMM_SHARE_HUGE, + + DMM_SHARE_ANY = -1 +}; + +struct dmm_share +{ + int type; /* share type enum dmm_share_type */ + pid_t pid; /* owner/creator pid */ + void *base; /* base logical address */ + size_t size; /* memory size */ + char path[DMM_SHARE_PATH_MAX]; /* share path */ +}; + +int dmm_heap_create (struct dmm_share *share); +int dmm_heap_delete (struct dmm_share *share); +int dmm_heap_attach (struct dmm_share *share); +int dmm_heap_detach (struct dmm_share *share); + +int dmm_fshm_create (struct dmm_share *share); +int dmm_fshm_delete (struct dmm_share *share); +int dmm_fshm_attach (struct dmm_share *share); +int dmm_fshm_detach (struct dmm_share *share); + +int dmm_huge_create (struct dmm_share *share); +int dmm_huge_delete (struct dmm_share *share); +int dmm_huge_attach (struct dmm_share *share); +int dmm_huge_detach (struct dmm_share *share); + +#define DMM_SHARE_DISPATCH(share, action) \ +({ \ + int _r; \ + switch (share->type) \ + { \ + case DMM_SHARE_HEAP: \ + _r = dmm_heap_##action(share); \ + break; \ + case DMM_SHARE_FSHM: \ + _r = dmm_fshm_##action(share); \ + break; \ + case DMM_SHARE_HUGE: \ + _r = dmm_huge_##action(share); \ + break; \ + default: \ + _r = -1; \ + } \ + _r; \ +}) + +/* create share memory +input: share->type, share->size, share->pid +output: share->base, share->path +*/ +inline static int +dmm_share_create (struct dmm_share *share) +{ + return DMM_SHARE_DISPATCH (share, create); +} + +/* delete share memory +input: share->type, share->base, share->size, share->path +*/ +inline static int +dmm_share_delete (struct dmm_share *share) +{ + return DMM_SHARE_DISPATCH (share, delete); +} + +/* attach share memory +input: share->type share->path [share->size] [share->base] +output: share->base, share->size +*/ +inline static int +dmm_share_attach (struct dmm_share *share) +{ + return DMM_SHARE_DISPATCH (share, attach); +} + +/* attach share memory +input: share->type share->size share->base +*/ +inline static int +dmm_share_detach (struct dmm_share *share) +{ + return DMM_SHARE_DISPATCH (share, detach); +} + +#undef DMM_SHARE_DISPATCH + +#endif /* #ifndef _DMM_SHARE_H_ */ -- cgit 1.2.3-korg