// File: /workspace/github_c_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
cmpl $0xf, %edi
jae 0x1a90
movq %rsi, %r14
testq %rsi, %rsi
je 0x1aaf
movl %edi, %eax
imulq $0x58, %rax, %r13
leaq 0x4808(%rip), %r15      # 0x6140
movq 0x18(%r13,%r15), %r12
movzwl (%r12), %esi
movzwl 0x6(%r12), %eax
movl %eax, %ecx
subl %esi, %ecx
movl $0x1, %ebp
cmpl $0x200, %ecx            # imm = 0x200
je 0x1a48
cmpl $0x1ff, %ecx            # imm = 0x1FF
jne 0x196f
movl $0x2, %ebp
jmp 0x1a48
movq 0x20(%r13,%r15), %rdi
movzwl %ax, %esi
movl %esi, %ecx
shrl %ecx
leal -0x1(%rcx), %r8d
leal 0xfe(%rcx), %r9d
testw %r8w, %r8w
cmovnsl %r8d, %r9d
movl $0x0, %ebx
testw %si, %si
je 0x19e4
andl $0xffffff00, %r9d       # imm = 0xFFFFFF00
negl %r9d
addl %r9d, %ecx
decl %ecx
movswq %cx, %r8
movzwl 0xe(%r12,%r8,4), %ecx
movzwl 0x10(%r12,%r8,4), %ebx
addl %ecx, %ebx
leaq (%rbx,%rdx), %rcx
movzwl 0xc(%r12), %esi
cmpq %rsi, %rcx
jb 0x19e4
movzwl 0x2(%r12), %ecx
andl $0x1fe, %ecx            # imm = 0x1FE
movzwl 0xe(%r12,%rcx,2), %ecx
movl $0x0, %ebx
cmpq %rdx, %rcx
jbe 0x1a59
incl %eax
movw %ax, 0x4(%r12)
movl %ebx, %eax
addq %rax, %rdi
movq %r14, %rsi
movq %rdx, %rbp
callq 0x1130
movq %rbp, %rdx
movzwl 0x6(%r12), %eax
movl %eax, %ecx
andl $0x1fe, %ecx            # imm = 0x1FE
movw %bx, 0xe(%r12,%rcx,2)
movw %dx, 0x10(%r12,%rcx,2)
addl $0x2, %eax
movw %ax, 0x4(%r12)
movw %ax, 0x6(%r12)
movabsq $0x2a2a515f512a2a, %rax # imm = 0x2A2A515F512A2A
cmpq %rax, (%r14)
je 0x1a46
addq %r13, %r15
movl 0x2c(%r15), %eax
addl %edx, %eax
decl %eax
movl %eax, 0x2c(%r15)
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1ef0(%rip), %rdi      # 0x3950
movq %rdx, %rbx
movq %r8, %r14
callq 0x1070
movzwl 0xe(%r12,%r14,4), %esi
movzwl 0x10(%r12,%r14,4), %edx
movzwl 0xc(%r12), %r8d
leaq 0x1e33(%rip), %rdi      # 0x38b7
movq %rbx, %rcx
xorl %eax, %eax
callq 0x10c0
jmp 0x1a48
leaq 0x1d9b(%rip), %rdi      # 0x3832
leaq 0x16f7(%rip), %rsi      # 0x3195
leaq 0x1dc2(%rip), %rcx      # 0x3867
movl $0x259, %edx            # imm = 0x259
callq 0x10d0
leaq 0x1de0(%rip), %rdi      # 0x3896
leaq 0x16d8(%rip), %rsi      # 0x3195
leaq 0x1da3(%rip), %rcx      # 0x3867
movl $0x25a, %edx            # imm = 0x25A
callq 0x10d0