// File: /workspace/github_c_makefile_star2_O2/sharpyfox[P]citrusleaf-client/src/cl_shm.c
// Function: citrusleaf_use_shm
int citrusleaf_use_shm(int num_nodes, key_t key) 
{
	if (g_shm_initiated) {
		return SHM_OK;
	}

	g_max_nodes = (num_nodes > 0)? num_nodes : DEFAULT_NUM_NODES_FOR_SHM;
	
	if (0==key) {
		key = DEFAULT_SHM_KEY;
	}

	/* Time to use shared memory */
	g_shared_memory = true;
	
	cf_debug("Shared memory key is %d",key);

	if (key == -1) {
		return SHM_ERROR;
	}
	void * shm_pt = (void*)0;
	
	/* The size of the shared memory is the size of the shm structure*/
	g_shm_info.shm_sz = sizeof(shm) + sizeof(shm_ninfo) * g_max_nodes;
	
	/* Fix the update thread end condition to false and update period to 1*/
	g_shm_info.update_thread_end_cond = false;
	g_shm_info.update_period = 1;
	
	// Checking if the value of kernel.shmmax is less than g_shm_info.shm_sz
	// In that case we should exit specifying the error
	size_t shm_max;
	FILE *f = fopen(SHMMAX_SYS_FILE, "r");

	if (!f) {
		cf_error("Failed to open file: %s", SHMMAX_SYS_FILE);
		return SHM_ERROR;
	}

	if (fscanf(f, "%zu", &shm_max) != 1) {
		cf_error("Failed to read shmmax from file: %s", SHMMAX_SYS_FILE);
		fclose(f);
		return SHM_ERROR;
	}

	fclose(f);

	if(shm_max < g_shm_info.shm_sz) {
		cf_error("Shared memory size %zu exceeds system max %zu.", g_shm_info.shm_sz, shm_max);
		cf_error("You can increase shared memory size by: sysctl -w kernel.shmmax=<new_size>");
		return SHM_ERROR;
	}
	
	// First try to exclusively create a shared memory, for this only one process will succeed.
 	// others will fail giving an errno of EEXIST
	 if((g_shm_info.id = shmget(key,g_shm_info.shm_sz,IPC_CREAT | IPC_EXCL | 0666))<0) {
		// if there are any other errors apart from EEXIST, we can return gracefully 
		if(errno != EEXIST) {
			cf_error("Error in getting shared memory exclusively: %s", strerror(errno));
			return SHM_ERROR;	
		}
		else {
			// For all the processes that failed to create with EEXIST,
			// we try to get the shared memory again so that we
			// have a valid shmid
			if((g_shm_info.id = shmget(key,g_shm_info.shm_sz,IPC_CREAT | 0666))<0) {
				cf_error("Error in attaching to shared memory: %s", strerror(errno));
				return SHM_ERROR;
			}
	
			// Attach to the shared memory
			if((shm_pt = shmat(g_shm_info.id,NULL,0))==(void*)-1) {
				cf_error("Error in attaching to shared memory: %s pid: %d", strerror(errno), getpid());
				return SHM_ERROR;
			}
		
			// The shared memory base pointer
			g_shm_pt = (shm*)shm_pt;
		}
	}
	else {
		// The process who got the shared memory in the exclusive case
		cf_debug("Succeeded in creating shm : pid %d shmid %d", getpid(), g_shm_info.id);

		// Attach to the shared memory
		if ((shm_pt = shmat(g_shm_info.id,NULL,0))==(void*)-1) {
			cf_error("Error in attaching to shared memory: %s pid: %d", strerror(errno), getpid());
			return SHM_ERROR;
		}

		// The shared memory base pointer
		g_shm_pt = (shm*)shm_pt;
		memset(g_shm_pt,0,g_shm_info.shm_sz);

		// If you are the one who created the shared memory, only you can initialize the mutexes.
		// Seems fair!
		// because if we let everyone initialize the mutexes, we are in deep deep trouble
		pthread_mutexattr_t attr;
		pthread_mutexattr_init (&attr);
		pthread_mutexattr_setpshared (&attr, PTHREAD_PROCESS_SHARED);
		pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP);
		if(pthread_mutex_init (&(g_shm_pt->shm_lock), &attr)!=0) {
			cf_error("Mutex init failed pid %d",getpid());
			pthread_mutexattr_destroy(&attr);
			return SHM_ERROR;
		}
		pthread_mutexattr_destroy(&attr);
	}
	pthread_create(&g_shm_update_thr, 0, cl_shm_updater_fn, 0);

	// all well? return aok!
	g_shm_initiated = true;
	return SHM_OK;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x18, %rsp
xorl %ebx, %ebx
cmpb $0x0, 0xd0f1(%rip)      # 0x175d0
jne 0xa64f
testl %edi, %edi
pushq $0x40
popq %rax
cmovgl %edi, %eax
leaq 0xadd4(%rip), %r15      # 0x152c8
testl %esi, %esi
movl $0xdb35a5f, %ebx        # imm = 0xDB35A5F
movl %eax, 0xd0d3(%rip)      # 0x175d4
leaq 0xd0d0(%rip), %rax      # 0x175d8
cmovnel %esi, %ebx
movb $0x1, (%rax)
movl (%r15), %eax
cmpl $0x3, %eax
jl 0xa530
leaq 0xadb3(%rip), %rax      # 0x152d0
leaq 0x4e46(%rip), %rsi      # 0xf36a
movq (%rax), %rcx
pushq $0x3
popq %rdi
movl %ebx, %edx
xorl %eax, %eax
callq *%rcx
cmpl $-0x1, %ebx
je 0xa64c
movslq 0xd094(%rip), %rax      # 0x175d4
leaq 0x4e3b(%rip), %rdi      # 0xf382
leaq 0x4417(%rip), %rsi      # 0xe965
movb $0x0, 0xd09b(%rip)      # 0x175f0
movb $0x1, 0xd09c(%rip)      # 0x175f8
imulq $0x2f9068, %rax, %rax   # imm = 0x2F9068
addq $0x38, %rax
movq %rax, 0xd07a(%rip)      # 0x175e8
callq 0x22a0
testq %rax, %rax
je 0xa5f7
movq %rax, %r14
movq %rax, %rdi
leaq 0x43b5(%rip), %rsi      # 0xe93a
leaq 0x10(%rsp), %rdx
xorl %eax, %eax
callq 0x2500
cmpl $0x1, %eax
jne 0xa620
movq %r14, %rdi
callq 0x2250
movq 0x10(%rsp), %rcx
movq 0xd03a(%rip), %rdx      # 0x175e8
cmpq %rdx, %rcx
jae 0xa65c
cmpl $0x0, (%r15)
js 0xa5d5
leaq 0xad0c(%rip), %rax      # 0x152d0
leaq 0x4e0b(%rip), %rsi      # 0xf3d6
xorl %edi, %edi
movq (%rax), %r8
xorl %eax, %eax
callq *%r8
pushq $-0x1
popq %rbx
cmpl $0x0, (%r15)
js 0xa64f
leaq 0xaceb(%rip), %rax      # 0x152d0
leaq 0x4e19(%rip), %rsi      # 0xf405
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0xa64f
pushq $-0x1
popq %rbx
cmpl $0x0, (%r15)
js 0xa64f
leaq 0xacc9(%rip), %rax      # 0x152d0
leaq 0x4d8c(%rip), %rsi      # 0xf39a
leaq 0x4d6d(%rip), %rdx      # 0xf382
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0xa64f
cmpl $0x0, (%r15)
js 0xa644
leaq 0xaca3(%rip), %rax      # 0x152d0
leaq 0x4d7e(%rip), %rsi      # 0xf3b2
leaq 0x4d47(%rip), %rdx      # 0xf382
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
movq %r14, %rdi
callq 0x2250
pushq $-0x1
popq %rbx
movl %ebx, %eax
addq $0x18, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq %rdx, %rsi
movl %ebx, %edi
movl $0x7b6, %edx            # imm = 0x7B6
callq 0x2160
testl %eax, %eax
movl %eax, 0xcf6d(%rip)      # 0x175e0
js 0xa74b
movl (%r15), %ecx
cmpl $0x3, %ecx
jl 0xa6ac
leaq 0xac48(%rip), %rax      # 0x152d0
movq (%rax), %rbx
callq 0x23a0
movl 0xcf4a(%rip), %ecx      # 0x175e0
leaq 0x4e3a(%rip), %rsi      # 0xf4d7
pushq $0x3
popq %rdi
movl %eax, %edx
xorl %eax, %eax
callq *%rbx
movl 0xcf34(%rip), %eax      # 0x175e0
movl %eax, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2330
cmpq $-0x1, %rax
je 0xa79d
movq 0xcf20(%rip), %rdx      # 0x175e8
movq %rax, %rdi
xorl %esi, %esi
movq %rax, 0xcf2c(%rip)      # 0x17600
callq 0x2140
leaq 0xc(%rsp), %rbx
movq %rbx, %rdi
callq 0x2050
pushq $0x1
popq %rbp
movq %rbx, %rdi
movl %ebp, %esi
callq 0x2300
movq %rbx, %rdi
movl %ebp, %esi
callq 0x21e0
movq 0xcefc(%rip), %rdi      # 0x17600
movq %rbx, %rsi
addq $0x10, %rdi
callq 0x2400
testl %eax, %eax
je 0xa812
cmpl $0x0, (%r15)
js 0xa73c
leaq 0xabab(%rip), %rax      # 0x152d0
movq (%rax), %rbx
callq 0x23a0
movl %eax, %edx
leaq 0x4dcd(%rip), %rsi      # 0xf503
xorl %edi, %edi
xorl %eax, %eax
callq *%rbx
leaq 0xc(%rsp), %rdi
callq 0x23f0
jmp 0xa64c
callq 0x2040
movl (%rax), %edi
cmpl $0x11, %edi
jne 0xa7e0
movq 0xce86(%rip), %rsi      # 0x175e8
movl %ebx, %edi
movl $0x3b6, %edx            # imm = 0x3B6
movq %rax, %r14
callq 0x2160
testl %eax, %eax
movl %eax, 0xce67(%rip)      # 0x175e0
js 0xa841
movl %eax, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2330
cmpq $-0x1, %rax
je 0xa876
movq %rax, 0xce65(%rip)      # 0x17600
jmp 0xa81c
pushq $-0x1
popq %rbx
cmpl $0x0, (%r15)
js 0xa64f
leaq 0xab1f(%rip), %rax      # 0x152d0
movq (%rax), %r15
callq 0x2040
movl (%rax), %edi
callq 0x20b0
movq %rax, %r14
callq 0x23a0
movl %eax, %ecx
leaq 0x4cd6(%rip), %rsi      # 0xf4a7
xorl %edi, %edi
movq %r14, %rdx
xorl %eax, %eax
callq *%r15
jmp 0xa64f
pushq $-0x1
popq %rbx
cmpl $0x0, (%r15)
js 0xa64f
leaq 0xaadc(%rip), %rax      # 0x152d0
movq (%rax), %r14
callq 0x20b0
movq %rax, %rdx
leaq 0x4c4a(%rip), %rsi      # 0xf450
xorl %edi, %edi
xorl %eax, %eax
callq *%r14
jmp 0xa64f
leaq 0xc(%rsp), %rdi
callq 0x23f0
leaq 0x72(%rip), %rdx        # 0xa895
leaq 0xcdde(%rip), %rdi      # 0x17608
xorl %esi, %esi
xorl %ecx, %ecx
xorl %ebx, %ebx
callq 0x24e0
movb $0x1, 0xcd94(%rip)      # 0x175d0
jmp 0xa64f
pushq $-0x1
popq %rbx
cmpl $0x0, (%r15)
js 0xa64f
leaq 0xaa7b(%rip), %rax      # 0x152d0
movq (%rax), %r15
movl (%r14), %edi
callq 0x20b0
movq %rax, %rdx
leaq 0x4c15(%rip), %rsi      # 0xf47f
xorl %edi, %edi
xorl %eax, %eax
callq *%r15
jmp 0xa64f
pushq $-0x1
popq %rbx
cmpl $0x0, (%r15)
js 0xa64f
leaq 0xaa46(%rip), %rax      # 0x152d0
movq (%rax), %r15
movl (%r14), %edi
jmp 0xa7bb