Add support for AArch32
[vpp.git] / svm / ssvm.c
1 /*
2  * Copyright (c) 2015 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 #include "ssvm.h"
16
17 int ssvm_master_init (ssvm_private_t * ssvm, u32 master_index)
18 {
19   int ssvm_fd;
20   u8 * ssvm_filename;
21   u8 junk = 0;
22   int flags;
23   ssvm_shared_header_t * sh;
24   u64 ticks = clib_cpu_time_now();
25   u64 randomize_baseva;
26   void * oldheap;
27
28   if (ssvm->ssvm_size == 0)
29     return SSVM_API_ERROR_NO_SIZE;
30
31   ssvm_filename = format (0, "/dev/shm/%s%c", ssvm->name, 0);
32
33   unlink ((char *) ssvm_filename);
34
35   vec_free(ssvm_filename);
36
37   ssvm_fd = shm_open((char *) ssvm->name, O_RDWR | O_CREAT | O_EXCL, 0777);
38
39   if (ssvm_fd < 0)
40     {
41       clib_unix_warning ("create segment '%s'", ssvm->name);
42       return SSVM_API_ERROR_CREATE_FAILURE;
43     }
44
45   lseek(ssvm_fd, ssvm->ssvm_size, SEEK_SET);
46   if (write(ssvm_fd, &junk, 1) != 1)
47     {
48       clib_unix_warning ("set ssvm size");
49       close(ssvm_fd);
50       return SSVM_API_ERROR_SET_SIZE;
51     }
52   
53   flags = MAP_SHARED;
54   if (ssvm->requested_va)
55     flags |= MAP_FIXED;
56
57   randomize_baseva = (ticks & 15) * MMAP_PAGESIZE;
58
59   if (ssvm->requested_va)
60     ssvm->requested_va += randomize_baseva;
61   
62   sh = ssvm->sh = (ssvm_shared_header_t *) mmap((void *)ssvm->requested_va, ssvm->ssvm_size, 
63                                 PROT_READ | PROT_WRITE, flags, ssvm_fd, 0);
64
65   if (ssvm->sh == MAP_FAILED)
66     {
67       clib_unix_warning ("mmap");
68       close(ssvm_fd);
69       return SSVM_API_ERROR_MMAP;
70     }
71
72   close(ssvm_fd);
73
74   ssvm->my_pid = getpid();
75   sh->master_pid = ssvm->my_pid;
76   sh->ssvm_size = ssvm->ssvm_size;
77   sh->heap = mheap_alloc_with_flags 
78     (((u8 *)sh) + MMAP_PAGESIZE, ssvm->ssvm_size - MMAP_PAGESIZE, 
79      MHEAP_FLAG_DISABLE_VM | MHEAP_FLAG_THREAD_SAFE);
80
81   sh->ssvm_va = pointer_to_uword(sh);
82   sh->master_index = master_index;
83
84   oldheap = ssvm_push_heap (sh);
85   sh->name = format (0, "%s%c", ssvm->name, 0);
86   ssvm_pop_heap (oldheap);
87
88   ssvm->i_am_master = 1;
89
90   /* The application has to set set sh->ready... */
91   return 0;
92 }
93
94 int ssvm_slave_init (ssvm_private_t * ssvm, int timeout_in_seconds)
95 {
96     struct stat stat;
97     int ssvm_fd = -1;
98     ssvm_shared_header_t * sh;
99
100     ssvm->i_am_master = 0;
101
102     while (timeout_in_seconds-- > 0)
103       {
104         if (ssvm_fd < 0)
105           ssvm_fd = shm_open((char *)ssvm->name, O_RDWR, 0777);
106         if (ssvm_fd < 0)
107           {
108             sleep (1);
109             continue;
110           }
111         if (fstat(ssvm_fd, &stat) < 0)
112           {
113             sleep (1);
114             continue;
115           }
116         
117         if (stat.st_size > 0)
118           goto map_it;
119       }
120     clib_warning ("slave timeout");
121     return SSVM_API_ERROR_SLAVE_TIMEOUT;
122         
123  map_it:
124     sh = (void *) mmap (0, MMAP_PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 
125                         ssvm_fd, 0);
126     if (sh == MAP_FAILED)
127       {
128         clib_unix_warning ("slave research mmap");
129         close (ssvm_fd);
130         return SSVM_API_ERROR_MMAP;
131       }
132     
133     while (timeout_in_seconds-- > 0)
134       {
135         if (sh->ready)
136           goto re_map_it;
137       }
138     close (ssvm_fd);
139     munmap (sh, MMAP_PAGESIZE);
140     clib_warning ("slave timeout 2");
141     return SSVM_API_ERROR_SLAVE_TIMEOUT;
142     
143  re_map_it:
144     ssvm->requested_va = (u64) sh->ssvm_va;
145     ssvm->ssvm_size = sh->ssvm_size;
146     munmap (sh, MMAP_PAGESIZE);
147
148     sh = ssvm->sh = (void *) mmap((void *)ssvm->requested_va, ssvm->ssvm_size, 
149                                   PROT_READ | PROT_WRITE, 
150                                   MAP_SHARED | MAP_FIXED,
151                                   ssvm_fd, 0);
152     
153     if (sh == MAP_FAILED)
154       {
155         clib_unix_warning ("slave final mmap");
156         close (ssvm_fd);
157         return SSVM_API_ERROR_MMAP;
158       }
159     sh->slave_pid = getpid();
160     return 0;
161 }