static void throttlePipe_timerFunc( void* opaque ) { ThrottlePipe* pipe = opaque; int64_t now = qemu_get_clock_ns(vm_clock); DD("%s: TICK! now=%lld sendExpiration=%lld recvExpiration=%lld\n", __FUNCTION__, now, pipe->sendExpiration, pipe->recvExpiration); int flags = 0; if (pipe->sendExpiration && now > pipe->sendExpiration) { flags |= PIPE_WAKE_WRITE; pipe->sendExpiration = 0; } if (pipe->recvExpiration && now > pipe->recvExpiration) { flags |= PIPE_WAKE_READ; pipe->recvExpiration = 0; } flags &= pipe->pingpong.flags; if (flags != 0) { DD("%s: WAKE %d\n", __FUNCTION__, flags); goldfish_pipe_wake(pipe->pingpong.hwpipe, flags); } throttlePipe_rearm(pipe); }
static void throttlePipe_timerFunc( void* opaque ) { ThrottlePipe* pipe = opaque; int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); DD("%s: TICK! now=%lld sendExpiration=%lld recvExpiration=%lld\n", __FUNCTION__, now, pipe->sendExpiration, pipe->recvExpiration); /* Timer has expired, signal wake up if needed */ int flags = 0; if (pipe->sendExpiration && now > pipe->sendExpiration) { flags |= PIPE_WAKE_WRITE; pipe->sendExpiration = 0; } if (pipe->recvExpiration && now > pipe->recvExpiration) { flags |= PIPE_WAKE_READ; pipe->recvExpiration = 0; } flags &= pipe->pingpong.flags; if (flags != 0) { DD("%s: WAKE %d\n", __FUNCTION__, flags); goldfish_pipe_wake(pipe->pingpong.hwpipe, flags); } throttlePipe_rearm(pipe); }
void goldfish_pipe_close( void* hwpipe ) { Pipe* pipe = hwpipe; D("%s: channel=0x%x (closed=%d)", __FUNCTION__, pipe->channel, pipe->closed); if (!pipe->closed) { pipe->closed = 1; goldfish_pipe_wake( hwpipe, PIPE_WAKE_CLOSED ); } }
/* This is the function that gets called each time there is an asynchronous * event on the network pipe. */ static void netPipe_io_func( void* opaque, int fd, unsigned events ) { NetPipe* pipe = opaque; int wakeFlags = 0; /* Run the connector if we are in the CONNECTING state */ /* TODO: Add some sort of time-out, to deal with the case */ /* when the server is wedged. */ if (pipe->state == STATE_CONNECTING) { AsyncStatus status = asyncConnector_run(pipe->connector); if (status == ASYNC_NEED_MORE) { return; } else if (status == ASYNC_ERROR) { /* Could not connect, tell our client by closing the channel. */ netPipe_closeFromSocket(pipe); return; } pipe->state = STATE_CONNECTED; netPipe_resetState(pipe); return; } /* Otherwise, accept incoming data */ if ((events & LOOP_IO_READ) != 0) { if ((pipe->wakeWanted & PIPE_WAKE_READ) != 0) { wakeFlags |= PIPE_WAKE_READ; } } if ((events & LOOP_IO_WRITE) != 0) { if ((pipe->wakeWanted & PIPE_WAKE_WRITE) != 0) { wakeFlags |= PIPE_WAKE_WRITE; } } /* Send wake signal to the guest if needed */ if (wakeFlags != 0) { goldfish_pipe_wake(pipe->hwpipe, wakeFlags); pipe->wakeWanted &= ~wakeFlags; } /* Reset state */ netPipe_resetState(pipe); }
static int pingPongPipe_recvBuffers( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers ) { PingPongPipe* pipe = opaque; int ret = 0; while (numBuffers > 0) { int avail = pipe->count; if (avail <= 0) { if (ret == 0) ret = PIPE_ERROR_AGAIN; break; } if (avail > buffers[0].size) { avail = buffers[0].size; } int rpos = pipe->pos; if (rpos + avail <= pipe->size) { memcpy(buffers[0].data, pipe->buffer + rpos, avail); } else { int avail2 = pipe->size - rpos; memcpy(buffers[0].data, pipe->buffer + rpos, avail2); memcpy(buffers[0].data + avail2, pipe->buffer, avail - avail2); } pipe->count -= avail; pipe->pos += avail; if (pipe->pos >= pipe->size) { pipe->pos -= pipe->size; } ret += avail; numBuffers--; buffers++; } if (pipe->count < PINGPONG_SIZE && (pipe->flags & PIPE_WAKE_WRITE)) { goldfish_pipe_wake(pipe->hwpipe, PIPE_WAKE_WRITE); } return ret; }
static int goldfish_pipe_load( QEMUFile* file, void* opaque, int version_id ) { PipeDevice* dev = opaque; Pipe* pipe; if (version_id != GOLDFISH_PIPE_SAVE_VERSION) return -EINVAL; dev->address = qemu_get_be32(file); dev->size = qemu_get_be32(file); dev->status = qemu_get_be32(file); dev->channel = qemu_get_be32(file); dev->wakes = qemu_get_be32(file); dev->params_addr = qemu_get_be64(file); int count = qemu_get_sbe32(file); for ( ; count > 0; count-- ) { pipe = pipe_load(dev, file); if (pipe == NULL) { return -EIO; } pipe->next = dev->pipes; dev->pipes = pipe; } for ( pipe = dev->pipes; pipe; pipe = pipe->next ) { if (pipe->wanted != 0) goldfish_pipe_wake(pipe, pipe->wanted); if (pipe->closed != 0) goldfish_pipe_close(pipe); } return 0; }
static int pingPongPipe_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers ) { PingPongPipe* pipe = opaque; int ret = 0; int count; const GoldfishPipeBuffer* buff = buffers; const GoldfishPipeBuffer* buffEnd = buff + numBuffers; count = 0; for ( ; buff < buffEnd; buff++ ) count += buff->size; while (count > pipe->size - pipe->count) { size_t newsize = pipe->size*2; uint8_t* newbuff = realloc(pipe->buffer, newsize); int wpos = pipe->pos + pipe->count; if (newbuff == NULL) { break; } if (wpos > pipe->size) { wpos -= pipe->size; memcpy(newbuff + pipe->size, newbuff, wpos); } pipe->buffer = newbuff; pipe->size = newsize; D("pingpong buffer is now %d bytes", newsize); } for ( buff = buffers; buff < buffEnd; buff++ ) { int avail = pipe->size - pipe->count; if (avail <= 0) { if (ret == 0) ret = PIPE_ERROR_AGAIN; break; } if (avail > buff->size) { avail = buff->size; } int wpos = pipe->pos + pipe->count; if (wpos >= pipe->size) { wpos -= pipe->size; } if (wpos + avail <= pipe->size) { memcpy(pipe->buffer + wpos, buff->data, avail); } else { int avail2 = pipe->size - wpos; memcpy(pipe->buffer + wpos, buff->data, avail2); memcpy(pipe->buffer, buff->data + avail2, avail - avail2); } pipe->count += avail; ret += avail; } if (pipe->count > 0 && (pipe->flags & PIPE_WAKE_READ)) { goldfish_pipe_wake(pipe->hwpipe, PIPE_WAKE_READ); } return ret; }