// File: /workspace/github_c_makefile_star2_O3/USArmyResearchLab[P]ARL_OpenSHMEM/src/shmem_init.c
// Function: shmem_init
SHMEM_SCOPE
void shmem_init(void)
{
	int run_id;
	int my_pe;
	int n_pes;
	int n_pes_log2;
	size_t heap_size;

	debug("shmem_init begin");

	bzero(&__shmem,sizeof(shmem_internals_t));

	const char* env_var_run_id = getenv("SHMEM_RUN_ID");
	const char* env_var_my_pe = getenv("SHMEM_MY_PE");
	const char* env_var_n_pes = getenv("SHMEM_N_PES");
	const char* env_var_heap_size = getenv("SHMEM_SYMMETRIC_HEAP_SIZE");

	if ( env_var_run_id && env_var_my_pe && env_var_n_pes ) {
		run_id = atoi(env_var_run_id);
		my_pe = atoi(env_var_my_pe);
		n_pes = atoi(env_var_n_pes);
	} else {
		run_id = getpid();
		my_pe = 0;
		n_pes = 1;
		fprintf(stderr,"shmem warning: SHMEM_RUN_ID, SHMEM_MY_PE, or"
			" SHMEM_N_PES not set. Defaulting to serial execution\n");
	}

	if (env_var_heap_size) {
		size_t len = strnlen(env_var_heap_size,1024);
		unsigned int x = 1;
		if (env_var_heap_size[len-1]=='K') {
			x = 1024;
		} else if (env_var_heap_size[len-1]=='M') {
			x = 1024*1024;
		}
		heap_size = x * atoi(env_var_heap_size);
	} else {
		heap_size = 128*1024*1024;
		if (my_pe == 0) {
			fprintf(stderr,"shmem warning: SHMEM_SYMMETRIC_HEAP_SIZE not set."
				" Defaulting to %ld bytes\n", heap_size);
		}
	}

	debug("run_id=%d\nmy_pe=%d\nn_pes=%d\nheap_size=%ld\n",
		run_id, my_pe, n_pes, heap_size);

	if ( n_pes < 0 || n_pes > SHMEM_MAX_PES ) {
		fprintf(stderr,"shmem error: n_pes out of range: %d\n",n_pes);
		exit(-1);
	}

	if ( my_pe < 0 || my_pe >= n_pes ) {
		fprintf(stderr,"shmem error: my_pe out of range: %d\n",my_pe);
		exit(-1);
	}


	// log2_ceil of n_pes precalculated once
	n_pes_log2 = 0;
	unsigned int x = n_pes - 1;
	while (x > 0) {
		n_pes_log2++;
		x >>= 1;
	}

	__shmem.run_id = run_id;
	__shmem_my_pe = __shmem.my_pe = my_pe;
	__shmem_n_pes = __shmem.n_pes = n_pes;
	__shmem.n_pes_log2 = n_pes_log2;
	__shmem.heap_size = heap_size;


	__shmem.giant_barrier_count = 0;
	sem_init(&__shmem.giant_mutex,1,0);
	sem_init(&__shmem.giant_barrier_gate1,1,0);
	sem_init(&__shmem.giant_barrier_gate2,1,0);

	sem_init(&__shmem.sync_mutex,1,0);


	/* First we need to remap .data and .bss into a shm allocation. */

	int data_fd;
	void* data_start;
	size_t data_size;

	find_data_pages(&data_start,&data_size);

	intptr_t data_shm_base 
		= (intptr_t)shm_alloc(n_pes*data_size,run_id,0,&data_fd);
	
	munmap((void*)(data_shm_base+my_pe*data_size), data_size);

	remap_pages(data_fd, my_pe*data_size, data_start, data_size);

	__shmem.data_fd = data_fd;
	__shmem.data_base = (intptr_t)data_start;
	__shmem.data_size = data_size;
	__shmem.data_shm_base = data_shm_base;

	debug("symmetric data:\n\tdata_fd=%d\n\tdata_base=%p\n\tdata_size=%ld\n"
		"\tdata_shm_base=%p\n",data_fd,data_start,data_size,(void*)data_shm_base);


	/* we now have enough information to setup the symmetric heap -DAR */

	debug("shmem_init setup shared memory region");

	intptr_t heap_shm_base = (intptr_t)shm_alloc(n_pes*heap_size,run_id,1,0);

	debug("shmem_init shm_alloc returned %p",(void*)heap_shm_base);

	__shmem.heap_shm_base = heap_shm_base;

	debug("__shmem.heap_shm_base %p\n",(void*)__shmem.heap_shm_base);


	int c, r;
	for (c = 0, r = 1; r < __shmem.n_pes; c++, r <<= 1)
	{
		int to = __shmem.my_pe + r;
		if (to >= __shmem.n_pes) to -= __shmem.n_pes;
		long* lock = (long*)(__shmem.barrier_sync + c);
		long* remote_lock = (long*)shmem_ptr((void*)lock, to);
		__shmem.barrier_psync[c] = remote_lock;
	}
	debug("pe %d barrier_psync[0] %p",__shmem.my_pe,__shmem.barrier_psync[0]);


	__shmem.local_mem_base 
		= __shmem.heap_shm_base + my_pe * heap_size + getpagesize();

	__shmem.free_mem = __shmem.local_mem_base;

	__shmem.xmem0 = xmalloc_init( 
		(void*)__shmem.local_mem_base, heap_size - getpagesize(), 0 );

	debug("[%d] before barrier\n",my_pe);

	__shmem.p_giant_mutex = (sem_t*)shmem_ptr((void*)&__shmem.giant_mutex,0);

	if (my_pe == 0) sem_post(&__shmem.giant_mutex);
	sem_post(&__shmem.sync_mutex);


	shmem_sync_all();


	debug("[%d] after barrier\n",my_pe);


	if (__shmem.n_pes == 1) return;

	if (!__shmem.my_pe) {
		debug("master set psync to 1 @ %p",__shmem.barrier_psync[0]);
		*__shmem.barrier_psync[0] = 1;
	}

	debug("spin on sync at %p",__shmem.barrier_sync);
	while(*__shmem.barrier_sync == SHMEM_SYNC_VALUE);

	if (__shmem.my_pe) {
		debug("slave set psync to 1 @ %p",__shmem.barrier_psync[0]);
		*__shmem.barrier_psync[0] = 1;
	}

	debug("set sync to SHMEM_SYNC_VALUE @ %p",__shmem.barrier_sync);
	*__shmem.barrier_sync = SHMEM_SYNC_VALUE;

	debug("shmem_init done");

	
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
leaq 0x4aeb(%rip), %rdi      # 0x61f0
xorl %r13d, %r13d
movl $0x298, %edx            # imm = 0x298
xorl %esi, %esi
callq 0x1130
leaq 0x296d(%rip), %rdi      # 0x4088
callq 0x1030
movq %rax, %r14
leaq 0x296b(%rip), %rdi      # 0x4095
callq 0x1030
movq %rax, %r15
leaq 0x2968(%rip), %rdi      # 0x40a1
callq 0x1030
movq %rax, %r12
leaq 0x2965(%rip), %rdi      # 0x40ad
callq 0x1030
movq %rax, %rbx
testq %r14, %r14
je 0x1afe
testq %r15, %r15
je 0x1afe
testq %r12, %r12
je 0x1afe
movq %r14, %rdi
callq 0x1210
movl %eax, %r14d
movq %r15, %rdi
callq 0x1210
movl %eax, %r13d
movq %r12, %rdi
callq 0x1210
movl %eax, %r15d
testq %rbx, %rbx
je 0x17cb
movl $0x400, %esi            # imm = 0x400
movq %rbx, %rdi
callq 0x1140
movb -0x1(%rbx,%rax), %bpl
movq %rbx, %rdi
callq 0x1210
movl %eax, %ebx
xorl %eax, %eax
cmpb $0x4d, %bpl
movl $0x14, %edx
cmovnel %eax, %edx
cmpb $0x4b, %bpl
movl $0xa, %ecx
cmovnel %edx, %ecx
shll %cl, %ebx
jmp 0x17d9
movl $0x8000000, %ebx        # imm = 0x8000000
testl %r13d, %r13d
je 0x1b35
cmpl $0x10001, %r15d         # imm = 0x10001
jae 0x1b5f
cmpl %r15d, %r13d
jae 0x1b67
leal -0x1(%r15), %eax
bsrl %eax, %ecx
xorl $-0x20, %ecx
addl $0x21, %ecx
testl %eax, %eax
cmovel %eax, %ecx
movl %r14d, 0x49e8(%rip)     # 0x61f0
movl %r13d, 0x49e5(%rip)     # 0x61f4
movl %r13d, 0x492a(%rip)     # 0x6140
movl %r15d, 0x49db(%rip)     # 0x61f8
movl %r15d, 0x4920(%rip)     # 0x6144
movl %ecx, 0x49d2(%rip)      # 0x61fc
movq %rbx, 0x18(%rsp)
movq %rbx, 0x4b0a(%rip)      # 0x6340
movl $0x0, 0x4a78(%rip)      # 0x62b8
leaq 0x4a49(%rip), %rdi      # 0x6290
movl $0x1, %esi
xorl %edx, %edx
callq 0x11d0
leaq 0x4a66(%rip), %rdi      # 0x62c0
movl $0x1, %esi
xorl %edx, %edx
callq 0x11d0
leaq 0x4a73(%rip), %rdi      # 0x62e0
movl $0x1, %esi
xorl %edx, %edx
callq 0x11d0
leaq 0x4a80(%rip), %rdi      # 0x6300
movl $0x1, %esi
xorl %edx, %edx
callq 0x11d0
callq 0x1220
movslq %eax, %rdx
movq %rdx, %rax
negq %rax
leaq 0x488f(%rip), %r12      # 0x6130
andq %rax, %r12
leaq 0x4c0d(%rip), %rcx      # 0x64b8
subq %r12, %rcx
andq %rcx, %rax
movq %rdx, 0x30(%rsp)
leaq (%rax,%rdx), %rbx
cmpq %rcx, %rax
cmoveq %rcx, %rbx
movl %r15d, %eax
movq %rbx, %rdi
movq %rax, 0x28(%rsp)
imulq %rax, %rdi
movl %r14d, %esi
leaq 0x14(%rsp), %r14
movl %esi, 0xc(%rsp)
xorl %edx, %edx
movq %r14, %rcx
callq 0x1b6f
movl %r13d, 0x10(%rsp)
movl %r13d, %r15d
movq %rbx, %r13
imulq %r15, %r13
movq %rax, 0x20(%rsp)
leaq (%rax,%r13), %rdi
movq %rbx, %rsi
callq 0x11c0
movl (%r14), %ebp
xorl %edi, %edi
movq %rbx, %rsi
movl $0x3, %edx
movl $0x22, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
xorl %r9d, %r9d
callq 0x10e0
testq %rax, %rax
je 0x199c
cmpq $0x8, %rbx
jae 0x194e
movq %r12, %rdi
movq %rbx, %rsi
movl $0x3, %edx
movl $0x11, %ecx
movl %ebp, %r8d
movq %r13, %r9
callq 0x10e0
jmp 0x199c
movq %rax, %r14
movl %ebp, %r8d
movq %rbx, %rbp
shrq $0x3, %rbp
xorl %eax, %eax
movq (%r12,%rax,8), %rcx
movq %rcx, (%r14,%rax,8)
incq %rax
cmpq %rax, %rbp
jne 0x195d
movq %r12, %rdi
movq %rbx, %rsi
movl $0x3, %edx
movl $0x11, %ecx
movq %r13, %r9
callq 0x10e0
testq %rax, %rax
je 0x199c
xorl %ecx, %ecx
movq (%r14,%rcx,8), %rdx
movq %rdx, (%rax,%rcx,8)
incq %rcx
cmpq %rcx, %rbp
jne 0x198c
movl 0x14(%rsp), %eax
movl %eax, 0x497a(%rip)      # 0x6320
movq %r12, 0x4983(%rip)      # 0x6330
movq %rbx, 0x4974(%rip)      # 0x6328
movq 0x20(%rsp), %rax
movq %rax, 0x4978(%rip)      # 0x6338
movq 0x18(%rsp), %rbx
movq 0x28(%rsp), %rdi
imulq %rbx, %rdi
xorl %r14d, %r14d
movl $0x1, %ebp
movl 0xc(%rsp), %esi
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x1b6f
movq %rax, 0x495b(%rip)      # 0x6348
movl 0x4805(%rip), %ecx      # 0x61f8
cmpl $0x2, %ecx
movl 0x10(%rsp), %r12d
jl 0x1a3c
leaq 0x495c(%rip), %rbx      # 0x6360
movl 0x47ea(%rip), %esi      # 0x61f4
addl %ebp, %esi
cmpl %ecx, %esi
cmovll %r14d, %ecx
subl %ecx, %esi
movq %rbx, %rdi
callq 0x1d0c
movq %rax, 0x40(%rbx)
addl %ebp, %ebp
movl 0x47d0(%rip), %ecx      # 0x61f8
addq $0x8, %rbx
cmpl %ecx, %ebp
jl 0x1a04
movq 0x4911(%rip), %rax      # 0x6348
movq 0x18(%rsp), %rbx
imulq %rbx, %r15
movq 0x30(%rsp), %rcx
addq %rcx, %r15
addq %rax, %r15
movq %r15, 0x48fe(%rip)      # 0x6350
movq %r15, 0x48ff(%rip)      # 0x6358
subq %rcx, %rbx
movq %r15, %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x1eb0
movq %rax, 0x4a10(%rip)      # 0x6480
leaq 0x4819(%rip), %rdi      # 0x6290
xorl %esi, %esi
callq 0x1d0c
movq %rax, 0x482b(%rip)      # 0x62b0
testl %r12d, %r12d
jne 0x1a96
leaq 0x47ff(%rip), %rdi      # 0x6290
callq 0x1160
leaq 0x4863(%rip), %rdi      # 0x6300
callq 0x1160
callq 0x1d54
cmpl $0x1, 0x474a(%rip)      # 0x61f8
je 0x1aef
movl 0x473e(%rip), %eax      # 0x61f4
testl %eax, %eax
jne 0x1ac8
movq 0x48df(%rip), %rcx      # 0x63a0
movq $0x1, (%rcx)
cmpq $0x0, 0x4890(%rip)      # 0x6360
je 0x1ac8
testl %eax, %eax
je 0x1ae4
movq 0x48c3(%rip), %rax      # 0x63a0
movq $0x1, (%rax)
movq $0x0, 0x4871(%rip) # 0x6360
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x10a0
movl %eax, %r14d
movq 0x44eb(%rip), %rax      # 0x5ff8
movq (%rax), %rcx
leaq 0x25b0(%rip), %rdi      # 0x40c7
movl $0x61, %esi
movl $0x1, %edx
callq 0x1240
movl $0x1, %r15d
testq %rbx, %rbx
jne 0x1791
movq 0x44bc(%rip), %rax      # 0x5ff8
movq (%rax), %rdi
leaq 0x25e3(%rip), %rsi      # 0x4129
xorl %r13d, %r13d
movl $0x8000000, %ebx        # imm = 0x8000000
movl $0x8000000, %edx        # imm = 0x8000000
xorl %eax, %eax
callq 0x1180
jmp 0x17d9
movl %r15d, %edi
callq 0x1293
movl %r13d, %edi
callq 0x1270