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,136 @@ 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+ int need_sync = (* address == NULL );
128+ void * base = NULL ;
129+ void * ptr = NULL ;
130+ int rc , i ;
131+ void * * bases ;
132+
133+ bases = calloc (nprocs , sizeof (* bases ));
134+ if (NULL == bases ) {
135+ return OSHMEM_ERROR ;
136+ }
137+
138+ if (oshmem_my_proc_id () == 0 ) {
139+ ptr = memheap_mmap_get (NULL , size );
140+ base = ptr ;
141+ }
142+
143+ rc = oshmem_shmem_bcast (& base , sizeof (base ), 0 );
144+ if (OSHMEM_SUCCESS != rc ) {
145+ MEMHEAP_ERROR ("Failed to exchange allocated vma for base segment "
146+ "(error %d)" , rc );
147+ goto out ;
148+ }
149+
150+ if (oshmem_my_proc_id () != 0 ) {
151+ ptr = memheap_mmap_get (base , size );
152+ }
153+
154+ MEMHEAP_VERBOSE (100 , "#%d: exchange base address: base %p: %s" ,
155+ oshmem_my_proc_id (), base ,
156+ (base == ptr )? "ok" : "unavailable" );
157+
158+ * address = base ;
159+ if (need_sync ) {
160+ /* They all succeed or fail to allow fallback */
161+ rc = oshmem_shmem_allgather (& ptr , bases , sizeof (ptr ));
162+ if (OSHMEM_SUCCESS != rc ) {
163+ MEMHEAP_ERROR ("Failed to exchange selected vma for base segment "
164+ "(error %d)" , rc );
165+ goto out ;
166+ }
167+
168+ for (i = 0 ; i < nprocs ; i ++ ) {
169+ if ((NULL == bases [i ]) || (bases [i ] != base )) {
170+ * address = NULL ;
171+ break ;
172+ }
173+ }
174+ } else if (ptr != base ) {
175+ /* Any failure terminates the rank and others start teardown */
176+ rc = OSHMEM_ERROR ;
177+ }
178+
179+ out :
180+ if (((OSHMEM_SUCCESS != rc ) || (* address == NULL )) && (ptr != NULL )) {
181+ (void )munmap (ptr , size );
182+ }
183+
184+ free (bases );
185+ return rc ;
186+ }
187+
188+
189+ /*
190+ * The returned mca_sshmem_base_start_address value is reserved by using
191+ * mmap() for the expected size.
192+ */
193+ static int memheap_base_segment_setup (size_t size )
194+ {
195+ int rc ;
196+
197+ if ((mca_sshmem_base_start_address == (void * )UINTPTR_MAX ) ||
198+ (mca_sshmem_base_start_address == NULL )) {
199+ if (UINTPTR_MAX == 0xFFFFFFFF ) {
200+ /**
201+ * if 32 bit we set sshmem_base_start_adress to 0
202+ * to let OS allocate segment automatically
203+ */
204+ mca_sshmem_base_start_address = NULL ;
205+ return OSHMEM_SUCCESS ;
206+ }
207+
208+ rc = memheap_exchange_base_address (size , & mca_sshmem_base_start_address );
209+ if (OSHMEM_SUCCESS != rc ) {
210+ MEMHEAP_ERROR ("Failed to setup base segment address (error %d)" , rc );
211+ return rc ;
212+ }
213+
214+ if (NULL != mca_sshmem_base_start_address ) {
215+ goto done ; /* Region is reserved */
216+ }
217+
218+ #if defined(__aarch64__ )
219+ mca_sshmem_base_start_address = (void * )0xAB0000000000 ;
220+ #else
221+ mca_sshmem_base_start_address = (void * )0xFF000000 ;
222+ #endif
223+ }
224+
225+ if (mca_sshmem_base_start_address != memheap_mmap_get (
226+ mca_sshmem_base_start_address , size )) {
227+ MEMHEAP_ERROR ("Failed to create segment address %p/%zu" ,
228+ mca_sshmem_base_start_address , size );
229+ return OSHMEM_ERROR ;
230+ }
231+
232+ done :
233+ if (oshmem_my_proc_id () == 0 ) {
234+ MEMHEAP_VERBOSE (10 , "Using symmetric segment address %p/%zu" ,
235+ mca_sshmem_base_start_address , size );
236+ }
237+
238+ return OSHMEM_SUCCESS ;
239+ }
240+
109241static memheap_context_t * _memheap_create (void )
110242{
111243 int rc = OSHMEM_SUCCESS ;
@@ -123,13 +255,18 @@ static memheap_context_t* _memheap_create(void)
123255
124256 OPAL_TIMING_ENV_NEXT (timing , "_memheap_size()" );
125257
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" ) ;
258+ /* Locate and reserve symmetric area */
259+ rc = memheap_base_segment_setup ( user_size + MEMHEAP_BASE_PRIVATE_SIZE );
260+ if ( OSHMEM_SUCCESS != rc ) {
261+ MEMHEAP_ERROR ( "Failed to negotiate base segment addres" );
262+ return NULL ;
131263 }
132264
265+ /* Initialize symmetric area */
266+ rc = mca_memheap_base_alloc_init (& mca_memheap_base_map ,
267+ user_size + MEMHEAP_BASE_PRIVATE_SIZE , 0 ,
268+ "regular_mem" );
269+
133270 OPAL_TIMING_ENV_NEXT (timing , "mca_memheap_base_alloc_init()" );
134271
135272 /* Initialize atomic symmetric area */
0 commit comments