2525#include "oshmem/mca/sshmem/base/base.h"
2626#include "ompi/util/timings.h"
2727
28+ #include <sys/mman.h>
29+
2830mca_memheap_base_config_t mca_memheap_base_config = {
2931 .device_nic_mem_seg_size = 0
3032};
@@ -106,6 +108,128 @@ static size_t _memheap_size(void)
106108 return (size_t ) memheap_align (oshmem_shmem_info_env .symmetric_heap_size );
107109}
108110
111+ static void * memheap_mmap_get (void * hint , size_t size )
112+ {
113+ void * addr ;
114+
115+ addr = mmap (hint , size ,
116+ PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , -1 , 0 );
117+ if (addr == MAP_FAILED ) {
118+ return NULL ;
119+ }
120+
121+ return addr ;
122+ }
123+
124+ static int memheap_exchange_base_address (size_t size , void * * address )
125+ {
126+ int nprocs = oshmem_num_procs ();
127+ void * base = NULL ;
128+ void * ptr = NULL ;
129+ int rc , i ;
130+ void * * bases ;
131+
132+ bases = calloc (nprocs , sizeof (* bases ));
133+ if (NULL == bases ) {
134+ return OSHMEM_ERROR ;
135+ }
136+
137+ if (oshmem_my_proc_id () == 0 ) {
138+ ptr = memheap_mmap_get (NULL , size );
139+ base = ptr ;
140+ }
141+
142+ rc = oshmem_shmem_bcast (& base , sizeof (base ), 0 );
143+ if (OSHMEM_SUCCESS != rc ) {
144+ MEMHEAP_ERROR ("Failed to exchange allocated vma for base segment "
145+ "(error %d)" , rc );
146+ goto out ;
147+ }
148+
149+ if (oshmem_my_proc_id () != 0 ) {
150+ ptr = memheap_mmap_get (base , size );
151+ }
152+
153+ MEMHEAP_VERBOSE (100 , "#%d: exchange base address: base %p: %s" ,
154+ oshmem_my_proc_id (), base ,
155+ (base == ptr )? "ok" : "unavailable" );
156+
157+ rc = oshmem_shmem_allgather (& ptr , bases , sizeof (ptr ));
158+ if (OSHMEM_SUCCESS != rc ) {
159+ MEMHEAP_ERROR ("Failed to exchange selected vma for base segment "
160+ "(error %d)" , rc );
161+ goto out ;
162+ }
163+
164+ * address = base ;
165+ for (i = 0 ; i < nprocs ; i ++ ) {
166+ if ((NULL == bases [i ]) || (bases [i ] != base )) {
167+ * address = NULL ;
168+ break ;
169+ }
170+ }
171+
172+ out :
173+ if (((OSHMEM_SUCCESS != rc ) || (* address == NULL )) && (NULL != ptr )) {
174+ (void )munmap (ptr , size );
175+ }
176+
177+ free (bases );
178+ return rc ;
179+ }
180+
181+
182+ /*
183+ * The returned mca_sshmem_base_start_address value is reserved by using
184+ * mmap() for the expected size.
185+ */
186+ static int memheap_base_segment_setup (size_t size )
187+ {
188+ int rc ;
189+
190+ if (mca_sshmem_base_start_address == (void * )UINTPTR_MAX ) {
191+ if (UINTPTR_MAX == 0xFFFFFFFF ) {
192+ /**
193+ * if 32 bit we set sshmem_base_start_adress to 0
194+ * to let OS allocate segment automatically
195+ */
196+ mca_sshmem_base_start_address = NULL ;
197+ return OSHMEM_SUCCESS ;
198+ }
199+
200+ rc = memheap_exchange_base_address (size , & mca_sshmem_base_start_address );
201+ if (OSHMEM_SUCCESS != rc ) {
202+ MEMHEAP_ERROR ("Failed to setup base segment address (error %d)" , rc );
203+ return rc ;
204+ }
205+
206+ if (NULL != mca_sshmem_base_start_address ) {
207+ goto done ; /* Region is reserved */
208+ }
209+
210+ #if defined(__aarch64__ )
211+ mca_sshmem_base_start_address = (void * )0xAB0000000000 ;
212+ #else
213+ mca_sshmem_base_start_address = (void * )0xFF000000 ;
214+ #endif
215+ }
216+
217+ if (mca_sshmem_base_start_address != memheap_mmap_get (
218+ mca_sshmem_base_start_address , size )) {
219+ MEMHEAP_ERROR ("Failed to create segment address %p/%zu" ,
220+ mca_sshmem_base_start_address , size );
221+ return OSHMEM_ERROR ;
222+ }
223+
224+ done :
225+ if (oshmem_my_proc_id () == 0 ) {
226+ MEMHEAP_VERBOSE (10 , "Using symmetric segment address %p/%zu" ,
227+ mca_sshmem_base_start_address , size );
228+ }
229+
230+ return OSHMEM_SUCCESS ;
231+ }
232+
109233static memheap_context_t * _memheap_create (void )
110234{
111235 int rc = OSHMEM_SUCCESS ;
@@ -123,13 +247,18 @@ static memheap_context_t* _memheap_create(void)
123247
124248 OPAL_TIMING_ENV_NEXT (timing , "_memheap_size()" );
125249
126- /* Inititialize symmetric area */
127- if ( OSHMEM_SUCCESS == rc ) {
128- rc = mca_memheap_base_alloc_init ( & mca_memheap_base_map ,
129- user_size + MEMHEAP_BASE_PRIVATE_SIZE , 0 ,
130- "regular_mem" ) ;
250+ /* Locate and reserve symmetric area */
251+ rc = memheap_base_segment_setup ( user_size + MEMHEAP_BASE_PRIVATE_SIZE );
252+ if ( OSHMEM_SUCCESS != rc ) {
253+ MEMHEAP_ERROR ( "Failed to negotiate base segment addres" );
254+ return NULL ;
131255 }
132256
257+ /* Inititialize symmetric area */
258+ rc = mca_memheap_base_alloc_init (& mca_memheap_base_map ,
259+ user_size + MEMHEAP_BASE_PRIVATE_SIZE , 0 ,
260+ "regular_mem" );
261+
133262 OPAL_TIMING_ENV_NEXT (timing , "mca_memheap_base_alloc_init()" );
134263
135264 /* Initialize atomic symmetric area */
0 commit comments