From f42fd0fed8991031ba62defa434a212af48ee1d3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 13 Nov 2012 14:40:53 +1000 Subject: qxl: move garbage collector + alloc into qxl_mem.c This moves a lot more code out of the qxl_driver.c file. Signed-off-by: Dave Airlie --- src/qxl_driver.c | 178 ----------------------------------------------------- src/qxl_mem.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 178 deletions(-) diff --git a/src/qxl_driver.c b/src/qxl_driver.c index 9384b6f..8e2bf37 100644 --- a/src/qxl_driver.c +++ b/src/qxl_driver.c @@ -151,184 +151,6 @@ qxl_allocate_monitors_config (qxl_screen_t *qxl) memset (qxl->monitors_config, 0, size); } -static uint64_t -qxl_garbage_collect_internal (qxl_screen_t *qxl, uint64_t id) -{ - /* We assume that there the two low bits of a pointer are - * available. If the low one is set, then the command in - * question is a cursor command - */ -#define POINTER_MASK ((1 << 2) - 1) - - union QXLReleaseInfo *info = u64_to_pointer (id & ~POINTER_MASK); - struct QXLCursorCmd *cmd = (struct QXLCursorCmd *)info; - struct QXLDrawable *drawable = (struct QXLDrawable *)info; - struct QXLSurfaceCmd *surface_cmd = (struct QXLSurfaceCmd *)info; - int is_cursor = FALSE; - int is_surface = FALSE; - int is_drawable = FALSE; - - if ((id & POINTER_MASK) == 1) - is_cursor = TRUE; - else if ((id & POINTER_MASK) == 2) - is_surface = TRUE; - else - is_drawable = TRUE; - - if (is_cursor && cmd->type == QXL_CURSOR_SET) - { - struct QXLCursor *cursor = (void *)virtual_address ( - qxl, u64_to_pointer (cmd->u.set.shape), qxl->main_mem_slot); - - qxl_free (qxl->mem, cursor, "cursor image"); - } - else if (is_drawable && drawable->type == QXL_DRAW_COPY) - { - struct QXLImage *image = virtual_address ( - qxl, u64_to_pointer (drawable->u.copy.src_bitmap), qxl->main_mem_slot); - - if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) - { - qxl_surface_unref (qxl->surface_cache, image->surface_image.surface_id); - qxl_surface_cache_sanity_check (qxl->surface_cache); - qxl_free (qxl->mem, image, "surface image"); - } - else - { - qxl_image_destroy (qxl, image); - } - } - else if (is_drawable && drawable->type == QXL_DRAW_COMPOSITE) - { - struct QXLTransform *src_trans, *mask_trans; - struct QXLImage *src_img, *mask_img; - struct QXLComposite *composite = &drawable->u.composite; - - /* Source */ - src_img = virtual_address ( - qxl, u64_to_pointer (drawable->u.composite.src), qxl->main_mem_slot); - qxl_free (qxl->mem, src_img, "image struct"); - - if (composite->src_transform) - { - src_trans = virtual_address ( - qxl, u64_to_pointer (composite->src_transform), qxl->main_mem_slot); - qxl_free (qxl->mem, src_trans, "transform"); - } - - /* Mask */ - if (drawable->u.composite.mask) - { - if (drawable->u.composite.mask_transform) - { - mask_trans = virtual_address ( - qxl, u64_to_pointer (drawable->u.composite.mask_transform), qxl->main_mem_slot); - - qxl_free (qxl->mem, mask_trans, "transform"); - } - - mask_img = virtual_address ( - qxl, u64_to_pointer (drawable->u.composite.mask), qxl->main_mem_slot); - qxl_free (qxl->mem, mask_img, "image struct"); - } - } - else if (is_surface && surface_cmd->type == QXL_SURFACE_CMD_DESTROY) - { - qxl_surface_recycle (qxl->surface_cache, surface_cmd->surface_id); - qxl_surface_cache_sanity_check (qxl->surface_cache); - } - - id = info->next; - - qxl_free (qxl->mem, info, "command"); - - return id; -} - -int -qxl_garbage_collect (qxl_screen_t *qxl) -{ - uint64_t id; - int i = 0; - - while (qxl_ring_pop (qxl->release_ring, &id)) - { - while (id) - { - id = qxl_garbage_collect_internal (qxl, id); - - i++; - } - } - - return i; -} - -static void -qxl_usleep (int useconds) -{ - struct timespec t; - - t.tv_sec = useconds / 1000000; - t.tv_nsec = (useconds - (t.tv_sec * 1000000)) * 1000; - - errno = 0; - while (nanosleep (&t, &t) == -1 && errno == EINTR) - ; -} - -int -qxl_handle_oom (qxl_screen_t *qxl) -{ - qxl_io_notify_oom (qxl); - -#if 0 - ErrorF ("."); - qxl_usleep (10000); -#endif - - if (!(qxl_garbage_collect (qxl))) - qxl_usleep (10000); - - return qxl_garbage_collect (qxl); -} - -void * -qxl_allocnf (qxl_screen_t *qxl, unsigned long size, const char *name) -{ - void *result; - int n_attempts = 0; - -#if 0 - static int nth_oom = 1; -#endif - - qxl_garbage_collect (qxl); - - while (!(result = qxl_alloc (qxl->mem, size, name))) - { -#if 0 - ErrorF ("eliminated memory (%d)\n", nth_oom++); -#endif - if (!qxl_garbage_collect (qxl)) - { - if (qxl_handle_oom (qxl)) - { - n_attempts = 0; - } - else if (++n_attempts == 1000) - { - ErrorF ("Out of memory allocating %ld bytes\n", size); - qxl_mem_dump_stats (qxl->mem, "Out of mem - stats\n"); - fprintf (stderr, "Out of memory\n"); - exit (1); - } - } - } - - return result; -} - static Bool qxl_blank_screen (ScreenPtr pScreen, int mode) { diff --git a/src/qxl_mem.c b/src/qxl_mem.c index 87e0ab4..18ff3d9 100644 --- a/src/qxl_mem.c +++ b/src/qxl_mem.c @@ -25,6 +25,9 @@ #endif #include +#include +#include +#include #include "qxl.h" #include "mspace.h" @@ -237,3 +240,182 @@ qxl_mark_mem_unverifiable (qxl_screen_t *qxl) qxl_mem_unverifiable (qxl->mem); qxl_mem_unverifiable (qxl->surf_mem); } + + +static uint64_t +qxl_garbage_collect_internal (qxl_screen_t *qxl, uint64_t id) +{ + /* We assume that there the two low bits of a pointer are + * available. If the low one is set, then the command in + * question is a cursor command + */ +#define POINTER_MASK ((1 << 2) - 1) + + union QXLReleaseInfo *info = u64_to_pointer (id & ~POINTER_MASK); + struct QXLCursorCmd *cmd = (struct QXLCursorCmd *)info; + struct QXLDrawable *drawable = (struct QXLDrawable *)info; + struct QXLSurfaceCmd *surface_cmd = (struct QXLSurfaceCmd *)info; + int is_cursor = FALSE; + int is_surface = FALSE; + int is_drawable = FALSE; + + if ((id & POINTER_MASK) == 1) + is_cursor = TRUE; + else if ((id & POINTER_MASK) == 2) + is_surface = TRUE; + else + is_drawable = TRUE; + + if (is_cursor && cmd->type == QXL_CURSOR_SET) + { + struct QXLCursor *cursor = (void *)virtual_address ( + qxl, u64_to_pointer (cmd->u.set.shape), qxl->main_mem_slot); + + qxl_free (qxl->mem, cursor, "cursor image"); + } + else if (is_drawable && drawable->type == QXL_DRAW_COPY) + { + struct QXLImage *image = virtual_address ( + qxl, u64_to_pointer (drawable->u.copy.src_bitmap), qxl->main_mem_slot); + + if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) + { + qxl_surface_unref (qxl->surface_cache, image->surface_image.surface_id); + qxl_surface_cache_sanity_check (qxl->surface_cache); + qxl_free (qxl->mem, image, "surface image"); + } + else + { + qxl_image_destroy (qxl, image); + } + } + else if (is_drawable && drawable->type == QXL_DRAW_COMPOSITE) + { + struct QXLTransform *src_trans, *mask_trans; + struct QXLImage *src_img, *mask_img; + struct QXLComposite *composite = &drawable->u.composite; + + /* Source */ + src_img = virtual_address ( + qxl, u64_to_pointer (drawable->u.composite.src), qxl->main_mem_slot); + qxl_free (qxl->mem, src_img, "image struct"); + + if (composite->src_transform) + { + src_trans = virtual_address ( + qxl, u64_to_pointer (composite->src_transform), qxl->main_mem_slot); + qxl_free (qxl->mem, src_trans, "transform"); + } + + /* Mask */ + if (drawable->u.composite.mask) + { + if (drawable->u.composite.mask_transform) + { + mask_trans = virtual_address ( + qxl, u64_to_pointer (drawable->u.composite.mask_transform), qxl->main_mem_slot); + + qxl_free (qxl->mem, mask_trans, "transform"); + } + + mask_img = virtual_address ( + qxl, u64_to_pointer (drawable->u.composite.mask), qxl->main_mem_slot); + qxl_free (qxl->mem, mask_img, "image struct"); + } + } + else if (is_surface && surface_cmd->type == QXL_SURFACE_CMD_DESTROY) + { + qxl_surface_recycle (qxl->surface_cache, surface_cmd->surface_id); + qxl_surface_cache_sanity_check (qxl->surface_cache); + } + + id = info->next; + + qxl_free (qxl->mem, info, "command"); + + return id; +} + +int +qxl_garbage_collect (qxl_screen_t *qxl) +{ + uint64_t id; + int i = 0; + + while (qxl_ring_pop (qxl->release_ring, &id)) + { + while (id) + { + id = qxl_garbage_collect_internal (qxl, id); + + i++; + } + } + + return i; +} + +static void +qxl_usleep (int useconds) +{ + struct timespec t; + + t.tv_sec = useconds / 1000000; + t.tv_nsec = (useconds - (t.tv_sec * 1000000)) * 1000; + + errno = 0; + while (nanosleep (&t, &t) == -1 && errno == EINTR) + ; +} + +int +qxl_handle_oom (qxl_screen_t *qxl) +{ + qxl_io_notify_oom (qxl); + +#if 0 + ErrorF ("."); + qxl_usleep (10000); +#endif + + if (!(qxl_garbage_collect (qxl))) + qxl_usleep (10000); + + return qxl_garbage_collect (qxl); +} + +void * +qxl_allocnf (qxl_screen_t *qxl, unsigned long size, const char *name) +{ + void *result; + int n_attempts = 0; + +#if 0 + static int nth_oom = 1; +#endif + + qxl_garbage_collect (qxl); + + while (!(result = qxl_alloc (qxl->mem, size, name))) + { +#if 0 + ErrorF ("eliminated memory (%d)\n", nth_oom++); +#endif + if (!qxl_garbage_collect (qxl)) + { + if (qxl_handle_oom (qxl)) + { + n_attempts = 0; + } + else if (++n_attempts == 1000) + { + ErrorF ("Out of memory allocating %ld bytes\n", size); + qxl_mem_dump_stats (qxl->mem, "Out of mem - stats\n"); + fprintf (stderr, "Out of memory\n"); + exit (1); + } + } + } + + return result; +} -- cgit v1.2.3