// File: dadocolussi[P]gdc-circular_queue/src/gdc_circular_queue_factory.c
// Function: gdc_circular_queue_map_shared
gdc_circular_queue*
gdc_circular_queue_map_shared(const char *name)
{
	// Ignore size. The true size is defined in the mapped memory.
	long page_size = sysconf(_SC_PAGESIZE);
	if (page_size == -1)
	{
		return NULL;
	}
	assert(page_size > 0);
	
	int fd = shm_open(name, O_RDWR, S_IRWXU);
	if (fd == -1)
	{
		return NULL;
	}
	
	struct stat st;
	int status = fstat(fd, &st);
	if (status != 0 || st.st_size <= page_size)
	{
		// Not fully initialized yet.
		close(fd);
		return NULL;
	}
	
	size_t init_size = gdc_circular_queue_footprint(0);
	void *p = mmap(
		NULL,
		init_size,
		PROT_READ | PROT_WRITE,
		MAP_SHARED,
		fd,
		0);
	if (p == MAP_FAILED)
	{
		close(fd);
		return NULL;
	}
	
	gdc_circular_queue *q = p;
	atomic_thread_fence(memory_order_acquire);
	size_t capacity = gdc_circular_queue_capacity(q);
	
	if (capacity == 0)
	{
		munmap(p, init_size);
		close(fd);
		errno = EAGAIN;
		return NULL;
	}
	
	size_t footprint = gdc_circular_queue_footprint(capacity);
	
	if (munmap(p, init_size) != 0)
	{
		close(fd);
		return NULL;
	}
	
	p = mmap(
		NULL,
		footprint + capacity,
		PROT_READ | PROT_WRITE,
		MAP_SHARED,
		fd,
		0);
	if (p == MAP_FAILED)
	{
		close(fd);
		return NULL;
	}
	
	q = p;
	void *pp = (char*)p + footprint;
	void *p2 = mmap(
		pp,
		capacity,
		PROT_READ | PROT_WRITE, 
		MAP_SHARED | MAP_FIXED,
		fd,
		page_size);
	if (p2 == MAP_FAILED)
	{
		munmap(p, footprint + capacity);
		close(fd);
		return NULL;
	}
	
	if (close(fd) != 0)
	{
		munmap(p, footprint + capacity);
		close(fd);
		return NULL;
	}
	
	return q;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rdi, -0x10(%rbp)
movl $0x1e, %edi
callq 0xe430
movq %rax, -0x18(%rbp)
cmpq $-0x1, -0x18(%rbp)
jne 0x7c431
movq $0x0, -0x8(%rbp)
jmp 0x7c6df
cmpq $0x0, -0x18(%rbp)
jle 0x7c43a
jmp 0x7c459
leaq 0x4dd7(%rip), %rdi      # 0x81218
leaq 0x4dde(%rip), %rsi      # 0x81226
movl $0xbe, %edx
leaq 0x4df3(%rip), %rcx      # 0x81247
callq 0xe440
movq -0x10(%rbp), %rdi
movl $0x2, %esi
movl $0x1c0, %edx            # imm = 0x1C0
callq 0xeac0
movl %eax, -0x1c(%rbp)
cmpl $-0x1, -0x1c(%rbp)
jne 0x7c482
movq $0x0, -0x8(%rbp)
jmp 0x7c6df
movl -0x1c(%rbp), %edi
leaq -0xb0(%rbp), %rsi
callq 0xeaa0
movl %eax, -0xb4(%rbp)
cmpl $0x0, -0xb4(%rbp)
jne 0x7c4aa
movq -0x80(%rbp), %rax
cmpq -0x18(%rbp), %rax
jg 0x7c4bf
movl -0x1c(%rbp), %edi
callq 0xec60
movq $0x0, -0x8(%rbp)
jmp 0x7c6df
xorl %eax, %eax
movl %eax, %edi
callq 0x7c280
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rsi
movl -0x1c(%rbp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x3, %edx
movl $0x1, %ecx
movq %r9, %rdi
callq 0xeb80
movq %rax, -0xc8(%rbp)
movq $-0x1, %rax
cmpq %rax, -0xc8(%rbp)
jne 0x7c51d
movl -0x1c(%rbp), %edi
callq 0xec60
movq $0x0, -0x8(%rbp)
jmp 0x7c6df
movq -0xc8(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rdi
callq 0x7ba80
movq %rax, -0xd8(%rbp)
cmpq $0x0, -0xd8(%rbp)
jne 0x7c57b
movq -0xc8(%rbp), %rdi
movq -0xc0(%rbp), %rsi
callq 0xe360
movl -0x1c(%rbp), %edi
callq 0xec60
callq 0xe070
movl $0xb, (%rax)
movq $0x0, -0x8(%rbp)
jmp 0x7c6df
movq -0xd8(%rbp), %rdi
callq 0x7c280
movq %rax, -0xe0(%rbp)
movq -0xc8(%rbp), %rdi
movq -0xc0(%rbp), %rsi
callq 0xe360
cmpl $0x0, %eax
je 0x7c5bb
movl -0x1c(%rbp), %edi
callq 0xec60
movq $0x0, -0x8(%rbp)
jmp 0x7c6df
movq -0xe0(%rbp), %rsi
addq -0xd8(%rbp), %rsi
movl -0x1c(%rbp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x3, %edx
movl $0x1, %ecx
movq %r9, %rdi
callq 0xeb80
movq %rax, -0xc8(%rbp)
movq $-0x1, %rax
cmpq %rax, -0xc8(%rbp)
jne 0x7c610
movl -0x1c(%rbp), %edi
callq 0xec60
movq $0x0, -0x8(%rbp)
jmp 0x7c6df
movq -0xc8(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0xc8(%rbp), %rax
addq -0xe0(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rdi
movq -0xd8(%rbp), %rsi
movl -0x1c(%rbp), %r8d
movq -0x18(%rbp), %r9
movl $0x3, %edx
movl $0x11, %ecx
callq 0xeb80
movq %rax, -0xf0(%rbp)
movq $-0x1, %rax
cmpq %rax, -0xf0(%rbp)
jne 0x7c69b
movq -0xc8(%rbp), %rdi
movq -0xe0(%rbp), %rsi
addq -0xd8(%rbp), %rsi
callq 0xe360
movl -0x1c(%rbp), %edi
callq 0xec60
movq $0x0, -0x8(%rbp)
jmp 0x7c6df
movl -0x1c(%rbp), %edi
callq 0xec60
cmpl $0x0, %eax
je 0x7c6d4
movq -0xc8(%rbp), %rdi
movq -0xe0(%rbp), %rsi
addq -0xd8(%rbp), %rsi
callq 0xe360
movl -0x1c(%rbp), %edi
callq 0xec60
movq $0x0, -0x8(%rbp)
jmp 0x7c6df
movq -0xd0(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xf0, %rsp
popq %rbp
retq
nopl (%rax)