├── .MODULE_LICENSE_BSD ├── .MODULE_NAME_libshdata ├── .gitignore ├── COPYING ├── README ├── atom.mk ├── examples ├── 1prod_1cons.c ├── common.c ├── common.h ├── example_log.h └── stress_test.c ├── include ├── libshdata-concurrency-hooks.h └── libshdata.h ├── src ├── backend │ ├── shd_baremetal.c │ ├── shd_baremetal.h │ ├── shd_dev_mem.c │ ├── shd_dev_mem.h │ ├── shd_shm.c │ └── shd_shm.h ├── lookup │ ├── shd_lookup_default.c │ └── shd_lookup_x1.c ├── shd.c ├── shd_ctx.c ├── shd_ctx.h ├── shd_data.c ├── shd_data.h ├── shd_hdr.c ├── shd_hdr.h ├── shd_mdata_hdr.c ├── shd_mdata_hdr.h ├── shd_private.h ├── shd_sample.c ├── shd_sample.h ├── shd_search.c ├── shd_search.h ├── shd_section.c ├── shd_section.h ├── shd_sync.c ├── shd_sync.h ├── shd_utils.h ├── shd_window.c └── shd_window.h └── tests ├── concurrency ├── hooks_implem.c └── hooks_implem.h ├── lookup └── section_lookup.c ├── shd_test.c ├── shd_test.h ├── shd_test_api.c ├── shd_test_api_adv.c ├── shd_test_concurrency.c ├── shd_test_error.c ├── shd_test_func_read_adv.c ├── shd_test_func_read_basic.c ├── shd_test_func_read_hdr.c ├── shd_test_func_write_adv.c ├── shd_test_func_write_basic.c ├── shd_test_helper.c └── shd_test_helper.h /.MODULE_LICENSE_BSD: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Parrot S.A. 2 | -------------------------------------------------------------------------------- /.MODULE_NAME_libshdata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Parrot-Developers/libshdata/d9ec4bdba834d8f3daf6bf9aa6da374bc462961f/.MODULE_NAME_libshdata -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.gcda 3 | *.gcno 4 | libshdata-test 5 | .cproject 6 | .project 7 | .settings/ 8 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Parrot SA 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | * Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright 8 | notice, this list of conditions and the following disclaimer in the 9 | documentation and/or other materials provided with the distribution. 10 | * Neither the name of the Parrot Company nor the 11 | names of its contributors may be used to endorse or promote products 12 | derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | libshdata 2 | 3 | Lock free shared-memory library 4 | 5 | The use-case handled by this library is that of one producer and several 6 | consumers, that periodically exchange data that varies with time (e.g. the 7 | acceleration on the 3 axis seen by an IMU sensor) ; therefore all the data 8 | that is shared using this library has to be time-stamped. 9 | Consumers can search for data produced right after/right before/close to a 10 | given date, or for the latest data, and can retrieve that data and its 11 | associated timestamps, one by one or in batch. It can also retrieve bits of that 12 | data, called "quantities". 13 | The producer, on its side, defines the data format and decides how far in data 14 | history the consumers are allowed to go (which basically setups the length of 15 | the ring-buffer used for communication). 16 | All write & read operations are lock-free. 17 | See libshdata.h & examples directory for more information 18 | -------------------------------------------------------------------------------- /atom.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := libshdata 6 | LOCAL_CATEGORY_PATH := libs 7 | LOCAL_DESCRIPTION := Shared memory low level library 8 | LOCAL_SRC_FILES := src/shd.c \ 9 | src/shd_ctx.c \ 10 | src/shd_section.c \ 11 | src/shd_mdata_hdr.c \ 12 | src/shd_hdr.c \ 13 | src/shd_data.c \ 14 | src/shd_sync.c \ 15 | src/shd_sample.c \ 16 | src/shd_window.c \ 17 | src/shd_search.c \ 18 | src/backend/shd_dev_mem.c \ 19 | src/backend/shd_shm.c 20 | LOCAL_CFLAGS += -DBUILD_TARGET_CPU=$(TARGET_CPU) 21 | 22 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 23 | 24 | LOCAL_C_INCLUDES := \ 25 | $(LOCAL_PATH)/src 26 | 27 | LOCAL_LIBRARIES := libshdata-section-lookup libfutils 28 | 29 | LOCAL_CONDITIONAL_LIBRARIES := \ 30 | OPTIONAL:libulog \ 31 | OPTIONAL:libshdata-concurrency-hooks-implem 32 | 33 | include $(BUILD_LIBRARY) 34 | 35 | ifeq ($(TARGET_CPU),$(filter %$(TARGET_CPU),tegrax1 tegrak1)) 36 | 37 | # X1 implementation of shd_section_lookup() 38 | include $(CLEAR_VARS) 39 | LOCAL_MODULE := libshdata-section-lookup 40 | LOCAL_CATEGORY_PATH := libs 41 | LOCAL_DESCRIPTION := X1/K1 lookup table for /dev/mem 42 | LOCAL_SRC_FILES := src/lookup/shd_lookup_x1.c 43 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/src 44 | LOCAL_DEPENDS_HEADERS := liblk-shdata 45 | LOCAL_LIBRARIES := libfutils 46 | include $(BUILD_STATIC_LIBRARY) 47 | 48 | else 49 | 50 | # Default implementation of shd_section_lookup() 51 | include $(CLEAR_VARS) 52 | LOCAL_MODULE := libshdata-section-lookup 53 | LOCAL_CATEGORY_PATH := libs 54 | LOCAL_DESCRIPTION := Dummy lookup table for /dev/mem 55 | LOCAL_SRC_FILES := src/lookup/shd_lookup_default.c 56 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/src 57 | include $(BUILD_STATIC_LIBRARY) 58 | 59 | endif 60 | 61 | # Stress test 62 | include $(CLEAR_VARS) 63 | LOCAL_MODULE := libshdata-stress 64 | LOCAL_CATEGORY_PATH := libs/libshdata/examples 65 | LOCAL_DESCRIPTION := Configurable stress test for libshdata 66 | LOCAL_SRC_FILES := examples/stress_test.c examples/common.c 67 | LOCAL_LIBRARIES := libshdata libfutils 68 | include $(BUILD_EXECUTABLE) 69 | 70 | # Example code 71 | include $(CLEAR_VARS) 72 | LOCAL_MODULE := libshdata-1prod-1cons 73 | LOCAL_CATEGORY_PATH := libs/libshdata/examples 74 | LOCAL_DESCRIPTION := Example code for libshdata with 1 prod and 1 cons 75 | LOCAL_SRC_FILES := examples/1prod_1cons.c examples/common.c 76 | LOCAL_LIBRARIES := libshdata 77 | include $(BUILD_EXECUTABLE) 78 | 79 | # Unit testing 80 | ifdef TARGET_TEST 81 | 82 | include $(CLEAR_VARS) 83 | LOCAL_MODULE := libshdata-concurrency-hooks-implem 84 | LOCAL_CATEGORY_PATH := libs 85 | LOCAL_DESCRIPTION := Implementation of libshdata concurrency hook points 86 | 87 | LOCAL_SRC_FILES := tests/concurrency/hooks_implem.c 88 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include 89 | include $(BUILD_LIBRARY) 90 | 91 | include $(CLEAR_VARS) 92 | LOCAL_MODULE := tst-libshdata 93 | LOCAL_SRC_FILES := \ 94 | tests/shd_test.c \ 95 | tests/shd_test_helper.c \ 96 | tests/shd_test_api.c \ 97 | tests/shd_test_api_adv.c \ 98 | tests/shd_test_func_write_basic.c \ 99 | tests/shd_test_func_read_adv.c \ 100 | tests/shd_test_func_read_basic.c \ 101 | tests/shd_test_func_read_hdr.c \ 102 | tests/shd_test_func_write_adv.c \ 103 | tests/shd_test_error.c \ 104 | tests/shd_test_concurrency.c \ 105 | tests/lookup/section_lookup.c 106 | 107 | LOCAL_C_INCLUDES := \ 108 | $(LOCAL_PATH)/src 109 | 110 | LOCAL_LIBRARIES := libshdata libcunit libshdata-concurrency-hooks-implem 111 | 112 | include $(BUILD_EXECUTABLE) 113 | 114 | endif 115 | -------------------------------------------------------------------------------- /examples/1prod_1cons.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * @file 1prod_1cons.c 26 | * 27 | * @brief Basic libshdata example with 1 producer and 1 consumer 28 | * 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "example_log.h" 39 | #include "common.h" 40 | #include "libshdata.h" 41 | 42 | #define BLOB_NAME "example_1prod_1cons" 43 | #define NUMBER_OF_SAMPLES 20 44 | 45 | struct example_prod_blob ex_blob = { 46 | .i1 = 0, 47 | .c1 = 'a', 48 | .li1 = 0, 49 | .ui1 = 0, 50 | .f1 = 0.0, 51 | .acc = { 0.0, 0.0, 0.0 }, 52 | .angles = { 53 | 0.0, 54 | 0.0, 55 | 0.0 56 | }, 57 | .state = 0 58 | }; 59 | 60 | struct ex_metadata_blob_hdr ex_metadata_hdr = { 61 | .i1 = 0xCAFE, 62 | .i2 = 0xDEAD, 63 | .c1 = "Hello", 64 | }; 65 | 66 | static struct ex_conf s_conf = { 67 | .prod_period = 1000, 68 | .cons_period = 1000, 69 | .repeats = 50, 70 | .total_time = 10 71 | }; 72 | 73 | struct shd_hdr_user_info ex_hdr_info = { 74 | .blob_size = sizeof(ex_blob), 75 | .max_nb_samples = NUMBER_OF_SAMPLES, 76 | .rate = 1000, 77 | .blob_metadata_hdr_size = sizeof(ex_metadata_hdr) 78 | }; 79 | 80 | static bool alarm_set; 81 | static void alarmHandler(int dummy) 82 | { 83 | alarm_set = true; 84 | } 85 | 86 | static void usage() 87 | { 88 | printf("Configurable example code for libshdata\n"); 89 | printf("Usage :\n"); 90 | printf("\tp : producer period\n"); 91 | printf("\tc : consumer period\n"); 92 | printf("\tr : number of loops to execute\n"); 93 | printf("\tt : test duration\n"); 94 | 95 | exit(0); 96 | } 97 | 98 | static void parse_command(int argc, char *argv[], struct ex_conf *s_conf) 99 | { 100 | int opt; 101 | 102 | while ((opt = getopt(argc, argv, "p:c:r:t:h")) != -1) { 103 | switch (opt) { 104 | case 'p': 105 | s_conf->prod_period = (uint32_t)strtol(optarg, NULL, 0); 106 | break; 107 | case 'c': 108 | s_conf->cons_period = (uint32_t)strtol(optarg, NULL, 0); 109 | break; 110 | case 'r': 111 | s_conf->repeats = (uint32_t)strtol(optarg, NULL, 0); 112 | break; 113 | case 't': 114 | s_conf->total_time = (uint32_t)strtol(optarg, NULL, 0); 115 | break; 116 | case 'h': 117 | default: 118 | usage(); 119 | break; 120 | } 121 | } 122 | } 123 | 124 | static void producer_loop(void) 125 | { 126 | struct shd_ctx *ctx_prod; 127 | struct shd_sample_metadata sample_meta; 128 | int ret; 129 | unsigned int index; 130 | unsigned int repeats = (s_conf.total_time * 1000) 131 | / s_conf.prod_period + 1; 132 | 133 | ctx_prod = shd_create(BLOB_NAME, NULL, &ex_hdr_info, &ex_metadata_hdr); 134 | if (ctx_prod != NULL) 135 | ULOGP("Successfully created new memory section"); 136 | 137 | ualarm(s_conf.prod_period, s_conf.prod_period); 138 | for (index = 0; index < repeats; index++) { 139 | if (clock_gettime(CLOCK_MONOTONIC, &sample_meta.ts) < 0) { 140 | ULOGP("Could not get time"); 141 | return; 142 | } 143 | 144 | update_blob(&ex_blob); 145 | ret = shd_write_new_blob(ctx_prod, 146 | &ex_blob, 147 | sizeof(ex_blob), 148 | &sample_meta); 149 | 150 | ULOGP("Wrote sample at date : %ld_%ld", sample_meta.ts.tv_sec, 151 | sample_meta.ts.tv_nsec); 152 | 153 | while (!alarm_set) 154 | usleep(s_conf.prod_period/10); 155 | alarm_set = false; 156 | } 157 | shd_close(ctx_prod, NULL); 158 | } 159 | 160 | static void consumer_loop(void) 161 | { 162 | struct shd_ctx *ctx_cons = NULL; 163 | struct shd_revision *rev; 164 | struct example_prod_blob read_blob; 165 | struct shd_sample_search search = { 166 | .nb_values_after_date = 0, 167 | .nb_values_before_date = 0, 168 | .method = SHD_LATEST 169 | }; 170 | struct shd_quantity_sample blob_samp[1] = { 171 | { .ptr = &read_blob, .size = sizeof(read_blob) } 172 | }; 173 | int ret = -EAGAIN; 174 | unsigned int index; 175 | unsigned int repeats = (s_conf.total_time * 1000) 176 | / s_conf.cons_period + 1; 177 | 178 | while (ctx_cons == NULL) 179 | ctx_cons = shd_open(BLOB_NAME, NULL, &rev); 180 | 181 | ULOGC("Successfully open memory section"); 182 | 183 | ualarm(s_conf.cons_period, s_conf.cons_period); 184 | for (index = 0; index < repeats; index++) { 185 | do { 186 | ret = shd_read_from_sample(ctx_cons, 0, &search, NULL, 187 | blob_samp); 188 | if (ret < 0) 189 | usleep(s_conf.cons_period/10); 190 | } while (ret == -EAGAIN); 191 | 192 | if (ret <= 0) 193 | ULOGC("Error encountered while reading from " 194 | "sample : %s", strerror(-ret)); 195 | 196 | ret = shd_end_read(ctx_cons, rev); 197 | if (ret < 0) 198 | ULOGC("Error encountered while ending read : %s", 199 | strerror(-ret)); 200 | if (ret == -ENODEV) { 201 | ULOGC("Reopening memory section ..."); 202 | do { 203 | shd_close(ctx_cons, rev); 204 | ctx_cons = shd_open(BLOB_NAME, NULL, &rev); 205 | } while (ctx_cons == NULL); 206 | } else if (ret == 0) { 207 | ULOGC("Read sample at date : %ld_%ld", 208 | blob_samp[0].meta.ts.tv_sec, 209 | blob_samp[0].meta.ts.tv_nsec); 210 | } 211 | 212 | while (!alarm_set) 213 | usleep(s_conf.cons_period/10); 214 | alarm_set = false; 215 | } 216 | shd_close(ctx_cons, rev); 217 | } 218 | 219 | int main(int argc, char *argv[]) 220 | { 221 | parse_command(argc, argv, &s_conf); 222 | alarm_set = false; 223 | pid_t pid = fork(); 224 | 225 | if (pid == 0) { 226 | /* Child code */ 227 | ULOGP("PID = %d", getpid()); 228 | signal(SIGALRM, alarmHandler); 229 | consumer_loop(); 230 | exit(0); 231 | } else if (pid > 0) { 232 | /* Parent code */ 233 | ULOGC("PID = %d", getpid()); 234 | signal(SIGALRM, alarmHandler); 235 | producer_loop(); 236 | ULOG("Waiting for child to terminate"); 237 | wait(NULL); 238 | } else { 239 | ULOG("Oops"); 240 | } 241 | 242 | return 0; 243 | } 244 | -------------------------------------------------------------------------------- /examples/common.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * @file common.c 26 | * 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include "common.h" 33 | 34 | void update_blob(struct example_prod_blob *s_blob) 35 | { 36 | s_blob->i1++; 37 | s_blob->li1++; 38 | s_blob->ui1++; 39 | s_blob->f1 += 0.1; 40 | s_blob->acc.x += 0.01; 41 | s_blob->acc.x += 0.02; 42 | s_blob->acc.x += 0.05; 43 | s_blob->angles.rho += 0.1; 44 | s_blob->angles.phi += 0.2; 45 | s_blob->angles.theta += 0.5; 46 | } 47 | -------------------------------------------------------------------------------- /examples/common.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file common.h 27 | * 28 | */ 29 | 30 | #ifndef COMMON_H_ 31 | #define COMMON_H_ 32 | 33 | #include 34 | 35 | struct acceleration { 36 | double x; 37 | double y; 38 | double z; 39 | }; 40 | 41 | struct angles { 42 | double rho; 43 | double phi; 44 | double theta; 45 | }; 46 | 47 | enum flight_state_t { 48 | STATE_FLYING, 49 | STATE_HOVERING, 50 | STATE_LANDING, 51 | STATE_TAKEOFF 52 | }; 53 | 54 | struct example_prod_blob { 55 | int i1; 56 | char c1; 57 | long int li1; 58 | unsigned int ui1; 59 | float f1; 60 | struct acceleration acc; 61 | struct angles angles; 62 | enum flight_state_t state; 63 | }; 64 | 65 | struct ex_metadata_blob_hdr { 66 | int i1; 67 | int i2; 68 | const char c1[10]; 69 | }; 70 | 71 | struct ex_conf { 72 | uint32_t prod_period; /* in us */ 73 | uint32_t cons_period; /* in us */ 74 | uint32_t repeats; 75 | uint32_t total_time; /* in ms */ 76 | }; 77 | 78 | void update_blob(struct example_prod_blob *s_blob); 79 | 80 | #endif /* COMMON_H_ */ 81 | -------------------------------------------------------------------------------- /examples/example_log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file example_log.h 27 | * 28 | * @brief shared memory private stuff. 29 | * 30 | */ 31 | 32 | #ifndef _EXAMPLE_LOG_H_ 33 | #define _EXAMPLE_LOG_H_ 34 | 35 | #include 36 | 37 | /** Generic log */ 38 | #define ULOG(_fmt, ...) fprintf(stderr, _fmt "\n", ##__VA_ARGS__) 39 | /** General log */ 40 | #define ULOGI(_fmt, ...) ULOG("[info] " _fmt, ##__VA_ARGS__) 41 | /** Log for producer*/ 42 | #define ULOGP(_fmt, ...) ULOG("[prod] " _fmt, ##__VA_ARGS__) 43 | /** Log as consumer */ 44 | #define ULOGC(_fmt, ...) ULOG("[cons] " _fmt, ##__VA_ARGS__) 45 | 46 | #endif /* _EXAMPLE_LOG_H_ */ 47 | -------------------------------------------------------------------------------- /include/libshdata-concurrency-hooks.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file libshdata-concurrency-hooks.h 27 | * 28 | * @brief Definitions of hooks for concurrency tests 29 | */ 30 | 31 | #ifndef _LIBSHDATA_CONCURRENCY_HOOKS_H_ 32 | #define _LIBSHDATA_CONCURRENCY_HOOKS_H_ 33 | 34 | enum shd_concurrency_hook { 35 | HOOK_SECTION_CREATED_BEFORE_UNLOCK = 0, 36 | HOOK_SECTION_CREATED_BEFORE_TRUNCATE, 37 | HOOK_SECTION_CREATED_NOT_RESIZED, 38 | HOOK_SECTION_CREATED_LOCK_TAKEN, 39 | HOOK_SECTION_OPEN_START, 40 | HOOK_SECTION_OPEN_MMAP_DONE, 41 | HOOK_SAMPLE_WRITE_START, 42 | HOOK_SAMPLE_WRITE_BEFORE_COMMIT, 43 | HOOK_SAMPLE_WRITE_AFTER_COMMIT, 44 | HOOK_WINDOW_SEARCH_START, 45 | HOOK_WINDOW_SEARCH_OVER, 46 | HOOK_TOTAL 47 | }; 48 | 49 | /* 50 | * @brief Function called at each hook point : defined as a weak symbol here, 51 | * and as a strong symbol in libshdata's test code. In normal operation this 52 | * code doesn't do anything but go through the "false" branch of the test in 53 | * SHD_HOOK (obviously a slight performance hit) 54 | */ 55 | void __attribute__((weak)) shd_concurrency_hook(enum shd_concurrency_hook hook); 56 | 57 | #define SHD_HOOK(a) \ 58 | do { \ 59 | if (shd_concurrency_hook) \ 60 | shd_concurrency_hook(a); \ 61 | } while (0) 62 | 63 | 64 | #endif /* _LIBSHDATA_CONCURRENCY_HOOKS_H_ */ 65 | -------------------------------------------------------------------------------- /src/backend/shd_baremetal.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_baremetal.c 27 | * 28 | * @brief baremetal backend 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include "shd_hdr.h" 36 | #include "shd_baremetal.h" 37 | 38 | struct shd_baremetal_priv { 39 | void *ptr; 40 | }; 41 | 42 | static int create_internal(const void *raw_param, void **priv) 43 | { 44 | struct shd_baremetal_priv *self; 45 | const struct shd_baremetal_backend_param *param = raw_param; 46 | 47 | self = calloc(1, sizeof(*self)); 48 | if (!self) 49 | return -ENOMEM; 50 | 51 | self->ptr = (void *) param->address; 52 | 53 | *priv = self; 54 | 55 | return 0; 56 | } 57 | 58 | static int shd_baremetal_create(const char *blob_name, 59 | size_t size, 60 | const void *raw_param, 61 | void **priv, 62 | bool *first_creation) 63 | { 64 | int ret; 65 | 66 | ret = create_internal(raw_param, priv); 67 | if (ret < 0) 68 | return ret; 69 | 70 | *first_creation = false; 71 | 72 | return 0; 73 | } 74 | 75 | static int shd_baremetal_open(const char *blob_name, 76 | const void *raw_param, 77 | void **priv) 78 | { 79 | return create_internal(raw_param, priv); 80 | } 81 | 82 | static int shd_baremetal_close(void *priv) 83 | { 84 | struct shd_baremetal_priv *self = priv; 85 | 86 | free(self); 87 | 88 | return 0; 89 | } 90 | 91 | static int shd_baremetal_read_header(struct shd_hdr *hdr, void *priv) 92 | { 93 | struct shd_baremetal_priv *self = priv; 94 | 95 | memcpy(hdr, self->ptr, sizeof(*hdr)); 96 | 97 | return 0; 98 | } 99 | 100 | static int shd_baremetal_get_section(size_t size, 101 | void **out_ptr, void *priv) 102 | { 103 | struct shd_baremetal_priv *self = priv; 104 | 105 | *out_ptr = self->ptr; 106 | 107 | return 0; 108 | } 109 | 110 | static int shd_baremetal_resize(void *priv) 111 | { 112 | return 0; 113 | } 114 | 115 | static int shd_baremetal_lock(void *priv) 116 | { 117 | return 0; 118 | } 119 | 120 | static int shd_baremetal_unlock(void *priv) 121 | { 122 | return 0; 123 | } 124 | 125 | const struct shd_section_backend shd_baremetal_backend = { 126 | .create = shd_baremetal_create, 127 | .open = shd_baremetal_open, 128 | .close = shd_baremetal_close, 129 | .hdr_read = shd_baremetal_read_header, 130 | .get_section_start = shd_baremetal_get_section, 131 | .section_resize = shd_baremetal_resize, 132 | .section_lock = shd_baremetal_lock, 133 | .section_unlock = shd_baremetal_unlock 134 | }; 135 | -------------------------------------------------------------------------------- /src/backend/shd_baremetal.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_baremetal.h 27 | * 28 | * @brief baremetal backend 29 | * 30 | */ 31 | 32 | #include "shd_section.h" 33 | 34 | struct shd_baremetal_backend_param { 35 | uintptr_t address; 36 | }; 37 | 38 | extern const struct shd_section_backend shd_baremetal_backend; 39 | -------------------------------------------------------------------------------- /src/backend/shd_dev_mem.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_dev_mem.c 27 | * 28 | * @brief /dev/mem 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include /* For ftruncate */ 36 | #include /* for flock */ 37 | #include /* For shm and PROT flags */ 38 | #include 39 | #include "shd_hdr.h" 40 | #include "shd_section.h" 41 | #include "shd_private.h" 42 | #include "backend/shd_dev_mem.h" 43 | 44 | struct shd_dev_mem_priv { 45 | int fd; 46 | uintptr_t offset; 47 | struct shd_section_addr addr; 48 | int writable; 49 | size_t creation_size; 50 | }; 51 | 52 | static int open_internal(const struct shd_dev_mem_backend_param *param, 53 | int flags, 54 | struct shd_dev_mem_priv **priv) 55 | { 56 | struct shd_dev_mem_priv *self; 57 | int ret; 58 | 59 | self = calloc(1, sizeof(*self)); 60 | if (!self) 61 | return -ENOMEM; 62 | 63 | /* Open the base */ 64 | self->fd = open("/dev/mem", flags, 0666); 65 | if (self->fd == -1) { 66 | ret = -errno; 67 | goto clear; 68 | } 69 | 70 | ret = fd_set_close_on_exec(self->fd); 71 | if (ret < 0) 72 | goto close_fd; 73 | 74 | self->offset = param->offset; 75 | 76 | *priv = self; 77 | 78 | return 0; 79 | 80 | close_fd: 81 | close(self->fd); 82 | clear: 83 | free(self); 84 | 85 | return ret; 86 | } 87 | 88 | static int shd_dev_mem_create(const char *blob_name, 89 | size_t size, 90 | const void *raw_param, 91 | void **priv, 92 | bool *first_creation) 93 | { 94 | const struct shd_dev_mem_backend_param *param = raw_param; 95 | struct shd_dev_mem_priv *self; 96 | int flags = O_EXCL | O_RDWR | param->open_flags; 97 | int ret; 98 | 99 | ret = open_internal(param, flags, &self); 100 | if (ret < 0) 101 | return ret; 102 | 103 | self->writable = 1; 104 | self->creation_size = size; 105 | 106 | *priv = self; 107 | *first_creation = false; 108 | 109 | return 0; 110 | } 111 | 112 | static int shd_dev_mem_open(const char *blob_name, 113 | const void *raw_param, 114 | void **priv) 115 | { 116 | const struct shd_dev_mem_backend_param *param = raw_param; 117 | struct shd_dev_mem_priv *self; 118 | int flags = O_EXCL | O_RDONLY | param->open_flags; 119 | int ret; 120 | 121 | ret = open_internal(param, flags, &self); 122 | if (ret < 0) 123 | return ret; 124 | 125 | self->writable = 0; 126 | 127 | *priv = self; 128 | 129 | return 0; 130 | } 131 | 132 | static int shd_dev_mem_close(void *priv) 133 | { 134 | struct shd_dev_mem_priv *self = priv; 135 | 136 | if (self->addr.ptr) 137 | munmap(self->addr.ptr, self->addr.size); 138 | 139 | close(self->fd); 140 | free(self); 141 | 142 | return 0; 143 | } 144 | 145 | static int shd_dev_mem_read_header(struct shd_hdr *hdr, void *priv) 146 | { 147 | struct shd_dev_mem_priv *self = priv; 148 | void *ptr; 149 | 150 | ptr = mmap(0, sizeof(*hdr), 151 | PROT_READ, 152 | MAP_SHARED, 153 | self->fd, 154 | self->offset); 155 | if (ptr == MAP_FAILED) 156 | return -ENOMEM; 157 | 158 | memcpy(hdr, ptr, sizeof(*hdr)); 159 | munmap(ptr, sizeof(*hdr)); 160 | 161 | return 0; 162 | } 163 | 164 | static int shd_dev_mem_get_section(size_t size, 165 | void **out_ptr, void *priv) 166 | { 167 | struct shd_dev_mem_priv *self = priv; 168 | void *ptr; 169 | 170 | ptr = mmap(0, size, 171 | self->writable ? PROT_WRITE : PROT_READ, 172 | MAP_SHARED, 173 | self->fd, 174 | self->offset); 175 | if (ptr == MAP_FAILED) 176 | return -ENOMEM; 177 | 178 | self->addr.ptr = ptr; 179 | self->addr.size = size; 180 | 181 | *out_ptr = ptr; 182 | 183 | return 0; 184 | } 185 | 186 | static int shd_dev_mem_resize(void *priv) 187 | { 188 | return 0; 189 | } 190 | 191 | static int shd_dev_mem_lock(void *priv) 192 | { 193 | return 0; 194 | } 195 | 196 | static int shd_dev_mem_unlock(void *priv) 197 | { 198 | return 0; 199 | } 200 | 201 | const struct shd_section_backend shd_dev_mem_backend = { 202 | .create = shd_dev_mem_create, 203 | .open = shd_dev_mem_open, 204 | .close = shd_dev_mem_close, 205 | .hdr_read = shd_dev_mem_read_header, 206 | .get_section_start = shd_dev_mem_get_section, 207 | .section_resize = shd_dev_mem_resize, 208 | .section_lock = shd_dev_mem_lock, 209 | .section_unlock = shd_dev_mem_unlock 210 | }; 211 | -------------------------------------------------------------------------------- /src/backend/shd_dev_mem.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_dev_mem.h 27 | * 28 | * @brief /dev/mem 29 | * 30 | */ 31 | 32 | #ifndef _SHD_DEV_MEM_H_ 33 | #define _SHD_DEV_MEM_H_ 34 | 35 | #include "shd_section.h" 36 | 37 | struct shd_dev_mem_backend_param { 38 | uintptr_t offset; 39 | int open_flags; 40 | }; 41 | 42 | extern const struct shd_section_backend shd_dev_mem_backend; 43 | 44 | #endif /* _SHD_DEV_MEM_H_ */ 45 | -------------------------------------------------------------------------------- /src/backend/shd_shm.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_shm.c 27 | * 28 | * @brief shd backend. 29 | * 30 | */ 31 | 32 | #define _GNU_SOURCE 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include /* For ftruncate */ 38 | #include /* For NAME_MAX macro */ 39 | #include /* for flock */ 40 | #include /* For shm and PROT flags */ 41 | #include 42 | #include 43 | #include "shd_hdr.h" 44 | #include "shd_section.h" 45 | #include "shd_private.h" 46 | #include "backend/shd_shm.h" 47 | 48 | #define SHD_SECTION_PREFIX "/shd_" 49 | 50 | struct shd_shm_priv { 51 | int fd; 52 | struct shd_section_addr addr; 53 | int writable; 54 | size_t creation_size; 55 | }; 56 | 57 | static int shd_shm_open_internal(struct shd_shm_priv *self, 58 | const char *blob_name, 59 | int flags, 60 | int mode) 61 | { 62 | char *path; 63 | int ret; 64 | 65 | ret = asprintf(&path, "%s%s", SHD_SECTION_PREFIX, blob_name); 66 | if (ret < 0) 67 | return -ENOMEM; 68 | 69 | self->fd = shm_open(path, flags, mode); 70 | if (self->fd == -1) { 71 | ret = -errno; 72 | goto error; 73 | } 74 | 75 | return 0; 76 | 77 | error: 78 | free(path); 79 | 80 | return ret; 81 | } 82 | 83 | static int shd_shm_open_other_root(struct shd_shm_priv *self, 84 | const struct shd_shm_backend_param *param, 85 | const char *blob_name, 86 | int flags, 87 | int mode) 88 | { 89 | char *path; 90 | int ret; 91 | 92 | ret = asprintf(&path, "%s%s%s", 93 | param->root, SHD_SECTION_PREFIX, blob_name); 94 | if (ret < 0) 95 | return -ENOMEM; 96 | 97 | self->fd = open(path, flags, mode); 98 | if (self->fd == -1) { 99 | ret = -errno; 100 | goto clear_path; 101 | } 102 | 103 | ret = fd_set_close_on_exec(self->fd); 104 | if (ret < 0) 105 | goto close_fd; 106 | 107 | free(path); 108 | 109 | return 0; 110 | 111 | close_fd: 112 | close(self->fd); 113 | clear_path: 114 | free(path); 115 | 116 | return ret; 117 | } 118 | 119 | static int open_internal(const char *blob_name, 120 | const struct shd_shm_backend_param *param, 121 | int flags, 122 | struct shd_shm_priv **priv) 123 | { 124 | struct shd_shm_priv *self; 125 | int mode = 0666; 126 | int ret; 127 | 128 | self = calloc(1, sizeof(*self)); 129 | if (!self) 130 | return -ENOMEM; 131 | 132 | if (!param || !param->root) { 133 | ret = shd_shm_open_internal(self, blob_name, flags, mode); 134 | if (ret < 0) 135 | goto error; 136 | } else { 137 | ret = shd_shm_open_other_root(self, param, blob_name, 138 | flags, mode); 139 | if (ret < 0) 140 | goto error; 141 | } 142 | 143 | *priv = self; 144 | 145 | return 0; 146 | 147 | error: 148 | free(self); 149 | 150 | return ret; 151 | } 152 | 153 | static int shd_shm_create(const char *blob_name, 154 | size_t size, 155 | const void *raw_param, 156 | void **priv, 157 | bool *first_creation) 158 | { 159 | const struct shd_shm_backend_param *param = raw_param; 160 | struct shd_shm_priv *self; 161 | int ret; 162 | 163 | ret = open_internal(blob_name, param, O_CREAT | O_EXCL | O_RDWR, &self); 164 | if (ret == 0) { 165 | *first_creation = true; 166 | } else if (ret == -EEXIST) { 167 | ret = open_internal(blob_name, param, O_EXCL | O_RDWR, &self); 168 | if (ret < 0) 169 | return ret; 170 | 171 | *first_creation = false; 172 | } else { 173 | return ret; 174 | } 175 | 176 | self->writable = 1; 177 | self->creation_size = size; 178 | 179 | *priv = self; 180 | 181 | return 0; 182 | } 183 | 184 | static int shd_shm_open(const char *blob_name, 185 | const void *raw_param, 186 | void **priv) 187 | { 188 | const struct shd_shm_backend_param *param = raw_param; 189 | struct shd_shm_priv *self; 190 | int ret; 191 | 192 | ret = open_internal(blob_name, param, O_EXCL | O_RDONLY, &self); 193 | if (ret < 0) 194 | return ret; 195 | 196 | self->writable = 0; 197 | 198 | *priv = self; 199 | 200 | return 0; 201 | } 202 | 203 | static int shd_shm_close(void *priv) 204 | { 205 | struct shd_shm_priv *self = priv; 206 | 207 | if (self->addr.ptr) 208 | munmap(self->addr.ptr, self->addr.size); 209 | 210 | close(self->fd); 211 | free(self); 212 | 213 | return 0; 214 | } 215 | 216 | static int shd_shm_read_header(struct shd_hdr *hdr, void *priv) 217 | { 218 | struct shd_shm_priv *self = priv; 219 | void *ptr; 220 | int ret; 221 | 222 | if (lseek(self->fd, 0, SEEK_END) <= 0) { 223 | ULOGW("Can not m'map in zero-sized file"); 224 | return -ENOMEM; 225 | } 226 | 227 | ptr = mmap(0, 228 | sizeof(hdr), 229 | PROT_READ, 230 | MAP_SHARED, 231 | self->fd, 232 | 0); 233 | if (ptr == MAP_FAILED) { 234 | ret = -errno; 235 | ULOGW("Could not allocate memory : %m"); 236 | return ret; 237 | } 238 | 239 | memcpy(hdr, ptr, sizeof(*hdr)); 240 | munmap(ptr, sizeof(*hdr)); 241 | 242 | return 0; 243 | } 244 | 245 | static int shd_shm_get_section(size_t size, 246 | void **out_ptr, void *priv) 247 | { 248 | struct shd_shm_priv *self = priv; 249 | void *ptr = NULL; 250 | int ret; 251 | 252 | ptr = mmap(0, 253 | size, 254 | self->writable ? PROT_WRITE : PROT_READ, 255 | MAP_SHARED, 256 | self->fd, 257 | 0); 258 | if (ptr == MAP_FAILED) { 259 | ret = -errno; 260 | ULOGW("Could not allocate memory : %m"); 261 | return ret; 262 | } 263 | 264 | self->addr.ptr = ptr; 265 | self->addr.size = size; 266 | 267 | *out_ptr = ptr; 268 | 269 | return 0; 270 | } 271 | 272 | static int shd_shm_resize(void *priv) 273 | { 274 | struct shd_shm_priv *self = priv; 275 | 276 | return ftruncate(self->fd, self->creation_size); 277 | } 278 | 279 | static int shd_shm_lock(void *priv) 280 | { 281 | struct shd_shm_priv *self = priv; 282 | 283 | return flock(self->fd, LOCK_EX | LOCK_NB); 284 | } 285 | 286 | static int shd_shm_unlock(void *priv) 287 | { 288 | struct shd_shm_priv *self = priv; 289 | 290 | return flock(self->fd, LOCK_UN); 291 | } 292 | 293 | const struct shd_section_backend shd_shm_backend = { 294 | .create = shd_shm_create, 295 | .open = shd_shm_open, 296 | .close = shd_shm_close, 297 | .hdr_read = shd_shm_read_header, 298 | .get_section_start = shd_shm_get_section, 299 | .section_resize = shd_shm_resize, 300 | .section_lock = shd_shm_lock, 301 | .section_unlock = shd_shm_unlock 302 | }; 303 | -------------------------------------------------------------------------------- /src/backend/shd_shm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_shm.h 27 | * 28 | * @brief shd backend. 29 | * 30 | */ 31 | 32 | #ifndef _SHD_SHM_H_ 33 | #define _SHD_SHM_H_ 34 | 35 | struct shd_shm_backend_param { 36 | const char *root; 37 | }; 38 | 39 | extern const struct shd_section_backend shd_shm_backend; 40 | 41 | #endif /* _SHD_SHM_H_ */ 42 | -------------------------------------------------------------------------------- /src/lookup/shd_lookup_default.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_lookup_default.c 27 | * 28 | * @brief Default implementation of section lookup function 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include "shd_section.h" 36 | #include "backend/shd_shm.h" 37 | 38 | int __attribute__((weak)) shd_section_lookup(const char *blob_name, 39 | struct shd_section_properties *properties) 40 | { 41 | properties->backend = &shd_shm_backend; 42 | properties->backend_param = NULL; 43 | shd_sync_primitives_set_builtin(&properties->primitives); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /src/lookup/shd_lookup_x1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file dev_lookup_x1.c 27 | * 28 | * @brief section lookup function for X1 target 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "shd_section.h" 37 | #include "backend/shd_shm.h" 38 | #include "backend/shd_dev_mem.h" 39 | #include 40 | 41 | static const struct { 42 | const char *name; 43 | struct shd_dev_mem_backend_param param; 44 | } bpmp_sections[] = { 45 | { 46 | .name = "imu_flight", 47 | .param = { 48 | .offset = LIBLK_SHD_IMU_FLIGHT_ADDR, 49 | } 50 | }, { 51 | .name = "imu_cam", 52 | .param = { 53 | .offset = LIBLK_SHD_IMU_CAM_ADDR, 54 | } 55 | },{ 56 | .name = "cam_h", 57 | .param = { 58 | .offset = LIBLK_SHD_CAM_H_ADDR, 59 | } 60 | },{ 61 | .name = "cam_v", 62 | .param = { 63 | .offset = LIBLK_SHD_CAM_V_ADDR, 64 | } 65 | },{ 66 | .name = "cppm", 67 | .param = { 68 | .offset = LIBLK_SHD_CPPM_ADDR, 69 | } 70 | },{ 71 | .name = "ulog", 72 | .param = { 73 | .offset = LIBLK_SHD_ULOG_ADDR, 74 | } 75 | }, 76 | }; 77 | 78 | static int bpmp_add_and_fetch(int *ptr, int value) 79 | { 80 | __sync_synchronize(); 81 | *ptr += value; 82 | __sync_synchronize(); 83 | return *ptr; 84 | } 85 | 86 | static struct shd_sync_primitives bpmp_sync_primitives = { 87 | .add_and_fetch = bpmp_add_and_fetch, 88 | }; 89 | 90 | int shd_section_lookup(const char *blob_name, 91 | struct shd_section_properties *properties) 92 | { 93 | size_t i; 94 | 95 | /* check if the section is stored in the memory shared with the bmbp */ 96 | for (i = 0; i < SIZEOF_ARRAY(bpmp_sections); i++) { 97 | if (!strcmp(blob_name, bpmp_sections[i].name)) { 98 | properties->backend = &shd_dev_mem_backend; 99 | properties->backend_param = &bpmp_sections[i].param; 100 | properties->primitives = bpmp_sync_primitives; 101 | 102 | return 0; 103 | } 104 | } 105 | 106 | /* on other cases use default backend (shm backend) */ 107 | properties->backend = &shd_shm_backend; 108 | properties->backend_param = NULL; 109 | shd_sync_primitives_set_builtin(&properties->primitives); 110 | 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /src/shd_ctx.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_ctx.c 27 | * 28 | * @brief shared memory data context implementation 29 | * 30 | */ 31 | 32 | #include /* For error codes */ 33 | #include /* For NULL pointer */ 34 | #include /* For memory allocation functions */ 35 | #include /* for strerror */ 36 | #include /* for close */ 37 | 38 | #include "shd_private.h" 39 | #include "shd_section.h" 40 | #include "shd_ctx.h" 41 | #include "shd_window.h" 42 | #include "shd_sync.h" 43 | #include "libshdata.h" 44 | 45 | struct shd_ctx *shd_ctx_new(struct shd_section_id *id, const char *blob_name) 46 | { 47 | struct shd_ctx *ctx; 48 | const char *env_search_method; 49 | 50 | /* Allocate context structure */ 51 | ctx = calloc(1, sizeof(*ctx)); 52 | if (ctx == NULL) 53 | goto error; 54 | 55 | ctx->blob_name = strdup(blob_name); 56 | ctx->id = *id; 57 | ctx->sync_ctx = shd_sync_ctx_new(id); 58 | if (ctx->sync_ctx == NULL) 59 | goto error; 60 | 61 | ctx->window = shd_window_new(); 62 | if (ctx->window == NULL) 63 | goto error; 64 | 65 | /* Set internal search method according to environment variable, if 66 | * existing and valid ; else default to naive search method */ 67 | env_search_method = getenv("LIBSHDATA_CONFIG_INTERNAL_SEARCH_METHOD"); 68 | if (env_search_method == NULL) { 69 | ctx->hint = SHD_WINDOW_REF_SEARCH_NAIVE; 70 | } else { 71 | if (!strcmp(env_search_method, "NAIVE")) 72 | ctx->hint = SHD_WINDOW_REF_SEARCH_NAIVE; 73 | else if (!strcmp(env_search_method, "BINARY")) 74 | ctx->hint = SHD_WINDOW_REF_SEARCH_BINARY; 75 | else if (!strcmp(env_search_method, "DATE")) 76 | ctx->hint = SHD_WINDOW_REF_SEARCH_DATE; 77 | else 78 | ctx->hint = SHD_WINDOW_REF_SEARCH_NAIVE; 79 | } 80 | 81 | return ctx; 82 | 83 | error: 84 | if (ctx != NULL) { 85 | shd_sync_ctx_destroy(ctx->sync_ctx); 86 | shd_window_destroy(ctx->window); 87 | shd_ctx_destroy(ctx); 88 | } 89 | return NULL; 90 | } 91 | 92 | int shd_ctx_mmap(struct shd_ctx *ctx, 93 | const struct shd_hdr_user_info *hdr_info) 94 | { 95 | if (ctx == NULL) 96 | return -EINVAL; 97 | 98 | ctx->sect_mmap = shd_section_mapping_new(&ctx->id, hdr_info); 99 | if (ctx->sect_mmap == NULL) 100 | return -EFAULT; 101 | ctx->desc = shd_data_section_desc_new(ctx, hdr_info); 102 | if (ctx->desc == NULL) 103 | return -EFAULT; 104 | 105 | return 0; 106 | } 107 | 108 | int shd_ctx_destroy(struct shd_ctx *ctx) 109 | { 110 | if (ctx != NULL) { 111 | shd_section_free(&ctx->id); 112 | shd_sync_ctx_destroy(ctx->sync_ctx); 113 | shd_section_mapping_destroy(ctx->sect_mmap); 114 | free(ctx->blob_name); 115 | free(ctx->desc); 116 | shd_window_destroy(ctx->window); 117 | free(ctx); 118 | } 119 | 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /src/shd_ctx.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_ctx.h 27 | * 28 | * @brief shared memory data context management. 29 | * 30 | */ 31 | 32 | #ifndef _SHD_CTX_H_ 33 | #define _SHD_CTX_H_ 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | #include 40 | #include "shd_section.h" 41 | #include "libshdata.h" 42 | 43 | struct shd_ctx { 44 | /* shared memory section identifier */ 45 | struct shd_section_id id; 46 | /* full name of the shared memory section */ 47 | char *blob_name; 48 | /* synchronization-related context */ 49 | struct shd_sync_ctx *sync_ctx; 50 | /* structure of the shared memory data section */ 51 | struct shd_data_section_desc *desc; 52 | /* M'maped pointers to the shared memory section */ 53 | struct shd_section *sect_mmap; 54 | /* current window of matching samples */ 55 | struct shd_window *window; 56 | /* Favored method of search, setup by environment variable */ 57 | enum shd_ref_sample_search_hint hint; 58 | /* Pointer to the library-allocated metadata */ 59 | struct shd_sample_metadata *metadata; 60 | }; 61 | 62 | /* 63 | * @brief Allocate and create a new shared memory context 64 | * 65 | * @param[in] id : file descriptor to the open shared memory section that 66 | * should be associated to that context 67 | * @param[in] blob_name : name of the blob within the shared memory section 68 | * 69 | * @return : an allocated shared memory context, 70 | * NULL in case of error 71 | */ 72 | struct shd_ctx *shd_ctx_new(struct shd_section_id *id, const char *blob_name); 73 | 74 | /* 75 | * @brief M'map shared memory section into context 76 | * 77 | * @param[in] ctx : context to m'map 78 | * @param[in] hdr_info : pointer to the header structure that contains all info 79 | * regarding the shared memory section 80 | * 81 | * @return : 0 in case of success, 82 | * -EINVAL if ctx is NULL 83 | * -EFAULT if a fault is detected while m'maping 84 | */ 85 | int shd_ctx_mmap(struct shd_ctx *ctx, 86 | const struct shd_hdr_user_info *hdr_info); 87 | 88 | /* 89 | * @brief Destroys a shared memory context 90 | * 91 | * @param[in] ctx : context to destroy 92 | * 93 | * @return : 0 in case of success 94 | */ 95 | int shd_ctx_destroy(struct shd_ctx *ctx); 96 | 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | 102 | #endif /* _SHD_CTX_H_ */ 103 | -------------------------------------------------------------------------------- /src/shd_data.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_data.c 27 | * 28 | * @brief shared memory data section management. 29 | * 30 | */ 31 | 32 | #define _GNU_SOURCE 33 | 34 | #include 35 | #include 36 | #include 37 | #include /* for memcpy function */ 38 | #include /* For memory allocation functions */ 39 | #include 40 | #include 41 | #include "shd_ctx.h" 42 | #include "shd_sync.h" 43 | #include "shd_data.h" 44 | #include "shd_utils.h" 45 | #include "shd_private.h" 46 | #include "shd_sample.h" 47 | #include "shd_window.h" 48 | #include "shd_section.h" 49 | #include "libshdata.h" 50 | 51 | struct shd_sample * 52 | shd_data_get_sample_ptr(const struct shd_data_section_desc *desc, 53 | int index) 54 | { 55 | return (struct shd_sample *) ((char *)desc->data_section_start 56 | + index * shd_sample_get_size(desc->blob_size)); 57 | } 58 | 59 | int shd_data_clear_section(const struct shd_data_section_desc *desc) 60 | { 61 | unsigned int i; 62 | memset(desc->data_section_start, 63 | 0, 64 | shd_data_get_total_size(desc->blob_size, desc->nb_samples)); 65 | for (i = 0; i < desc->nb_samples; i++) { 66 | struct shd_sample *samp = shd_data_get_sample_ptr(desc, i); 67 | shd_sync_invalidate_sample(&samp->sync); 68 | } 69 | 70 | return 0; 71 | } 72 | 73 | int shd_data_reserve_write(struct shd_ctx *ctx) 74 | { 75 | int ret; 76 | int index; 77 | struct shd_sample *curr_sample; 78 | 79 | ret = shd_sync_start_write_session(ctx->sync_ctx, 80 | ctx->sect_mmap->sync_top); 81 | 82 | if (ret < 0) 83 | return ret; 84 | 85 | index = shd_sync_get_next_write_index(ctx->sect_mmap->sync_top, 86 | ctx->desc); 87 | curr_sample = shd_data_get_sample_ptr(ctx->desc, 88 | index); 89 | 90 | ret = shd_sync_start_sample_write(ctx->sync_ctx, 91 | ctx->sect_mmap->sync_top, 92 | &curr_sample->sync, 93 | ctx->desc); 94 | 95 | if (ret < 0) 96 | return ret; 97 | 98 | return 0; 99 | } 100 | 101 | int shd_data_write_metadata(struct shd_ctx *ctx, 102 | const struct shd_sample_metadata *metadata) 103 | { 104 | struct shd_sample *curr_sample; 105 | int index = shd_sync_get_local_write_index(ctx->sync_ctx); 106 | if (index == -1) 107 | return -EPERM; 108 | 109 | curr_sample = shd_data_get_sample_ptr(ctx->desc, 110 | index); 111 | 112 | return shd_sample_write(curr_sample, 113 | 0, 114 | metadata, 115 | sizeof(*metadata)); 116 | } 117 | 118 | int shd_data_write_quantity(struct shd_ctx *ctx, 119 | const struct shd_quantity *quantity, 120 | const void *src) 121 | { 122 | struct shd_sample *curr_sample; 123 | ptrdiff_t blob_offset; 124 | int index = shd_sync_get_local_write_index(ctx->sync_ctx); 125 | if (index == -1) 126 | return -EPERM; 127 | 128 | 129 | curr_sample = shd_data_get_sample_ptr(ctx->desc, 130 | index); 131 | 132 | blob_offset = offsetof(struct shd_sample, blob); 133 | 134 | return shd_sample_write(curr_sample, 135 | blob_offset + quantity->quantity_offset, 136 | src, 137 | quantity->quantity_size); 138 | } 139 | 140 | int shd_data_end_write(struct shd_ctx *ctx) 141 | { 142 | int index = shd_sync_get_local_write_index(ctx->sync_ctx); 143 | if (index == -1) 144 | return -EPERM; 145 | 146 | return shd_sync_end_write_session(ctx->sync_ctx, 147 | ctx->sect_mmap->sync_top); 148 | } 149 | 150 | int shd_data_find(struct shd_ctx *ctx, 151 | const struct shd_sample_search *search) 152 | { 153 | int ret; 154 | struct shd_sample *wstart; 155 | int t_index; 156 | 157 | t_index = shd_sync_get_last_write_index(ctx->sect_mmap->sync_top); 158 | if (t_index == -1) 159 | return -EAGAIN; 160 | /* @todo EAGAIN should also be returned if there hasn't been enough 161 | * writes to the shared memory section yet 162 | */ 163 | 164 | if ((search->nb_values_after_date + search->nb_values_before_date + 1) 165 | > ctx->desc->nb_samples) 166 | return -EINVAL; 167 | 168 | ret = shd_window_set(ctx->window, ctx->sect_mmap->sync_top, 169 | search, ctx->desc, 170 | ctx->hint); 171 | 172 | if (ret < 0) { 173 | return ret; 174 | } else { 175 | wstart = shd_data_get_sample_ptr(ctx->desc, 176 | ctx->window->start_idx); 177 | shd_sync_start_read_session(ctx->sync_ctx, &wstart->sync); 178 | return ctx->window->nb_matches; 179 | } 180 | } 181 | 182 | int shd_data_read_metadata(struct shd_ctx *ctx, 183 | struct shd_sample_metadata **metadata) 184 | { 185 | int ret = -1; 186 | 187 | if (ctx->window == NULL) { 188 | ret = -EPERM; 189 | goto exit; 190 | } 191 | 192 | *metadata = calloc(ctx->window->nb_matches, 193 | sizeof(struct shd_sample_metadata)); 194 | if (*metadata == NULL) { 195 | ret = -ENOMEM; 196 | goto exit; 197 | } 198 | 199 | shd_window_read(ctx->window, ctx->desc, *metadata, 200 | sizeof(struct shd_sample_metadata), 201 | offsetof(struct shd_sample, metadata)); 202 | 203 | ret = interval_between(ctx->window->start_idx, 204 | ctx->window->ref_idx, 205 | ctx->desc->nb_samples); 206 | 207 | ctx->metadata = *metadata; 208 | 209 | exit: 210 | return ret; 211 | } 212 | 213 | int shd_data_read_blob(struct shd_ctx *ctx, void *dst, size_t dst_size) 214 | { 215 | int ret = -ENOSYS; 216 | size_t req_size; 217 | 218 | if (ctx->window->nb_matches < 0) { 219 | ret = -EPERM; 220 | goto exit; 221 | } 222 | 223 | req_size = ctx->desc->blob_size * ctx->window->nb_matches; 224 | if (dst_size < req_size) { 225 | ret = -EINVAL; 226 | goto exit; 227 | } 228 | 229 | ret = shd_window_read(ctx->window, ctx->desc, dst, 230 | ctx->desc->blob_size, 231 | offsetof(struct shd_sample, blob)); 232 | 233 | exit: 234 | return ret; 235 | } 236 | 237 | int shd_data_read_quantity(struct shd_ctx *ctx, 238 | const struct shd_quantity *quantity, 239 | void *dst, 240 | size_t dst_size) 241 | { 242 | int ret = -ENOSYS; 243 | size_t req_size; 244 | 245 | if (ctx->window->nb_matches < 0) { 246 | ret = -EPERM; 247 | goto exit; 248 | } 249 | 250 | req_size = quantity->quantity_size * ctx->window->nb_matches; 251 | if (dst_size < req_size) { 252 | ret = -EINVAL; 253 | goto exit; 254 | } 255 | 256 | ret = shd_window_read(ctx->window, ctx->desc, dst, 257 | quantity->quantity_size, 258 | offsetof(struct shd_sample, blob) 259 | + quantity->quantity_offset); 260 | exit: 261 | return ret; 262 | } 263 | 264 | int shd_data_read_quantity_sample(struct shd_ctx *ctx, 265 | int n_quantities, 266 | const struct shd_quantity quantity[], 267 | struct shd_quantity_sample qty_samples[]) 268 | { 269 | int ret = 0; 270 | int q_idx = 0; 271 | int s_index; 272 | struct shd_sample *curr; 273 | 274 | if (ctx->window->nb_matches < 0) { 275 | ret = -EPERM; 276 | goto exit; 277 | } 278 | if (ctx->window->nb_matches != 1) { 279 | ret = -EINVAL; 280 | goto exit; 281 | } 282 | 283 | s_index = ctx->window->ref_idx; 284 | curr = shd_data_get_sample_ptr(ctx->desc, s_index); 285 | 286 | for (q_idx = 0; q_idx < n_quantities; q_idx++) { 287 | /* Check that the destination buffer is large enough */ 288 | if (quantity[q_idx].quantity_size 289 | <= qty_samples[q_idx].size) { 290 | /* Copy quantity data */ 291 | shd_sample_read(curr, 292 | quantity[q_idx].quantity_offset 293 | + offsetof(struct shd_sample, 294 | blob), 295 | qty_samples[q_idx].ptr, 296 | qty_samples[q_idx].size); 297 | /* Copy quantity metadata */ 298 | shd_sample_read(curr, 299 | offsetof(struct shd_sample, metadata), 300 | &qty_samples[q_idx].meta, 301 | sizeof(struct shd_sample_metadata)); 302 | 303 | ret++; 304 | } 305 | } 306 | 307 | exit: 308 | return ret; 309 | } 310 | 311 | int shd_data_check_validity(struct shd_ctx *ctx, struct shd_revision *rev) 312 | { 313 | struct shd_sample *w_start; 314 | int ret; 315 | 316 | if (ctx->window->start_idx >= 0) 317 | w_start = shd_data_get_sample_ptr(ctx->desc, 318 | ctx->window->start_idx); 319 | else 320 | return -EPERM; 321 | 322 | ret = shd_sync_end_read_session(ctx->sync_ctx, &w_start->sync); 323 | 324 | if (ret < 0) 325 | return ret; 326 | 327 | ret = shd_sync_check_revision_nb(rev, 328 | ctx->sect_mmap->sync_top); 329 | 330 | return ret; 331 | } 332 | 333 | int shd_data_end_read(struct shd_ctx *ctx) 334 | { 335 | int ret; 336 | 337 | ret = shd_window_reset(ctx->window); 338 | if (ret < 0) { 339 | ret = -EPERM; 340 | goto exit; 341 | } 342 | 343 | exit: 344 | free(ctx->metadata); 345 | return 0; 346 | } 347 | 348 | size_t shd_data_get_total_size(size_t blob_size, 349 | uint32_t max_nb_samples) 350 | { 351 | return max_nb_samples * shd_sample_get_size(blob_size); 352 | } 353 | 354 | struct shd_data_section_desc *shd_data_section_desc_new(struct shd_ctx *ctx, 355 | const struct shd_hdr_user_info *hdr_info) 356 | { 357 | struct shd_data_section_desc *desc; 358 | const struct shd_hdr_user_info *user_info; 359 | 360 | /* Allocate context structure */ 361 | desc = calloc(1, sizeof(*desc)); 362 | if (desc == NULL) 363 | return NULL; 364 | 365 | desc->data_section_start = ctx->sect_mmap->data_top; 366 | if (hdr_info == NULL) 367 | user_info = ctx->sect_mmap->header_top; 368 | else 369 | user_info = hdr_info; 370 | desc->blob_size = user_info->blob_size; 371 | desc->nb_samples = user_info->max_nb_samples; 372 | 373 | return desc; 374 | } 375 | 376 | -------------------------------------------------------------------------------- /src/shd_data.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_data.h 27 | * 28 | * @brief shared memory data section management. 29 | * 30 | */ 31 | 32 | #ifndef _SHD_DATA_H_ 33 | #define _SHD_DATA_H_ 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | #include 40 | #include 41 | 42 | struct shd_data_section_desc { 43 | /* Start of data section (pointer to the first sample) */ 44 | void *data_section_start; 45 | /* Size of a blob */ 46 | size_t blob_size; 47 | /* Total number of samples */ 48 | uint32_t nb_samples; 49 | }; 50 | 51 | #include "libshdata.h" 52 | 53 | /* 54 | * @brief Get pointer to sample 55 | * 56 | * @param[in] desc : description of the data section 57 | * @param[in] index : index of the sample 58 | * 59 | * @return : pointer to the sample 60 | */ 61 | struct shd_sample * 62 | shd_data_get_sample_ptr(const struct shd_data_section_desc *desc, 63 | int index); 64 | 65 | /* 66 | * @brief Clear a given memory section (setting it all to zero) 67 | * 68 | * @param[in] id : id of the section to clear 69 | * 70 | * @return : 0 in case of success 71 | */ 72 | int shd_data_clear_section(const struct shd_data_section_desc *desc); 73 | 74 | /* 75 | * @brief Reserve write in a new data slot 76 | * 77 | * @param[in,out] ctx : current shared memory context 78 | * 79 | * @return : 0 in case of success, 80 | * -EINVAL if arguments are invalid, 81 | * -EALREADY if an operation is already in progress, 82 | * -EFAULT if at least one write occurred outside of the current 83 | * context, indicating a severe fault 84 | */ 85 | int shd_data_reserve_write(struct shd_ctx *ctx); 86 | 87 | /* 88 | * @brief Write metadata for the current data slot 89 | * 90 | * @param[in,out] ctx : current shared memory context 91 | * @param[in] metadata : metadata to write 92 | * 93 | * @return : 0 in case of success, 94 | * -EINVAL if arguments are invalid, 95 | * -EALREADY if an operation is already in progress, 96 | * -EPERM if the operation is not permitted (out-of-sequence call) 97 | */ 98 | int shd_data_write_metadata(struct shd_ctx *ctx, 99 | const struct shd_sample_metadata *metadata); 100 | 101 | /* 102 | * @brief Write quantity into the current data slot 103 | * 104 | * @param[in,out] ctx : current shared memory context 105 | * @param[in] quantity : quantity to write 106 | * @param[in] src : quantity source 107 | * 108 | * @return : 0 in case of success, 109 | * -EPERM if the operation is not permitted (out-of-sequence call) 110 | */ 111 | int shd_data_write_quantity(struct shd_ctx *ctx, 112 | const struct shd_quantity *quantity, 113 | const void *src); 114 | 115 | /* 116 | * @brief End write operation to current data slot 117 | * 118 | * @param[in,out] ctx : current shared memory context 119 | * 120 | * @return : 0 in case of success, 121 | * -EPERM if the operation is not permitted 122 | */ 123 | int shd_data_end_write(struct shd_ctx *ctx); 124 | 125 | /* 126 | * @brief Find the set of samples that match a given search 127 | * 128 | * @param[in,out] ctx : current shared memory context 129 | * @param[in] search : search parameters 130 | * 131 | * @return : number of matches in case of success, 132 | * -EINVAL if number of values to search excesses the size of the 133 | * section 134 | * -EAGAIN if no value has yet been produced in that memory section 135 | * -ENOENT if no sample has been found to match the search 136 | */ 137 | int shd_data_find(struct shd_ctx *ctx, 138 | const struct shd_sample_search *search); 139 | 140 | /* 141 | * @brief Allocate and fill a structure describing metadata for a range of 142 | * samples that matched a previous search 143 | * 144 | * @param[in,out] ctx : current shared memory context 145 | * @param[out] metadata : pointer to pointer to an array of read metadata 146 | * 147 | * @return : index of the reference sample in the metadata array in case of 148 | * success, 149 | * -EPERM if the function was called out of sequence, 150 | */ 151 | int shd_data_read_metadata(struct shd_ctx *ctx, 152 | struct shd_sample_metadata **metadata); 153 | 154 | /* 155 | * @brief Copy all the blobs of the previously selected samples into a user- 156 | * defined buffer 157 | * 158 | * @param[in] ctx : current shared memory context 159 | * @param[out] dst : destination buffer 160 | * @param[in] dst_size : size of destination buffer 161 | * 162 | * @return : number of samples that were read on success, 163 | * -EINVAL if any argument is invalid, or destination buffer is too 164 | * small 165 | * -EPERM if the function was called out of sequence 166 | */ 167 | int shd_data_read_blob(struct shd_ctx *ctx, void *dst, size_t dst_size); 168 | 169 | /* 170 | * @brief Copy a given quantity of the previously selected samples into a user- 171 | * defined buffer 172 | * 173 | * @param[in] ctx : current shared memory context 174 | * @param[in] quantity : quantity to read 175 | * @param[out] dst : destination buffer 176 | * @param[in] dst_size : size of destination buffer 177 | * 178 | * @return : number of samples that were read on success, 179 | * -EINVAL if any argument is invalid, or destination buffer is too 180 | * small 181 | * -EPERM if the function was called out of sequence 182 | */ 183 | int shd_data_read_quantity(struct shd_ctx *ctx, 184 | const struct shd_quantity *quantity, 185 | void *dst, 186 | size_t dst_size); 187 | 188 | /* 189 | * @brief Copy a set of quantities of a previously defined sample into user- 190 | * defined buffers 191 | * 192 | * @param[in] ctx : current shared memory context 193 | * @param[in] n_quantities : number of different quantities to read (set to 194 | * zero to read the whole blob) 195 | * @param[in] quantity : pointer to an array of structures describing the 196 | * quantities to read (irrelevant if n_quantities is set to 0) 197 | * @param[in,out] qty_samples : pointer to an array of structures that describe 198 | * the buffer where to output the quantities of the matching sample and their 199 | * metadata 200 | * 201 | * @return : number of quantities read in total, 202 | * -EPERM if the function is called out-of-sequence 203 | * -EINVAL if more than one sample has to be read 204 | * 205 | */ 206 | int shd_data_read_quantity_sample(struct shd_ctx *ctx, 207 | int n_quantities, 208 | const struct shd_quantity quantity[], 209 | struct shd_quantity_sample qty_samples[]); 210 | 211 | /* 212 | * @brief Check if last read session was valid 213 | * 214 | * @param[in] ctx : current shared memory context 215 | * @param[in] rev : pointer to the revision structure that was output when 216 | * section was open 217 | * 218 | * @return : 0 if no problem was encountered, 219 | * -EPERM if call was out-of-sequence, 220 | * -EFAULT if read sample(s) was/were overwritten during last reading 221 | * sequence, 222 | * -ENODEV if blob format changed since the memory section was open 223 | */ 224 | int shd_data_check_validity(struct shd_ctx *ctx, struct shd_revision *rev); 225 | 226 | /* 227 | * @brief Free all data associated to last read session 228 | * 229 | * @param[in] ctx : current shared memory context 230 | * 231 | * @return : 0 if no problem was encountered, 232 | * -EINVAL if argument is NULL, 233 | * -EPERM if call was out-of-sequence, 234 | * -errno in case of error 235 | */ 236 | int shd_data_end_read(struct shd_ctx *ctx); 237 | 238 | /* 239 | * @brief Get total size of the data section 240 | * 241 | * @param[in] blob_size : size of a blob 242 | * @param[in] max_nb_samples : total number of samples in the section 243 | * 244 | * @return : total size of the data section 245 | */ 246 | size_t shd_data_get_total_size(size_t blob_size, 247 | uint32_t max_nb_samples); 248 | 249 | /* 250 | * @brief Allocate and get data section description 251 | * 252 | * @param[in] ctx : current shared memory context 253 | * @param[in] hdr_info : user header info 254 | * 255 | * @return : data section description, 256 | * NULL in case of error 257 | */ 258 | struct shd_data_section_desc *shd_data_section_desc_new(struct shd_ctx *ctx, 259 | const struct shd_hdr_user_info *hdr_info); 260 | 261 | #ifdef __cplusplus 262 | } 263 | #endif 264 | 265 | #endif /* _SHD_DATA_H_ */ 266 | -------------------------------------------------------------------------------- /src/shd_hdr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_ctx.h 27 | * 28 | * @brief shared memory section header management. 29 | * 30 | */ 31 | 32 | #include 33 | #include /* for memcpy function */ 34 | #include /* For memory allocation functions */ 35 | #include 36 | #include /* For lseek */ 37 | #include "shd_private.h" 38 | #include "shd_hdr.h" 39 | #include "libshdata.h" 40 | 41 | 42 | int shd_hdr_write(void *hdr_start, const struct shd_hdr_user_info *user_hdr) 43 | { 44 | int ret; 45 | struct shd_hdr *hdr = hdr_start; 46 | 47 | ret = memcmp(&hdr->user_info, user_hdr, sizeof(*user_hdr)); 48 | 49 | if (ret != 0) { 50 | ULOGI("Writing a new header into memory section"); 51 | memcpy(&hdr->user_info, user_hdr, sizeof(*user_hdr)); 52 | ret = -1; 53 | } else { 54 | ULOGI("New user header matches the one already present in " 55 | "shared memory"); 56 | ret = 0; 57 | } 58 | 59 | shd_sync_hdr_init(&hdr->sync_info); 60 | hdr->magic_number = SHD_MAGIC_NUMBER; 61 | hdr->lib_version_maj = SHD_VERSION_MAJOR; 62 | hdr->lib_version_min = SHD_VERSION_MINOR; 63 | 64 | return ret; 65 | } 66 | 67 | int shd_hdr_read(const struct shd_section_id *id, void *hdr_start, 68 | struct shd_hdr_user_info *hdr_user) 69 | { 70 | int ret; 71 | 72 | if (hdr_user == NULL) { 73 | ret = -EINVAL; 74 | goto exit; 75 | } 76 | 77 | if (hdr_start != NULL) { 78 | struct shd_hdr *hdr = hdr_start; 79 | 80 | memcpy(hdr_user, &hdr->user_info, sizeof(*hdr_user)); 81 | } else { 82 | struct shd_hdr hdr; 83 | 84 | ret = (*id->backend.hdr_read) (&hdr, id->instance); 85 | 86 | /* Copy the header and library version into user own memory in 87 | * all cases, then unmap the shared memory region */ 88 | memcpy(hdr_user, &hdr.user_info, sizeof(*hdr_user)); 89 | 90 | /* Check whether the section that was read and is supposed to 91 | * be a shared memory section is a shared memory section indeed. 92 | * This case can arise e.g. when reading from /dev/mem */ 93 | if (hdr.magic_number != SHD_MAGIC_NUMBER) { 94 | ULOGE("Mapped memory section is not a shared memory " 95 | "section"); 96 | ret = -EFAULT; 97 | goto exit; 98 | } 99 | 100 | /* If the library version registered in the shared memory 101 | * region does not match the one we are using, return an error. 102 | * The memcpy was therefore useless but is completely harmless, 103 | * and the code to remove the mapping from memory is kept 104 | * common. 105 | */ 106 | if (hdr.lib_version_maj != SHD_VERSION_MAJOR) { 107 | ULOGE("Trying to read a section created with another " 108 | "version of the library : update your " 109 | "software !"); 110 | ret = -EFAULT; 111 | goto exit; 112 | } 113 | } 114 | ret = 0; 115 | 116 | exit: 117 | return ret; 118 | } 119 | 120 | size_t shd_hdr_get_mdata_size(void *hdr_start) 121 | { 122 | struct shd_hdr_user_info *hdr = hdr_start; 123 | 124 | return hdr->blob_metadata_hdr_size; 125 | } 126 | -------------------------------------------------------------------------------- /src/shd_hdr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_ctx.h 27 | * 28 | * @brief shared memory section header management. 29 | * 30 | */ 31 | 32 | #ifndef _SHD_HDR_H_ 33 | #define _SHD_HDR_H_ 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | #include 40 | #include "shd_sync.h" 41 | #include "shd_section.h" 42 | #include "libshdata.h" 43 | 44 | struct shd_hdr { 45 | /* Magic number */ 46 | uint64_t magic_number; 47 | /* Library version major */ 48 | uint32_t lib_version_maj; 49 | /* Library version minor */ 50 | uint32_t lib_version_min; 51 | /* user-defined info */ 52 | struct shd_hdr_user_info user_info; 53 | /* sync-related info */ 54 | struct shd_sync_hdr sync_info; 55 | }; 56 | 57 | /* 58 | * @brief Write section header into shared memory 59 | * 60 | * Segmentation fault will occur if the process has no write access to the 61 | * address pointed by hdr_start 62 | * 63 | * @param[in] hdr_start : pointer to the start of the shared memory header 64 | * @param[in] hdr : pointer to the memory structure describing the header 65 | * 66 | * @return : 0 if the header that was already present in the memory section 67 | * was already filled with the new header value, 68 | * -1 otherwise 69 | */ 70 | int shd_hdr_write(void *hdr_start, const struct shd_hdr_user_info *hdr); 71 | 72 | /* 73 | * @brief Copy user info from header of shared memory section 74 | * 75 | * If the section is already m'mapped into memory, hdr_start argument must be 76 | * non null and point to the top of the shared memory section. 77 | * Else, hdr_start argument is discarded and a file descriptor to the open 78 | * shared memory section must be provided. 79 | * 80 | * @param[in] id : identifier of the open shared memory section 81 | * @param[in] hdr_start : pointer to the start of the shared memory header 82 | * @param[out] hdr_user : pointer to a user-allocated destination buffer for 83 | * the user info 84 | * 85 | * @return : 0 in case of success, 86 | * -EINVAL if the arguments are invalid 87 | * -ENOMEM if the header could not be mapped 88 | * -EFAULT if the shared memory section was created using another 89 | * library version, or the mapped memory section is not a shared memory section 90 | */ 91 | int shd_hdr_read(const struct shd_section_id *id, 92 | void *hdr_start, 93 | struct shd_hdr_user_info *hdr_user); 94 | 95 | /* 96 | * @brief Get size of metadata header 97 | * 98 | * @param[in] hdr_start : pointer to the start of the shared memory header 99 | * 100 | * @return : size of metadata header in case of success 101 | */ 102 | size_t shd_hdr_get_mdata_size(void *hdr_start); 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | 108 | #endif /* _SHD_HDR_H_ */ 109 | -------------------------------------------------------------------------------- /src/shd_mdata_hdr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_mdata_hdr.c 27 | * 28 | * @brief shared memory metadata header management. 29 | * 30 | */ 31 | 32 | #include /* for memcpy function */ 33 | #include 34 | #include "shd_private.h" 35 | #include "shd_mdata_hdr.h" 36 | 37 | int shd_mdata_hdr_write(void *mdata_hdr_start, 38 | const void *src, 39 | size_t mdata_size) 40 | { 41 | int ret = memcmp(mdata_hdr_start, src, mdata_size); 42 | 43 | if (ret != 0) { 44 | ULOGI("Writing a new metadata header into memory section"); 45 | memcpy(mdata_hdr_start, src, mdata_size); 46 | ret = -1; 47 | } else { 48 | ULOGI("New metadata header matches the one already present in " 49 | "shared memory"); 50 | ret = 0; 51 | } 52 | return ret; 53 | } 54 | 55 | int shd_mdata_hdr_read(void *mdata_hdr_start, void *dst, size_t dst_size) 56 | { 57 | if (dst == NULL) 58 | return -EINVAL; 59 | 60 | memcpy(dst, mdata_hdr_start, dst_size); 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /src/shd_mdata_hdr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_mdata_hdr.h 27 | * 28 | * @brief shared memory metadata header management. 29 | * 30 | */ 31 | 32 | #ifndef _SHD_MDATA_H_ 33 | #define _SHD_MDATA_H_ 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | #include 40 | 41 | /* 42 | * @brief Write metadata section into shared memory 43 | * 44 | * Segmentation fault will occur if the process has no write access to the 45 | * address pointed by hdr_start 46 | * 47 | * @param[in] mdata_hdr_start : pointer to the start of the shared memory header 48 | * @param[in] src : pointer to the memory structure describing the header 49 | * @param[in] mdata_size : size of the metadata header 50 | * 51 | * @return : 0 if the metadata that was already present in the memory section 52 | * was already filled with the new metadata value, 53 | * -1 otherwise 54 | */ 55 | int shd_mdata_hdr_write(void *mdata_hdr_start, 56 | const void *src, 57 | size_t mdata_size); 58 | 59 | /* 60 | * @brief Read metadata section from shared memory 61 | * 62 | * @param[in] mdata_hdr_start : pointer to the start of the shared memory header 63 | * @param[in] dst : pointer to the destination memory structure 64 | * @param[in] dst_size : size of the destination buffer 65 | * 66 | * @return : 0 if metadata was correctly copied, 67 | * -EINVAL if dst is invalid 68 | */ 69 | int shd_mdata_hdr_read(void *mdata_hdr_start, void *dst, size_t dst_size); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif /* _SHD_MDATA_H_ */ 76 | -------------------------------------------------------------------------------- /src/shd_private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * shd_private.h 27 | * 28 | * @brief shared memory private stuff. 29 | * 30 | */ 31 | 32 | #ifndef _SHD_PRIV_H_ 33 | #define _SHD_PRIV_H_ 34 | 35 | #include 36 | 37 | #if defined(BUILD_LIBULOG) 38 | #define ULOG_TAG libshdata 39 | #include 40 | 41 | #else 42 | /** Generic log */ 43 | #define ULOG(_fmt, ...) fprintf(stderr, _fmt "\n", ##__VA_ARGS__) 44 | /** Log as debug */ 45 | #define ULOGD(_fmt, ...) ULOG("[D]" _fmt, ##__VA_ARGS__) 46 | /** Log as info */ 47 | #define ULOGI(_fmt, ...) ULOG("[I]" _fmt, ##__VA_ARGS__) 48 | /** Log as warning */ 49 | #define ULOGW(_fmt, ...) ULOG("[W]" _fmt, ##__VA_ARGS__) 50 | /** Log as error */ 51 | #define ULOGE(_fmt, ...) ULOG("[E]" _fmt, ##__VA_ARGS__) 52 | #endif 53 | 54 | #endif /* _SHD_PRIV_H_ */ 55 | -------------------------------------------------------------------------------- /src/shd_sample.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_sample.c 27 | * 28 | * @brief shared memory sample management 29 | * 30 | */ 31 | 32 | #include 33 | #include /* for memcpy function */ 34 | #include "futils/timetools.h" 35 | #include "shd_utils.h" 36 | #include "shd_private.h" 37 | #include "shd_sample.h" 38 | 39 | size_t shd_sample_get_size(size_t blob_size) 40 | { 41 | return ALIGN_UP(offsetof(struct shd_sample, blob) + blob_size); 42 | } 43 | 44 | int shd_sample_read(struct shd_sample *sample, 45 | ptrdiff_t offset, 46 | void *dst, 47 | size_t length) 48 | { 49 | memcpy(dst, (char *)sample + offset, length); 50 | return 0; 51 | } 52 | 53 | int shd_sample_write(struct shd_sample *sample, 54 | ptrdiff_t offset, 55 | const void *src, 56 | size_t length) 57 | { 58 | memcpy((char *)sample + offset, src, length); 59 | return 0; 60 | } 61 | 62 | int shd_sample_timestamp_cmp(struct shd_sample *sample, 63 | struct timespec date) 64 | { 65 | return time_timespec_cmp(&sample->metadata.ts, &date); 66 | } 67 | 68 | int shd_sample_closest_timestamp(struct shd_sample *before, 69 | struct shd_sample *after, 70 | struct timespec date) 71 | { 72 | int ret; 73 | struct timespec duration_before; 74 | struct timespec duration_after; 75 | 76 | ret = time_timespec_diff(&before->metadata.ts, 77 | &date, 78 | &duration_before); 79 | if (ret < 0) 80 | goto exit; 81 | 82 | ret = time_timespec_diff(&date, 83 | &after->metadata.ts, 84 | &duration_after); 85 | if (ret < 0) 86 | goto exit; 87 | 88 | /* The comparison returns 1 if "duration_after" is bigger than 89 | * "duration_before", meaning "before" is closer from date than "after" 90 | */ 91 | ret = time_timespec_cmp(&duration_after, &duration_before); 92 | 93 | exit: 94 | return ret; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /src/shd_sample.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_sample.h 27 | * 28 | * @brief shared memory sample management 29 | * 30 | */ 31 | 32 | #ifndef SHD_SAMPLE_H_ 33 | #define SHD_SAMPLE_H_ 34 | 35 | #include 36 | #include "shd_sync.h" 37 | #include "libshdata.h" 38 | 39 | /* @todo this structure should certainly not need to be exposed in this 40 | * header */ 41 | struct shd_sample { 42 | struct shd_sample_metadata metadata; 43 | struct shd_sync_sample sync; 44 | void *blob; 45 | }; 46 | 47 | /* 48 | * @brief Get the total size of a sample 49 | * 50 | * @param[in] blob_size : size of the blob contained in the sample 51 | * 52 | * @return : size of the sample 53 | */ 54 | size_t shd_sample_get_size(size_t blob_size); 55 | 56 | /* 57 | * @brief Read some data from a given sample 58 | * 59 | * @param[in] sample : pointer to the sample to read from 60 | * @param[in] offset : offset within the sample at which data should be read 61 | * @param[in] dst : destination buffer for the data 62 | * @param[in] length : length of the data to copy 63 | * 64 | * @return : 0 in any case 65 | */ 66 | int shd_sample_read(struct shd_sample *sample, 67 | ptrdiff_t offset, 68 | void *dst, 69 | size_t length); 70 | 71 | /* 72 | * @brief Write some data into a given sample 73 | * 74 | * @param[in] sample : pointer to the sample to read from 75 | * @param[in] offset : offset within the sample at which data should be written 76 | * @param[in] src : data to copy 77 | * @param[in] length : length of the data to copy 78 | * 79 | * @return : 0 in any case 80 | */ 81 | int shd_sample_write(struct shd_sample *sample, 82 | ptrdiff_t offset, 83 | const void *src, 84 | size_t length); 85 | 86 | /* 87 | * @brief Compare a sample timestamp against a given date 88 | * 89 | * @param[in] sample : pointer to the sample to read 90 | * @param[in] date : date against which to compare the sample 91 | * 92 | * @return 0 if sample timestamp equals date 93 | * -1 if sample timestamp is before date 94 | * 1 if sample timestamp is after date 95 | */ 96 | int shd_sample_timestamp_cmp(struct shd_sample *sample, 97 | struct timespec date); 98 | 99 | /* 100 | * @brief Out of 2 samples, return which one is closer to a given date 101 | * 102 | * @param[in] s1 : pointer to the first sample 103 | * @param[in] s2 : pointer to the second sample 104 | * @param[in] date : reference date 105 | * 106 | * @return 0 if s1 and s2 are equally close from date 107 | * 1 if s1 is closer to date than s2 108 | * -1 if s2 is closer to date than s1 109 | */ 110 | int shd_sample_closest_timestamp(struct shd_sample *s1, 111 | struct shd_sample *s2, 112 | struct timespec date); 113 | 114 | #endif /* SHD_SAMPLE_H_ */ 115 | -------------------------------------------------------------------------------- /src/shd_search.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_search.h 27 | * 28 | * @brief shared memory search methods 29 | * 30 | */ 31 | 32 | #ifndef SHD_SEARCH_H_ 33 | #define SHD_SEARCH_H_ 34 | 35 | #include "shd_data.h" 36 | #include "shd_sync.h" 37 | 38 | /* 39 | * @brief Structure to hold the context of a search 40 | */ 41 | struct search_ctx { 42 | /* Index of the most recent sample in the buffer */ 43 | int t_index; 44 | /* Number of writes in the buffer slot containing the most recent 45 | * sample */ 46 | int nb_writes_top; 47 | }; 48 | 49 | char *shd_search_method_to_str(enum shd_search_method_t method); 50 | 51 | /* 52 | * @brief Get the max depth for a search within the section 53 | * 54 | * @details If the section has been recently created and hasn't looped at least 55 | * once through the whole buffer, not all the samples are valid ; this function 56 | * allows to limit the scope of the search only to the valid samples 57 | * 58 | * @param[in] desc : pointer to section description 59 | * @param[in] ctx : search context 60 | * 61 | * @return max possible depth, varying between 0 if no sample has been produced 62 | * and the total number of samples 63 | */ 64 | unsigned int shd_search_get_max_depth(const struct shd_data_section_desc *desc, 65 | const struct search_ctx *ctx); 66 | 67 | /* 68 | * @brief Get oldest sample in the section 69 | * 70 | * @details : if the section hasn't been written in full at least once, the 71 | * returned sample is indeed the oldest within the section. Else, it is the 72 | * second-oldest (to minimize the chances that the returned sample is 73 | * overwritten during the next read) 74 | * 75 | * @param[in] desc : description of the section 76 | * @param[in] ctx : context of the search 77 | * 78 | * @return index of the oldest sample if applicable, 79 | * -1 else 80 | */ 81 | int shd_search_oldest(const struct shd_data_section_desc *desc, 82 | const struct search_ctx *ctx); 83 | /* 84 | * @brief Search for the sample whose timestamp is right after a given date 85 | * 86 | * @param[in] desc : description of the section 87 | * @param[in] date : reference date 88 | * @param[in] ctx : context of the search 89 | * @param[in] hint : method to use for this search 90 | * 91 | * @return index of the sample if a match is found, 92 | * -1 else 93 | */ 94 | int shd_search_first_match_after(const struct shd_data_section_desc *desc, 95 | const struct timespec *date, 96 | const struct search_ctx *ctx, 97 | enum shd_ref_sample_search_hint hint); 98 | 99 | /* 100 | * @brief Search for the sample whose timestamp is right before a given date 101 | * 102 | * @param[in] desc : description of the section 103 | * @param[in] date : reference date 104 | * @param[in] ctx : context of the search 105 | * @param[in] hint : method to use for this search 106 | * 107 | * @return index of the sample if a match is found, 108 | * -1 else 109 | */ 110 | int shd_search_first_match_before(const struct shd_data_section_desc *desc, 111 | const struct timespec *date, 112 | const struct search_ctx *ctx, 113 | enum shd_ref_sample_search_hint hint); 114 | 115 | /* 116 | * @brief Search for the sample whose timestamp is the closest to a given date 117 | * 118 | * @param[in] desc : description of the section 119 | * @param[in] date : reference date 120 | * @param[in] ctx : context of the search 121 | * @param[in] hint : method to use for this search 122 | * 123 | * @return index of the sample if a match is found, 124 | * -1 else 125 | */ 126 | int shd_search_closest_match(const struct shd_data_section_desc *desc, 127 | const struct timespec *date, 128 | const struct search_ctx *ctx, 129 | enum shd_ref_sample_search_hint hint); 130 | 131 | /* 132 | * @brief Start a search session 133 | * 134 | * @param[in] hdr : pointer to the section's synchronization header 135 | * @param[in] desc : pointer to the section's description 136 | * 137 | * @return the context of the section at the time of call 138 | */ 139 | struct search_ctx shd_search_start(const struct shd_sync_hdr *hdr, 140 | const struct shd_data_section_desc *desc); 141 | 142 | /* 143 | * @brief End a search session 144 | * 145 | * @param[in] hdr : pointer to the synchronization header 146 | * @param[in] ctx : pointer to the search context at the start of the search 147 | * @param[in] w_start_idx : index of the start of the window 148 | * @param[in] desc : pointer to the description of the section 149 | * 150 | * @return true if the window was overwritten during the search, 151 | * false otherwise 152 | */ 153 | bool shd_search_end(const struct shd_sync_hdr *hdr, 154 | const struct search_ctx *ctx, 155 | int w_start_idx, 156 | const struct shd_data_section_desc *desc); 157 | 158 | #endif /* SHD_SEARCH_H_ */ 159 | -------------------------------------------------------------------------------- /src/shd_section.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_section.c 27 | * 28 | * @brief shared memory section management. 29 | * 30 | */ 31 | 32 | #define _GNU_SOURCE 33 | #include /* For error codes */ 34 | #include /* For mode constants */ 35 | #include /* For O_* constants */ 36 | #include /* String operations */ 37 | #include /* NULL pointer */ 38 | #include /* For memory allocation functions */ 39 | #include /* for flock */ 40 | #include /* For ftruncate */ 41 | #include "shd_private.h" 42 | #include "shd_section.h" 43 | #include "shd_hdr.h" 44 | #include "shd_data.h" 45 | #include "shd_utils.h" 46 | 47 | struct shd_section_mapping { 48 | ptrdiff_t metadata_offset; 49 | size_t metadata_size; 50 | ptrdiff_t data_offset; 51 | size_t data_size; 52 | size_t total_size; 53 | ptrdiff_t hdr_offset; 54 | ptrdiff_t sync_offset; 55 | }; 56 | 57 | static void get_offsets(const struct shd_hdr_user_info *hdr_info, 58 | struct shd_section_mapping *offsets) 59 | { 60 | offsets->metadata_offset = ALIGN_UP(sizeof(struct shd_hdr)); 61 | offsets->hdr_offset = offsetof(struct shd_hdr, user_info); 62 | offsets->sync_offset = offsetof(struct shd_hdr, sync_info); 63 | offsets->metadata_size = hdr_info->blob_metadata_hdr_size; 64 | offsets->data_offset = ALIGN_UP(offsets->metadata_offset + 65 | offsets->metadata_size); 66 | offsets->data_size = shd_data_get_total_size(hdr_info->blob_size, 67 | hdr_info->max_nb_samples); 68 | offsets->total_size = offsets->data_offset + offsets->data_size; 69 | } 70 | 71 | static struct shd_section *get_mmap(char *ptr, 72 | struct shd_section_mapping *offsets) 73 | { 74 | struct shd_section *map; 75 | 76 | map = calloc(1, sizeof(*map)); 77 | if (map == NULL) 78 | return NULL; 79 | 80 | map->section_top = ptr; 81 | map->header_top = ptr + offsets->hdr_offset; 82 | map->sync_top = ptr + offsets->sync_offset; 83 | map->metadata_blob_top = ptr + offsets->metadata_offset; 84 | map->data_top = ptr + offsets->data_offset; 85 | map->total_size = offsets->total_size; 86 | 87 | return map; 88 | } 89 | 90 | static int init_section_infos(const char *blob_name, 91 | struct shd_section_id *id, 92 | struct shd_section_properties *properties) 93 | { 94 | int ret; 95 | 96 | if (blob_name == NULL || strchr(blob_name, '/') != NULL) 97 | return -EINVAL; 98 | 99 | ret = shd_section_lookup(blob_name, properties); 100 | if (ret < 0) { 101 | ULOGE("blob '%s' not found", blob_name); 102 | return -ENOENT; 103 | } 104 | 105 | id->backend = *properties->backend; 106 | id->primitives = properties->primitives; 107 | 108 | return 0; 109 | } 110 | 111 | int shd_section_create(const char *blob_name, size_t size, 112 | struct shd_section_id *id, bool *first_creation) 113 | { 114 | struct shd_section_properties properties; 115 | int ret; 116 | 117 | ret = init_section_infos(blob_name, id, &properties); 118 | if (ret < 0) 119 | return ret; 120 | 121 | return (*id->backend.create) (blob_name, size, properties.backend_param, 122 | &id->instance, first_creation); 123 | } 124 | 125 | int shd_section_open(const char *blob_name, 126 | struct shd_section_id *id) 127 | { 128 | struct shd_section_properties properties; 129 | int ret; 130 | 131 | ret = init_section_infos(blob_name, id, &properties); 132 | if (ret < 0) 133 | return ret; 134 | 135 | return (*id->backend.open) (blob_name, properties.backend_param, 136 | &id->instance); 137 | } 138 | 139 | int shd_section_lock(const struct shd_section_id *id) 140 | { 141 | return (*id->backend.section_lock) (id->instance); 142 | } 143 | 144 | int shd_section_unlock(const struct shd_section_id *id) 145 | { 146 | return (*id->backend.section_unlock) (id->instance); 147 | } 148 | 149 | int shd_section_resize(const struct shd_section_id *id) 150 | { 151 | return (*id->backend.section_resize) (id->instance); 152 | } 153 | 154 | int shd_section_free(const struct shd_section_id *id) 155 | { 156 | return (*id->backend.close) (id->instance); 157 | } 158 | 159 | struct shd_section *shd_section_mapping_new(const struct shd_section_id *id, 160 | const struct shd_hdr_user_info *hdr_info) 161 | { 162 | struct shd_section *map = NULL; 163 | struct shd_hdr_user_info src_hdr_user; 164 | struct shd_section_mapping offsets; 165 | void *ptr = NULL; 166 | int ret; 167 | 168 | /* Either we can get the information from hdr_info itself, or we have 169 | * to get it from the header of the shared memory section */ 170 | if (hdr_info != NULL) { 171 | src_hdr_user = *hdr_info; 172 | } else { 173 | ret = shd_hdr_read(id, NULL, &src_hdr_user); 174 | if (ret < 0) 175 | goto error; 176 | } 177 | 178 | get_offsets(&src_hdr_user, &offsets); 179 | 180 | ret = (*id->backend.get_section_start) (offsets.total_size, 181 | &ptr, id->instance); 182 | if (ret < 0) { 183 | ULOGW("Could not allocate memory : %s", strerror(-ret)); 184 | return NULL; 185 | } 186 | 187 | map = get_mmap(ptr, &offsets); 188 | 189 | return map; 190 | 191 | error: 192 | return NULL; 193 | } 194 | 195 | int shd_section_mapping_destroy(struct shd_section *map) 196 | { 197 | free(map); 198 | 199 | return 0; 200 | } 201 | 202 | size_t shd_section_get_total_size(const struct shd_hdr_user_info *hdr_info) 203 | { 204 | if (hdr_info == NULL) 205 | return -1; 206 | 207 | return ALIGN_UP(sizeof(struct shd_hdr)) 208 | + ALIGN_UP(hdr_info->blob_metadata_hdr_size) 209 | + shd_data_get_total_size(hdr_info->blob_size, 210 | hdr_info->max_nb_samples); 211 | } 212 | 213 | -------------------------------------------------------------------------------- /src/shd_section.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_section.h 27 | * 28 | * @brief shared memory section management : allows abstraction from the 29 | * implementation of the shared memory section, whose correspondance with a 30 | * blob name can be either supported by : 31 | * * shm_open (setting the section in a given file prefixed by shd_ in 32 | * /dev/shm) 33 | * * open (setting the section in a given file prefixed by shd_ in 34 | * the directory passed in parameter) 35 | * * an external "dev-mem-lookup" module which for each blob name gives the 36 | * offset in /dev/mem that should be used 37 | * 38 | */ 39 | 40 | #ifndef _SHD_SECTION_H_ 41 | #define _SHD_SECTION_H_ 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | #include 48 | #include /* For NAME_MAX macro */ 49 | #include 50 | #include "libshdata.h" 51 | #include "shd_sync.h" 52 | 53 | struct shd_hdr; 54 | 55 | struct shd_section_addr { 56 | void *ptr; 57 | size_t size; 58 | }; 59 | 60 | struct shd_section_backend { 61 | /** 62 | * @brief Create a section 63 | * 64 | * @param[in] blob_name : name of the blob to add to the directory 65 | * @param[in] size : the size of the section to create 66 | * @param[in] param : backend-specific configuration parameter 67 | * @param[out] priv : backend instance 68 | * @param[out] first_creation : true if the section didn't exist 69 | * 70 | * @return 0 in case of success, else a negative errno 71 | * 72 | */ 73 | int (*create) (const char *blob_name, 74 | size_t size, 75 | const void *param, 76 | void **priv, 77 | bool *first_creation); 78 | 79 | /** 80 | * @brief Open a section 81 | * 82 | * @param[in] blob_name : name of the blob to add to the directory 83 | * @param[in] param : backend-specific configuration parameter 84 | * @param[out] priv : backend instance 85 | * 86 | * @return 0 in case of success, else a negative errno 87 | * 88 | */ 89 | int (*open) (const char *blob_name, 90 | const void *param, 91 | void **priv); 92 | 93 | /** 94 | * @brief Close and clear a section 95 | * 96 | * @param[in] priv : backend instance 97 | * @return 0 in case of success, else a negative errno 98 | */ 99 | int (*close) (void *priv); 100 | 101 | /** 102 | * @brief Read the header of a section 103 | * 104 | * @param[out] hdr : the header to fill 105 | * @param[in] priv : backend instance 106 | * 107 | * @return 0 in case of success, else a negative errno 108 | */ 109 | int (*hdr_read) (struct shd_hdr *hdr, void *priv); 110 | 111 | /** 112 | * @brief Get the start of a section 113 | * 114 | * @param[in] size : the expected section size 115 | * @param[out] out_ptr : pointer to the start of the section 116 | * @param[in] priv : backend instance 117 | * 118 | * @return 0 in case of success, else a negative errno 119 | */ 120 | int (*get_section_start) (size_t size, 121 | void **out_ptr, void *priv); 122 | 123 | /** 124 | * @brief Resize a section 125 | * 126 | * This function should use the "size" parameter given in create() 127 | * 128 | * @param[in] priv : backend instance 129 | * 130 | * @return 0 in case of success, else a negative errno 131 | */ 132 | int (*section_resize) (void *priv); 133 | 134 | /** 135 | * @brief Lock a section 136 | * 137 | * @param[in] size : the new section size 138 | * @param[in] priv : backend instance 139 | * 140 | * @return 0 in case of success, else a negative errno 141 | */ 142 | int (*section_lock) (void *priv); 143 | 144 | /** 145 | * @brief Unlock a section 146 | * 147 | * @param[in] priv : backend instance 148 | * 149 | * @return 0 in case of success, else a negative errno 150 | */ 151 | int (*section_unlock) (void *priv); 152 | }; 153 | 154 | struct shd_section_properties { 155 | const struct shd_section_backend *backend; 156 | const void *backend_param; 157 | 158 | struct shd_sync_primitives primitives; 159 | }; 160 | 161 | struct shd_section_id { 162 | struct shd_section_backend backend; 163 | struct shd_sync_primitives primitives; 164 | void *instance; 165 | }; 166 | 167 | struct shd_section { 168 | /* m'mapped pointer to the top of the shared memory section */ 169 | void *section_top; 170 | /* m'mapped pointer to the top of the header of the shared memory 171 | * section */ 172 | void *header_top; 173 | /* m'mapped pointer to the synchronization info in the header of the 174 | * shared memory */ 175 | void *sync_top; 176 | /* m'mapped pointer to the top of the metadata blob section header */ 177 | void *metadata_blob_top; 178 | /* m'mapped pointer to the top of the data section */ 179 | void *data_top; 180 | /* Total shared memory section size */ 181 | size_t total_size; 182 | }; 183 | 184 | /* 185 | * @brief Attempt to create a new shared memory section for a blob 186 | * 187 | * @param[in] blob_name : name of the blob to add to the directory 188 | * @param[in] size : size of the section to create 189 | * 190 | * @return : 0 in case of success, 191 | * -ENAMETOOLONG if blob_name exceeds max length 192 | * -EINVAL if blob_name contains a "/" 193 | * -EEXIST if a memory section has already been created for this blob, 194 | * other negative errno in case of error in "fcntl" 195 | */ 196 | int shd_section_create(const char *blob_name, size_t size, 197 | struct shd_section_id *id, bool *first_creation); 198 | 199 | /* 200 | * @brief Open a possibly already existing shared memory section for a blob 201 | * 202 | * @param[in] blob_name : name of the blob to add to the directory 203 | * 204 | * @return : 0 in case of success, 205 | * -ENAMETOOLONG if blob_name exceeds max length 206 | * -EINVAL if blob_name contains a "/", 207 | * other negative errno in case of error in "fcntl" 208 | */ 209 | int shd_section_open(const char *blob_name, 210 | struct shd_section_id *id); 211 | 212 | /* 213 | * @brief Lock a given memory section 214 | * 215 | * @param[in] id : id of the section to lock 216 | * 217 | * @return : 0 in case of success, 218 | * -EWOULDBLOCK if the section is already locked by another process 219 | */ 220 | int shd_section_lock(const struct shd_section_id *id); 221 | 222 | /* 223 | * @brief Unlock a given memory section 224 | * 225 | * @param[in] id : id of the section to unlock 226 | * 227 | * @return : 0 in case of success, 228 | * -errno in case of error 229 | */ 230 | int shd_section_unlock(const struct shd_section_id *id); 231 | 232 | /* 233 | * @brief Resize a given memory section 234 | * 235 | * @param[in] id : id of the section to unlock 236 | * 237 | * @return : 0 in case of success, 238 | */ 239 | int shd_section_resize(const struct shd_section_id *id); 240 | 241 | /* 242 | * @brief Free a given memory section 243 | * 244 | * @param[in] id : id of the section to free 245 | * 246 | * @return : 0 in case of success 247 | */ 248 | int shd_section_free(const struct shd_section_id *id); 249 | 250 | /* 251 | * @brief Allocate a structure which contains m'mapped pointers to each 252 | * subsection of a shared memory section 253 | * 254 | * Two possible cases here : 255 | * - either the memory section is already properly formatted, and mapping 256 | * information is extracted from the actual memory section header (consumer 257 | * side, most likely) 258 | * - or it is being created, and mapping information is extracted from the 259 | * arguments of the function (producer side, most likely) 260 | * 261 | * @param[in] id : identifier for the open shared memory section 262 | * @param[in] hdr_info : header info for that memory section (NULL if this 263 | * information is not available from caller's private memory) 264 | * 265 | * @return : pointer to the mapping, 266 | * NULL in case of error 267 | */ 268 | struct shd_section *shd_section_mapping_new(const struct shd_section_id *id, 269 | const struct shd_hdr_user_info *hdr_info); 270 | 271 | /* 272 | * @brief Destroy a memory section mapping 273 | * 274 | * @param[in] map : mapping to destroy 275 | * 276 | * @return : 0 in all cases 277 | */ 278 | int shd_section_mapping_destroy(struct shd_section *map); 279 | 280 | /* 281 | * @brief Return the total size of a shared memory section 282 | * 283 | * @param[in] hdr_info : header info for that memory section (NULL if this 284 | * information is not available from caller's private memory) 285 | * 286 | * @return : size of the section, 287 | * -1 in case of error 288 | */ 289 | size_t shd_section_get_total_size(const struct shd_hdr_user_info *hdr_info); 290 | 291 | /** 292 | * @brief Find a section from its name 293 | * 294 | * The implementation of the function is provided by the running platform. 295 | * A default implementation is available for tests purposes. This implementation 296 | * always indicate to use /dev/shm backend. 297 | * 298 | * @param[in] blob_name : name of the blob to look for 299 | * @param[out] properties : the properties of the section 300 | * 301 | * @return : 0 if the section has been found 302 | * -ENOENT if the section is unknown 303 | */ 304 | int shd_section_lookup(const char *blob_name, 305 | struct shd_section_properties *properties); 306 | 307 | #ifdef __cplusplus 308 | } 309 | #endif 310 | 311 | #endif /* _SHD_SECTION_H_ */ 312 | -------------------------------------------------------------------------------- /src/shd_sync.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_sync.c 27 | * 28 | */ 29 | 30 | #include /* For NULL pointer */ 31 | #include /* For memory allocation functions */ 32 | #include 33 | 34 | #include "shd_private.h" 35 | #include "shd_utils.h" 36 | #include "shd_data.h" 37 | #include "shd_section.h" 38 | #include "shd_sync.h" 39 | 40 | static int builtin_add_and_fetch(int *ptr, int value) 41 | { 42 | return __sync_add_and_fetch(ptr, value); 43 | } 44 | 45 | int shd_sync_hdr_init(struct shd_sync_hdr *sync_hdr) 46 | { 47 | sync_hdr->write_index = -1; 48 | sync_hdr->nb_ongoing_writes = 0; 49 | 50 | return 0; 51 | } 52 | 53 | struct shd_sync_ctx *shd_sync_ctx_new(const struct shd_section_id *id) 54 | { 55 | struct shd_sync_ctx *ctx; 56 | 57 | ctx = calloc(1, sizeof(*ctx)); 58 | if (ctx == NULL) 59 | return NULL; 60 | 61 | ctx->index = -1; 62 | ctx->prev_index = -1; 63 | ctx->primitives = id->primitives; 64 | 65 | return ctx; 66 | } 67 | 68 | int shd_sync_ctx_destroy(struct shd_sync_ctx *ctx) 69 | { 70 | if (ctx != NULL) 71 | free(ctx); 72 | 73 | return 0; 74 | } 75 | 76 | int shd_sync_start_write_session(struct shd_sync_ctx *ctx, 77 | struct shd_sync_hdr *hdr) 78 | { 79 | /* Number of writes currently going on is atomically incremented, and 80 | * its new value should be 1 (since only one write can be in progress 81 | * at a given moment) */ 82 | if (ctx->primitives.add_and_fetch(&hdr->nb_ongoing_writes, 1) != 1) { 83 | if (ctx->index != -1) { 84 | ULOGW("A write is already in progress within " 85 | "this producer"); 86 | return -EALREADY; 87 | } else { 88 | ULOGE("Abnormal write already in progress by another " 89 | "producer"); 90 | return -EPERM; 91 | } 92 | } 93 | 94 | return 0; 95 | } 96 | 97 | int shd_sync_start_sample_write(struct shd_sync_ctx *ctx, 98 | struct shd_sync_hdr *hdr, 99 | struct shd_sync_sample *samp, 100 | const struct shd_data_section_desc *desc) 101 | { 102 | uint32_t unexpected_samples; 103 | 104 | if (ctx == NULL || hdr == NULL) 105 | return -EINVAL; 106 | if (ctx->index != -1) 107 | return -EALREADY; 108 | 109 | /* Invalidate sample */ 110 | ctx->primitives.add_and_fetch(&samp->nb_writes, 1); 111 | /* Update local index */ 112 | index_increment_from(&ctx->index, &hdr->write_index, desc->nb_samples); 113 | 114 | unexpected_samples = interval_between(ctx->prev_index, 115 | ctx->index, 116 | desc->nb_samples) - 1; 117 | 118 | /* Only one sample should have been written since the previous write, 119 | * otherwise another thread has written into the section */ 120 | if (unexpected_samples > 0 && ctx->prev_index != -1) { 121 | ULOGW("%d sample(s) unexpectedly written since last write " 122 | "operation in this thread", 123 | unexpected_samples); 124 | return -EFAULT; 125 | } 126 | 127 | ULOGD("Starting write on sample at index : %d, nb_writes : %d", 128 | ctx->index, samp->nb_writes); 129 | 130 | return 0; 131 | } 132 | 133 | int shd_sync_end_write_session(struct shd_sync_ctx *ctx, 134 | struct shd_sync_hdr *hdr) 135 | { 136 | if (ctx == NULL || hdr == NULL) 137 | return -EINVAL; 138 | 139 | ULOGD("End of write on sample at index : %d", ctx->index); 140 | hdr->write_index = ctx->index; 141 | hdr->nb_ongoing_writes = 0; 142 | ctx->prev_index = ctx->index; 143 | ctx->index = -1; 144 | return 0; 145 | } 146 | 147 | int shd_sync_start_read_session(struct shd_sync_ctx *ctx, 148 | struct shd_sync_sample *samp) 149 | { 150 | if (ctx == NULL || samp == NULL) 151 | return -EINVAL; 152 | 153 | ctx->nb_writes = samp->nb_writes; 154 | ULOGD("Starting read session, nb_writes = %d", ctx->nb_writes); 155 | return 0; 156 | } 157 | 158 | int shd_sync_end_read_session(struct shd_sync_ctx *ctx, 159 | struct shd_sync_sample *samp) 160 | { 161 | int ret = -1; 162 | if (ctx == NULL || samp == NULL) { 163 | ret = -EINVAL; 164 | goto exit; 165 | } 166 | 167 | if (ctx->nb_writes != samp->nb_writes) { 168 | ULOGW("Current sample has been overwritten during read : " 169 | "expected value : %d, read : %d", ctx->nb_writes, 170 | samp->nb_writes); 171 | ret = -EFAULT; 172 | } else { 173 | ret = 0; 174 | } 175 | 176 | ctx->nb_writes = -1; 177 | 178 | exit: 179 | return ret; 180 | } 181 | 182 | int shd_sync_get_nb_writes(const struct shd_sync_sample *samp) 183 | { 184 | return samp->nb_writes; 185 | } 186 | 187 | int shd_sync_invalidate_sample(struct shd_sync_sample *samp) 188 | { 189 | samp->nb_writes = -1; 190 | return 0; 191 | } 192 | 193 | bool shd_sync_is_sample_valid(const struct shd_sync_sample *samp) 194 | { 195 | return samp->nb_writes != -1; 196 | } 197 | 198 | int shd_sync_invalidate_section(struct shd_sync_ctx *ctx, 199 | struct shd_sync_hdr *hdr, bool creation) 200 | { 201 | if (ctx == NULL || hdr == NULL) 202 | return -EINVAL; 203 | 204 | if (creation) 205 | hdr->revision.nb_creations = 1; 206 | else 207 | ctx->primitives.add_and_fetch(&hdr->revision.nb_creations, 1); 208 | return 0; 209 | } 210 | 211 | int shd_sync_update_global_revision_nb(struct shd_sync_ctx *ctx, 212 | struct shd_sync_hdr *hdr) 213 | { 214 | if (ctx == NULL || hdr == NULL) 215 | return -EINVAL; 216 | 217 | /* The revision number should be odd after a call to this function */ 218 | if (ctx->primitives.add_and_fetch(&hdr->revision.nb_creations, 1) % 2 219 | != 0) 220 | return -EFAULT; 221 | else 222 | return hdr->revision.nb_creations; 223 | } 224 | 225 | int shd_sync_update_local_revision_nb(struct shd_sync_ctx *ctx, 226 | struct shd_sync_hdr *hdr) 227 | { 228 | /* If the revision number is odd, the section is being updated */ 229 | if (hdr->revision.nb_creations % 2 == 1) 230 | return -EAGAIN; 231 | 232 | ctx->revision.nb_creations = hdr->revision.nb_creations; 233 | return ctx->revision.nb_creations; 234 | } 235 | 236 | int shd_sync_check_revision_nb(struct shd_revision *rev, 237 | struct shd_sync_hdr *hdr) 238 | { 239 | if (rev->nb_creations == hdr->revision.nb_creations) 240 | return 0; 241 | else 242 | return -ENODEV; 243 | } 244 | 245 | int shd_sync_get_local_write_index(const struct shd_sync_ctx *ctx) 246 | { 247 | if (ctx == NULL) 248 | return -1; 249 | 250 | return ctx->index; 251 | } 252 | 253 | int shd_sync_get_next_write_index(const struct shd_sync_hdr *hdr, 254 | const struct shd_data_section_desc *desc) 255 | { 256 | if (hdr == NULL) 257 | return -1; 258 | 259 | return index_next(hdr->write_index, desc->nb_samples); 260 | } 261 | 262 | int shd_sync_get_last_write_index(const struct shd_sync_hdr *hdr) 263 | { 264 | if (hdr == NULL) 265 | return -1; 266 | 267 | return hdr->write_index; 268 | } 269 | 270 | int shd_sync_primitives_set_builtin(struct shd_sync_primitives *primitives) 271 | { 272 | if (!primitives) 273 | return -EINVAL; 274 | 275 | primitives->add_and_fetch = builtin_add_and_fetch; 276 | 277 | return 0; 278 | } 279 | -------------------------------------------------------------------------------- /src/shd_sync.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_sync.h 27 | * 28 | * @brief shared memory synchronization data management 29 | * 30 | */ 31 | 32 | #ifndef _SHD_SYNC_H_ 33 | #define _SHD_SYNC_H_ 34 | 35 | #include 36 | #include 37 | 38 | struct shd_revision { 39 | /* 40 | * revision number of the memory section : an odd value indicates that 41 | * the section is being rewritten, an even value indicates twice the 42 | * number of times since the start of the system that the memory 43 | * section has been created 44 | * @todo update this value only if the metadata related to the memory 45 | * section has changed (so that a failure of a producer does not 46 | * necessarily make the consumers remap the section) 47 | */ 48 | int nb_creations; 49 | }; 50 | 51 | /* 52 | * @brief Header-level synchronization data 53 | */ 54 | struct shd_sync_hdr { 55 | /* revision of the memory section */ 56 | struct shd_revision revision; 57 | /* index of currently written buffer slot */ 58 | int write_index; 59 | /* Number of writes currently going on in the section : in nominal 60 | * function, it should always only be 0 or 1 */ 61 | int nb_ongoing_writes; 62 | }; 63 | 64 | /* 65 | * @brief Synchronization primitives required by the library 66 | */ 67 | struct shd_sync_primitives { 68 | int (*add_and_fetch) (int *ptr, int value); 69 | }; 70 | 71 | /* 72 | * @brief Context-level synchronization data 73 | */ 74 | struct shd_sync_ctx { 75 | /* revision of the memory section as seen by the context when 76 | * the section was open */ 77 | struct shd_revision revision; 78 | /* index of the reference buffer slot as last seen by the caller (-1 79 | * means there is no operation in progress) */ 80 | int index; 81 | /* index of the buffer slot that was last written (-1 if no write 82 | * operation has occurred yet) */ 83 | int prev_index; 84 | /* number of writes to the reference memory slot as last seen by the 85 | * caller */ 86 | int nb_writes; 87 | /* Primitives to use on the section */ 88 | struct shd_sync_primitives primitives; 89 | }; 90 | 91 | /* 92 | * @brief Sample-level synchronization data 93 | */ 94 | struct shd_sync_sample { 95 | /* number of writes to the memory slot currently in use for the 96 | * sample 97 | */ 98 | int nb_writes; 99 | }; 100 | 101 | #include "shd_data.h" 102 | 103 | struct shd_section_id; 104 | 105 | /* 106 | * @brief Init synchronization header 107 | * 108 | * @param[in,out] sync_hdr : pointer to the header to init 109 | * 110 | * @return : 0 in case of success, 111 | * -errno in case of error 112 | */ 113 | int shd_sync_hdr_init(struct shd_sync_hdr *sync_hdr); 114 | 115 | /* 116 | * @brief Allocate and create a new sync context 117 | * 118 | * @param[in] id : The id of the section 119 | * 120 | * @return : an allocated sync context, 121 | * NULL in case of error 122 | */ 123 | struct shd_sync_ctx *shd_sync_ctx_new(const struct shd_section_id *id); 124 | 125 | /* 126 | * @brief Destroy a sync context 127 | * 128 | * @param[in,out] ctx : sync context to destroy 129 | * 130 | * @return : an allocated sync context, 131 | * NULL in case of error 132 | */ 133 | int shd_sync_ctx_destroy(struct shd_sync_ctx *ctx); 134 | 135 | /* 136 | * @brief Start writing session 137 | * 138 | * @param[in,out] ctx : current synchronization context 139 | * @param[in,out] hdr : pointer to the synchronization part of the section 140 | * header 141 | * 142 | * @return : 0 in case of success, 143 | * -EALREADY if an operation from the same context is already in 144 | * progress (most likely meaning that an API function was called 145 | * more than once) 146 | * -EPERM if another thread is currently writing on this memory 147 | * section (which indicates two producers are trying to write in the 148 | * same section) 149 | */ 150 | 151 | int shd_sync_start_write_session(struct shd_sync_ctx *ctx, 152 | struct shd_sync_hdr *hdr); 153 | 154 | /* 155 | * @brief Start write session on a new sample 156 | * 157 | * @param[in,out] ctx : current synchronization context 158 | * @param[in,out] hdr : pointer to the synchronization part of the section 159 | * header 160 | * @param[in,out] samp : pointer to the synchronization part of the sample 161 | * @param[in] desc : description of the data section 162 | * 163 | * @return : 0 in case of success, 164 | * -EINVAL if arguments are invalid, 165 | * -EALREADY if an operation is already in progress, 166 | * -EFAULT if at least one write occurred outside of the current 167 | * context, indicating a severe fault 168 | */ 169 | int shd_sync_start_sample_write(struct shd_sync_ctx *ctx, 170 | struct shd_sync_hdr *hdr, 171 | struct shd_sync_sample *samp, 172 | const struct shd_data_section_desc *desc); 173 | 174 | /* 175 | * @brief End write session on a sample 176 | * 177 | * @param[in,out] ctx : current synchronization context 178 | * @param[in,out] hdr : pointer to the synchronization part of the section 179 | * header 180 | * 181 | * @return : 0 in case of success, 182 | * -EINVAL if arguments are invalid, 183 | * -EALREADY if an operation is already in progress 184 | */ 185 | int shd_sync_end_write_session(struct shd_sync_ctx *ctx, 186 | struct shd_sync_hdr *hdr); 187 | 188 | /* 189 | * @brief Start read session on a sample (most likely the sample at the start 190 | * of a reading window) 191 | * 192 | * @param[in,out] ctx : current synchronization context 193 | * @param[in,out] samp : pointer to the synchronization part of the sample 194 | * 195 | * @return : 0 in case of success, 196 | * -EINVAL if arguments are invalid, 197 | * -EALREADY if an operation is already in progress 198 | */ 199 | int shd_sync_start_read_session(struct shd_sync_ctx *ctx, 200 | struct shd_sync_sample *samp); 201 | /* 202 | * @brief End read session on a sample 203 | * 204 | * @param[in,out] ctx : current synchronization context 205 | * @param[in,out] samp : pointer to the synchronization part of the sample 206 | * 207 | * @return : 0 in case of success, 208 | * -EINVAL if arguments are invalid, 209 | * -EFAULT if read sample(s) was/were overwritten during last reading 210 | * sequence 211 | */ 212 | int shd_sync_end_read_session(struct shd_sync_ctx *ctx, 213 | struct shd_sync_sample *samp); 214 | 215 | /* 216 | * @brief Get number of writes on a given sample 217 | * 218 | * @param[in] samp : Pointer to the sample 219 | * 220 | * @return : number of writes on the sample 221 | */ 222 | int shd_sync_get_nb_writes(const struct shd_sync_sample *samp); 223 | 224 | /* 225 | * @brief Invalidate given sample 226 | * 227 | * @param[in] samp : pointer to the sample 228 | * 229 | * @return : 0 in all cases 230 | */ 231 | int shd_sync_invalidate_sample(struct shd_sync_sample *samp); 232 | 233 | /* 234 | * @brief Indicates validity of a sample 235 | * 236 | * @param[in] samp : pointer to the sample 237 | * 238 | * @return : true if the sample is valid, 239 | * false otherwise 240 | */ 241 | bool shd_sync_is_sample_valid(const struct shd_sync_sample *samp); 242 | 243 | /* 244 | * @brief Invalidate a data section 245 | * 246 | * @param[in,out] ctx : current synchronization context 247 | * @param[in] hdr : synchronization header for that section 248 | * @param[in] first_creation : boolean indicating whether the section has just 249 | * been created 250 | * 251 | * @return : 0 in case of success 252 | */ 253 | int shd_sync_invalidate_section(struct shd_sync_ctx *ctx, 254 | struct shd_sync_hdr *hdr, 255 | bool creation); 256 | 257 | /* 258 | * @brief Update global data section revision number 259 | * 260 | * @todo update revision number only if the section or data format has changed 261 | * 262 | * @param[in,out] ctx : current synchronization context 263 | * @param[in] hdr : synchronization header for that section 264 | * 265 | * @return : new revision number in case of success, 266 | * -EFAULT if the revision number is incoherent 267 | */ 268 | int shd_sync_update_global_revision_nb(struct shd_sync_ctx *ctx, 269 | struct shd_sync_hdr *hdr); 270 | 271 | /* 272 | * @brief Update local revision number in the current context 273 | * 274 | * @param[in] ctx : current synchronization context 275 | * @param[in] hdr : synchronization header for that section 276 | * 277 | * @return : current revision number in case of success, 278 | * -EAGAIN if the section is being updated by a producer 279 | */ 280 | int shd_sync_update_local_revision_nb(struct shd_sync_ctx *ctx, 281 | struct shd_sync_hdr *hdr); 282 | 283 | /* 284 | * @brief Check whether context and global data section revision number match 285 | * 286 | * @param[in] rev : pointer to the revision structure that was output when 287 | * section was open 288 | * @param[in] hdr : synchronization header for that section 289 | * 290 | * @return : 0 in case of success, 291 | * -ENODEV if the section revision number has changed 292 | */ 293 | int shd_sync_check_revision_nb(struct shd_revision *rev, 294 | struct shd_sync_hdr *hdr); 295 | 296 | /* 297 | * @brief get write index as seen by current context 298 | * 299 | * @param[in] ctx : current synchronization context 300 | * 301 | * @return : write index in case of success, 302 | * -1 if index or arguments are invalid 303 | */ 304 | int shd_sync_get_local_write_index(const struct shd_sync_ctx *ctx); 305 | 306 | /* 307 | * @brief get next write index 308 | * 309 | * @param[in] hdr : pointer to the header of the memory section 310 | * @param[in] desc : description of the data section 311 | * 312 | * @return :next write index in case of success, 313 | * -1 if index or arguments are invalid 314 | */ 315 | int shd_sync_get_next_write_index(const struct shd_sync_hdr *hdr, 316 | const struct shd_data_section_desc *desc); 317 | 318 | /* 319 | * @brief get last write index 320 | * 321 | * @param[in] hdr : pointer to the header of the memory section 322 | * 323 | * @return : write index in case of success, 324 | * -1 if index or arguments are invalid 325 | */ 326 | int shd_sync_get_last_write_index(const struct shd_sync_hdr *hdr); 327 | 328 | /** 329 | * @brief init a shd_sync_primitves to gcc builtin primitives 330 | * 331 | * @param[in] primitives : the primitives to init 332 | * 333 | * @return : 0 if no error 334 | * -EINVAL if primitives is NULL 335 | */ 336 | int shd_sync_primitives_set_builtin(struct shd_sync_primitives *primitives); 337 | 338 | #endif /* _SHD_SYNC_H_ */ 339 | -------------------------------------------------------------------------------- /src/shd_utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_utils.h 27 | * 28 | * @brief shared memory useful macros 29 | * 30 | */ 31 | 32 | #ifndef SHD_UTILS_H_ 33 | #define SHD_UTILS_H_ 34 | 35 | #include 36 | 37 | #define ALIGN_UP(x) ALIGN(x, 4) 38 | #define ALIGN(x, a) __ALIGN_MASK(x, (__typeof__(x))(a)-1) 39 | #define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) 40 | 41 | 42 | static inline int max(int a, int b) 43 | { 44 | return a > b ? a : b; 45 | } 46 | 47 | static inline int min(int a, int b) 48 | { 49 | return a < b ? a : b; 50 | } 51 | 52 | 53 | /* 54 | * idx2 is known to have happened AFTER idx1 55 | */ 56 | static inline uint32_t interval_between(int idx1, int idx2, uint32_t size) 57 | { 58 | if (idx1 <= idx2) 59 | return idx2 - idx1; 60 | else 61 | return idx2 + size - idx1; 62 | } 63 | 64 | static inline int index_n_after(int idx, int n, uint32_t size) 65 | { 66 | return (idx+n)%size; 67 | } 68 | 69 | static inline int index_n_before(int idx, int n, uint32_t size) 70 | { 71 | return (idx+size-n)%size; 72 | } 73 | 74 | static inline int index_next(int idx, uint32_t size) 75 | { 76 | return index_n_after(idx, 1, size); 77 | } 78 | 79 | static inline int index_previous(int idx, uint32_t size) 80 | { 81 | return index_n_before(idx, 1, size); 82 | } 83 | 84 | static inline void index_increment(int *idx, uint32_t size) 85 | { 86 | int new_idx = index_next(*idx, size); 87 | *idx = new_idx; 88 | } 89 | 90 | static inline void index_increment_from(int *idx_dest, 91 | int *idx_src, 92 | uint32_t size) 93 | { 94 | int new_idx = index_next(*idx_src, size); 95 | *idx_dest = new_idx; 96 | } 97 | 98 | static inline void index_decrement(int *idx, uint32_t size) 99 | { 100 | int new_idx = index_previous(*idx, size); 101 | *idx = new_idx; 102 | } 103 | 104 | #endif /* SHD_UTILS_H_ */ 105 | -------------------------------------------------------------------------------- /src/shd_window.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_window.c 27 | * 28 | * @brief shared memory section window management. 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include /* For memory allocation functions */ 35 | #include 36 | #include 37 | 38 | #include "shd_data.h" 39 | #include "shd_utils.h" 40 | #include "shd_private.h" 41 | #include "shd_sample.h" 42 | #include "libshdata.h" 43 | #include "shd_window.h" 44 | 45 | #include "shd_search.h" 46 | 47 | int shd_window_set(struct shd_window *window, 48 | const struct shd_sync_hdr *hdr, 49 | const struct shd_sample_search *search, 50 | const struct shd_data_section_desc *desc, 51 | enum shd_ref_sample_search_hint hint) 52 | { 53 | int ref_idx = -1; 54 | int ret = -1; 55 | struct search_ctx ctx = shd_search_start(hdr, desc); 56 | 57 | SHD_HOOK(HOOK_WINDOW_SEARCH_START); 58 | 59 | ULOGD("Setting reading window using method %s for date %ld_%ld", 60 | shd_search_method_to_str(search->method), 61 | search->date.tv_sec, 62 | search->date.tv_nsec); 63 | 64 | shd_window_reset(window); 65 | 66 | switch (search->method) { 67 | case SHD_LATEST: 68 | ref_idx = ctx.t_index; 69 | break; 70 | case SHD_OLDEST: 71 | ref_idx = shd_search_oldest(desc, &ctx); 72 | break; 73 | case SHD_CLOSEST: 74 | ref_idx = shd_search_closest_match(desc, &search->date, 75 | &ctx, hint); 76 | break; 77 | case SHD_FIRST_AFTER: 78 | ref_idx = shd_search_first_match_after(desc, &search->date, 79 | &ctx, hint); 80 | break; 81 | case SHD_FIRST_BEFORE: 82 | ref_idx = shd_search_first_match_before(desc, &search->date, 83 | &ctx, hint); 84 | break; 85 | default: 86 | ULOGW("Invalid sample search method"); 87 | ret = -EINVAL; 88 | goto exit; 89 | break; 90 | } 91 | 92 | SHD_HOOK(HOOK_WINDOW_SEARCH_OVER); 93 | 94 | if (ref_idx < 0) { 95 | ret = -ENOENT; 96 | goto exit; 97 | } else { 98 | /* Number of samples which have been produced after wr_index */ 99 | int nb_more_recent_samples = interval_between(ref_idx, 100 | ctx.t_index, 101 | desc->nb_samples); 102 | 103 | /* Number of samples which have been produced between t_index+1 104 | * and wr_index. t_index is the most recent sample. t_index+1 105 | * is the oldest. */ 106 | int nb_older_samples = interval_between( 107 | index_next(ctx.t_index, desc->nb_samples), 108 | ref_idx, 109 | desc->nb_samples); 110 | 111 | int w_start_idx = index_n_before(ref_idx, 112 | min(nb_older_samples, 113 | search->nb_values_before_date), 114 | desc->nb_samples); 115 | 116 | if (shd_search_end(hdr, &ctx, w_start_idx, desc)) { 117 | ULOGW("Samples window set during search has been " 118 | "overwritten"); 119 | ret = -EFAULT; 120 | goto exit; 121 | } else { 122 | window->ref_idx = ref_idx; 123 | window->end_idx = index_n_after( 124 | ref_idx, 125 | min(nb_more_recent_samples, 126 | search->nb_values_after_date), 127 | desc->nb_samples); 128 | window->start_idx = index_n_before( 129 | ref_idx, 130 | min(nb_older_samples, 131 | search->nb_values_before_date), 132 | desc->nb_samples); 133 | window->nb_matches = 1 + interval_between( 134 | window->start_idx, 135 | window->end_idx, 136 | desc->nb_samples); 137 | } 138 | } 139 | 140 | ULOGD("Search ended with : nb_matches = %d, w_start = %d, " 141 | "w_ref = %d, w_end = %d", 142 | window->nb_matches, 143 | window->start_idx, 144 | window->ref_idx, 145 | window->end_idx); 146 | if (window->ref_idx >= 0) { 147 | struct shd_sample *r_samp = shd_data_get_sample_ptr(desc, 148 | window->ref_idx); 149 | ULOGD("Reference sample has timestamp : %ld_%ld", 150 | r_samp->metadata.ts.tv_sec, 151 | r_samp->metadata.ts.tv_nsec); 152 | } 153 | 154 | ret = window->nb_matches; 155 | exit: 156 | return ret; 157 | } 158 | 159 | int shd_window_read(struct shd_window *window, 160 | struct shd_data_section_desc *desc, 161 | void *dst, 162 | size_t data_size, 163 | ptrdiff_t s_offset) 164 | { 165 | int s_index; /* index in data section */ 166 | int d_index; /* index in destination buffer*/ 167 | struct shd_sample *curr = NULL; 168 | 169 | /* 170 | * Iterate over the whole window of matching samples 171 | * Due to the fact that we use a circular buffer, the source index 172 | * cannot just be simply incremented but needs to be computed using a 173 | * function that computes a modular addition. 174 | */ 175 | for (s_index = window->start_idx, d_index = 0; 176 | d_index < window->nb_matches; 177 | s_index = index_next(s_index, desc->nb_samples), 178 | d_index++) { 179 | char *curr_dst; 180 | curr = shd_data_get_sample_ptr(desc, s_index); 181 | curr_dst = (char *) dst + data_size * d_index; 182 | shd_sample_read(curr, s_offset, curr_dst, data_size); 183 | } 184 | 185 | return d_index; 186 | } 187 | 188 | struct shd_window *shd_window_new(void) 189 | { 190 | struct shd_window *window; 191 | 192 | window = calloc(1, sizeof(*window)); 193 | if (window == NULL) 194 | return NULL; 195 | 196 | shd_window_reset(window); 197 | 198 | return window; 199 | } 200 | 201 | int shd_window_reset(struct shd_window *window) 202 | { 203 | if (window == NULL) 204 | return -EINVAL; 205 | if (window->nb_matches < 0) 206 | return -EPERM; 207 | 208 | window->start_idx = -1; 209 | window->ref_idx = -1; 210 | window->end_idx = -1; 211 | window->nb_matches = -1; 212 | 213 | return 0; 214 | } 215 | 216 | int shd_window_destroy(struct shd_window *window) 217 | { 218 | free(window); 219 | return 0; 220 | } 221 | -------------------------------------------------------------------------------- /src/shd_window.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_window.h 27 | * 28 | * @brief shared memory section window management. A window is a set of 29 | * consecutive samples that match a given search. 30 | * 31 | */ 32 | 33 | #ifndef SHD_WINDOW_H_ 34 | #define SHD_WINDOW_H_ 35 | 36 | /* 37 | * Structure describing a sample window 38 | */ 39 | struct shd_window { 40 | /* Index of window's start sample */ 41 | int start_idx; 42 | /* Index of window's reference sample */ 43 | int ref_idx; 44 | /* Index of window's end sample */ 45 | int end_idx; 46 | /* Total number of samples in the window */ 47 | int nb_matches; 48 | }; 49 | 50 | #include "libshdata.h" 51 | #include "shd_sync.h" 52 | 53 | /* 54 | * @brief Copy some data from a window of samples 55 | * 56 | * @param[in] window : pointer to a structure describing the window of samples 57 | * to read 58 | * @param[in] desc : pointer to a structure describing the data section 59 | * @param[out] dst : pointer to destination buffer 60 | * @param[in] data_size : size of the data to copy 61 | * @param[in] s_offset : offset of the data to copy, from the start of the 62 | * sample 63 | * 64 | * @return : number of samples that were read 65 | */ 66 | int shd_window_read(struct shd_window *window, 67 | struct shd_data_section_desc *desc, 68 | void *dst, 69 | size_t data_size, 70 | ptrdiff_t s_offset); 71 | 72 | /* 73 | * @brief Define the current window 74 | * 75 | * @param[out] window : updated window of matching samples 76 | * @param[in] hdr : pointer to section synchronization header 77 | * @param[in] search : pointer to a structure describing the search that the 78 | * window should match 79 | * @param[in] desc : pointer to a structure describing the data section 80 | * @param[in] hint : hint for sample search method to use 81 | * 82 | * @return number of matching samples in case of success, 83 | * -EINVAL in case of invalid parameter 84 | * -EFAULT if result window was overwritten during search, 85 | * -ENOENT if no result was found 86 | */ 87 | int shd_window_set(struct shd_window *window, 88 | const struct shd_sync_hdr *hdr, 89 | const struct shd_sample_search *search, 90 | const struct shd_data_section_desc *desc, 91 | enum shd_ref_sample_search_hint hint); 92 | 93 | /* 94 | * @brief Allocate and create a new window structure 95 | * 96 | * @return : an allocated window in case of success, 97 | * NULL in case of error 98 | */ 99 | struct shd_window *shd_window_new(void); 100 | 101 | /* 102 | * @brief Reset a given window 103 | * 104 | * @param[in] window : pointer to the window to reset 105 | * 106 | * @return : 0 in case of success, 107 | * -EINVAL if argument is NULL 108 | * -EPERM if window is already empty (most likely due to an 109 | * out-of-sequence call) 110 | */ 111 | int shd_window_reset(struct shd_window *window); 112 | 113 | /* 114 | * @brief Destroy a window structure 115 | * 116 | * @param[in] window : pointer to the window to destroy 117 | * 118 | * @return : 0 in case of success 119 | */ 120 | int shd_window_destroy(struct shd_window *window); 121 | 122 | #endif /* SHD_WINDOW_H_ */ 123 | -------------------------------------------------------------------------------- /tests/concurrency/hooks_implem.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file hooks_implem.c 27 | * 28 | * @brief Implem file for libshdata concurrency hook points 29 | */ 30 | 31 | #include "hooks_implem.h" 32 | #include 33 | #include 34 | 35 | #define WAIT_ON_CONDITION(cond) \ 36 | do { \ 37 | while(cond) { \ 38 | usleep(10000); \ 39 | } \ 40 | } while(0) 41 | 42 | /* Global structure used to share information between libshdata inner code and 43 | * test code */ 44 | struct { 45 | useconds_t applicable_delay; 46 | enum concurrency_strategy stategy[HOOK_TOTAL]; 47 | int counter; 48 | uint32_t flags[2][2]; 49 | uint32_t parallel_counter; 50 | } concurrency_env; 51 | 52 | void shd_concurrency_clean_hooks(void) 53 | { 54 | int i, j; 55 | concurrency_env.counter = 0; 56 | concurrency_env.applicable_delay = 10000; 57 | for (i = 0; i < HOOK_TOTAL; i++) 58 | concurrency_env.stategy[i] = DO_NOTHING; 59 | for (i = 0; i < 2; i++) 60 | for (j = 0; j < 2; j++) 61 | concurrency_env.flags[i][j] = 0; 62 | concurrency_env.parallel_counter = 0; 63 | } 64 | 65 | void shd_concurrency_set_hook_strategy(enum shd_concurrency_hook hook, 66 | enum concurrency_strategy strat) 67 | { 68 | concurrency_env.stategy[hook] = strat; 69 | } 70 | 71 | void shd_concurrency_set_applicable_delay(useconds_t delay) 72 | { 73 | concurrency_env.applicable_delay = delay; 74 | } 75 | 76 | void shd_concurrency_emulate_thread_completion(int thread_id) 77 | { 78 | int i; 79 | for (i = 0; i < 2; i++) 80 | concurrency_env.flags[thread_id][i] = 1; 81 | } 82 | 83 | int shd_concurrency_has_thread_completed(int thread_id) 84 | { 85 | return concurrency_env.flags[thread_id][1] == 1; 86 | } 87 | 88 | void shd_concurrency_emulate_action_complete() 89 | { 90 | __sync_fetch_and_add(&concurrency_env.parallel_counter, 1); 91 | } 92 | 93 | void shd_concurrency_hook(enum shd_concurrency_hook hook) 94 | { 95 | switch(concurrency_env.stategy[hook]) 96 | { 97 | case DO_NOTHING: 98 | return; 99 | case DELAY_FOR_ALL_THREADS: 100 | usleep(concurrency_env.applicable_delay); 101 | break; 102 | case DELAY_FOR_FIRST_THREAD: 103 | if (__sync_fetch_and_add(&concurrency_env.counter, 1) == 0) 104 | usleep(concurrency_env.applicable_delay); 105 | break; 106 | 107 | case FIRST_THREAD_SIGNALS_FIRST_ACTION: 108 | __sync_fetch_and_add(&concurrency_env.flags[0][0], 1); 109 | break; 110 | 111 | case SECOND_THREAD_WAITS_FIRST_THREAD_FIRST_ACTION: 112 | WAIT_ON_CONDITION(concurrency_env.flags[0][0] == 0); 113 | concurrency_env.flags[1][0] = 1; 114 | break; 115 | 116 | case SECOND_THREAD_SIGNALS_SECOND_ACTION: 117 | if (concurrency_env.flags[1][0] == 1) 118 | __sync_fetch_and_add(&concurrency_env.flags[1][1], 1); 119 | break; 120 | 121 | case FIRST_THREAD_WAITS_SECOND_THREAD_SECOND_ACTION: 122 | WAIT_ON_CONDITION(concurrency_env.flags[1][1] == 0); 123 | concurrency_env.flags[0][1] = 1; 124 | break; 125 | 126 | case PARALLEL_BOTH_THREADS_SIGNAL_ACTION: 127 | __sync_fetch_and_add(&concurrency_env.parallel_counter, 1); 128 | break; 129 | 130 | case PARALLEL_BOTH_THREADS_WAIT_ALL_ACTIONS_COMPLETE: 131 | WAIT_ON_CONDITION(concurrency_env.parallel_counter < 2); 132 | break; 133 | 134 | default: 135 | break; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /tests/concurrency/hooks_implem.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file hooks_implem.h 27 | * 28 | * @brief Interface for implementation of the hooks added into libshdata's main 29 | * code that are used for concurrency tests 30 | * 31 | * @details 32 | * This module implements various strategy for concurrency tests. Delays are 33 | * rather easy to understand, but we also provide a way to define more 34 | * complex behaviors, such as two threads waiting for each other while they are 35 | * following the same execution path, or while they follow different execution 36 | * paths 37 | */ 38 | 39 | #ifndef HOOKS_IMPLEM_H_ 40 | #define HOOKS_IMPLEM_H_ 41 | 42 | #include 43 | #include 44 | #include "libshdata-concurrency-hooks.h" 45 | 46 | enum concurrency_strategy { 47 | DO_NOTHING, 48 | DELAY_FOR_ALL_THREADS, 49 | DELAY_FOR_FIRST_THREAD, 50 | 51 | /* Strategies to use when the two threads follow a different 52 | * execution path */ 53 | FIRST_THREAD_SIGNALS_FIRST_ACTION, 54 | SECOND_THREAD_WAITS_FIRST_THREAD_FIRST_ACTION, 55 | SECOND_THREAD_SIGNALS_SECOND_ACTION, 56 | FIRST_THREAD_WAITS_SECOND_THREAD_SECOND_ACTION, 57 | 58 | /* Strategies to use when the two threads follow the same execution 59 | * path */ 60 | PARALLEL_BOTH_THREADS_SIGNAL_ACTION, 61 | PARALLEL_BOTH_THREADS_WAIT_ALL_ACTIONS_COMPLETE 62 | }; 63 | 64 | /* 65 | * @brief Init all hooks to do nothing and reset internal state 66 | */ 67 | void shd_concurrency_clean_hooks(void); 68 | 69 | /* 70 | * @brief Set the strategy to follow for a given hook point 71 | */ 72 | void shd_concurrency_set_hook_strategy(enum shd_concurrency_hook hook, 73 | enum concurrency_strategy strat); 74 | 75 | /* 76 | * @brief Set the delay that should be applied when such a strategy is chosen 77 | */ 78 | void shd_concurrency_set_applicable_delay(useconds_t delay); 79 | 80 | /* 81 | * @brief Emulate thread completion 82 | * 83 | * @details Should be called when the execution path of a given thread is 84 | * expected to break from normal (e.g. earlier return from a function call due 85 | * to a correctly-detected error), potentially preventing it from hitting its 86 | * second hook point (and thus blocking the other thread) 87 | */ 88 | void shd_concurrency_emulate_thread_completion(int thread_id); 89 | 90 | /* 91 | * @brief Return whether thread has completed or not 92 | * 93 | * @details this function is useful if we need to complete an action in test 94 | * code that is supposed to occur only once a given thread as finished its 95 | * task 96 | */ 97 | int shd_concurrency_has_thread_completed(int thread_id); 98 | 99 | /* 100 | * @brief Emulate end of action 101 | * 102 | * @details Should be called when the execution path of a given thread is 103 | * expected to break from normal (e.g. earlier return from a function call due 104 | * to a correctly-detected error), potentially preventing it from completing 105 | * its expected action (and thus blocking the other thread) 106 | */ 107 | void shd_concurrency_emulate_action_complete(void); 108 | 109 | /* 110 | * @brief Entry point for libshdata's main code 111 | */ 112 | void shd_concurrency_hook(enum shd_concurrency_hook hook); 113 | 114 | #endif /* HOOKS_IMPLEM_H_ */ 115 | -------------------------------------------------------------------------------- /tests/lookup/section_lookup.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file section_lookup.c 27 | * 28 | * @brief Implem file for dev-mem lookup feature for unit-test mode 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "backend/shd_shm.h" 40 | #include "backend/shd_dev_mem.h" 41 | 42 | #define BLOB_NAME_MAX_SIZE 255 43 | 44 | /* This function to return the physical address from a virtual address is 45 | * shamelessly copied-pasted from here : http://stackoverflow.com/a/28987409 46 | * (Stack overflow topic "How to find the physical address of a variable from 47 | * user-space in Linux?") 48 | */ 49 | static uintptr_t vtop(uintptr_t vaddr) 50 | { 51 | FILE *pagemap; 52 | uintptr_t paddr = 0; 53 | int offset = (vaddr / sysconf(_SC_PAGESIZE)) * sizeof(uint64_t); 54 | uint64_t e; 55 | 56 | /* https://www.kernel.org/doc/Documentation/vm/pagemap.txt */ 57 | pagemap = fopen("/proc/self/pagemap", "r"); 58 | if (pagemap) { 59 | if (lseek(fileno(pagemap), offset, SEEK_SET) == offset) { 60 | if (fread(&e, sizeof(uint64_t), 1, pagemap)) { 61 | if (e & (1ULL << 63)) { 62 | paddr = e & ((1ULL << 54) - 1); 63 | paddr = paddr * sysconf(_SC_PAGESIZE); 64 | paddr = paddr | (vaddr & 65 | (sysconf(_SC_PAGESIZE) - 1)); 66 | } 67 | } 68 | } 69 | fclose(pagemap); 70 | } 71 | return paddr; 72 | } 73 | 74 | int shd_section_lookup(const char *blob_name, 75 | struct shd_section_properties *properties) 76 | { 77 | if (!strncmp(blob_name, "myBlob_open-close-dev-mem", 78 | BLOB_NAME_MAX_SIZE)) { 79 | /* Called from test_api_open_from_dev_mem() */ 80 | static bool first_call = true; 81 | static void *base_ptr = NULL; 82 | static struct shd_dev_mem_backend_param backend_param; 83 | 84 | if (first_call) { 85 | /* Allocate a given memory space of which we 86 | * will then return the physical address */ 87 | long int page_size = sysconf(_SC_PAGESIZE); 88 | int ret = posix_memalign((void **) &base_ptr, 89 | page_size, page_size * 4); 90 | if (ret) 91 | return -ENOMEM; 92 | first_call = false; 93 | } 94 | 95 | /* Access the allocated memory to force a page-fault to 96 | * ensure that the page is actually loaded in the TLB, 97 | * and the physical address is therefore accessible */ 98 | volatile int dummy = *(int *) base_ptr; 99 | dummy++; 100 | 101 | backend_param.offset = vtop((uintptr_t) base_ptr); 102 | 103 | properties->backend = &shd_dev_mem_backend; 104 | properties->backend_param = &backend_param; 105 | shd_sync_primitives_set_builtin(&properties->primitives); 106 | 107 | return 0; 108 | } else if (!strncmp(blob_name, "myBlob_override", BLOB_NAME_MAX_SIZE)) { 109 | /* Called from test_api_override_shm_dir() */ 110 | static const struct shd_shm_backend_param backend_param = { 111 | .root = "/tmp/" 112 | }; 113 | 114 | properties->backend = &shd_shm_backend; 115 | properties->backend_param = &backend_param; 116 | shd_sync_primitives_set_builtin(&properties->primitives); 117 | 118 | return 0; 119 | } else { 120 | properties->backend = &shd_shm_backend; 121 | properties->backend_param = NULL; 122 | shd_sync_primitives_set_builtin(&properties->primitives); 123 | 124 | return 0; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /tests/shd_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_test.c 27 | * 28 | * @brief shared memory test. 29 | * 30 | */ 31 | 32 | #include "libshdata.h" 33 | #include "shd_test.h" 34 | #include "stdlib.h" 35 | 36 | extern CU_TestInfo s_api_tests[]; 37 | extern CU_TestInfo s_api_adv_tests[]; 38 | extern CU_TestInfo s_func_basic_write_tests[]; 39 | extern CU_TestInfo s_func_adv_read_tests[]; 40 | extern CU_TestInfo s_func_basic_read_tests[]; 41 | extern CU_TestInfo s_func_read_hdr_tests[]; 42 | extern CU_TestInfo s_func_adv_write_tests[]; 43 | extern CU_TestInfo s_error_tests[]; 44 | extern CU_TestInfo s_concurrency_tests[]; 45 | 46 | static int use_binary_search(void) 47 | { 48 | return setenv("LIBSHDATA_CONFIG_INTERNAL_SEARCH_METHOD", "BINARY", 1); 49 | } 50 | 51 | static int reset_search_method(void) 52 | { 53 | return unsetenv("LIBSHDATA_CONFIG_INTERNAL_SEARCH_METHOD"); 54 | } 55 | 56 | static CU_SuiteInfo s_suites[] = { 57 | {(char *)"API", NULL, NULL, s_api_tests}, 58 | {(char *)"Advanced API", NULL, NULL, s_api_adv_tests}, 59 | {(char *)"functional write with basic API", 60 | NULL, NULL, s_func_basic_write_tests}, 61 | {(char *)"functional read with basic API (basic search)", 62 | NULL, NULL, s_func_basic_read_tests}, 63 | {(char *)"functional read with basic API (binary search)", 64 | use_binary_search, reset_search_method, s_func_basic_read_tests}, 65 | {(char *)"functional read with advanced API (basic search)", 66 | NULL, NULL, s_func_adv_read_tests}, 67 | {(char *)"functional read with advanced API (binary search)", 68 | use_binary_search, reset_search_method, s_func_adv_read_tests}, 69 | {(char *)"functional header read functions", 70 | NULL, NULL, s_func_read_hdr_tests}, 71 | {(char *)"functional write with advanced API", 72 | NULL, NULL, s_func_adv_write_tests}, 73 | {(char *)"error cases", NULL, NULL, s_error_tests}, 74 | {(char *)"concurrency tests", NULL, NULL, s_concurrency_tests}, 75 | CU_SUITE_INFO_NULL, 76 | }; 77 | 78 | int main(void) 79 | { 80 | CU_initialize_registry(); 81 | CU_register_suites(s_suites); 82 | if (getenv("CUNIT_OUT_NAME") != NULL) 83 | CU_set_output_filename(getenv("CUNIT_OUT_NAME")); 84 | if (getenv("CUNIT_AUTOMATED") != NULL) { 85 | CU_automated_run_tests(); 86 | CU_list_tests_to_file(); 87 | } else { 88 | CU_basic_set_mode(CU_BRM_VERBOSE); 89 | CU_basic_run_tests(); 90 | } 91 | CU_cleanup_registry(); 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /tests/shd_test.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_test.h 27 | * 28 | * @brief shared memory private stuff. 29 | * 30 | */ 31 | 32 | #ifndef _SHD_TEST_H_ 33 | #define _SHD_TEST_H_ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include /* For NAME_MAX macro */ 40 | #include /* For memory allocation functions */ 41 | #include 42 | #include 43 | #include 44 | 45 | #include "libshdata.h" 46 | #include 47 | #include 48 | #include 49 | 50 | 51 | /** Generic log */ 52 | #define ULOG(_fmt, ...) fprintf(stderr, _fmt "\n", ##__VA_ARGS__) 53 | /** Log as debug */ 54 | #define ULOGD(_fmt, ...) ULOG("[D]" _fmt, ##__VA_ARGS__) 55 | /** Log as info */ 56 | #define ULOGI(_fmt, ...) ULOG("[I]" _fmt, ##__VA_ARGS__) 57 | /** Log as warning */ 58 | #define ULOGW(_fmt, ...) ULOG("[W]" _fmt, ##__VA_ARGS__) 59 | /** Log as error */ 60 | #define ULOGE(_fmt, ...) ULOG("[E]" _fmt, ##__VA_ARGS__) 61 | 62 | 63 | 64 | #endif /* _SHD_TEST_H_ */ 65 | -------------------------------------------------------------------------------- /tests/shd_test_error.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_test_error.c 27 | * 28 | * @brief 29 | * 30 | */ 31 | 32 | #include "shd_test.h" 33 | #include "shd_test_helper.h" 34 | 35 | static void test_error_overwrite_during_read(void) 36 | { 37 | struct shd_ctx *ctx_prod, *ctx_cons; 38 | int ret, index; 39 | struct shd_sample_metadata sample_meta = METADATA_INIT; 40 | /* The search is setup to lookup for the maximum possible number of 41 | * samples */ 42 | struct shd_sample_search search = { 43 | .nb_values_after_date = 0, 44 | .nb_values_before_date = 0, 45 | .method = SHD_LATEST 46 | }; 47 | struct shd_revision *rev; 48 | struct prod_blob read_blob; 49 | struct shd_quantity_sample blob_samp[1] = { 50 | { .ptr = &read_blob, .size = sizeof(read_blob) } 51 | }; 52 | 53 | /* Create a producer and a consumer context to play with */ 54 | ctx_prod = shd_create(BLOB_NAME("overwrite-during-read"), NULL, 55 | &s_hdr_info, 56 | &s_metadata_hdr); 57 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_prod); 58 | ctx_cons = shd_open(BLOB_NAME("overwrite-during-read"), NULL, &rev); 59 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_cons); 60 | 61 | /* Produce at least one sample */ 62 | ret = shd_write_new_blob(ctx_prod, 63 | &s_blob, 64 | sizeof(s_blob), 65 | &sample_meta); 66 | CU_ASSERT_EQUAL_FATAL(ret, 0); 67 | 68 | /* Try to read the whole blob in a valid way */ 69 | ret = shd_read_from_sample(ctx_cons, 0, &search, NULL, 70 | blob_samp); 71 | CU_ASSERT_TRUE_FATAL(ret > 0); 72 | 73 | /* Now that the latest the sample has been selected for read, write 74 | * just enough new samples to overwrite the slot which was being read 75 | */ 76 | ret = 0; 77 | for (index = 0; index < NUMBER_OF_SAMPLES + 1; index++) { 78 | if (time_step(&sample_meta.ts) < 0) 79 | CU_FAIL_FATAL("Could not get time"); 80 | ret += shd_write_new_blob(ctx_prod, 81 | &s_blob, 82 | sizeof(s_blob), 83 | &sample_meta); 84 | } 85 | CU_ASSERT_EQUAL_FATAL(ret, 0); 86 | 87 | /* Declare end of read */ 88 | ret = shd_end_read(ctx_cons, rev); 89 | CU_ASSERT_EQUAL(ret, -EFAULT); 90 | 91 | /* Close should unfold normally */ 92 | ret = shd_close(ctx_cons, rev); 93 | CU_ASSERT_EQUAL(ret, 0); 94 | ret = shd_close(ctx_prod, NULL); 95 | CU_ASSERT_EQUAL(ret, 0); 96 | } 97 | 98 | static void test_error_read_with_no_produced_sample(void) 99 | { 100 | struct shd_ctx *ctx_prod, *ctx_cons; 101 | int ret; 102 | struct prod_blob read_blob; 103 | struct shd_sample_metadata sample_meta = METADATA_INIT; 104 | struct shd_sample_search search = { 105 | .nb_values_after_date = 0, 106 | .nb_values_before_date = 0, 107 | .method = SHD_LATEST 108 | }; 109 | struct shd_revision *rev; 110 | struct shd_quantity_sample blob_samp[1] = { 111 | { .ptr = &read_blob, .size = sizeof(read_blob) } 112 | }; 113 | 114 | /* Create a producer and a consumer context to play with */ 115 | ctx_prod = shd_create(BLOB_NAME("error-read-with-no-prod-sample"), 116 | NULL, 117 | &s_hdr_info, 118 | &s_metadata_hdr); 119 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_prod); 120 | ctx_cons = shd_open(BLOB_NAME("error-read-with-no-prod-sample"), 121 | NULL, 122 | &rev); 123 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_cons); 124 | 125 | if (time_step(&sample_meta.ts) < 0) 126 | CU_FAIL_FATAL("Could not get time"); 127 | if (time_step(&search.date) < 0) 128 | CU_FAIL_FATAL("Could not get time"); 129 | 130 | /* Try to read the whole blob */ 131 | ret = shd_read_from_sample(ctx_cons, 0, &search, NULL, 132 | blob_samp); 133 | CU_ASSERT_EQUAL(ret, -EAGAIN); 134 | 135 | ret = shd_end_read(ctx_cons, rev); 136 | CU_ASSERT_EQUAL(ret, -EPERM); 137 | 138 | /* Close should unfold normally */ 139 | ret = shd_close(ctx_prod, NULL); 140 | CU_ASSERT_EQUAL(ret, 0); 141 | ret = shd_close(ctx_cons, rev); 142 | CU_ASSERT_EQUAL(ret, 0); 143 | } 144 | 145 | 146 | static void test_error_read_data_undersized_buffer(void) 147 | { 148 | struct shd_ctx *ctx_prod, *ctx_cons; 149 | int ret; 150 | struct prod_blob read_blob; 151 | struct shd_sample_metadata sample_meta = METADATA_INIT; 152 | struct shd_sample_search search = { 153 | .nb_values_after_date = 0, 154 | .nb_values_before_date = 0, 155 | .method = SHD_LATEST 156 | }; 157 | struct shd_revision *rev; 158 | struct shd_quantity_sample blob_samp[1] = { 159 | { .ptr = &read_blob, .size = sizeof(read_blob) - 1 } 160 | }; 161 | struct shd_quantity_sample q_samp[2] = { 162 | { .ptr = &read_blob.i1, .size = sizeof(read_blob.i1) - 1 }, 163 | QTY_SAMPLE_FIELD(read_blob, c1) 164 | }; 165 | const struct shd_quantity quantity[2] = { 166 | QUANTITY_FIELD(prod_blob, s_blob, i1), 167 | QUANTITY_FIELD(prod_blob, s_blob, c1) 168 | }; 169 | 170 | if (time_step(&sample_meta.ts) < 0) 171 | CU_FAIL_FATAL("Could not get time"); 172 | if (time_step(&search.date) < 0) 173 | CU_FAIL_FATAL("Could not get time"); 174 | 175 | /* Create a producer and a consumer context to play with */ 176 | ctx_prod = shd_create(BLOB_NAME("error-read-undersized-buffer"), 177 | NULL, 178 | &s_hdr_info, 179 | &s_metadata_hdr); 180 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_prod); 181 | ctx_cons = shd_open(BLOB_NAME("error-read-undersized-buffer"), 182 | NULL, 183 | &rev); 184 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_cons); 185 | 186 | /* Produce at least one sample in the shared memory section */ 187 | ret = shd_write_new_blob(ctx_prod, 188 | &s_blob, 189 | sizeof(s_blob), 190 | &sample_meta); 191 | CU_ASSERT_EQUAL_FATAL(ret, 0); 192 | 193 | /* Try to read the whole blob ; this should fail since the destination 194 | * buffer is too small */ 195 | ret = shd_read_from_sample(ctx_cons, 0, &search, NULL, 196 | blob_samp); 197 | CU_ASSERT_EQUAL(ret, 0); 198 | 199 | /* Try to read 2 quantities ; one buffer is under-sized, so only one 200 | * should be read */ 201 | ret = shd_read_from_sample(ctx_cons, 2, &search, quantity, 202 | q_samp); 203 | CU_ASSERT_EQUAL(ret, 1); 204 | 205 | /* This call is valid */ 206 | ret = shd_end_read(ctx_cons, rev); 207 | CU_ASSERT_EQUAL(ret, 0); 208 | 209 | /* Close should unfold normally */ 210 | ret = shd_close(ctx_prod, NULL); 211 | CU_ASSERT_EQUAL(ret, 0); 212 | ret = shd_close(ctx_cons, rev); 213 | CU_ASSERT_EQUAL(ret, 0); 214 | } 215 | 216 | 217 | static void test_error_revision_nb(void) 218 | { 219 | struct shd_ctx *ctx_prod, *ctx_cons; 220 | int ret; 221 | struct prod_blob read_blob; 222 | struct shd_sample_metadata sample_meta = METADATA_INIT; 223 | struct shd_sample_search search = { 224 | .nb_values_after_date = 0, 225 | .nb_values_before_date = 0, 226 | .method = SHD_LATEST 227 | }; 228 | struct shd_revision *rev; 229 | struct shd_quantity_sample blob_samp[1] = { 230 | { .ptr = &read_blob, .size = sizeof(read_blob) } 231 | }; 232 | 233 | /* Create a producer and a consumer context to play with */ 234 | ctx_prod = shd_create(BLOB_NAME("error-revision-nb"), NULL, 235 | &s_hdr_info, 236 | &s_metadata_hdr); 237 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_prod); 238 | ctx_cons = shd_open(BLOB_NAME("error-revision-nb"), NULL, &rev); 239 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_cons); 240 | 241 | /* The producer closes and re-opens its memory section, possibly 242 | * updating the blob format ; in the mean time the consumer keeps its 243 | * context as it was when the producer first opened the section */ 244 | ret = shd_close(ctx_prod, NULL); 245 | CU_ASSERT_EQUAL(ret, 0); 246 | ctx_prod = shd_create(BLOB_NAME("error-revision-nb"), NULL, 247 | &s_hdr_info, 248 | &s_metadata_hdr); 249 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_prod); 250 | 251 | if (time_step(&sample_meta.ts) < 0) 252 | CU_FAIL_FATAL("Could not get time"); 253 | if (time_step(&search.date) < 0) 254 | CU_FAIL_FATAL("Could not get time"); 255 | 256 | /* Produce at least one sample in the shared memory section */ 257 | ret = shd_write_new_blob(ctx_prod, 258 | &s_blob, 259 | sizeof(s_blob), 260 | &sample_meta); 261 | CU_ASSERT_EQUAL_FATAL(ret, 0); 262 | 263 | /* Try to read the whole blob ; this should work */ 264 | ret = shd_read_from_sample(ctx_cons, 0, &search, NULL, 265 | blob_samp); 266 | CU_ASSERT_TRUE(ret > 0); 267 | 268 | /* ... but this function call should signal that the revision number 269 | * has changed */ 270 | ret = shd_end_read(ctx_cons, rev); 271 | CU_ASSERT_EQUAL(ret, -ENODEV); 272 | 273 | /* The consumer then closes and reopen its context */ 274 | ret = shd_close(ctx_cons, rev); 275 | CU_ASSERT_EQUAL(ret, 0); 276 | ctx_cons = shd_open(BLOB_NAME("error-revision-nb"), NULL, &rev); 277 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_cons); 278 | 279 | /* And now everything should work properly */ 280 | ret = shd_read_from_sample(ctx_cons, 0, &search, NULL, 281 | blob_samp); 282 | CU_ASSERT_TRUE(ret > 0); 283 | CU_ASSERT_TRUE(time_is_equal(&blob_samp[0].meta.ts, 284 | &sample_meta.ts)); 285 | CU_ASSERT_TRUE(time_is_equal(&blob_samp[0].meta.exp, 286 | &sample_meta.exp)); 287 | ret = shd_end_read(ctx_cons, rev); 288 | CU_ASSERT_EQUAL(ret, 0); 289 | 290 | /* Close should unfold normally */ 291 | ret = shd_close(ctx_prod, NULL); 292 | CU_ASSERT_EQUAL(ret, 0); 293 | ret = shd_close(ctx_cons, rev); 294 | CU_ASSERT_EQUAL(ret, 0); 295 | } 296 | 297 | 298 | CU_TestInfo s_error_tests[] = { 299 | {(char *)"sample overwrite during read", 300 | &test_error_overwrite_during_read}, 301 | {(char *)"try to read when no sample has been produced yet", 302 | &test_error_read_with_no_produced_sample}, 303 | {(char *)"try to read data with under-sized buffers", 304 | &test_error_read_data_undersized_buffer}, 305 | {(char *)"try to read without updating revision number", 306 | &test_error_revision_nb}, 307 | CU_TEST_INFO_NULL, 308 | }; 309 | -------------------------------------------------------------------------------- /tests/shd_test_func_read_hdr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_test_func_read_hdr.c 27 | * 28 | * @brief 29 | * 30 | */ 31 | 32 | #include "shd_test.h" 33 | #include "shd_test_helper.h" 34 | 35 | static void test_func_read_hdr(void) 36 | { 37 | struct shd_ctx *ctx_prod, *ctx_cons; 38 | int ret; 39 | struct shd_revision *rev; 40 | struct shd_hdr_user_info usr_info; 41 | 42 | /* Create a producer and a consumer context to play with */ 43 | ctx_prod = shd_create(BLOB_NAME("func-read-hdr"), 44 | NULL, 45 | &s_hdr_info, 46 | &s_metadata_hdr); 47 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_prod); 48 | ctx_cons = shd_open(BLOB_NAME("func-read-hdr"), NULL, &rev); 49 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_cons); 50 | 51 | /* Read the section header and check that all the fields match exactly 52 | * to their original counterpart */ 53 | ret = shd_read_section_hdr(ctx_cons, &usr_info, rev); 54 | CU_ASSERT_EQUAL_FATAL(ret, 0); 55 | CU_ASSERT_EQUAL(usr_info.blob_metadata_hdr_size, 56 | s_hdr_info.blob_metadata_hdr_size); 57 | CU_ASSERT_EQUAL(usr_info.blob_size, 58 | s_hdr_info.blob_size); 59 | CU_ASSERT_EQUAL(usr_info.max_nb_samples, 60 | s_hdr_info.max_nb_samples); 61 | CU_ASSERT_EQUAL(usr_info.rate, 62 | s_hdr_info.rate); 63 | 64 | /* Close should unfold normally */ 65 | ret = shd_close(ctx_prod, NULL); 66 | CU_ASSERT_EQUAL(ret, 0); 67 | ret = shd_close(ctx_cons, rev); 68 | CU_ASSERT_EQUAL(ret, 0); 69 | } 70 | 71 | static void test_func_read_metadata_hdr(void) 72 | { 73 | struct shd_ctx *ctx_prod, *ctx_cons; 74 | int ret; 75 | struct shd_revision *rev; 76 | struct blob_metadata_hdr mdata_hdr; 77 | 78 | /* Create a producer and a consumer context to play with */ 79 | ctx_prod = shd_create(BLOB_NAME("func-read-metadata-hdr"), NULL, 80 | &s_hdr_info, 81 | &s_metadata_hdr); 82 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_prod); 83 | ctx_cons = shd_open(BLOB_NAME("func-read-metadata-hdr"), NULL, &rev); 84 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_cons); 85 | 86 | /* Read the section header and check that all the fields match exactly 87 | * to their original counterpart */ 88 | ret = shd_read_blob_metadata_hdr(ctx_cons, 89 | &mdata_hdr, 90 | sizeof(mdata_hdr), 91 | rev); 92 | CU_ASSERT_EQUAL_FATAL(ret, 0); 93 | CU_ASSERT_EQUAL(mdata_hdr.i1, TEST_VAL_MDATA_i1); 94 | CU_ASSERT_EQUAL(mdata_hdr.i2, TEST_VAL_MDATA_i2); 95 | CU_ASSERT_EQUAL(mdata_hdr.li1, TEST_VAL_MDATA_li1); 96 | CU_ASSERT_EQUAL(strncmp(mdata_hdr.c1, 97 | TEST_VAL_MDATA_c1, 98 | strlen(TEST_VAL_MDATA_c1)), 0); 99 | CU_ASSERT_EQUAL(strncmp(mdata_hdr.c2, 100 | TEST_VAL_MDATA_c2, 101 | strlen(TEST_VAL_MDATA_c2)), 0); 102 | 103 | /* Close should unfold normally */ 104 | ret = shd_close(ctx_prod, NULL); 105 | CU_ASSERT_EQUAL(ret, 0); 106 | ret = shd_close(ctx_cons, rev); 107 | CU_ASSERT_EQUAL(ret, 0); 108 | } 109 | 110 | CU_TestInfo s_func_read_hdr_tests[] = { 111 | {(char *)"Read section header", 112 | &test_func_read_hdr}, 113 | {(char *)"Read blob metadata header", 114 | &test_func_read_metadata_hdr}, 115 | CU_TEST_INFO_NULL, 116 | }; 117 | 118 | -------------------------------------------------------------------------------- /tests/shd_test_func_write_adv.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_test_func_write_2.c 27 | * 28 | * @brief 29 | * 30 | */ 31 | 32 | #define SHD_ADVANCED_READ_API 33 | #define SHD_ADVANCED_WRITE_API 34 | #include "shd_test.h" 35 | #include "shd_test_helper.h" 36 | 37 | static void test_func_adv_write_by_quantity(void) 38 | { 39 | 40 | struct shd_ctx *ctx_prod, *ctx_cons; 41 | int ret; 42 | struct shd_sample_metadata sample_meta = METADATA_INIT; 43 | struct shd_sample_search search = { 44 | .nb_values_after_date = 0, 45 | .nb_values_before_date = 0, 46 | .method = SHD_LATEST 47 | }; 48 | struct shd_sample_metadata *metadata = NULL; 49 | struct shd_search_result result; 50 | struct prod_blob read_blob; 51 | struct shd_revision *rev; 52 | 53 | /* Create a producer and a consumer context to play with */ 54 | ctx_prod = shd_create(BLOB_NAME("write-2-by-quantity"), NULL, 55 | &s_hdr_info, 56 | &s_metadata_hdr); 57 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_prod); 58 | ctx_cons = shd_open(BLOB_NAME("write-2-by-quantity"), NULL, &rev); 59 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx_cons); 60 | 61 | if (time_step(&sample_meta.ts) < 0) 62 | CU_FAIL_FATAL("Could not get time"); 63 | 64 | /* Declare production of a new sample */ 65 | ret = shd_new_sample(ctx_prod, &sample_meta); 66 | CU_ASSERT_EQUAL(ret, 0); 67 | 68 | /* Write the whole blob quantity by quantity, ensure that everything 69 | * goes right at each step */ 70 | ret = shd_write_quantity(ctx_prod, &q_s_blob_i1, 71 | QUANTITY_PTR(s_blob, i1)); 72 | CU_ASSERT_EQUAL(ret, 0); 73 | ret = shd_write_quantity(ctx_prod, &q_s_blob_c1, 74 | QUANTITY_PTR(s_blob, c1)); 75 | CU_ASSERT_EQUAL(ret, 0); 76 | ret = shd_write_quantity(ctx_prod, &q_s_blob_li1, 77 | QUANTITY_PTR(s_blob, li1)); 78 | CU_ASSERT_EQUAL(ret, 0); 79 | ret = shd_write_quantity(ctx_prod, &q_s_blob_ui1, 80 | QUANTITY_PTR(s_blob, ui1)); 81 | CU_ASSERT_EQUAL(ret, 0); 82 | ret = shd_write_quantity(ctx_prod, &q_s_blob_f1, 83 | QUANTITY_PTR(s_blob, f1)); 84 | CU_ASSERT_EQUAL(ret, 0); 85 | ret = shd_write_quantity(ctx_prod, &q_s_blob_acc, 86 | QUANTITY_PTR(s_blob, acc)); 87 | CU_ASSERT_EQUAL(ret, 0); 88 | ret = shd_write_quantity(ctx_prod, &q_s_blob_angles, 89 | QUANTITY_PTR(s_blob, angles)); 90 | CU_ASSERT_EQUAL(ret, 0); 91 | ret = shd_write_quantity(ctx_prod, &q_s_blob_state, 92 | QUANTITY_PTR(s_blob, state)); 93 | CU_ASSERT_EQUAL(ret, 0); 94 | 95 | /* Commit the new sample */ 96 | ret = shd_commit_sample(ctx_prod); 97 | CU_ASSERT_EQUAL(ret, 0); 98 | 99 | /* Select the newly-produced sample for reading */ 100 | ret = shd_select_samples(ctx_cons, &search, 101 | &metadata, &result); 102 | CU_ASSERT_EQUAL_FATAL(ret, 0); 103 | 104 | /* Read the whole sample blob and check it matches the original */ 105 | ret = shd_read_quantity(ctx_cons, NULL, 106 | &read_blob, sizeof(read_blob)); 107 | CU_ASSERT_TRUE(ret > 0); 108 | CU_ASSERT_TRUE(compare_blobs(s_blob, read_blob)); 109 | 110 | /* Declare end of read */ 111 | ret = shd_end_read(ctx_cons, rev); 112 | CU_ASSERT_EQUAL(ret, 0); 113 | 114 | /* Close should unfold normally */ 115 | ret = shd_close(ctx_cons, rev); 116 | CU_ASSERT_EQUAL(ret, 0); 117 | ret = shd_close(ctx_prod, NULL); 118 | CU_ASSERT_EQUAL(ret, 0); 119 | } 120 | 121 | CU_TestInfo s_func_adv_write_tests[] = { 122 | {(char *)"write by quantity", &test_func_adv_write_by_quantity}, 123 | CU_TEST_INFO_NULL, 124 | }; 125 | -------------------------------------------------------------------------------- /tests/shd_test_func_write_basic.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_test_func_write.c 27 | * 28 | * @brief 29 | * 30 | */ 31 | 32 | #include "shd_test.h" 33 | #include "shd_test_helper.h" 34 | 35 | static void test_func_basic_write_by_blob_whole_once(void) 36 | { 37 | struct shd_ctx *ctx; 38 | int ret; 39 | struct shd_sample_metadata sample_meta = METADATA_INIT; 40 | int index; 41 | 42 | /* Create a producer context to play with */ 43 | ctx = shd_create(BLOB_NAME("write-by-b-once"), NULL, 44 | &s_hdr_info, 45 | &s_metadata_hdr); 46 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx); 47 | 48 | /* Write the whole section once 49 | * shd_write_new_blob should always return 0 */ 50 | ret = 0; 51 | for (index = 0; index < NUMBER_OF_SAMPLES; index++) { 52 | if (time_step(&sample_meta.ts) < 0) 53 | CU_FAIL_FATAL("Could not get time"); 54 | ret += shd_write_new_blob(ctx, 55 | &s_blob, 56 | sizeof(s_blob), 57 | &sample_meta); 58 | } 59 | CU_ASSERT_EQUAL(ret, 0); 60 | 61 | /* Close should unfold normally */ 62 | ret = shd_close(ctx, NULL); 63 | CU_ASSERT_EQUAL(ret, 0); 64 | } 65 | 66 | static void test_func_basic_write_by_blob_whole_twice(void) 67 | { 68 | struct shd_ctx *ctx; 69 | int ret; 70 | struct shd_sample_metadata sample_meta = METADATA_INIT; 71 | int index; 72 | 73 | /* Create a producer context to play with */ 74 | ctx = shd_create(BLOB_NAME("write-by-b-twice"), NULL, 75 | &s_hdr_info, 76 | &s_metadata_hdr); 77 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx); 78 | 79 | /* Write the whole section twice 80 | * shd_write_new_blob should always return 0 */ 81 | ret = 0; 82 | for (index = 0; index < 2 * NUMBER_OF_SAMPLES; index++) { 83 | if (time_step(&sample_meta.ts) < 0) 84 | CU_FAIL_FATAL("Could not get time"); 85 | ret += shd_write_new_blob(ctx, 86 | &s_blob, 87 | sizeof(s_blob), 88 | &sample_meta); 89 | } 90 | CU_ASSERT_EQUAL(ret, 0); 91 | 92 | /* Close should unfold normally */ 93 | ret = shd_close(ctx, NULL); 94 | CU_ASSERT_EQUAL(ret, 0); 95 | } 96 | 97 | static void test_func_write_change_blob_structure(void) 98 | { 99 | struct shd_ctx *ctx; 100 | int ret; 101 | struct shd_sample_metadata sample_meta = METADATA_INIT; 102 | int index; 103 | struct shd_hdr_user_info s_hdr_alt_info; 104 | 105 | /* Create a producer context to play with */ 106 | ctx = shd_create(BLOB_NAME("write-change-blob"), NULL, 107 | &s_hdr_info, 108 | &s_metadata_hdr); 109 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx); 110 | 111 | /* Write the whole section once 112 | * shd_write_new_blob should always return 0 */ 113 | ret = 0; 114 | for (index = 0; index < NUMBER_OF_SAMPLES; index++) { 115 | if (time_step(&sample_meta.ts) < 0) 116 | CU_FAIL_FATAL("Could not get time"); 117 | ret += shd_write_new_blob(ctx, 118 | &s_blob, 119 | sizeof(s_blob), 120 | &sample_meta); 121 | } 122 | CU_ASSERT_EQUAL(ret, 0); 123 | 124 | /* Close should unfold normally */ 125 | ret = shd_close(ctx, NULL); 126 | CU_ASSERT_EQUAL(ret, 0); 127 | 128 | /* Recreate the same section with a different blob size and repeat the 129 | * same operations : everything should unfold normally */ 130 | memcpy(&s_hdr_alt_info, &s_hdr_info, sizeof(s_hdr_info)); 131 | s_hdr_alt_info.blob_size = sizeof(s_blob_alt_size); 132 | ctx = shd_create(BLOB_NAME("write-change-blob"), NULL, 133 | &s_hdr_alt_info, 134 | &s_metadata_hdr); 135 | CU_ASSERT_PTR_NOT_NULL_FATAL(ctx); 136 | 137 | /* Write the whole section once 138 | * shd_write_new_blob should always return 0 */ 139 | ret = 0; 140 | for (index = 0; index < NUMBER_OF_SAMPLES; index++) { 141 | if (time_step(&sample_meta.ts) < 0) 142 | CU_FAIL_FATAL("Could not get time"); 143 | ret += shd_write_new_blob(ctx, 144 | &s_blob_alt_size, 145 | sizeof(s_blob_alt_size), 146 | &sample_meta); 147 | } 148 | CU_ASSERT_EQUAL(ret, 0); 149 | 150 | /* Close should unfold normally */ 151 | ret = shd_close(ctx, NULL); 152 | CU_ASSERT_EQUAL(ret, 0); 153 | } 154 | 155 | CU_TestInfo s_func_basic_write_tests[] = { 156 | {(char *)"write by blob whole section once", 157 | &test_func_basic_write_by_blob_whole_once}, 158 | {(char *)"write by blob whole section twice", 159 | &test_func_basic_write_by_blob_whole_twice}, 160 | {(char *)"write by blob and then change blob structure", 161 | &test_func_write_change_blob_structure}, 162 | CU_TEST_INFO_NULL, 163 | }; 164 | -------------------------------------------------------------------------------- /tests/shd_test_helper.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_test_helper.c 27 | * 28 | * @brief 29 | * 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "libshdata.h" 38 | #include "shd_test_helper.h" 39 | 40 | struct prod_blob s_blob = { 41 | .i1 = TEST_VAL_i1, 42 | .c1 = TEST_VAL_c1, 43 | .li1 = TEST_VAL_li1, 44 | .ui1 = TEST_VAL_ui1, 45 | .f1 = TEST_VAL_f1, 46 | .acc = { TEST_VAL_acc_x, TEST_VAL_acc_y, TEST_VAL_acc_z }, 47 | .angles = { 48 | TEST_VAL_angles_rho, 49 | TEST_VAL_angles_phi, 50 | TEST_VAL_angles_theta 51 | }, 52 | .state = TEST_VAL_state 53 | }; 54 | 55 | struct prod_blob_alt_size s_blob_alt_size = { 56 | .i1 = TEST_VAL_i1, 57 | .c1 = TEST_VAL_c1, 58 | .li1 = TEST_VAL_li1, 59 | .angles = { 60 | TEST_VAL_angles_rho, 61 | TEST_VAL_angles_phi, 62 | TEST_VAL_angles_theta 63 | }, 64 | .state = TEST_VAL_state 65 | }; 66 | 67 | /* 68 | * Declaration of all the quantity structures 69 | */ 70 | QUANTITY_DEF(prod_blob, s_blob, i1); 71 | QUANTITY_DEF(prod_blob, s_blob, c1); 72 | QUANTITY_DEF(prod_blob, s_blob, li1); 73 | QUANTITY_DEF(prod_blob, s_blob, ui1); 74 | QUANTITY_DEF(prod_blob, s_blob, f1); 75 | QUANTITY_DEF(prod_blob, s_blob, acc); 76 | QUANTITY_DEF(prod_blob, s_blob, angles); 77 | QUANTITY_DEF(prod_blob, s_blob, state); 78 | 79 | struct blob_metadata_hdr s_metadata_hdr = { 80 | .i1 = TEST_VAL_MDATA_i1, 81 | .c1 = TEST_VAL_MDATA_c1, 82 | .i2 = TEST_VAL_MDATA_i2, 83 | .c2 = TEST_VAL_MDATA_c2, 84 | .li1 = TEST_VAL_MDATA_li1 85 | }; 86 | 87 | struct shd_hdr_user_info s_hdr_info = { 88 | .blob_size = sizeof(s_blob), 89 | .max_nb_samples = NUMBER_OF_SAMPLES, 90 | .rate = 1000, 91 | .blob_metadata_hdr_size = sizeof(s_metadata_hdr) 92 | }; 93 | 94 | static bool compare_d(double d1, double d2) 95 | { 96 | return fabs((double)(d1) - (d2)) <= fabs((double)(DOUBLE_PRECISION)); 97 | } 98 | static bool compare_f(float f1, float f2) 99 | { 100 | return fabs((double)(f1) - (f2)) <= fabs((double)(FLOAT_PRECISION)); 101 | } 102 | 103 | bool compare_blobs(struct prod_blob b1, struct prod_blob b2) 104 | { 105 | return b1.i1 == b2.i1 106 | && b1.c1 == b2.c1 107 | && b1.li1 == b2.li1 108 | && b1.ui1 == b2.ui1 109 | && compare_f(b1.f1, b2.f1) 110 | && compare_d(b1.acc.x, b2.acc.x) 111 | && compare_d(b1.acc.y, b2.acc.y) 112 | && compare_d(b1.acc.z, b2.acc.z) 113 | && compare_d(b1.angles.rho, b2.angles.rho) 114 | && compare_d(b1.angles.phi, b2.angles.phi) 115 | && compare_d(b1.angles.theta, b2.angles.theta) 116 | && b1.state == b2.state; 117 | } 118 | 119 | #define BILLION 1000000000 120 | static struct timespec time_add(struct timespec t1, struct timespec t2) 121 | { 122 | long sec = t2.tv_sec + t1.tv_sec; 123 | long nsec = t2.tv_nsec + t1.tv_nsec; 124 | if (nsec >= BILLION) { 125 | nsec -= BILLION; 126 | sec++; 127 | } 128 | return (struct timespec){ .tv_sec = sec, .tv_nsec = nsec }; 129 | } 130 | 131 | static struct timespec time_remove(struct timespec t1, struct timespec t2) 132 | { 133 | long sec = t1.tv_sec - t2.tv_sec; 134 | long nsec = t1.tv_nsec - t2.tv_nsec; 135 | if (nsec < 0) { 136 | nsec += BILLION; 137 | sec--; 138 | } 139 | return (struct timespec){ .tv_sec = sec, .tv_nsec = nsec }; 140 | } 141 | 142 | static int time_cmp(struct timespec a, struct timespec b) 143 | { 144 | if (a.tv_sec != b.tv_sec) { 145 | if (a.tv_sec > b.tv_sec) 146 | return 1; 147 | else 148 | return -1; 149 | } else { 150 | if (a.tv_nsec > b.tv_nsec) 151 | return 1; 152 | else if (a.tv_nsec < b.tv_nsec) 153 | return -1; 154 | else 155 | return 0; 156 | } 157 | } 158 | 159 | bool time_is_equal(struct timespec *t1, struct timespec *t2) 160 | { 161 | return (time_cmp(*t1, *t2) == 0); 162 | } 163 | /* Return true is t1 is after t2 */ 164 | bool time_is_after(struct timespec *t1, struct timespec *t2) 165 | { 166 | return (time_cmp(*t1, *t2) > 0); 167 | } 168 | /* Return true is t1 is before t2 */ 169 | bool time_is_before(struct timespec *t1, struct timespec *t2) 170 | { 171 | return (time_cmp(*t1, *t2) < 0); 172 | } 173 | 174 | #define STEP_NANO 1000000 175 | static const struct timespec step = { 176 | .tv_sec = 0, 177 | .tv_nsec = STEP_NANO 178 | }; 179 | static const struct timespec small_step = { 180 | .tv_sec = 0, 181 | .tv_nsec = STEP_NANO / 10 182 | }; 183 | 184 | int time_step(struct timespec *t) 185 | { 186 | *t = time_add(*t, step); 187 | return 0; 188 | } 189 | static int time_small_step(struct timespec *t) 190 | { 191 | *t = time_add(*t, small_step); 192 | return 0; 193 | } 194 | 195 | static int time_back_step(struct timespec *t) 196 | { 197 | *t = time_remove(*t, step); 198 | return 0; 199 | } 200 | static int time_back_small_step(struct timespec *t) 201 | { 202 | *t = time_remove(*t, small_step); 203 | return 0; 204 | } 205 | 206 | struct timespec time_in_past(struct timespec current, int back_steps) 207 | { 208 | int i; 209 | struct timespec ret; 210 | 211 | ret = (struct timespec){ .tv_sec = current.tv_sec, 212 | .tv_nsec = current.tv_nsec}; 213 | for (i = 0; i < back_steps; i++) 214 | time_back_step(&ret); 215 | 216 | return ret; 217 | } 218 | 219 | struct timespec time_in_past_before(struct timespec current, int back_steps) 220 | { 221 | struct timespec ret = time_in_past(current, back_steps); 222 | time_back_small_step(&ret); 223 | return ret; 224 | } 225 | 226 | struct timespec time_in_past_after(struct timespec current, int back_steps) 227 | { 228 | struct timespec ret = time_in_past(current, back_steps); 229 | time_small_step(&ret); 230 | return ret; 231 | } 232 | 233 | int time_set(struct timespec *dest, struct timespec value) 234 | { 235 | dest->tv_nsec = value.tv_nsec; 236 | dest->tv_sec = value.tv_sec; 237 | return 0; 238 | } 239 | 240 | int get_unique_blob_name(const char *root, char *dest) 241 | { 242 | struct timespec current_time; 243 | if (clock_gettime(CLOCK_REALTIME, ¤t_time) < 0) 244 | return -1; 245 | 246 | return snprintf(dest, NAME_MAX, "%s-%ld-%ld", root, 247 | current_time.tv_sec, 248 | current_time.tv_nsec); 249 | } 250 | -------------------------------------------------------------------------------- /tests/shd_test_helper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015 Parrot S.A. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of the Parrot Company nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PARROT COMPANY BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | * 26 | * @file shd_test_helper.h 27 | * 28 | * @brief 29 | * 30 | */ 31 | 32 | #ifndef SHD_TEST_HELPER_H_ 33 | #define SHD_TEST_HELPER_H_ 34 | 35 | #include 36 | #include 37 | 38 | #define NUMBER_OF_SAMPLES 20 39 | #define CLOSEST_SEARCH_INDEX 7 40 | #define TEST_BLOB_NAME "myBlob" 41 | #define BLOB_NAME(a) "myBlob_" a 42 | /* Ugly but useful macro to create a quantity from any field in a blob 43 | * The name of that new structure will be q_blobname_fieldname 44 | */ 45 | #define QUANTITY_DEF(t, b, q) struct shd_quantity q_##b##_##q = \ 46 | QUANTITY_FIELD(t, b, q) 47 | 48 | #define QUANTITY_DECL(b, q) extern struct shd_quantity q_##b##_##q; 49 | #define QUANTITY_FIELD(t, b, q) { offsetof(struct t, q), sizeof(b.q) } 50 | #define QTY_SAMPLE_FIELD(b, q) { .ptr = &b.q, .size = sizeof(b.q) } 51 | 52 | #define QUANTITY_PTR(b, q) ((void *) &b.q) 53 | 54 | #define QUANTITIES_NB_IN_BLOB 8 55 | 56 | #define TEST_VAL_i1 (0xAB) 57 | #define TEST_VAL_c1 ('h') 58 | #define TEST_VAL_li1 (-0xDEADCAFE) 59 | #define TEST_VAL_ui1 (0xCAFE) 60 | #define TEST_VAL_f1 (1.2345) 61 | #define TEST_VAL_acc_x (9.81) 62 | #define TEST_VAL_acc_y (-9.81) 63 | #define TEST_VAL_acc_z (9.81) 64 | #define TEST_VAL_angles_rho (180.0) 65 | #define TEST_VAL_angles_phi (90.0) 66 | #define TEST_VAL_angles_theta (-270.0) 67 | #define TEST_VAL_state (STATE_LANDING) 68 | #define FLOAT_PRECISION (0.0000001) 69 | #define DOUBLE_PRECISION (0.000000001) 70 | 71 | #define TEST_VAL_MDATA_i1 (0xCAFE) 72 | #define TEST_VAL_MDATA_c1 "Hello" 73 | #define TEST_VAL_MDATA_i2 0xDEAD 74 | #define TEST_VAL_MDATA_c2 "Lorem ipsum dolor sit amet, consectetur "\ 75 | "adipiscing elit. Sed non risus. " 76 | #define TEST_VAL_MDATA_li1 0x4567 77 | 78 | 79 | /* Time simulation functions 80 | * ... this code should surely be unit tested as well */ 81 | #define TIME_INIT ((struct timespec) { .tv_nsec = 0, .tv_sec = 0 }) 82 | #define METADATA_INIT ((struct shd_sample_metadata) \ 83 | { .ts = TIME_INIT, .exp = TIME_INIT }) 84 | 85 | /* 86 | * Type declarations for the definition of our test blob 87 | */ 88 | struct acceleration { 89 | double x; 90 | double y; 91 | double z; 92 | }; 93 | 94 | struct angles { 95 | double rho; 96 | double phi; 97 | double theta; 98 | }; 99 | 100 | enum flight_state_t { 101 | STATE_FLYING, 102 | STATE_HOVERING, 103 | STATE_LANDING, 104 | STATE_TAKEOFF 105 | }; 106 | 107 | struct prod_blob { 108 | int i1; 109 | char c1; 110 | long int li1; 111 | unsigned int ui1; 112 | float f1; 113 | struct acceleration acc; 114 | struct angles angles; 115 | enum flight_state_t state; 116 | }; 117 | 118 | struct prod_blob_alt_size { 119 | int i1; 120 | char c1; 121 | long int li1; 122 | struct angles angles; 123 | enum flight_state_t state; 124 | }; 125 | 126 | struct blob_metadata_hdr { 127 | int i1; 128 | const char c1[10]; 129 | int i2; 130 | const char c2[255]; 131 | long int li1; 132 | }; 133 | 134 | extern struct prod_blob s_blob; 135 | extern struct prod_blob_alt_size s_blob_alt_size; 136 | extern struct blob_metadata_hdr s_metadata_hdr; 137 | extern struct shd_hdr_user_info s_hdr_info; 138 | 139 | QUANTITY_DECL(s_blob, i1); 140 | QUANTITY_DECL(s_blob, c1); 141 | QUANTITY_DECL(s_blob, li1); 142 | QUANTITY_DECL(s_blob, ui1); 143 | QUANTITY_DECL(s_blob, f1); 144 | QUANTITY_DECL(s_blob, acc); 145 | QUANTITY_DECL(s_blob, angles); 146 | QUANTITY_DECL(s_blob, state); 147 | 148 | 149 | struct timespec time_in_past(struct timespec current, int back_steps); 150 | struct timespec time_in_past_before(struct timespec current, int back_steps); 151 | struct timespec time_in_past_after(struct timespec current, int back_steps); 152 | int time_set(struct timespec *dest, struct timespec value); 153 | 154 | 155 | bool time_is_equal(struct timespec *t1, struct timespec *t2); 156 | bool time_is_after(struct timespec *t1, struct timespec *t2); 157 | bool time_is_before(struct timespec *t1, struct timespec *t2); 158 | int time_step(struct timespec *t); 159 | 160 | bool compare_blobs(struct prod_blob b1, struct prod_blob b2); 161 | 162 | int get_unique_blob_name(const char *root, char *dest); 163 | 164 | #endif /* SHD_TEST_HELPER_H_ */ 165 | --------------------------------------------------------------------------------