rem: panic("port %id: tail > cap %d", ports[slot].id, ports[slot].capacity);
add: panic("port %ld: tail > cap %ld", ports[slot].id, ports[slot].capacity);
context: read_port_etc(port_id id,				int32	*msg_code,				void	*msg_buffer,				size_t	buffer_size,				uint32	flags,				bigtime_t	timeout){	int		slot;	int 	state;	sem_id	cached_semid;	size_t 	siz;	int		res;	int		t;	cbuf*	msg_store;	int32	code;	int		err;		if(ports_active == false)		return B_BAD_PORT_ID;	if(id < 0)		return B_BAD_PORT_ID;	if(msg_code == NULL)		return EINVAL;	if((msg_buffer == NULL) && (buffer_size > 0))		return EINVAL;	if (timeout < 0)		return EINVAL;	flags = flags & (PORT_FLAG_USE_USER_MEMCPY | B_CAN_INTERRUPT | B_TIMEOUT);	slot = id % MAX_PORTS;	state = disable_interrupts();	GRAB_PORT_LOCK(ports[slot]);	if(ports[slot].id != id) {		RELEASE_PORT_LOCK(ports[slot]);		restore_interrupts(state);		dprintf("read_port_etc: invalid port_id %d\n", id);		return B_BAD_PORT_ID;	}	// store sem_id in local variable	cached_semid = ports[slot].read_sem;	// unlock port && enable ints/	RELEASE_PORT_LOCK(ports[slot]);	restore_interrupts(state);	// XXX -> possible race condition if port gets deleted (->sem deleted too), therefore	// sem_id is cached in local variable up here		// get 1 entry from the queue, block if needed	res = acquire_sem_etc(cached_semid, 1, flags, timeout);	// XXX: possible race condition if port read by two threads...	//      both threads will read in 2 different slots allocated above, simultaneously	// 		slot is a thread-local variable	if (res == B_BAD_SEM_ID || res == EINTR) {		/* somebody deleted the port or the sem went away */		return B_BAD_PORT_ID;	}	if (res == B_TIMED_OUT) {		// timed out, or, if timeout=0, 'would block'		return B_BAD_PORT_ID;	}	if (res != B_NO_ERROR) {		dprintf("write_port_etc: res unknown error %d\n", res);		return res;	}	state = disable_interrupts();	GRAB_PORT_LOCK(ports[slot]);	t = ports[slot].tail;	if (t < 0)		panic("port %id: tail < 0", ports[slot].id);	if (t > ports[slot].capacity)		panic("port %id: tail > cap %d", ports[slot].id, ports[slot].capacity);	ports[slot].tail = (ports[slot].tail + 1) % ports[slot].capacity;	msg_store	= ports[slot].msg_queue[t].data_cbuf;	code 		= ports[slot].msg_queue[t].msg_code;		// mark queue entry unused	ports[slot].msg_queue[t].data_cbuf	= NULL;	// check output buffer size	siz	= min(buffer_size, ports[slot].msg_queue[t].data_len);		cached_semid = ports[slot].write_sem;	RELEASE_PORT_LOCK(ports[slot]);	restore_interrupts(state);	// copy message	*msg_code = code;	if (siz > 0) {		if (flags & PORT_FLAG_USE_USER_MEMCPY) {			if ((err = cbuf_user_memcpy_from_chain(msg_buffer, msg_store, 0, siz) < 0))	{				// leave the port intact, for other threads that might not crash				cbuf_free_chain(msg_store);				release_sem(cached_semid); 				return err;			}		} else			cbuf_memcpy_from_chain(msg_buffer, msg_store, 0, siz);	}	// free the cbuf	cbuf_free_chain(msg_store);	// make one spot in queue available again for write	release_sem(cached_semid);	return siz;}