Beispiel #1
0
/*
 * expand the size of pipe while there is data to be read,
 * and then free the old buffer once the current buffered
 * data has been transferred to new storage.
 * Required: PIPE_LOCK and io lock to be held by caller.
 * returns 0 on success or no expansion possible
 */
static int 
expand_pipespace(struct pipe *p, int target_size)
{
	struct pipe tmp, oldpipe;
	int error;
	tmp.pipe_buffer.buffer = 0;
	
	if (p->pipe_buffer.size >= (unsigned) target_size) {
		return 0; /* the existing buffer is max size possible */
	}
	
	/* create enough space in the target */
	error = pipespace(&tmp, target_size);
	if (error != 0)
		return (error);

	oldpipe.pipe_buffer.buffer = p->pipe_buffer.buffer;
	oldpipe.pipe_buffer.size = p->pipe_buffer.size;
	
	memcpy(tmp.pipe_buffer.buffer, p->pipe_buffer.buffer, p->pipe_buffer.size);
	if (p->pipe_buffer.cnt > 0 && p->pipe_buffer.in <= p->pipe_buffer.out ){
		/* we are in State 3 and need extra copying for read to be consistent */
		memcpy(&tmp.pipe_buffer.buffer[p->pipe_buffer.size], p->pipe_buffer.buffer, p->pipe_buffer.size);
		p->pipe_buffer.in += p->pipe_buffer.size;
	}

	p->pipe_buffer.buffer = tmp.pipe_buffer.buffer;
	p->pipe_buffer.size = tmp.pipe_buffer.size;


	pipe_free_kmem(&oldpipe);
	return 0;
}
Beispiel #2
0
/*
 * Allocate kva for pipe circular buffer, the space is pageable.
 * This routine will 'realloc' the size of a pipe safely, if it fails
 * it will retain the old buffer.
 * If it fails it will return ENOMEM.
 */
int
pipespace(struct pipe *cpipe, u_int size)
{
	caddr_t buffer;

	buffer = (caddr_t)uvm_km_valloc(kernel_map, size);
	if (buffer == NULL) {
		return (ENOMEM);
	}

	/* free old resources if we are resizing */
	pipe_free_kmem(cpipe);
	cpipe->pipe_buffer.buffer = buffer;
	cpipe->pipe_buffer.size = size;
	cpipe->pipe_buffer.in = 0;
	cpipe->pipe_buffer.out = 0;
	cpipe->pipe_buffer.cnt = 0;

	amountpipekva += cpipe->pipe_buffer.size;

	return (0);
}
Beispiel #3
0
/*
 * Allocate kva for pipe circular buffer, the space is pageable.
 * This routine will 'realloc' the size of a pipe safely, if it fails
 * it will retain the old buffer.
 * If it fails it will return ENOMEM.
 */
int
pipespace(struct pipe *cpipe, u_int size)
{
	caddr_t buffer;

	buffer = km_alloc(size, &kv_any, &kp_pageable, &kd_waitok);
	if (buffer == NULL) {
		return (ENOMEM);
	}

	/* free old resources if we are resizing */
	pipe_free_kmem(cpipe);
	cpipe->pipe_buffer.buffer = buffer;
	cpipe->pipe_buffer.size = size;
	cpipe->pipe_buffer.in = 0;
	cpipe->pipe_buffer.out = 0;
	cpipe->pipe_buffer.cnt = 0;

	amountpipekva += cpipe->pipe_buffer.size;

	return (0);
}
Beispiel #4
0
/*
 * shutdown the pipe
 */
void
pipeclose(struct pipe *cpipe)
{
	struct pipe *ppipe;
	if (cpipe) {
		
		pipeselwakeup(cpipe);

		/*
		 * If the other side is blocked, wake it up saying that
		 * we want to close it down.
		 */
		cpipe->pipe_state |= PIPE_EOF;
		while (cpipe->pipe_busy) {
			wakeup(cpipe);
			cpipe->pipe_state |= PIPE_WANT;
			tsleep(cpipe, PRIBIO, "pipecl", 0);
		}

		/*
		 * Disconnect from peer
		 */
		if ((ppipe = cpipe->pipe_peer) != NULL) {
			pipeselwakeup(ppipe);

			ppipe->pipe_state |= PIPE_EOF;
			wakeup(ppipe);
			ppipe->pipe_peer = NULL;
		}

		/*
		 * free resources
		 */
		pipe_free_kmem(cpipe);
		pool_put(&pipe_pool, cpipe);
	}
}
Beispiel #5
0
/*
 * Allocate kva for pipe circular buffer, the space is pageable
 * This routine will 'realloc' the size of a pipe safely, if it fails
 * it will retain the old buffer.
 * If it fails it will return ENOMEM.
 */
static int
pipespace(struct pipe *cpipe, int size)
{
	vm_offset_t buffer;

	if (size <= 0)
		return(EINVAL);

	if ((buffer = (vm_offset_t)kalloc(size)) == 0 )
		return(ENOMEM);

	/* free old resources if we're resizing */
	pipe_free_kmem(cpipe);
	cpipe->pipe_buffer.buffer = (caddr_t)buffer;
	cpipe->pipe_buffer.size = size;
	cpipe->pipe_buffer.in = 0;
	cpipe->pipe_buffer.out = 0;
	cpipe->pipe_buffer.cnt = 0;

	OSAddAtomic(1, &amountpipes);
	OSAddAtomic(cpipe->pipe_buffer.size, &amountpipekva);

	return (0);
}