summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2012-11-13 14:40:53 +1000
committerDave Airlie <airlied@gmail.com>2012-11-13 14:40:53 +1000
commitf42fd0fed8991031ba62defa434a212af48ee1d3 (patch)
tree7098b5bc57ef9a94ffc08c7564aaaab542737d8a
parent2028a360b1df1ff3eda8810f0764903ca348f709 (diff)
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 <airlied@redhat.com>
-rw-r--r--src/qxl_driver.c178
-rw-r--r--src/qxl_mem.c182
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 <stdarg.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
#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;
+}