// File: /workspace/github_c_makefile_star2_O3/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 %r15
pushq %r14
pushq %rbx
subq $0x10, %rsp
xorl %ebx, %ebx
cmpb $0x0, 0xd70a(%rip)      # 0x185d0
jne 0xb044
testl %edi, %edi
movl $0x40, %eax
leaq 0xb3ee(%rip), %r15      # 0x162c8
movl $0xdb35a5f, %ebx        # imm = 0xDB35A5F
cmovgl %edi, %eax
testl %esi, %esi
movl %eax, 0xd6ea(%rip)      # 0x185d4
leaq 0xd6e7(%rip), %rax      # 0x185d8
cmovnel %esi, %ebx
movb $0x1, (%rax)
movl (%r15), %eax
cmpl $0x3, %eax
jl 0xaf1b
leaq 0xb3ca(%rip), %rax      # 0x162d0
leaq 0x544d(%rip), %rsi      # 0x1035a
movl $0x3, %edi
movl %ebx, %edx
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
cmpl $-0x1, %ebx
je 0xb03f
movslq 0xd6a9(%rip), %rax      # 0x185d4
leaq 0x5440(%rip), %rdi      # 0x10372
leaq 0x4a2c(%rip), %rsi      # 0xf965
movb $0x0, 0xd6b0(%rip)      # 0x185f0
movb $0x1, 0xd6b1(%rip)      # 0x185f8
imulq $0x2f9068, %rax, %rax   # imm = 0x2F9068
addq $0x38, %rax
movq %rax, 0xd68f(%rip)      # 0x185e8
callq 0x22a0
testq %rax, %rax
je 0xafe8
movq %rax, %r14
movq %rax, %rdi
leaq 0x49c6(%rip), %rsi      # 0xf93a
leaq 0x8(%rsp), %rdx
xorl %eax, %eax
callq 0x2500
cmpl $0x1, %eax
jne 0xb013
movq %r14, %rdi
callq 0x2250
movq 0x8(%rsp), %rcx
movq 0xd64b(%rip), %rdx      # 0x185e8
cmpq %rdx, %rcx
jae 0xb050
cmpl $0x0, (%r15)
js 0xafc4
leaq 0xb31d(%rip), %rax      # 0x162d0
leaq 0x540c(%rip), %rsi      # 0x103c6
xorl %edi, %edi
movq (%rax), %r8
xorl %eax, %eax
callq *%r8
cmpl $0x0, (%r15)
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
js 0xb044
leaq 0xb2fa(%rip), %rax      # 0x162d0
leaq 0x5418(%rip), %rsi      # 0x103f5
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0xb044
cmpl $0x0, (%r15)
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
js 0xb044
leaq 0xb2d6(%rip), %rax      # 0x162d0
leaq 0x5389(%rip), %rsi      # 0x1038a
leaq 0x536a(%rip), %rdx      # 0x10372
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
jmp 0xb044
cmpl $0x0, (%r15)
js 0xb037
leaq 0xb2b0(%rip), %rax      # 0x162d0
leaq 0x537b(%rip), %rsi      # 0x103a2
leaq 0x5344(%rip), %rdx      # 0x10372
xorl %edi, %edi
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
movq %r14, %rdi
callq 0x2250
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movl %ebx, %eax
addq $0x10, %rsp
popq %rbx
popq %r14
popq %r15
retq
movq %rdx, %rsi
movl %ebx, %edi
movl $0x7b6, %edx            # imm = 0x7B6
callq 0x2160
testl %eax, %eax
movl %eax, 0xd579(%rip)      # 0x185e0
js 0xb144
movl (%r15), %ecx
cmpl $0x3, %ecx
jl 0xb0a2
leaq 0xb254(%rip), %rax      # 0x162d0
movq (%rax), %rbx
callq 0x23a0
movl 0xd556(%rip), %ecx      # 0x185e0
movl %eax, %edx
leaq 0x5434(%rip), %rsi      # 0x104c7
movl $0x3, %edi
xorl %eax, %eax
callq *%rbx
movl 0xd53e(%rip), %eax      # 0x185e0
movl %eax, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2330
cmpq $-0x1, %rax
je 0xb199
movq 0xd52a(%rip), %rdx      # 0x185e8
movq %rax, %rdi
xorl %esi, %esi
movq %rax, 0xd536(%rip)      # 0x18600
callq 0x2140
leaq 0x4(%rsp), %rbx
movq %rbx, %rdi
callq 0x2050
movq %rbx, %rdi
movl $0x1, %esi
callq 0x2300
movq %rbx, %rdi
movl $0x1, %esi
callq 0x21e0
movq 0xd503(%rip), %rdi      # 0x18600
movq %rbx, %rsi
addq $0x10, %rdi
callq 0x2400
testl %eax, %eax
je 0xb212
cmpl $0x0, (%r15)
js 0xb135
leaq 0xb1b2(%rip), %rax      # 0x162d0
movq (%rax), %rbx
callq 0x23a0
movl %eax, %edx
leaq 0x53c4(%rip), %rsi      # 0x104f3
xorl %edi, %edi
xorl %eax, %eax
callq *%rbx
leaq 0x4(%rsp), %rdi
callq 0x23f0
jmp 0xb03f
callq 0x2040
movl (%rax), %edi
cmpl $0x11, %edi
jne 0xb1de
movq 0xd48d(%rip), %rsi      # 0x185e8
movl %ebx, %edi
movl $0x3b6, %edx            # imm = 0x3B6
movq %rax, %r14
callq 0x2160
testl %eax, %eax
movl %eax, 0xd46e(%rip)      # 0x185e0
js 0xb241
movl %eax, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2330
cmpq $-0x1, %rax
je 0xb278
movq %rax, 0xd46c(%rip)      # 0x18600
jmp 0xb21c
cmpl $0x0, (%r15)
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
js 0xb044
leaq 0xb121(%rip), %rax      # 0x162d0
movq (%rax), %r15
callq 0x2040
movl (%rax), %edi
callq 0x20b0
movq %rax, %r14
callq 0x23a0
movl %eax, %ecx
leaq 0x52c8(%rip), %rsi      # 0x10497
xorl %edi, %edi
movq %r14, %rdx
xorl %eax, %eax
callq *%r15
jmp 0xb044
cmpl $0x0, (%r15)
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
js 0xb044
leaq 0xb0dc(%rip), %rax      # 0x162d0
movq (%rax), %r14
callq 0x20b0
movq %rax, %rdx
leaq 0x523a(%rip), %rsi      # 0x10440
xorl %edi, %edi
xorl %eax, %eax
callq *%r14
jmp 0xb044
leaq 0x4(%rsp), %rdi
callq 0x23f0
leaq 0x76(%rip), %rdx        # 0xb299
leaq 0xd3de(%rip), %rdi      # 0x18608
xorl %esi, %esi
xorl %ecx, %ecx
xorl %ebx, %ebx
callq 0x24e0
movb $0x1, 0xd394(%rip)      # 0x185d0
jmp 0xb044
cmpl $0x0, (%r15)
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
js 0xb044
leaq 0xb079(%rip), %rax      # 0x162d0
movq (%rax), %r15
movl (%r14), %edi
callq 0x20b0
movq %rax, %rdx
leaq 0x5203(%rip), %rsi      # 0x1046f
xorl %edi, %edi
xorl %eax, %eax
callq *%r15
jmp 0xb044
cmpl $0x0, (%r15)
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
js 0xb044
leaq 0xb042(%rip), %rax      # 0x162d0
movq (%rax), %r15
movl (%r14), %edi
jmp 0xb1b9