[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC] PVFB: Add refresh period to XenStore parameters?
Hello, Something like this then? ioemu: transmit idleness information to avoid useless polls Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx> diff -r 32342f2b5742 extras/mini-os/fbfront.c --- a/extras/mini-os/fbfront.c Fri May 02 15:12:43 2008 +0100 +++ b/extras/mini-os/fbfront.c Mon May 05 17:44:16 2008 +0100 @@ -249,11 +249,41 @@ struct fbfront_dev { int stride; int mem_length; int offset; + + int status; }; void fbfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) { + struct fbfront_dev *dev = data; + struct xenfb_page *page = dev->page; + uint32_t prod, cons; + int i; + wake_up(&fbfront_queue); + prod = page->in_prod; + + if (prod == page->in_cons) + return; + + rmb(); /* ensure we see ring contents up to prod */ + + for (i = 0, cons = page->in_cons; cons != prod; i++, cons++) { + union xenfb_in_event *event = &XENFB_IN_RING_REF(page, cons); + switch (event->type) { + case XENFB_TYPE_BACKEND_STATUS: + dev->status = event->status.status; + printk("got status %d\n", dev->status); + break; + default: + /* ignore */ + break; + } + } + mb(); /* ensure we got ring contents */ + page->in_cons = cons; + + notify_remote_via_evtchn(dev->evtchn); } struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n) @@ -292,6 +322,7 @@ struct fbfront_dev *init_fbfront(char *n dev->stride = s->line_length = stride; dev->mem_length = s->mem_length = n * PAGE_SIZE; dev->offset = 0; + dev->status = XENFB_BACKEND_STATUS_ACTIVE; const int max_pd = sizeof(s->pd) / sizeof(s->pd[0]); unsigned long mapped = 0; @@ -405,6 +436,11 @@ static void fbfront_out_event(struct fbf wmb(); /* ensure ring contents visible */ page->out_prod = prod + 1; notify_remote_via_evtchn(dev->evtchn); +} + +int fbfront_status(struct fbfront_dev *dev) +{ + return dev->status; } void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height) diff -r 32342f2b5742 extras/mini-os/include/fbfront.h --- a/extras/mini-os/include/fbfront.h Fri May 02 15:12:43 2008 +0100 +++ b/extras/mini-os/include/fbfront.h Mon May 05 17:44:16 2008 +0100 @@ -36,6 +36,7 @@ int fbfront_open(struct fbfront_dev *dev int fbfront_open(struct fbfront_dev *dev); #endif +int fbfront_status(struct fbfront_dev *dev); void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int height); void fbfront_resize(struct fbfront_dev *dev, int width, int height, int stride, int depth, int offset); diff -r 32342f2b5742 tools/ioemu/hw/xenfb.c --- a/tools/ioemu/hw/xenfb.c Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/hw/xenfb.c Mon May 05 17:44:16 2008 +0100 @@ -59,6 +59,7 @@ struct xenfb { int offset; /* offset of the framebuffer */ int abs_pointer_wanted; /* Whether guest supports absolute pointer */ int button_state; /* Last seen pointer button state */ + int notified_active; /* Did we request update */ char protocol[64]; /* frontend protocol */ }; @@ -536,6 +537,40 @@ static void xenfb_on_fb_event(struct xen xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); } +static int xenfb_queue_full(struct xenfb *xenfb) +{ + struct xenfb_page *page = xenfb->fb.page; + uint32_t cons, prod; + + prod = page->in_prod; + cons = page->in_cons; + return prod - cons == XENFB_IN_RING_LEN; +} + +static void xenfb_send_event(struct xenfb *xenfb, union xenfb_in_event *event) +{ + uint32_t prod; + struct xenfb_page *page = xenfb->fb.page; + + prod = page->in_prod; + /* caller ensures !xenfb_queue_full() */ + xen_mb(); /* ensure ring space available */ + XENFB_IN_RING_REF(page, prod) = *event; + xen_wmb(); /* ensure ring contents visible */ + page->in_prod = prod + 1; + + xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); +} + +static void xenfb_send_status(struct xenfb *xenfb, int active) +{ + union xenfb_in_event event; + event.type = XENFB_TYPE_BACKEND_STATUS; + event.status.status = active ? XENFB_BACKEND_STATUS_ACTIVE + : XENFB_BACKEND_STATUS_IDLE ; + xenfb_send_event(xenfb, &event); +} + static void xenfb_on_kbd_event(struct xenfb *xenfb) { struct xenkbd_page *page = xenfb->kbd.page; @@ -707,6 +742,7 @@ static int xenfb_read_frontend_fb_config xenfb->protocol) < 0) xenfb->protocol[0] = '\0'; xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1"); + xenfb->notified_active = 1; /* TODO check for permitted ranges */ fb_page = xenfb->fb.page; @@ -1185,10 +1221,21 @@ static void xenfb_guest_copy(struct xenf dpy_update(xenfb->ds, x, y, w, h); } -/* Periodic update of display, no need for any in our case */ +/* Periodic update of display, just announce idleness to the front end */ static void xenfb_update(void *opaque) { struct xenfb *xenfb = opaque; + if (xenfb->ds->idle) { + if (xenfb->notified_active && !xenfb_queue_full(xenfb)) { + xenfb_send_status(xenfb, 0); + xenfb->notified_active = 0; + } + } else { + if (!xenfb->notified_active && !xenfb_queue_full(xenfb)) { + xenfb_send_status(xenfb, 1); + xenfb->notified_active = 1; + } + } } /* QEMU display state changed, so refresh the framebuffer copy */ @@ -1318,7 +1365,22 @@ static void xenfb_pv_setdata(DisplayStat static void xenfb_pv_refresh(DisplayState *ds) { + struct fbfront_dev *fb_dev = ds->opaque; + vga_hw_update(); + + if (!fb_dev) + return; + + if (fbfront_status(fb_dev)) { + /* Back to default interval */ + ds->gui_timer_interval = 0; + ds->idle = 0; + } else { + /* Sleeping interval */ + ds->gui_timer_interval = 500; + ds->idle = 1; + } } static void xenfb_kbd_handler(void *opaque) @@ -1447,6 +1509,7 @@ int xenfb_pv_display_init(DisplayState * ds->dpy_colourdepth = xenfb_pv_colourdepth; ds->dpy_setdata = xenfb_pv_setdata; ds->dpy_refresh = xenfb_pv_refresh; + ds->opaque = NULL; return 0; } diff -r 32342f2b5742 tools/ioemu/sdl.c --- a/tools/ioemu/sdl.c Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/sdl.c Mon May 05 17:44:16 2008 +0100 @@ -696,9 +696,11 @@ static void sdl_refresh(DisplayState *ds if (ev->active.gain) { /* Back to default interval */ ds->gui_timer_interval = 0; + ds->idle = 0; } else { /* Sleeping interval */ ds->gui_timer_interval = 500; + ds->idle = 1; } } break; diff -r 32342f2b5742 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/vl.c Mon May 05 17:44:16 2008 +0100 @@ -4467,6 +4467,8 @@ void dumb_display_init(DisplayState *ds) ds->dpy_resize = dumb_resize; ds->dpy_colourdepth = NULL; ds->dpy_refresh = dumb_refresh; + ds->gui_timer_interval = 500; + ds->idle = 1; } /***********************************************************/ diff -r 32342f2b5742 tools/ioemu/vl.h --- a/tools/ioemu/vl.h Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/vl.h Mon May 05 17:44:16 2008 +0100 @@ -939,6 +939,7 @@ struct DisplayState { void *opaque; uint32_t *palette; uint64_t gui_timer_interval; + int idle; int shared_buf; diff -r 32342f2b5742 tools/ioemu/vnc.c --- a/tools/ioemu/vnc.c Fri May 02 15:12:43 2008 +0100 +++ b/tools/ioemu/vnc.c Mon May 05 17:44:16 2008 +0100 @@ -778,6 +778,7 @@ static void _vnc_update_client(void *opa vs->has_update = 0; vnc_flush(vs); vs->last_update_time = now; + vs->ds->idle = 0; vs->timer_interval /= 2; if (vs->timer_interval < VNC_REFRESH_INTERVAL_BASE) @@ -790,26 +791,29 @@ static void _vnc_update_client(void *opa vs->timer_interval += VNC_REFRESH_INTERVAL_INC; if (vs->timer_interval > VNC_REFRESH_INTERVAL_MAX) { vs->timer_interval = VNC_REFRESH_INTERVAL_MAX; - if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL && - vs->update_requested) { - /* Send a null update. If the client is no longer - interested (e.g. minimised) it'll ignore this, and we - can stop scanning the buffer until it sends another - update request. */ - /* It turns out that there's a bug in realvncviewer 4.1.2 - which means that if you send a proper null update (with - no update rectangles), it gets a bit out of sync and - never sends any further requests, regardless of whether - it needs one or not. Fix this by sending a single 1x1 - update rectangle instead. */ - vnc_write_u8(vs, 0); - vnc_write_u8(vs, 0); - vnc_write_u16(vs, 1); - send_framebuffer_update(vs, 0, 0, 1, 1); - vnc_flush(vs); - vs->last_update_time = now; - vs->update_requested--; - return; + if (now - vs->last_update_time >= VNC_MAX_UPDATE_INTERVAL) { + if (!vs->update_requested) { + vs->ds->idle = 1; + } else { + /* Send a null update. If the client is no longer + interested (e.g. minimised) it'll ignore this, and we + can stop scanning the buffer until it sends another + update request. */ + /* It turns out that there's a bug in realvncviewer 4.1.2 + which means that if you send a proper null update (with + no update rectangles), it gets a bit out of sync and + never sends any further requests, regardless of whether + it needs one or not. Fix this by sending a single 1x1 + update rectangle instead. */ + vnc_write_u8(vs, 0); + vnc_write_u8(vs, 0); + vnc_write_u16(vs, 1); + send_framebuffer_update(vs, 0, 0, 1, 1); + vnc_flush(vs); + vs->last_update_time = now; + vs->update_requested--; + return; + } } } qemu_mod_timer(vs->timer, now + vs->timer_interval); @@ -970,6 +974,7 @@ static int vnc_client_io_error(VncState qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); closesocket(vs->csock); vs->csock = -1; + vs->ds->idle = 1; buffer_reset(&vs->input); buffer_reset(&vs->output); free_queue(vs); @@ -2443,6 +2448,7 @@ static void vnc_listen_read(void *opaque vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); if (vs->csock != -1) { VNC_DEBUG("New client on socket %d\n", vs->csock); + vs->ds->idle = 0; socket_set_nonblock(vs->csock); qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque); vnc_write(vs, "RFB 003.008\n", 12); @@ -2468,6 +2474,7 @@ void vnc_display_init(DisplayState *ds) exit(1); ds->opaque = vs; + ds->idle = 1; vnc_state = vs; vs->display = NULL; vs->password = NULL; diff -r 32342f2b5742 xen/include/public/io/fbif.h --- a/xen/include/public/io/fbif.h Fri May 02 15:12:43 2008 +0100 +++ b/xen/include/public/io/fbif.h Mon May 05 17:44:16 2008 +0100 @@ -80,14 +80,30 @@ union xenfb_out_event /* * Frontends should ignore unknown in events. - * No in events currently defined. */ + +/* + * Backend idleness report + * Backend sends it when the output window is somehow non visible + * (minimized, no client, etc.) + */ +#define XENFB_TYPE_BACKEND_STATUS 1 + +#define XENFB_BACKEND_STATUS_IDLE 0 +#define XENFB_BACKEND_STATUS_ACTIVE 1 + +struct xenfb_backend_status +{ + uint8_t type; /* XENFB_TYPE_BACKEND_STATUS */ + uint8_t status; /* XENFB_BACKEND_STATUS_* */ +}; #define XENFB_IN_EVENT_SIZE 40 union xenfb_in_event { uint8_t type; + struct xenfb_backend_status status; char pad[XENFB_IN_EVENT_SIZE]; }; _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |