Line data Source code
1 : /* 2 : * Copyright (c) 2015-2019 Cisco and/or its affiliates. 3 : * Licensed under the Apache License, Version 2.0 (the "License"); 4 : * you may not use this file except in compliance with the License. 5 : * You may obtain a copy of the License at: 6 : * 7 : * http://www.apache.org/licenses/LICENSE-2.0 8 : * 9 : * Unless required by applicable law or agreed to in writing, software 10 : * distributed under the License is distributed on an "AS IS" BASIS, 11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : * See the License for the specific language governing permissions and 13 : * limitations under the License. 14 : */ 15 : #ifndef __included_ssvm_h__ 16 : #define __included_ssvm_h__ 17 : 18 : #include <stdio.h> 19 : #include <stdlib.h> 20 : #include <sys/types.h> 21 : #include <sys/mman.h> 22 : #include <sys/stat.h> 23 : #include <netinet/in.h> 24 : #include <signal.h> 25 : #include <pthread.h> 26 : #include <unistd.h> 27 : #include <time.h> 28 : #include <fcntl.h> 29 : #include <string.h> 30 : #include <vppinfra/clib.h> 31 : #include <vppinfra/vec.h> 32 : #include <vppinfra/hash.h> 33 : #include <vppinfra/bitmap.h> 34 : #include <vppinfra/fifo.h> 35 : #include <vppinfra/time.h> 36 : #include <vppinfra/heap.h> 37 : #include <vppinfra/pool.h> 38 : #include <vppinfra/format.h> 39 : #include <vppinfra/lock.h> 40 : 41 : #ifndef MMAP_PAGESIZE 42 : #define MMAP_PAGESIZE (clib_mem_get_page_size()) 43 : #endif 44 : 45 : #define SSVM_N_OPAQUE 7 46 : 47 : typedef enum ssvm_segment_type_ 48 : { 49 : SSVM_SEGMENT_SHM = 0, 50 : SSVM_SEGMENT_MEMFD, 51 : SSVM_SEGMENT_PRIVATE, 52 : SSVM_N_SEGMENT_TYPES /**< Private segments */ 53 : } ssvm_segment_type_t; 54 : 55 : typedef struct 56 : { 57 : /* Spin-lock */ 58 : volatile u32 lock; 59 : volatile u32 owner_pid; 60 : int recursion_count; 61 : u32 tag; /* for debugging */ 62 : 63 : /* The allocation arena */ 64 : void *heap; 65 : 66 : /* Segment must be mapped at this address, or no supper */ 67 : uword ssvm_va; 68 : /* The actual mmap size */ 69 : uword ssvm_size; 70 : u32 server_pid; 71 : u32 client_pid; 72 : u8 *name; 73 : void *opaque[SSVM_N_OPAQUE]; 74 : 75 : /* Set when server init done */ 76 : volatile u32 ready; 77 : 78 : ssvm_segment_type_t type; 79 : } ssvm_shared_header_t; 80 : 81 : typedef struct 82 : { 83 : ssvm_shared_header_t *sh; 84 : uword ssvm_size; 85 : uword requested_va; 86 : u32 my_pid; 87 : u8 *name; 88 : u8 numa; /**< UNUSED: numa requested at alloc time */ 89 : int is_server; 90 : int huge_page; 91 : union 92 : { 93 : int fd; /**< memfd segments */ 94 : int attach_timeout; /**< shm segments attach timeout (sec) */ 95 : }; 96 : } ssvm_private_t; 97 : 98 : always_inline void 99 : ssvm_lock (ssvm_shared_header_t * h, u32 my_pid, u32 tag) 100 : { 101 : if (h->owner_pid == my_pid) 102 : { 103 : h->recursion_count++; 104 : return; 105 : } 106 : 107 : while (clib_atomic_test_and_set (&h->lock)) 108 : CLIB_PAUSE (); 109 : 110 : h->owner_pid = my_pid; 111 : h->recursion_count = 1; 112 : h->tag = tag; 113 : } 114 : 115 : always_inline void 116 : ssvm_lock_non_recursive (ssvm_shared_header_t * h, u32 tag) 117 : { 118 : while (clib_atomic_test_and_set (&h->lock)) 119 : CLIB_PAUSE (); 120 : 121 : h->tag = tag; 122 : } 123 : 124 : always_inline void 125 : ssvm_unlock (ssvm_shared_header_t * h) 126 : { 127 : if (--h->recursion_count == 0) 128 : { 129 : h->owner_pid = 0; 130 : h->tag = 0; 131 : clib_atomic_release (&h->lock); 132 : } 133 : } 134 : 135 : always_inline void 136 : ssvm_unlock_non_recursive (ssvm_shared_header_t * h) 137 : { 138 : h->tag = 0; 139 : clib_atomic_release (&h->lock); 140 : } 141 : 142 : static inline void * 143 411 : ssvm_push_heap (ssvm_shared_header_t * sh) 144 : { 145 : clib_mem_heap_t *oldheap; 146 411 : oldheap = clib_mem_set_heap (sh->heap); 147 411 : return ((void *) oldheap); 148 : } 149 : 150 : static inline void 151 411 : ssvm_pop_heap (void *oldheap) 152 : { 153 411 : clib_mem_set_heap (oldheap); 154 411 : } 155 : 156 : static inline void * 157 : ssvm_mem_alloc (ssvm_private_t * ssvm, uword size) 158 : { 159 : clib_mem_heap_t *oldheap; 160 : void *rv; 161 : 162 : oldheap = clib_mem_set_heap (ssvm->sh->heap); 163 : rv = clib_mem_alloc (size); 164 : clib_mem_set_heap (oldheap); 165 : return (rv); 166 : } 167 : 168 : #define foreach_ssvm_api_error \ 169 : _(NO_NAME, "No shared segment name", -100) \ 170 : _(NO_SIZE, "Size not set (server)", -101) \ 171 : _(CREATE_FAILURE, "Create failed", -102) \ 172 : _(SET_SIZE, "Set size failed", -103) \ 173 : _(MMAP, "mmap failed", -104) \ 174 : _(CLIENT_TIMEOUT, "Client map timeout", -105) 175 : 176 : typedef enum 177 : { 178 : #define _(n,s,c) SSVM_API_ERROR_##n = c, 179 : foreach_ssvm_api_error 180 : #undef _ 181 : } ssvm_api_error_enum_t; 182 : 183 : #define SSVM_API_ERROR_NO_NAME (-10) 184 : 185 : int ssvm_server_init (ssvm_private_t * ssvm, ssvm_segment_type_t type); 186 : int ssvm_client_init (ssvm_private_t * ssvm, ssvm_segment_type_t type); 187 : void ssvm_delete (ssvm_private_t * ssvm); 188 : 189 : int ssvm_server_init_shm (ssvm_private_t * ssvm); 190 : int ssvm_client_init_shm (ssvm_private_t * ssvm); 191 : void ssvm_delete_shm (ssvm_private_t * ssvm); 192 : 193 : int ssvm_server_init_memfd (ssvm_private_t * memfd); 194 : int ssvm_client_init_memfd (ssvm_private_t * memfd); 195 : void ssvm_delete_memfd (ssvm_private_t * memfd); 196 : 197 : int ssvm_server_init_private (ssvm_private_t * ssvm); 198 : int ssvm_client_init_private (ssvm_private_t * ssvm); 199 : void ssvm_delete_private (ssvm_private_t * ssvm); 200 : 201 : ssvm_segment_type_t ssvm_type (const ssvm_private_t * ssvm); 202 : u8 *ssvm_name (const ssvm_private_t * ssvm); 203 : 204 : #endif /* __included_ssvm_h__ */ 205 : 206 : /* 207 : * fd.io coding-style-patch-verification: ON 208 : * 209 : * Local Variables: 210 : * eval: (c-set-style "gnu") 211 : * End: 212 : */