// File: /workspace/github_c_makefile_star2_O0/umbrant[P]Non-blocking-Buffers/nbb.c
// Function: nbb_insert_item
int nbb_insert_item(int channel_id, const void* ptr_to_item, size_t size)
{
  assert(channel_id >= 0 && channel_id < SERVICE_MAX_CHANNELS);
  assert(ptr_to_item != NULL && size >= 0);

	struct buffer *buf = channel_list[channel_id].write;
	unsigned char *data_buf = channel_list[channel_id].write_data;

  unsigned short temp_ac = buf->ack_counter;

  assert(channel_id >= 0 && channel_id < SERVICE_MAX_CHANNELS);
  assert(ptr_to_item != NULL && size >= 0);

  if (buf->last_update_counter - temp_ac == 2 * BUFFER_SIZE) {
    return BUFFER_FULL;
  }

  if (buf->last_update_counter - temp_ac == (2 * BUFFER_SIZE) - 1) {
    return BUFFER_FULL_CONSUMER_READING;
  }

  // Check if there is space in the data region for new item
  // This works by checking how far the previous item extends,
  // and then if our size will fit in the remaining space
  // 
  // If it doesn't fit at the end, check at the head of the list too.
  struct channel_item* prev_item = 
				&(buf->items[(((buf->last_update_counter/2)-1)%BUFFER_SIZE)]);

	int item_offset;

	if(buf->last_update_counter == 0) {
		item_offset = 0;
	}
	else if((prev_item->offset+prev_item->size+size) <  buf->data_size) {
		item_offset = prev_item->offset + prev_item->size;
	}
	// Check if there's space at the head of the list for our item instead
	// This is done by checking the offset of the 
	// oldest unread item (at the ack counter)
	else if(buf->items[((buf->last_ack_counter)/2)%BUFFER_SIZE].offset > size) {
		item_offset = 0;
	} 
	// Couldn't fit at the end or the beginning. Sad.
	else {
		printf("else...\n");
		printf("poff: %d psize: %d size: %zu bsize: %d\n", prev_item->offset,
					prev_item->size, size, buf->data_size);
		return BUFFER_FULL;
	}

	// Update our new item in items[], say that we're writing
  buf->update_counter = buf->last_update_counter + 1;

	// Copy the item into the buffer's shm data region at offset
	memcpy(data_buf+item_offset, ptr_to_item, size);

	// Set the offset based on our above calculations
	buf->items[((buf->last_update_counter/2)%BUFFER_SIZE)].offset = item_offset;
	buf->items[((buf->last_update_counter/2)%BUFFER_SIZE)].size = size;

  // Done writing
  buf->update_counter = buf->last_update_counter + 2;

  // Also increment the recycle counter if it's in step w/ update_counter
  //if(recycle_counter == last_update_counter) {
  //	recycle_counter = update_counter;
  //}

  buf->last_update_counter = buf->update_counter;
 
  if(memcmp(NEW_CONN_NOTIFY_MSG, ptr_to_item, sizeof(NEW_CONN_NOTIFY_MSG))) {
    channel_list[channel_id].write_count += (size - 1); // Excluding '\0'
  }

  return OK;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
cmpl $0x0, -0x8(%rbp)
jl 0x1b01
cmpl $0xf, -0x8(%rbp)
jge 0x1b01
jmp 0x1b20
leaq 0x2e9b(%rip), %rdi      # 0x49a3
leaq 0x269a(%rip), %rsi      # 0x41a9
movl $0x259, %edx            # imm = 0x259
leaq 0x2ebd(%rip), %rcx      # 0x49d8
callq 0x10c0
cmpq $0x0, -0x10(%rbp)
je 0x1b30
cmpq $0x0, -0x18(%rbp)
jb 0x1b30
jmp 0x1b4f
leaq 0x2ed0(%rip), %rdi      # 0x4a07
leaq 0x266b(%rip), %rsi      # 0x41a9
movl $0x25a, %edx            # imm = 0x25A
leaq 0x2e8e(%rip), %rcx      # 0x49d8
callq 0x10c0
movslq -0x8(%rbp), %rcx
leaq 0x55e6(%rip), %rax      # 0x7140
imulq $0x58, %rcx, %rcx
addq %rcx, %rax
movq 0x18(%rax), %rax
movq %rax, -0x20(%rbp)
movslq -0x8(%rbp), %rcx
leaq 0x55cc(%rip), %rax      # 0x7140
imulq $0x58, %rcx, %rcx
addq %rcx, %rax
movq 0x20(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movw (%rax), %ax
movw %ax, -0x2a(%rbp)
cmpl $0x0, -0x8(%rbp)
jl 0x1b9c
cmpl $0xf, -0x8(%rbp)
jge 0x1b9c
jmp 0x1bbb
leaq 0x2e00(%rip), %rdi      # 0x49a3
leaq 0x25ff(%rip), %rsi      # 0x41a9
movl $0x261, %edx            # imm = 0x261
leaq 0x2e22(%rip), %rcx      # 0x49d8
callq 0x10c0
cmpq $0x0, -0x10(%rbp)
je 0x1bcb
cmpq $0x0, -0x18(%rbp)
jb 0x1bcb
jmp 0x1bea
leaq 0x2e35(%rip), %rdi      # 0x4a07
leaq 0x25d0(%rip), %rsi      # 0x41a9
movl $0x262, %edx            # imm = 0x262
leaq 0x2df3(%rip), %rcx      # 0x49d8
callq 0x10c0
movq -0x20(%rbp), %rax
movzwl 0x6(%rax), %eax
movzwl -0x2a(%rbp), %ecx
subl %ecx, %eax
cmpl $0x200, %eax            # imm = 0x200
jne 0x1c0b
movl $0x1, -0x4(%rbp)
jmp 0x1e4f
movq -0x20(%rbp), %rax
movzwl 0x6(%rax), %eax
movzwl -0x2a(%rbp), %ecx
subl %ecx, %eax
cmpl $0x1ff, %eax            # imm = 0x1FF
jne 0x1c2c
movl $0x2, -0x4(%rbp)
jmp 0x1e4f
movq -0x20(%rbp), %rax
addq $0xe, %rax
movq %rax, -0x48(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x6(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
subl $0x1, %eax
movl $0x100, %ecx            # imm = 0x100
cltd
idivl %ecx
movq -0x48(%rbp), %rax
movslq %edx, %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x6(%rax), %eax
cmpl $0x0, %eax
jne 0x1c7e
movl $0x0, -0x3c(%rbp)
jmp 0x1d3e
movq -0x38(%rbp), %rax
movzwl (%rax), %eax
movq -0x38(%rbp), %rcx
movzwl 0x2(%rcx), %ecx
addl %ecx, %eax
cltq
addq -0x18(%rbp), %rax
movq -0x20(%rbp), %rcx
movzwl 0xc(%rcx), %ecx
cmpq %rcx, %rax
jae 0x1cbb
movq -0x38(%rbp), %rax
movzwl (%rax), %eax
movq -0x38(%rbp), %rcx
movzwl 0x2(%rcx), %ecx
addl %ecx, %eax
movl %eax, -0x3c(%rbp)
jmp 0x1d3c
movq -0x20(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x2(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl $0x100, %ecx            # imm = 0x100
cltd
idivl %ecx
movq -0x50(%rbp), %rax
movslq %edx, %rcx
movzwl 0xe(%rax,%rcx,4), %eax
cmpq -0x18(%rbp), %rax
jbe 0x1cf6
movl $0x0, -0x3c(%rbp)
jmp 0x1d3a
leaq 0x2d2b(%rip), %rdi      # 0x4a28
movb $0x0, %al
callq 0x10b0
movq -0x38(%rbp), %rax
movzwl (%rax), %esi
movq -0x38(%rbp), %rax
movzwl 0x2(%rax), %edx
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movzwl 0xc(%rax), %r8d
leaq 0x2d0a(%rip), %rdi      # 0x4a31
movb $0x0, %al
callq 0x10b0
movl $0x1, -0x4(%rbp)
jmp 0x1e4f
jmp 0x1d3c
jmp 0x1d3e
movq -0x20(%rbp), %rax
movzwl 0x6(%rax), %eax
addl $0x1, %eax
movw %ax, %cx
movq -0x20(%rbp), %rax
movw %cx, 0x4(%rax)
movq -0x28(%rbp), %rdi
movslq -0x3c(%rbp), %rax
addq %rax, %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x1130
movl -0x3c(%rbp), %eax
movw %ax, -0x62(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x6(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl $0x100, %ecx            # imm = 0x100
cltd
idivl %ecx
movq -0x70(%rbp), %rax
movl %edx, %ecx
movw -0x62(%rbp), %dx
movslq %ecx, %rcx
movw %dx, 0xe(%rax,%rcx,4)
movq -0x18(%rbp), %rax
movw %ax, -0x52(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x6(%rax), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl $0x100, %ecx            # imm = 0x100
cltd
idivl %ecx
movq -0x60(%rbp), %rax
movl %edx, %ecx
movw -0x52(%rbp), %dx
movslq %ecx, %rcx
movw %dx, 0x10(%rax,%rcx,4)
movq -0x20(%rbp), %rax
movzwl 0x6(%rax), %eax
addl $0x2, %eax
movw %ax, %cx
movq -0x20(%rbp), %rax
movw %cx, 0x4(%rax)
movq -0x20(%rbp), %rax
movw 0x4(%rax), %cx
movq -0x20(%rbp), %rax
movw %cx, 0x6(%rax)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movabsq $0x2a2a515f512a2a, %rcx # imm = 0x2A2A515F512A2A
subq %rcx, %rax
setne %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x1e48
movq -0x18(%rbp), %rdx
subq $0x1, %rdx
movslq -0x8(%rbp), %rcx
leaq 0x5309(%rip), %rax      # 0x7140
imulq $0x58, %rcx, %rcx
addq %rcx, %rax
movslq 0x2c(%rax), %rcx
addq %rdx, %rcx
movl %ecx, 0x2c(%rax)
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax,%rax)