// File: /workspace/github_c_makefile_star2_O1/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, 0xe3de(%rip)      # 0x195d0
jne 0xb370
testl %edi, %edi
movl $0x40, %eax
cmovgl %edi, %eax
movl %eax, 0xe3cc(%rip)      # 0x195d4
testl %esi, %esi
movl $0xdb35a5f, %ebx        # imm = 0xDB35A5F
cmovnel %esi, %ebx
leaq 0xe3bf(%rip), %rax      # 0x195d8
movb $0x1, (%rax)
leaq 0xc0a5(%rip), %r15      # 0x172c8
movl (%r15), %eax
cmpl $0x3, %eax
jl 0xb247
leaq 0xc09e(%rip), %rax      # 0x172d0
movq (%rax), %rcx
leaq 0x60fe(%rip), %rsi      # 0x1133a
movl $0x3, %edi
movl %ebx, %edx
xorl %eax, %eax
callq *%rcx
cmpl $-0x1, %ebx
je 0xb36b
movslq 0xe37d(%rip), %rax      # 0x195d4
imulq $0x2f9068, %rax, %rax   # imm = 0x2F9068
addq $0x38, %rax
movq %rax, 0xe37f(%rip)      # 0x195e8
movb $0x0, 0xe380(%rip)      # 0x195f0
movb $0x1, 0xe381(%rip)      # 0x195f8
leaq 0x60d4(%rip), %rdi      # 0x11352
leaq 0x56c2(%rip), %rsi      # 0x10947
callq 0x22a0
testq %rax, %rax
je 0xb314
movq %rax, %r14
leaq 0x567f(%rip), %rsi      # 0x1091c
leaq 0x8(%rsp), %rdx
movq %rax, %rdi
xorl %eax, %eax
callq 0x2500
cmpl $0x1, %eax
jne 0xb33f
movq %r14, %rdi
callq 0x2250
movq 0x8(%rsp), %rcx
movq 0xe31f(%rip), %rdx      # 0x195e8
cmpq %rdx, %rcx
jae 0xb37c
cmpl $0x0, (%r15)
js 0xb2f0
leaq 0xbff1(%rip), %rax      # 0x172d0
movq (%rax), %r8
leaq 0x60bd(%rip), %rsi      # 0x113a6
xorl %edi, %edi
xorl %eax, %eax
callq *%r8
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
cmpl $0x0, (%r15)
js 0xb370
leaq 0xbfce(%rip), %rax      # 0x172d0
movq (%rax), %rcx
leaq 0x60c9(%rip), %rsi      # 0x113d5
xorl %edi, %edi
xorl %eax, %eax
callq *%rcx
jmp 0xb370
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
cmpl $0x0, (%r15)
js 0xb370
leaq 0xbfaa(%rip), %rax      # 0x172d0
movq (%rax), %rcx
leaq 0x603a(%rip), %rsi      # 0x1136a
leaq 0x601b(%rip), %rdx      # 0x11352
xorl %edi, %edi
xorl %eax, %eax
callq *%rcx
jmp 0xb370
cmpl $0x0, (%r15)
js 0xb363
leaq 0xbf84(%rip), %rax      # 0x172d0
movq (%rax), %rcx
leaq 0x602c(%rip), %rsi      # 0x11382
leaq 0x5ff5(%rip), %rdx      # 0x11352
xorl %edi, %edi
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
movl %ebx, %edi
movq %rdx, %rsi
movl $0x7b6, %edx            # imm = 0x7B6
callq 0x2160
movl %eax, 0xe24f(%rip)      # 0x195e0
testl %eax, %eax
js 0xb47e
movl (%r15), %eax
cmpl $0x3, %eax
jl 0xb3c8
leaq 0xbf28(%rip), %rax      # 0x172d0
movq (%rax), %rbx
callq 0x23a0
movl 0xe22a(%rip), %ecx      # 0x195e0
leaq 0x60ea(%rip), %rsi      # 0x114a7
movl $0x3, %edi
movl %eax, %edx
xorl %eax, %eax
callq *%rbx
movl 0xe212(%rip), %edi      # 0x195e0
xorl %esi, %esi
xorl %edx, %edx
callq 0x2330
cmpq $-0x1, %rax
je 0xb4d3
movq %rax, 0xe218(%rip)      # 0x19600
movq 0xe1f9(%rip), %rdx      # 0x195e8
movq %rax, %rdi
xorl %esi, %esi
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 0xe1d9(%rip), %rdi      # 0x19600
addq $0x10, %rdi
movq %rbx, %rsi
callq 0x2400
testl %eax, %eax
je 0xb54c
movl %eax, %ebx
cmpl $0x0, (%r15)
js 0xb462
leaq 0xbe86(%rip), %rax      # 0x172d0
movq (%rax), %r14
callq 0x23a0
leaq 0x607a(%rip), %rsi      # 0x114d3
xorl %edi, %edi
movl %eax, %edx
xorl %eax, %eax
callq *%r14
leaq 0x4(%rsp), %rdi
callq 0x23f0
testl %ebx, %ebx
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
jne 0xb370
jmp 0xb556
callq 0x2040
movl (%rax), %edi
cmpl $0x11, %edi
jne 0xb518
movq %rax, %r14
movq 0xe150(%rip), %rsi      # 0x195e8
movl %ebx, %edi
movl $0x3b6, %edx            # imm = 0x3B6
callq 0x2160
movl %eax, 0xe136(%rip)      # 0x195e0
testl %eax, %eax
js 0xb57b
movl %eax, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2330
cmpq $-0x1, %rax
je 0xb5b2
movq %rax, 0xe132(%rip)      # 0x19600
jmp 0xb556
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
cmpl $0x0, (%r15)
js 0xb370
leaq 0xbde7(%rip), %rax      # 0x172d0
movq (%rax), %r15
callq 0x2040
movl (%rax), %edi
callq 0x20b0
movq %rax, %r14
callq 0x23a0
leaq 0x5f70(%rip), %rsi      # 0x11477
xorl %edi, %edi
movq %r14, %rdx
movl %eax, %ecx
xorl %eax, %eax
callq *%r15
jmp 0xb370
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
cmpl $0x0, (%r15)
js 0xb370
leaq 0xbda2(%rip), %rax      # 0x172d0
movq (%rax), %r14
callq 0x20b0
leaq 0x5ee3(%rip), %rsi      # 0x11420
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq *%r14
jmp 0xb370
leaq 0x4(%rsp), %rdi
callq 0x23f0
leaq 0xe0ab(%rip), %rdi      # 0x19608
leaq 0x6f(%rip), %rdx        # 0xb5d3
xorl %ebx, %ebx
xorl %esi, %esi
xorl %ecx, %ecx
callq 0x24e0
movb $0x1, 0xe05a(%rip)      # 0x195d0
jmp 0xb370
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
cmpl $0x0, (%r15)
js 0xb370
leaq 0xbd3f(%rip), %rax      # 0x172d0
movq (%rax), %r15
movl (%r14), %edi
callq 0x20b0
leaq 0x5eac(%rip), %rsi      # 0x1144f
xorl %edi, %edi
movq %rax, %rdx
xorl %eax, %eax
callq *%r15
jmp 0xb370
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
cmpl $0x0, (%r15)
js 0xb370
leaq 0xbd08(%rip), %rax      # 0x172d0
movq (%rax), %r15
movl (%r14), %edi
jmp 0xb4f3