[Spice-devel] [PATCH qxl-win 4/4] display: not using globals, RHBZ #731644

Alon Levy alevy at redhat.com
Wed Aug 24 07:15:12 PDT 2011


On Wed, Aug 24, 2011 at 03:05:29PM +0300, Yonit Halperin wrote:
> due to the previous patch ("support clearing the pci-bar when the pdev is disabled for revision<3 as well"),
> surfaces_info and other resources like caches, are no longer shared between pdevs. Moreover,
> it is an error to use globals, since different display driver sessions have different memory space.
> 
> In addition I removed all the semaphores that are not related to the pci ram. These semaphores
> were protecting the surfaces_info array and the caches, however these sturctures belong only to one pdev,
> and according to http://msdn.microsoft.com/en-us/library/ff568281%28v=vs.85%29.aspx, can be accessed
> only from a single thread.
> 
> For the rest of the semaphores, I returned them to the same state that was in revision 1 => they
> are part of the PDev. However, this should be fixed:
> 1) In order to protect the device log buffer,
>    the print_sem must be shared by different pdevs and
>    different display sessions.

I guess we should just make an IOCTL for logging. IOCTL calls are serialized I think.

> 2) malloc_sem: not sure what it protects. Maybe globals in mspace?
>    since only the enabled pdev is allocating memory, I don't
>    think it is required (unless it is possible to have
>    AssertMode(x, enable) before AssertMode(y, disable).
> 3) cmd_sem, cursor_sem: again, since only the enabled pdev touches the cmd rings
>    I don't think it is required.

No better idea.

> 4) io_sem - same as print sem. Note that we should prevent starvation between
>             print_sem and io_sem in DebugPrintV.
Probably IOCTLs for all of them? or one IOCTL for an io to save on the ton of boilerplate.


Patch looks ok, would have been nice to split next time.

> ---
>  display/driver.c  |   41 ++--
>  display/qxldd.h   |  127 +++++++------
>  display/res.c     |  560 +++++++++++++++++++++--------------------------------
>  display/res.h     |    1 -
>  display/surface.c |   13 +-
>  display/surface.h |   28 +--
>  6 files changed, 321 insertions(+), 449 deletions(-)
> 
> diff --git a/display/driver.c b/display/driver.c
> index 0c6fe32..865d777 100644
> --- a/display/driver.c
> +++ b/display/driver.c
> @@ -106,13 +106,13 @@ static CallCounterInfo counters_info[NUM_CALL_COUNTERS] = {
>  
>  void DebugPrintV(PDev *pdev, const char *message, va_list ap)
>  {
> -    if (pdev && pdev->log_buf && pdev->Res) {
> -        EngAcquireSemaphore(pdev->Res->print_sem);
> +    if (pdev && pdev->log_buf) {
> +        EngAcquireSemaphore(pdev->print_sem);
>          _snprintf(pdev->log_buf, QXL_LOG_BUF_SIZE, QXLDD_DEBUG_PREFIX);
>          _vsnprintf(pdev->log_buf + strlen(QXLDD_DEBUG_PREFIX),
>                     QXL_LOG_BUF_SIZE - strlen(QXLDD_DEBUG_PREFIX), message, ap);
>          sync_io(pdev, pdev->log_port, 0);
> -        EngReleaseSemaphore(pdev->Res->print_sem);
> +        EngReleaseSemaphore(pdev->print_sem);
>      } else {
>          EngDebugPrint(QXLDD_DEBUG_PREFIX, (PCHAR)message, ap);
>      }
> @@ -248,7 +248,6 @@ BOOL DrvEnableDriver(ULONG engine_version, ULONG enable_data_size, PDRVENABLEDAT
>  #ifndef _WIN64
>      CheckAndSetSSE2();
>  #endif
> -    InitGlobalRes();
>      DEBUG_PRINT((NULL, 1, "%s: end\n", __FUNCTION__));
>      return TRUE;
>  }
> @@ -257,7 +256,6 @@ VOID DrvDisableDriver(VOID)
>  {
>      DEBUG_PRINT((NULL, 1, "%s\n", __FUNCTION__));
>      ResDestroyGlobals();
> -    CleanGlobalRes();
>  }
>  
>  DWORD GetAvailableModes(HANDLE driver, PVIDEO_MODE_INFORMATION *mode_info,
> @@ -541,6 +539,7 @@ static void DebugCountAliveSurfaces(PDev *pdev)
>          surface_info = GetSurfaceInfo(pdev, i);
>          if (surface_info->draw_area.base_mem != NULL) {
>              total++;
> +            // all should belong to the same pdev
TODO: verify that all belong to the same pdev?

>              if (surface_info->u.pdev == pdev) {
>                  of_pdev++;
>                  if (surface_info->draw_area.surf_obj == NULL) {
> @@ -563,7 +562,6 @@ VOID DrvDisablePDEV(DHPDEV in_pdev)
>      PDev* pdev = (PDev*)in_pdev;
>  
>      DEBUG_PRINT((pdev, 1, "%s: 0x%lx\n", __FUNCTION__, pdev));
> -    DebugCountAliveSurfaces(pdev);
>      ResDestroy(pdev);
>      DestroyPalette(pdev);
>      EngFreeMem(pdev);
> @@ -954,6 +952,8 @@ VOID DrvDisableSurface(DHPDEV in_pdev)
>          pdev->mem_slots = NULL;
>      }
>  
> +    DebugCountAliveSurfaces(pdev);
> +    ClearResources(pdev);
>      DEBUG_PRINT((pdev, 1, "%s: 0x%lx exit\n", __FUNCTION__, pdev));
>  }
>  
> @@ -965,7 +965,7 @@ static void FlushSurfaces(PDev *pdev)
>      RECTL area = {0, 0, 0, 0};
>  
>      if (pdev->pci_revision < QXL_REVISION_STABLE_V10) {
> -        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_SURFACES", __FUNCTION__));
> +        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_SURFACES\n", __FUNCTION__));
>          for (surface_id = pdev->n_surfaces - 1; surface_id >  0 ; --surface_id) {
>              surface_info = GetSurfaceInfo(pdev, surface_id);
>              // TODO: check what this condinitions means.
> @@ -991,7 +991,7 @@ static BOOL FlushRelease(PDev *pdev)
>      if (pdev->pci_revision<  QXL_REVISION_STABLE_V10) {
>          DWORD length;
>  
> -        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_RELEASE", __FUNCTION__));
> +        DEBUG_PRINT((pdev, 1, "%s: revision too old for QXL_IO_FLUSH_RELEASE\n", __FUNCTION__));
>          if (EngDeviceIoControl(pdev->driver, IOCTL_VIDEO_RESET_DEVICE,
>                                 NULL, 0, NULL, 0, &length)) {
>              DEBUG_PRINT((NULL, 0, "%s: reset failed 0x%lx\n", __FUNCTION__, pdev));
> @@ -1040,20 +1040,19 @@ static BOOL AssertModeDisable(PDev *pdev)
>          pdev->cmd_ring->prod, pdev->cmd_ring->cons,
>          pdev->cursor_ring->prod, pdev->cursor_ring->cons,
>          pdev->release_ring->prod, pdev->release_ring->cons,
> -        pdev->Res->free_outputs));
> -    DEBUG_PRINT((pdev, 4, "%s exit\n", __FUNCTION__));
> +        pdev->free_outputs));
> +    DEBUG_PRINT((pdev, 3, "%s exit\n", __FUNCTION__));
>      return TRUE;
>  }
>  
>  static void AssertModeEnable(PDev *pdev)
>  {
> -    InitResources(pdev);
>      InitDeviceMemoryResources(pdev);
>      DEBUG_PRINT((pdev, 3, "%s: [%d,%d] [%d,%d] [%d,%d] %lx\n", __FUNCTION__,
>          pdev->cmd_ring->prod, pdev->cmd_ring->cons,
>          pdev->cursor_ring->prod, pdev->cursor_ring->cons,
>          pdev->release_ring->prod, pdev->release_ring->cons,
> -        pdev->Res->free_outputs));
> +        pdev->free_outputs));
>      EnableQXLPrimarySurface(pdev);
>      CreateVRamSlot(pdev);
>      DebugCountAliveSurfaces(pdev);
> @@ -1378,6 +1377,8 @@ HBITMAP APIENTRY DrvCreateDeviceBitmap(DHPDEV dhpdev, SIZEL size, ULONG format)
>      pdev = (PDev *)dhpdev;
>  
>      if (!pdev->vram_slot_initialized || pdev->bitmap_format != format || pdev->fb == 0) {
> +        DEBUG_PRINT((pdev, 3, "%s failed: %p: slot_initialized %d, format(%d,%d), fb %p\n",
> +                    pdev->vram_slot_initialized,  pdev->bitmap_format, format, pdev->fb));
>          return 0;
>      }
>  
> @@ -1385,6 +1386,7 @@ HBITMAP APIENTRY DrvCreateDeviceBitmap(DHPDEV dhpdev, SIZEL size, ULONG format)
>  
>      surface_id = GetFreeSurface(pdev);
>      if (!surface_id) {
> +        DEBUG_PRINT((pdev, 3, "%s:%p GetFreeSurface failed\n", __FUNCTION__, pdev));
>          goto out_error;
>      }
>      DEBUG_PRINT((pdev, 3, "%s: %p: %d\n", __FUNCTION__, pdev, surface_id));
> @@ -1392,6 +1394,7 @@ HBITMAP APIENTRY DrvCreateDeviceBitmap(DHPDEV dhpdev, SIZEL size, ULONG format)
>      hbitmap = CreateDeviceBitmap(pdev, size, pdev->bitmap_format, &phys_mem, &base_mem, surface_id,
>                                   DEVICE_BITMAP_ALLOCATION_TYPE_VRAM);
>      if (!hbitmap) {
> +         DEBUG_PRINT((pdev, 3, "%s:%p CreateDeviceBitmap failed\n", __FUNCTION__, pdev));
>          goto out_error2;
>      }
>  
> @@ -1427,20 +1430,20 @@ VOID APIENTRY DrvDeleteDeviceBitmap(DHSURF dhsurf)
>  
>  void CountCall(PDev *pdev, int counter)
>  {
> -    if (pdev->Res->count_calls) {
> +    if (pdev->count_calls) {
>          int i;
>  
> -        pdev->Res->call_counters[counter]++;
> -        if((++pdev->Res->total_calls % 500) == 0) {
> -            DEBUG_PRINT((pdev, 0, "total eng calls is %u\n", pdev->Res->total_calls));
> +        pdev->call_counters[counter]++;
> +        if((++pdev->total_calls % 500) == 0) {
> +            DEBUG_PRINT((pdev, 0, "total eng calls is %u\n", pdev->total_calls));
>              for (i = 0; i < NUM_CALL_COUNTERS; i++) {
>                  DEBUG_PRINT((pdev, 0, "%s count is %u\n",
> -                             counters_info[i].name, pdev->Res->call_counters[i]));
> +                             counters_info[i].name, pdev->call_counters[i]));
>              }
>          }
> -        pdev->Res->count_calls = FALSE;
> +        pdev->count_calls = FALSE;
>      } else if (counters_info[counter].effective) {
> -        pdev->Res->count_calls = TRUE;
> +        pdev->count_calls = TRUE;
>      }
>  }
>  
> diff --git a/display/qxldd.h b/display/qxldd.h
> index 9b613c1..b03c3de 100644
> --- a/display/qxldd.h
> +++ b/display/qxldd.h
> @@ -206,57 +206,6 @@ struct SurfaceInfo {
>      } u;
>  };
>  
> -typedef struct DevRes {   
> -    MspaceInfo mspaces[NUM_MSPACES];
> -    HSEMAPHORE malloc_sem; /* Also protects release ring */
> -
> -    BOOL need_init;
> -    UINT64 free_outputs;
> -    UINT32 update_id;
> -
> -    HSEMAPHORE print_sem;
> -    HSEMAPHORE cmd_sem;
> -    HSEMAPHORE cursor_sem; /* Protects cursor_ring */
> -    HSEMAPHORE surface_sem; /* Protects surfaces allocation */
> -    HSEMAPHORE image_cache_sem; /* Protects image cache */
> -    HSEMAPHORE cursor_cache_sem; /* Protects cursor cache */
> -    HSEMAPHORE palette_cache_sem; /* Protects palette cache */
> -
> -    CacheImage cache_image_pool[IMAGE_POOL_SIZE];
> -    Ring cache_image_lru;
> -    Ring cursors_lru;
> -    Ring palette_lru;
> -
> -    ImageKey image_key_lookup[IMAGE_KEY_HASH_SIZE];
> -    struct CacheImage *image_cache[IMAGE_HASH_SIZE];
> -    struct InternalCursor *cursor_cache[CURSOR_HASH_SIZE];
> -    UINT32 num_cursors;
> -    UINT32 last_cursor_id;
> -    struct InternalPalette *palette_cache[PALETTE_HASH_SIZE];
> -    UINT32 num_palettes;
> -
> -    SurfaceInfo *surfaces_info;
> -    SurfaceInfo *free_surfaces;
> -
> -    HANDLE driver;
> -#ifdef DBG
> -    int num_free_pages;
> -    int num_outputs;
> -    int num_path_pages;
> -    int num_rects_pages;
> -    int num_bits_pages;
> -    int num_buf_pages;
> -    int num_glyphs_pages;
> -    int num_cursor_pages;
> -#endif
> -
> -#ifdef CALL_TEST
> -    BOOL count_calls;
> -    UINT32 total_calls;
> -    UINT32 call_counters[NUM_CALL_COUNTERS];
> -#endif
> -} DevRes;
> -
>  #define SSE_MASK 15
>  #define SSE_ALIGN 16
>  
> @@ -345,26 +294,82 @@ typedef struct PDev {
>  
>      UINT32 dev_id;
>  
> -    DevRes *Res;
> -
>      Ring update_trace;
>      UpdateTrace update_trace_items[NUM_UPDATE_TRACE_ITEMS];
>  
> +    UINT64 free_outputs;
> +
> +    MspaceInfo mspaces[NUM_MSPACES];
> +
> +    /*
> +     * TODO: reconsider semaphores according to
> +     * http://msdn.microsoft.com/en-us/library/ff568281%28v=vs.85%29.aspx
> +     * 1) In order to protect the device log buffer,
> +     *     the print_sem must be shared between different pdevs and
> +     *     different display sessions.
> +     * 2) malloc_sem: not sure what it protects. Maybe globals in mspace?
> +     *    since only the enabled pdev is allocating memory, I don't
> +     *    think it is required (unless it is possible to have
> +     *    AssertMode(x, enable) before AssertMode(y, disable).
> +     * 3) cmd_sem, cursor_sem: again, since only the enabled pdev touches the cmd rings
> +     *    I don't think it is required.
> +     * 4) io_sem - same as print sem. Note that we should prevent starvation between
> +     *    print_sem and io_sem in DebugPrintV.
> +     *
> +     */
> +    HSEMAPHORE malloc_sem; /* Also protects release ring */
> +    HSEMAPHORE print_sem;
> +    HSEMAPHORE cmd_sem;
> +    HSEMAPHORE cursor_sem; /* Protects cursor_ring */
> +
> +    CacheImage cache_image_pool[IMAGE_POOL_SIZE];
> +    Ring cache_image_lru;
> +    Ring cursors_lru;
> +    Ring palette_lru;
> +    ImageKey image_key_lookup[IMAGE_KEY_HASH_SIZE];
> +    struct CacheImage *image_cache[IMAGE_HASH_SIZE];
> +    struct InternalCursor *cursor_cache[CURSOR_HASH_SIZE];
> +    UINT32 num_cursors;
> +    UINT32 last_cursor_id;
> +    struct InternalPalette *palette_cache[PALETTE_HASH_SIZE];
> +    UINT32 num_palettes;
> +
>      UINT32 n_surfaces;
>      SurfaceInfo surface0_info;
> +    SurfaceInfo *surfaces_info;
> +    SurfaceInfo *free_surfaces;
> +
> +    UINT32 update_id;
>  
>      UINT32 enabled; /* 1 between DrvAssertMode(TRUE) and DrvAssertMode(FALSE) */
>  
> +
>      UCHAR  pci_revision;
> +
> +#ifdef DBG
> +    int num_free_pages;
> +    int num_outputs;
> +    int num_path_pages;
> +    int num_rects_pages;
> +    int num_bits_pages;
> +    int num_buf_pages;
> +    int num_glyphs_pages;
> +    int num_cursor_pages;
> +#endif
> +
> +#ifdef CALL_TEST
> +    BOOL count_calls;
> +    UINT32 total_calls;
> +    UINT32 call_counters[NUM_CALL_COUNTERS];
> +#endif
>  } PDev;
>  
>  
>  void DebugPrintV(PDev *pdev, const char *message, va_list ap);
>  void DebugPrint(PDev *pdev, int level, const char *message, ...);
>  
> -void InitGlobalRes();
> -void CleanGlobalRes();
>  void InitResources(PDev *pdev);
> +void ClearResources(PDev *pdev);
>  
>  #ifdef CALL_TEST
>  void CountCall(PDev *pdev, int counter);
> @@ -478,9 +483,9 @@ static _inline void sync_io(PDev *pdev, PUCHAR port, UCHAR val)
>  #ifdef DBG
>  #define DUMP_VRAM_MSPACE(pdev) \
>      do { \
> -        DEBUG_PRINT((pdev, 0, "%s: dumping mspace vram (%p, %p)\n", __FUNCTION__, pdev, global_res ? global_res[pdev->dev_id] : NULL)); \
> -        if (pdev && global_res && global_res[pdev->dev_id]) {  \
> -            mspace_malloc_stats(global_res[pdev->dev_id]->mspaces[MSPACE_TYPE_VRAM]._mspace); \
> +        DEBUG_PRINT((pdev, 0, "%s: dumping mspace vram (%p)\n", __FUNCTION__, pdev)); \
> +        if (pdev) {  \
> +            mspace_malloc_stats(pdev->mspaces[MSPACE_TYPE_VRAM]._mspace); \
>          } else { \
>              DEBUG_PRINT((pdev, 0, "nothing\n")); \
>          }\
> @@ -488,9 +493,9 @@ static _inline void sync_io(PDev *pdev, PUCHAR port, UCHAR val)
>  
>  #define DUMP_DEVRAM_MSPACE(pdev) \
>      do { \
> -        DEBUG_PRINT((pdev, 0, "%s: dumping mspace devram (%p, %p)\n", __FUNCTION__, pdev, global_res ? global_res[pdev->dev_id] : NULL)); \
> -        if (pdev && global_res && global_res[pdev->dev_id]) {  \
> -            mspace_malloc_stats(global_res[pdev->dev_id]->mspaces[MSPACE_TYPE_DEVRAM]._mspace); \
> +        DEBUG_PRINT((pdev, 0, "%s: dumping mspace devram (%p)\n", __FUNCTION__, pdev)); \
> +        if (pdev) {  \
> +            mspace_malloc_stats(pdev->mspaces[MSPACE_TYPE_DEVRAM]._mspace); \
>          } else { \
>              DEBUG_PRINT((pdev, 0, "nothing\n")); \
>          }\
> diff --git a/display/res.c b/display/res.c
> index 1274f43..f7c0a58 100644
> --- a/display/res.c
> +++ b/display/res.c
> @@ -186,7 +186,7 @@ UINT64 ReleaseOutput(PDev *pdev, UINT64 output_id)
>      next = *(UINT64*)output->data;
>      FreeMem(pdev, MSPACE_TYPE_DEVRAM, output);
>      DEBUG_PRINT((pdev, 10, "%s done\n", __FUNCTION__));
> -    ONDBG(pdev->Res->num_outputs--); //todo: atomic
> +    ONDBG(pdev->num_outputs--); //todo: atomic
>      return next;
>  }
>  
> @@ -326,14 +326,14 @@ static void WaitForReleaseRing(PDev* pdev)
>              DEBUG_PRINT((pdev, 0, "%s: 0x%lx: timeout\n", __FUNCTION__, pdev));
>              DEBUG_PRINT((pdev, 0,
>                  "\tfree %d out %d path %d rect %d bits %d buf %d glyph %d cursor %d\n",
> -                         pdev->Res->num_free_pages,
> -                         pdev->Res->num_outputs,
> -                         pdev->Res->num_path_pages,
> -                         pdev->Res->num_rects_pages,
> -                         pdev->Res->num_bits_pages,
> -                         pdev->Res->num_buf_pages,
> -                         pdev->Res->num_glyphs_pages,
> -                         pdev->Res->num_cursor_pages));
> +                         pdev->num_free_pages,
> +                         pdev->num_outputs,
> +                         pdev->num_path_pages,
> +                         pdev->num_rects_pages,
> +                         pdev->num_bits_pages,
> +                         pdev->num_buf_pages,
> +                         pdev->num_glyphs_pages,
> +                         pdev->num_cursor_pages));
>  #endif
>              //oom
>              sync_io(pdev, pdev->notify_oom_port, 0);
> @@ -349,7 +349,7 @@ static void FlushReleaseRing(PDev *pdev)
>      int notify;
>      int num_to_release = 50;
>  
> -    output = pdev->Res->free_outputs;
> +    output = pdev->free_outputs;
>  
>      while (1) {
>          while (output != 0) {
> @@ -368,19 +368,19 @@ static void FlushReleaseRing(PDev *pdev)
>          SPICE_RING_POP(pdev->release_ring, notify);
>      }
>  
> -    pdev->Res->free_outputs = output;
> +    pdev->free_outputs = output;
>  }
>  
>  void EmptyReleaseRing(PDev *pdev)
>  {
>      int count = 0;
>  
> -    EngAcquireSemaphore(pdev->Res->malloc_sem);
> -    while (pdev->Res->free_outputs || !SPICE_RING_IS_EMPTY(pdev->release_ring)) {
> +    EngAcquireSemaphore(pdev->malloc_sem);
> +    while (pdev->free_outputs || !SPICE_RING_IS_EMPTY(pdev->release_ring)) {
>          FlushReleaseRing(pdev);
>          count++;
>      }
> -    EngReleaseSemaphore(pdev->Res->malloc_sem);
> +    EngReleaseSemaphore(pdev->malloc_sem);
>      DEBUG_PRINT((pdev, 3, "%s: complete after %d rounds\n", __FUNCTION__, count));
>  }
>  
> @@ -390,29 +390,29 @@ static void *__AllocMem(PDev* pdev, UINT32 mspace_type, size_t size, BOOL force)
>  {
>      UINT8 *ptr;
>  
> -    ASSERT(pdev, pdev && pdev->Res->mspaces[mspace_type]._mspace);
> +    ASSERT(pdev, pdev && pdev->mspaces[mspace_type]._mspace);
>      DEBUG_PRINT((pdev, 12, "%s: 0x%lx %p(%d) size %u\n", __FUNCTION__, pdev,
> -        pdev->Res->mspaces[mspace_type]._mspace,
> -        mspace_footprint(pdev->Res->mspaces[mspace_type]._mspace),
> +        pdev->mspaces[mspace_type]._mspace,
> +        mspace_footprint(pdev->mspaces[mspace_type]._mspace),
>          size));
>  #ifdef DBG
>      if (pdev && pdev->log_level && *pdev->log_level > 11) {
> -        mspace_malloc_stats(pdev->Res->mspaces[mspace_type]._mspace);
> +        mspace_malloc_stats(pdev->mspaces[mspace_type]._mspace);
>      }
>  #endif
> -    EngAcquireSemaphore(pdev->Res->malloc_sem);
> +    EngAcquireSemaphore(pdev->malloc_sem);
>  
>      while (1) {
>          /* Release lots of queued resources, before allocating, as we
>             want to release early to minimize fragmentation risks. */
>          FlushReleaseRing(pdev);
>  
> -        ptr = mspace_malloc(pdev->Res->mspaces[mspace_type]._mspace, size);
> +        ptr = mspace_malloc(pdev->mspaces[mspace_type]._mspace, size);
>          if (ptr) {
>              break;
>          }
>  
> -        if (pdev->Res->free_outputs != 0 ||
> +        if (pdev->free_outputs != 0 ||
>              !SPICE_RING_IS_EMPTY(pdev->release_ring)) {
>              /* We have more things to free, try that */
>              continue;
> @@ -427,133 +427,60 @@ static void *__AllocMem(PDev* pdev, UINT32 mspace_type, size_t size, BOOL force)
>          }
>      }
>  
> -    EngReleaseSemaphore(pdev->Res->malloc_sem);
> -    ASSERT(pdev, (!ptr && !force) || (ptr >= pdev->Res->mspaces[mspace_type].mspace_start &&
> -                                      ptr < pdev->Res->mspaces[mspace_type].mspace_end));
> +    EngReleaseSemaphore(pdev->malloc_sem);
> +    ASSERT(pdev, (!ptr && !force) || (ptr >= pdev->mspaces[mspace_type].mspace_start &&
> +                                      ptr < pdev->mspaces[mspace_type].mspace_end));
>      DEBUG_PRINT((pdev, 13, "%s: 0x%lx done 0x%x\n", __FUNCTION__, pdev, ptr));
>      return ptr;
>  }
>  
>  static void FreeMem(PDev* pdev, UINT32 mspace_type, void *ptr)
>  {
> -    ASSERT(pdev, pdev && pdev->Res->mspaces[mspace_type]._mspace);
> +    ASSERT(pdev, pdev && pdev->mspaces[mspace_type]._mspace);
>  #ifdef DBG
> -    if (!((UINT8 *)ptr >= pdev->Res->mspaces[mspace_type].mspace_start &&
> -                 (UINT8 *)ptr < pdev->Res->mspaces[mspace_type].mspace_end)) {
> +    if (!((UINT8 *)ptr >= pdev->mspaces[mspace_type].mspace_start &&
> +                 (UINT8 *)ptr < pdev->mspaces[mspace_type].mspace_end)) {
>          DebugPrint(pdev, 0, "ASSERT failed @ %s, %p not in [%p, %p) (%d)\n", __FUNCTION__,
> -            ptr, pdev->Res->mspaces[mspace_type].mspace_start,
> -            pdev->Res->mspaces[mspace_type].mspace_end, mspace_type);
> +            ptr, pdev->mspaces[mspace_type].mspace_start,
> +            pdev->mspaces[mspace_type].mspace_end, mspace_type);
>          EngDebugBreak();
>      }
>  #endif
> -    EngAcquireSemaphore(pdev->Res->malloc_sem);
> -    mspace_free(pdev->Res->mspaces[mspace_type]._mspace, ptr);
> -    EngReleaseSemaphore(pdev->Res->malloc_sem);
> -}
> -
> -DevRes **global_res = NULL;
> -UINT8 num_global_res = 0;
> -HSEMAPHORE res_sem = NULL;
> -
> -void CleanGlobalRes()
> -{
> -    UINT32 i;
> -    DevRes *res;
> -
> -    if (global_res) {
> -        for (i = 0; i < num_global_res; ++i) {
> -            res = global_res[i];
> -            if (res != NULL) {
> -                if (res->surfaces_info) {
> -                    EngFreeMem(res->surfaces_info);
> -                    res->surfaces_info = NULL;
> -                }
> -                if (res->malloc_sem) {
> -                    EngDeleteSemaphore(res->malloc_sem);
> -                    res->malloc_sem = NULL;
> -                }
> -                if (res->cmd_sem) {
> -                    EngDeleteSemaphore(res->cmd_sem);
> -                    res->cmd_sem = NULL;
> -                }
> -                if (res->cursor_sem) {
> -                    EngDeleteSemaphore(res->cursor_sem);
> -                    res->cursor_sem = NULL;
> -                }
> -                if (res->print_sem) {
> -                    EngDeleteSemaphore(res->print_sem);
> -                    res->print_sem = NULL;
> -                }
> -                if (res->surface_sem) {
> -                    EngDeleteSemaphore(res->surface_sem);
> -                    res->surface_sem = NULL;
> -                }
> -                if (res->image_cache_sem) {
> -                    EngDeleteSemaphore(res->image_cache_sem);
> -                    res->image_cache_sem = NULL;
> -                }
> -                if (res->cursor_cache_sem) {
> -                    EngDeleteSemaphore(res->cursor_cache_sem);
> -                    res->cursor_cache_sem = NULL;
> -                }
> -                if (res->palette_cache_sem) {
> -                    EngDeleteSemaphore(res->palette_cache_sem);
> -                    res->palette_cache_sem = NULL;
> -                }
> -                EngFreeMem(res);
> -            }
> -        }
> -        EngFreeMem(global_res);
> -        global_res = NULL;
> -    }
> -    num_global_res = 0;
> -    if (res_sem) {
> -        EngDeleteSemaphore(res_sem);
> -        res_sem = NULL;
> -    }
> -}
> -
> -void InitGlobalRes()
> -{
> -    CleanGlobalRes();
> -    res_sem = EngCreateSemaphore();
> -    if (!res_sem) {
> -        EngDebugBreak();
> -    }
> +    EngAcquireSemaphore(pdev->malloc_sem);
> +    mspace_free(pdev->mspaces[mspace_type]._mspace, ptr);
> +    EngReleaseSemaphore(pdev->malloc_sem);
>  }
>  
>  static void InitMspace(PDev *pdev, UINT32 mspace_type, UINT8 *start, size_t capacity)
>  {
> -    DevRes *res = pdev->Res;
> -
> -    res->mspaces[mspace_type]._mspace = create_mspace_with_base(start, capacity, 0, pdev);
> -    res->mspaces[mspace_type].mspace_start = start;
> -    res->mspaces[mspace_type].mspace_end = start + capacity;
> +    pdev->mspaces[mspace_type]._mspace = create_mspace_with_base(start, capacity, 0, pdev);
> +    pdev->mspaces[mspace_type].mspace_start = start;
> +    pdev->mspaces[mspace_type].mspace_end = start + capacity;
>  }
>  
>  static void ResetCache(PDev *pdev)
>  {
>      int i;
>  
> -    RtlZeroMemory(pdev->Res->image_key_lookup,
> -                  sizeof(pdev->Res->image_key_lookup));
> -    RtlZeroMemory(pdev->Res->cache_image_pool,
> -                  sizeof(pdev->Res->cache_image_pool));
> -    RingInit(&pdev->Res->cache_image_lru);
> +    RtlZeroMemory(pdev->image_key_lookup,
> +                  sizeof(pdev->image_key_lookup));
> +    RtlZeroMemory(pdev->cache_image_pool,
> +                  sizeof(pdev->cache_image_pool));
> +    RingInit(&pdev->cache_image_lru);
>      for (i = 0; i < IMAGE_POOL_SIZE; i++) {
> -        RingAdd(pdev, &pdev->Res->cache_image_lru,
> -                &pdev->Res->cache_image_pool[i].lru_link);
> +        RingAdd(pdev, &pdev->cache_image_lru,
> +                &pdev->cache_image_pool[i].lru_link);
>      }
>  
> -    RtlZeroMemory(pdev->Res->image_cache, sizeof(pdev->Res->image_cache));
> -    RtlZeroMemory(pdev->Res->cursor_cache, sizeof(pdev->Res->cursor_cache));
> -    RingInit(&pdev->Res->cursors_lru);
> -    pdev->Res->num_cursors = 0;
> -    pdev->Res->last_cursor_id = 0;
> +    RtlZeroMemory(pdev->image_cache, sizeof(pdev->image_cache));
> +    RtlZeroMemory(pdev->cursor_cache, sizeof(pdev->cursor_cache));
> +    RingInit(&pdev->cursors_lru);
> +    pdev->num_cursors = 0;
> +    pdev->last_cursor_id = 0;
>  
> -    RtlZeroMemory(pdev->Res->palette_cache, sizeof(pdev->Res->palette_cache));
> -    RingInit(&pdev->Res->palette_lru);
> -    pdev->Res->num_palettes = 0;
> +    RtlZeroMemory(pdev->palette_cache, sizeof(pdev->palette_cache));
> +    RingInit(&pdev->palette_lru);
> +    pdev->num_palettes = 0;
>  }
>  
>  /* Init anything that resides on the device memory (pci vram and devram bars).
> @@ -562,126 +489,107 @@ static void ResetCache(PDev *pdev)
>   */
>  void InitDeviceMemoryResources(PDev *pdev)
>  {
> +    UINT32 i;
> +
>      DEBUG_PRINT((pdev, 0, "%s: %d, %d\n", __FUNCTION__, pdev->num_io_pages * PAGE_SIZE,
> -        pdev->fb_size));
> +                pdev->fb_size));
> +    RtlZeroMemory(pdev->update_trace_items, sizeof(pdev->update_trace_items));
> +    RingInit(&pdev->update_trace);
> +    for (i = 0; i < NUM_UPDATE_TRACE_ITEMS; i++) {
> +         RingAdd(pdev, &pdev->update_trace, &pdev->update_trace_items[i].link);
> +    }
>      InitMspace(pdev, MSPACE_TYPE_DEVRAM, pdev->io_pages_virt, pdev->num_io_pages * PAGE_SIZE);
>      InitMspace(pdev, MSPACE_TYPE_VRAM, pdev->fb, pdev->fb_size);
>      ResetCache(pdev);
> +    pdev->free_outputs = 0;
>  }
>  
> -static void InitRes(PDev *pdev)
> +void InitSurfaces(PDev *pdev)
>  {
>      UINT32 i;
> -
> -    pdev->Res->surface_sem = EngCreateSemaphore();
> -    if (!pdev->Res->surface_sem) {
> -        PANIC(pdev, "Res surface sem creation failed\n");
> -    }
> -    pdev->Res->surfaces_info = (SurfaceInfo *)EngAllocMem(FL_ZERO_MEMORY,
> -							  sizeof(SurfaceInfo) * pdev->n_surfaces, 
> -							  ALLOC_TAG);
> -    if (!pdev->Res->surfaces_info) {
> -        PANIC(pdev, "Res surfaces_info allocation failed\n");
> +    pdev->surfaces_info = (SurfaceInfo *)EngAllocMem(FL_ZERO_MEMORY,
> +                                                     sizeof(SurfaceInfo) * pdev->n_surfaces,
> +                                                     ALLOC_TAG);
> +    if (!pdev->surfaces_info) {
> +        PANIC(pdev, "surfaces_info allocation failed\n");
>      }
> -    pdev->Res->free_surfaces = &pdev->Res->surfaces_info[0];
> +
> +    pdev->free_surfaces = &pdev->surfaces_info[1];
>      for (i = 0; i < pdev->n_surfaces - 1; i++) {
> -        pdev->Res->surfaces_info[i].u.next_free = &pdev->Res->surfaces_info[i+1];
> +        pdev->surfaces_info[i].u.next_free = &pdev->surfaces_info[i+1];
>      }
> +}
>  
> -    pdev->Res->free_outputs = 0;
> -    pdev->Res->malloc_sem = EngCreateSemaphore();
> -    if (!pdev->Res->malloc_sem) {
> -        PANIC(pdev, "Res malloc sem creation failed\n");
> -    }
> -    pdev->Res->cmd_sem = EngCreateSemaphore();
> -    if (!pdev->Res->cmd_sem) {
> -        PANIC(pdev, "Res cmd sem creation failed\n");
> -    }
> -    pdev->Res->cursor_sem = EngCreateSemaphore();
> -    if (!pdev->Res->cursor_sem) {
> -        PANIC(pdev, "Res cursor sem creation failed\n");
> -    }
> -    pdev->Res->print_sem = EngCreateSemaphore();
> -    if (!pdev->Res->print_sem) {
> -        PANIC(pdev, "Res print sem creation failed\n");
> -    }
> -    pdev->Res->image_cache_sem = EngCreateSemaphore();
> -    if (!pdev->Res->image_cache_sem) {
> -        PANIC(pdev, "Res cache sem creation failed\n");
> -    }
> -    pdev->Res->cursor_cache_sem = EngCreateSemaphore();
> -    if (!pdev->Res->cursor_cache_sem) {
> -        PANIC(pdev, "Res cache sem creation failed\n");
> -    }
> -    pdev->Res->palette_cache_sem = EngCreateSemaphore();
> -    if (!pdev->Res->palette_cache_sem) {
> -        PANIC(pdev, "Res cache sem creation failed\n");
> +void ClearResources(PDev *pdev)
> +{
> +    if (pdev->surfaces_info) {
> +        EngFreeMem(pdev->surfaces_info);
> +        pdev->surfaces_info = NULL;
>      }
>  
> -    pdev->Res->update_id = *pdev->dev_update_id;
> -    InitDeviceMemoryResources(pdev);
> +    if (pdev->malloc_sem) {
> +        EngDeleteSemaphore(pdev->malloc_sem);
> +        pdev->malloc_sem = NULL;
> +    }
>  
> -    pdev->Res->driver = pdev->driver;
> +    if (pdev->cmd_sem) {
> +        EngDeleteSemaphore(pdev->cmd_sem);
> +        pdev->cmd_sem = NULL;
> +    }
>  
> -    ONDBG(pdev->Res->num_outputs = 0);
> -    ONDBG(pdev->Res->num_path_pages = 0);
> -    ONDBG(pdev->Res->num_rects_pages = 0);
> -    ONDBG(pdev->Res->num_bits_pages = 0);
> -    ONDBG(pdev->Res->num_buf_pages = 0);
> -    ONDBG(pdev->Res->num_glyphs_pages = 0);
> -    ONDBG(pdev->Res->num_cursor_pages = 0);
> +    if (pdev->cursor_sem) {
> +        EngDeleteSemaphore(pdev->cursor_sem);
> +        pdev->cursor_sem = NULL;
> +    }
>  
> -#ifdef CALL_TEST
> -    pdev->Res->count_calls = TRUE;
> -    pdev->Res->total_calls = 0;
> -    for (i = 0; i < NUM_CALL_COUNTERS; i++) {
> -        pdev->Res->call_counters[i] = 0;
> +    if (pdev->print_sem) {
> +        EngDeleteSemaphore(pdev->print_sem);
> +        pdev->print_sem = NULL;
>      }
> -#endif
>  }
>  
>  void InitResources(PDev *pdev)
>  {
> -    UINT32 i;
> -    UINT32 id;
> -    DevRes **new_global_res;
> -
>      DEBUG_PRINT((pdev, 3, "%s: entry\n", __FUNCTION__));
> -    RtlZeroMemory(pdev->update_trace_items, sizeof(pdev->update_trace_items));
> -    RingInit(&pdev->update_trace);
> -    for (i = 0; i < NUM_UPDATE_TRACE_ITEMS; i++) {
> -         RingAdd(pdev, &pdev->update_trace, &pdev->update_trace_items[i].link);
> -    }
>  
> -    EngAcquireSemaphore(res_sem);
> +    InitSurfaces(pdev);
> +    InitDeviceMemoryResources(pdev);
>  
> -    id = pdev->dev_id;
> -    if (id >= num_global_res) {
> -        new_global_res = EngAllocMem(FL_ZERO_MEMORY, (id + 1) * sizeof(DevRes *), ALLOC_TAG);
> -        if (!new_global_res) {
> -            PANIC(pdev, "new_global_res malloc failed\n");
> -        }
> -        for (i = 0; i < num_global_res; ++i) {
> -            new_global_res[i] = global_res[i];
> -        }
> -        if (global_res) {
> -            EngFreeMem(global_res);
> -        }
> -        num_global_res = id + 1;
> -        global_res = new_global_res;
> +    pdev->update_id = *pdev->dev_update_id;
> +
> +    pdev->malloc_sem = EngCreateSemaphore();
> +    if (!pdev->malloc_sem) {
> +        PANIC(pdev, "malloc sem creation failed\n");
> +    }
> +    pdev->cmd_sem = EngCreateSemaphore();
> +    if (!pdev->cmd_sem) {
> +        PANIC(pdev, "cmd sem creation failed\n");
> +    }
> +    pdev->cursor_sem = EngCreateSemaphore();
> +    if (!pdev->cursor_sem) {
> +        PANIC(pdev, "cursor sem creation failed\n");
> +    }
> +    pdev->print_sem = EngCreateSemaphore();
> +    if (!pdev->print_sem) {
> +        PANIC(pdev, "print sem creation failed\n");
>      }
>  
> -    if (global_res[id] == NULL) {
> -        global_res[id] = EngAllocMem(FL_ZERO_MEMORY, sizeof(DevRes), ALLOC_TAG);
> -        pdev->Res = global_res[id];
> -        DEBUG_PRINT((pdev, 3, "%s: calling InitRes (id == %d)\n", __FUNCTION__, id));
> -        InitRes(pdev);
> -         DEBUG_PRINT((pdev, 1, "%s: called InitRes (id == %d)\n", __FUNCTION__, id));
> -    } else {
> -        pdev->Res = global_res[id];
> +    ONDBG(pdev->num_outputs = 0);
> +    ONDBG(pdev->num_path_pages = 0);
> +    ONDBG(pdev->num_rects_pages = 0);
> +    ONDBG(pdev->num_bits_pages = 0);
> +    ONDBG(pdev->num_buf_pages = 0);
> +    ONDBG(pdev->num_glyphs_pages = 0);
> +    ONDBG(pdev->num_cursor_pages = 0);
> +
> +#ifdef CALL_TEST
> +    pdev->count_calls = TRUE;
> +    pdev->total_calls = 0;
> +    for (i = 0; i < NUM_CALL_COUNTERS; i++) {
> +        pdev->call_counters[i] = 0;
>      }
> +#endif
>      DEBUG_PRINT((pdev, 1, "%s: exit\n", __FUNCTION__));
> -    EngReleaseSemaphore(res_sem);
>  }
>  
>  static QXLDrawable *GetDrawable(PDev *pdev)
> @@ -693,7 +601,7 @@ static QXLDrawable *GetDrawable(PDev *pdev)
>      RESOURCE_TYPE(output, RESOURCE_TYPE_DRAWABLE);
>      ((QXLDrawable *)output->data)->release_info.id = (UINT64)output;
>      DEBUG_PRINT((pdev, 9, "%s 0x%x\n", __FUNCTION__, output));
> -    ONDBG(pdev->Res->num_outputs++); //todo: atomic
> +    ONDBG(pdev->num_outputs++); //todo: atomic
>      return(QXLDrawable *)output->data;
>  }
>  
> @@ -726,13 +634,13 @@ void PushDrawable(PDev *pdev, QXLDrawable *drawable)
>  {
>      QXLCommand *cmd;
>  
> -    EngAcquireSemaphore(pdev->Res->cmd_sem);
> +    EngAcquireSemaphore(pdev->cmd_sem);
>      WaitForCmdRing(pdev);
>      cmd = SPICE_RING_PROD_ITEM(pdev->cmd_ring);
>      cmd->type = QXL_CMD_DRAW;
>      cmd->data = PA(pdev, drawable, pdev->main_mem_slot);
>      PUSH_CMD(pdev);
> -    EngReleaseSemaphore(pdev->Res->cmd_sem);
> +    EngReleaseSemaphore(pdev->cmd_sem);
>  }
>  
>  static QXLSurfaceCmd *GetSurfaceCmd(PDev *pdev)
> @@ -744,7 +652,7 @@ static QXLSurfaceCmd *GetSurfaceCmd(PDev *pdev)
>      RESOURCE_TYPE(output, RESOURCE_TYPE_SURFACE);
>      ((QXLSurfaceCmd *)output->data)->release_info.id = (UINT64)output;
>      DEBUG_PRINT((pdev, 9, "%s 0x%x\n", __FUNCTION__, output));
> -    ONDBG(pdev->Res->num_outputs++); //todo: atomic
> +    ONDBG(pdev->num_outputs++); //todo: atomic
>      return(QXLSurfaceCmd *)output->data;
>  }
>  
> @@ -766,13 +674,13 @@ void PushSurfaceCmd(PDev *pdev, QXLSurfaceCmd *surface_cmd)
>  {
>      QXLCommand *cmd;
>  
> -    EngAcquireSemaphore(pdev->Res->cmd_sem);
> +    EngAcquireSemaphore(pdev->cmd_sem);
>      WaitForCmdRing(pdev);
>      cmd = SPICE_RING_PROD_ITEM(pdev->cmd_ring);
>      cmd->type = QXL_CMD_SURFACE;
>      cmd->data = PA(pdev, surface_cmd, pdev->main_mem_slot);
>      PUSH_CMD(pdev);
> -    EngReleaseSemaphore(pdev->Res->cmd_sem);
> +    EngReleaseSemaphore(pdev->cmd_sem);
>  }
>  
>  QXLPHYSICAL SurfaceToPhysical(PDev *pdev, UINT8 *base_mem)
> @@ -897,10 +805,10 @@ static void FreePath(PDev *pdev, Resource *res)
>          QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
>          chunk_phys = chunk->next_chunk;
>          FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
> -        ONDBG(pdev->Res->num_path_pages--);
> +        ONDBG(pdev->num_path_pages--);
>      }
>      FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
> -    ONDBG(pdev->Res->num_path_pages--);
> +    ONDBG(pdev->num_path_pages--);
>  
>      DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
>  }
> @@ -1004,7 +912,7 @@ static Resource *__GetPath(PDev *pdev, PATHOBJ *path)
>  
>      DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
>      res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, PATH_ALLOC_SIZE);
> -    ONDBG(pdev->Res->num_path_pages++);
> +    ONDBG(pdev->num_path_pages++);
>      res->refs = 1;
>      res->free = FreePath;
>      RESOURCE_TYPE(res, RESOURCE_TYPE_PATH);
> @@ -1019,7 +927,7 @@ static Resource *__GetPath(PDev *pdev, PATHOBJ *path)
>      now = chunk->data;
>      end = (UINT8 *)res + PATH_ALLOC_SIZE;
>      GetPathCommon(pdev, path, &chunk, &now, &end, &qxl_path->data_size,
> -                  &pdev->Res->num_path_pages);
> +                  &pdev->num_path_pages);
>  
>      DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
>      return res;
> @@ -1051,10 +959,10 @@ static void FreeClipRects(PDev *pdev, Resource *res)
>          QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
>          chunk_phys = chunk->next_chunk;
>          FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
> -        ONDBG(pdev->Res->num_rects_pages--);
> +        ONDBG(pdev->num_rects_pages--);
>      }
>      FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
> -    ONDBG(pdev->Res->num_rects_pages--);
> +    ONDBG(pdev->num_rects_pages--);
>  
>      DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
>  }
> @@ -1077,7 +985,7 @@ static Resource *GetClipRects(PDev *pdev, CLIPOBJ *clip)
>  
>      DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
>      res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, RECTS_ALLOC_SIZE);
> -    ONDBG(pdev->Res->num_rects_pages++);
> +    ONDBG(pdev->num_rects_pages++);
>      res->refs = 1;
>      res->free = FreeClipRects;
>      RESOURCE_TYPE(res, RESOURCE_TYPE_CLIP_RECTS);
> @@ -1106,7 +1014,7 @@ static Resource *GetClipRects(PDev *pdev, CLIPOBJ *clip)
>          for (now = buf.rects, end = now + buf.count; now < end; now++, dest++) {
>              if (dest == dest_end) {
>                  void *page = AllocMem(pdev, MSPACE_TYPE_DEVRAM, RECTS_CHUNK_ALLOC_SIZE);
> -                ONDBG(pdev->Res->num_rects_pages++);
> +                ONDBG(pdev->num_rects_pages++);
>                  chunk->next_chunk = PA(pdev, page, pdev->main_mem_slot);
>                  ((QXLDataChunk *)page)->prev_chunk = PA(pdev, chunk, pdev->main_mem_slot);
>                  chunk = (QXLDataChunk *)page;
> @@ -1460,12 +1368,10 @@ static void ImageKeyPut(PDev *pdev, HSURF hsurf, UINT64 unique, UINT32 key)
>      if (!unique) {
>          return;
>      }
> -    EngAcquireSemaphore(pdev->Res->image_cache_sem);
> -    image_key = &pdev->Res->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
> +    image_key = &pdev->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
>      image_key->hsurf = hsurf;
>      image_key->unique = unique;
>      image_key->key = key;
> -    EngReleaseSemaphore(pdev->Res->image_cache_sem);
>  }
>  
>  static BOOL ImageKeyGet(PDev *pdev, HSURF hsurf, UINT64 unique, UINT32 *key)
> @@ -1476,13 +1382,11 @@ static BOOL ImageKeyGet(PDev *pdev, HSURF hsurf, UINT64 unique, UINT32 *key)
>      if (!unique) {
>          return FALSE;
>      }
> -    EngAcquireSemaphore(pdev->Res->image_cache_sem);
> -    image_key = &pdev->Res->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
> +    image_key = &pdev->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
>      if (image_key->hsurf == hsurf && image_key->unique == unique) {
>          *key = image_key->key;
>          res = TRUE;
>      }
> -    EngReleaseSemaphore(pdev->Res->image_cache_sem);
>      return res;
>  }
>  
> @@ -1493,8 +1397,7 @@ static CacheImage *ImageCacheGetByKey(PDev *pdev, UINT32 key, BOOL check_rest,
>  {
>      CacheImage *cache_image;
>  
> -    EngAcquireSemaphore(pdev->Res->image_cache_sem);
> -    cache_image = pdev->Res->image_cache[IMAGE_HASH_VAL(key)];
> +    cache_image = pdev->image_cache[IMAGE_HASH_VAL(key)];
>      while (cache_image) {
>          if (cache_image->key == key && (!check_rest || (cache_image->format == format &&
>              cache_image->width == width && cache_image->height == height))) {
> @@ -1502,24 +1405,19 @@ static CacheImage *ImageCacheGetByKey(PDev *pdev, UINT32 key, BOOL check_rest,
>          }
>          cache_image = cache_image->next;
>      }
> -    EngReleaseSemaphore(pdev->Res->image_cache_sem);
>      return cache_image;
>  }
>  
> -/* Called with image_cache_sem held */
>  static void ImageCacheAdd(PDev *pdev, CacheImage *cache_image)
>  {
>      int key;
>  
> -    EngAcquireSemaphore(pdev->Res->image_cache_sem);
>      key = IMAGE_HASH_VAL(cache_image->key);
> -    cache_image->next = pdev->Res->image_cache[key];
> +    cache_image->next = pdev->image_cache[key];
>      cache_image->hits = 1;
> -    pdev->Res->image_cache[key] = cache_image;
> -    EngReleaseSemaphore(pdev->Res->image_cache_sem);
> +    pdev->image_cache[key] = cache_image;
>  }
>  
> -/* Called with image_cache_sem held */
>  static void ImageCacheRemove(PDev *pdev, CacheImage *cache_image)
>  {
>      CacheImage **cache_img;
> @@ -1527,7 +1425,7 @@ static void ImageCacheRemove(PDev *pdev, CacheImage *cache_image)
>      if (!cache_image->hits) {
>          return;
>      }
> -    cache_img = &pdev->Res->image_cache[IMAGE_HASH_VAL(cache_image->key)];
> +    cache_img = &pdev->image_cache[IMAGE_HASH_VAL(cache_image->key)];
>      while (*cache_img) {
>          if ((*cache_img)->key == cache_image->key) {
>              *cache_img = cache_image->next;
> @@ -1537,19 +1435,18 @@ static void ImageCacheRemove(PDev *pdev, CacheImage *cache_image)
>      }
>  }
>  
> -/* Called with image_cache_sem held */
>  static CacheImage *AllocCacheImage(PDev* pdev)
>  {
>      RingItem *item;
> -    while (!(item = RingGetTail(pdev, &pdev->Res->cache_image_lru))) {
> +    while (!(item = RingGetTail(pdev, &pdev->cache_image_lru))) {
>          /* malloc_sem protects release_ring too */
> -        EngAcquireSemaphore(pdev->Res->malloc_sem);
> -        if (pdev->Res->free_outputs == 0 &&
> +        EngAcquireSemaphore(pdev->malloc_sem);
> +        if (pdev->free_outputs == 0 &&
>              SPICE_RING_IS_EMPTY(pdev->release_ring)) {
>              WaitForReleaseRing(pdev);
>          }
>          FlushReleaseRing(pdev);
> -        EngReleaseSemaphore(pdev->Res->malloc_sem);
> +        EngReleaseSemaphore(pdev->malloc_sem);
>      }
>      RingRemove(pdev, item);
>      return CONTAINEROF(item, CacheImage, lru_link);
> @@ -1593,7 +1490,6 @@ static _inline void ReleasePalette(PDev *pdev, InternalPalette *palette)
>      }
>  }
>  
> -/* Called with palette_cache_sem held */
>  static _inline void PaletteCacheRemove(PDev *pdev, InternalPalette *palette)
>  {
>      InternalPalette **internal;
> @@ -1602,7 +1498,7 @@ static _inline void PaletteCacheRemove(PDev *pdev, InternalPalette *palette)
>      DEBUG_PRINT((pdev, 15, "%s\n", __FUNCTION__));
>  
>      ASSERT(pdev, palette->palette.unique);
> -    internal = &pdev->Res->palette_cache[PALETTE_HASH_VAL(palette->palette.unique)];
> +    internal = &pdev->palette_cache[PALETTE_HASH_VAL(palette->palette.unique)];
>  
>      while (*internal) {
>          if ((*internal)->palette.unique == palette->palette.unique) {
> @@ -1615,7 +1511,7 @@ static _inline void PaletteCacheRemove(PDev *pdev, InternalPalette *palette)
>  
>      RingRemove(pdev, &palette->lru_link);
>      ReleasePalette(pdev, palette);
> -    pdev->Res->num_palettes--;
> +    pdev->num_palettes--;
>  
>      if (!found) {
>          DEBUG_PRINT((pdev, 0, "%s: Error: palette 0x%x isn't in cache \n", __FUNCTION__, palette));
> @@ -1633,35 +1529,30 @@ static _inline InternalPalette *PaletteCacheGet(PDev *pdev, UINT32 unique)
>      if (!unique) {
>          return NULL;
>      }
> -    EngAcquireSemaphore(pdev->Res->palette_cache_sem);
>  
> -    now = pdev->Res->palette_cache[PALETTE_HASH_VAL(unique)];
> +    now = pdev->palette_cache[PALETTE_HASH_VAL(unique)];
>      while (now) {
>          if (now->palette.unique == unique) {
>              RingRemove(pdev, &now->lru_link);
> -            RingAdd(pdev, &pdev->Res->palette_lru, &now->lru_link);
> +            RingAdd(pdev, &pdev->palette_lru, &now->lru_link);
>              now->refs++;
> -            EngReleaseSemaphore(pdev->Res->palette_cache_sem);
>              DEBUG_PRINT((pdev, 13, "%s: found\n", __FUNCTION__));
>              return now;
>          }
>          now = now->next;
>      }
>      DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
> -    EngReleaseSemaphore(pdev->Res->palette_cache_sem);
>      return NULL;
>  }
>  
>  static void PaletteCacheClear(PDev *pdev)
>  {
>      DEBUG_PRINT((pdev, 1, "%s\n", __FUNCTION__));
> -    EngAcquireSemaphore(pdev->Res->palette_cache_sem);
> -    while(pdev->Res->num_palettes) {
> -        ASSERT(pdev, RingGetTail(pdev, &pdev->Res->palette_lru));
> -        PaletteCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->Res->palette_lru),
> +    while(pdev->num_palettes) {
> +        ASSERT(pdev, RingGetTail(pdev, &pdev->palette_lru));
> +        PaletteCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->palette_lru),
>                                               InternalPalette, lru_link));
>      }
> -    EngReleaseSemaphore(pdev->Res->palette_cache_sem);
>  }
>  
>  static _inline void PaletteCacheAdd(PDev *pdev, InternalPalette *palette)
> @@ -1675,21 +1566,19 @@ static _inline void PaletteCacheAdd(PDev *pdev, InternalPalette *palette)
>          return;
>      }
>  
> -    EngAcquireSemaphore(pdev->Res->palette_cache_sem);
> -    if (pdev->Res->num_palettes == PALETTE_CACHE_SIZE) {
> -        ASSERT(pdev, RingGetTail(pdev, &pdev->Res->palette_lru));
> -        PaletteCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->Res->palette_lru),
> +    if (pdev->num_palettes == PALETTE_CACHE_SIZE) {
> +        ASSERT(pdev, RingGetTail(pdev, &pdev->palette_lru));
> +        PaletteCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->palette_lru),
>                                               InternalPalette, lru_link));
>      }
>  
>      key = PALETTE_HASH_VAL(palette->palette.unique);
> -    palette->next = pdev->Res->palette_cache[key];
> -    pdev->Res->palette_cache[key] = palette;
> +    palette->next = pdev->palette_cache[key];
> +    pdev->palette_cache[key] = palette;
>  
> -    RingAdd(pdev, &pdev->Res->palette_lru, &palette->lru_link);
> +    RingAdd(pdev, &pdev->palette_lru, &palette->lru_link);
>      palette->refs++;
> -    pdev->Res->num_palettes++;
> -    EngReleaseSemaphore(pdev->Res->palette_cache_sem);
> +    pdev->num_palettes++;
>      DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
>  }
>  
> @@ -1732,10 +1621,8 @@ static void FreeQuicImage(PDev *pdev, Resource *res) // todo: defer
>  
>      internal = (InternalImage *)res->res;
>      if (internal->cache) {
> -        EngAcquireSemaphore(pdev->Res->image_cache_sem);
> -        RingAdd(pdev, &pdev->Res->cache_image_lru, &internal->cache->lru_link);
> +        RingAdd(pdev, &pdev->cache_image_lru, &internal->cache->lru_link);
>          internal->cache->image = NULL;
> -        EngReleaseSemaphore(pdev->Res->image_cache_sem);
>      }
>  
>      chunk_phys = ((QXLDataChunk *)internal->image.quic.data)->next_chunk;
> @@ -1743,11 +1630,11 @@ static void FreeQuicImage(PDev *pdev, Resource *res) // todo: defer
>          QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
>          chunk_phys = chunk->next_chunk;
>          FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
> -        ONDBG(pdev->Res->num_bits_pages--);
> +        ONDBG(pdev->num_bits_pages--);
>  
>      }
>      FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
> -    ONDBG(pdev->Res->num_bits_pages--);
> +    ONDBG(pdev->num_bits_pages--);
>      DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
>  }
>  
> @@ -1806,7 +1693,7 @@ static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_
>  
>      usr_data->chunk_io_words = alloc_size >> 2;
>  
> -    ONDBG(pdev->Res->num_bits_pages++);
> +    ONDBG(pdev->num_bits_pages++);
>  
>      *io_ptr = (UINT32 *)new_chank->data;
>      return usr_data->chunk_io_words;
> @@ -1848,7 +1735,7 @@ static _inline Resource *GetQuicImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color
>      alloc_size = MAX(alloc_size, QUIC_ALLOC_BASE + QUIC_BUF_MIN);
>  
>      image_res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, alloc_size);
> -    ONDBG(pdev->Res->num_bits_pages++);
> +    ONDBG(pdev->num_bits_pages++);
>      image_res->refs = 1;
>      image_res->free = FreeQuicImage;
>      RESOURCE_TYPE(image_res, RESOURCE_TYPE_QUIC_IMAGE);
> @@ -1898,10 +1785,8 @@ static void FreeBitmapImage(PDev *pdev, Resource *res) // todo: defer
>  
>      internal = (InternalImage *)res->res;
>      if (internal->cache) {
> -        EngAcquireSemaphore(pdev->Res->image_cache_sem);
> -        RingAdd(pdev, &pdev->Res->cache_image_lru, &internal->cache->lru_link);
> +        RingAdd(pdev, &pdev->cache_image_lru, &internal->cache->lru_link);
>          internal->cache->image = NULL;
> -        EngReleaseSemaphore(pdev->Res->image_cache_sem);
>      }
>  
>      if (internal->image.bitmap.palette) {
> @@ -1915,12 +1800,12 @@ static void FreeBitmapImage(PDev *pdev, Resource *res) // todo: defer
>          QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
>          chunk_phys = chunk->next_chunk;
>          FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
> -        ONDBG(pdev->Res->num_bits_pages--);
> +        ONDBG(pdev->num_bits_pages--);
>  
>      }
>  
>      FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
> -    ONDBG(pdev->Res->num_bits_pages--);
> +    ONDBG(pdev->num_bits_pages--);
>      DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
>  }
>  
> @@ -1990,7 +1875,7 @@ static _inline Resource *GetBitmapImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *col
>      alloc_size = BITMAP_ALLOC_BASE + BITS_BUF_MAX - BITS_BUF_MAX % line_size;
>      alloc_size = MIN(BITMAP_ALLOC_BASE + height * line_size, alloc_size);
>      image_res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, alloc_size);
> -    ONDBG(pdev->Res->num_bits_pages++);
> +    ONDBG(pdev->num_bits_pages++);
>  
>      image_res->refs = 1;
>      image_res->free = FreeBitmapImage;
> @@ -2023,7 +1908,7 @@ static _inline Resource *GetBitmapImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *col
>  #endif
>      for (; src != src_end; src -= surf->lDelta, alloc_size -= line_size) {
>          PutBytesAlign(pdev, &chunk, &dest, &dest_end, src, line_size,
> -                      &pdev->Res->num_bits_pages, alloc_size, line_size, use_sse);
> +                      &pdev->num_bits_pages, alloc_size, line_size, use_sse);
>      }
>  #ifndef _WIN64
>      if (use_sse) {
> @@ -2220,7 +2105,6 @@ static CacheImage *GetCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
>  
>      if (CacheSizeTest(pdev, surf)) {
>          CacheImage *cache_image;
> -        EngAcquireSemaphore(pdev->Res->image_cache_sem);
>          cache_image = AllocCacheImage(pdev);
>          ImageCacheRemove(pdev, cache_image);
>          cache_image->key = key;
> @@ -2229,13 +2113,13 @@ static CacheImage *GetCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
>          cache_image->width = surf->sizlBitmap.cx;
>          cache_image->height = surf->sizlBitmap.cy;
>          ImageCacheAdd(pdev, cache_image);
> -        RingAdd(pdev, &pdev->Res->cache_image_lru, &cache_image->lru_link);
> -        EngReleaseSemaphore(pdev->Res->image_cache_sem);
> +        RingAdd(pdev, &pdev->cache_image_lru, &cache_image->lru_link);
>          DEBUG_PRINT((pdev, 11, "%s: ImageCacheAdd %u\n", __FUNCTION__, key));
>      }
>      return NULL;
>  }
>  
> +// TODO: reconsider
>  static HSEMAPHORE image_id_sem = NULL;
>  
>  static _inline UINT32 get_image_serial()
> @@ -2302,7 +2186,7 @@ BOOL QXLGetBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phys, SU
>          alloc_size = sizeof(Resource) + sizeof(InternalImage);
>          image_res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, alloc_size);
>  
> -        ONDBG(pdev->Res->num_bits_pages++);
> +        ONDBG(pdev->num_bits_pages++);
>          image_res->refs = 1;
>          image_res->free = FreeSurfaceImage;
>          RESOURCE_TYPE(image_res, RESOURCE_TYPE_SURFACE_IMAGE);
> @@ -2469,7 +2353,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
>          alloc_size = sizeof(Resource) + sizeof(InternalImage);
>          image_res = AllocMem(pdev, MSPACE_TYPE_DEVRAM, alloc_size);
>  
> -        ONDBG(pdev->Res->num_bits_pages++);
> +        ONDBG(pdev->num_bits_pages++);
>          image_res->refs = 1;
>          image_res->free = FreeSurfaceImage;
>          RESOURCE_TYPE(image_res, RESOURCE_TYPE_SURFACE_IMAGE);
> @@ -2523,7 +2407,6 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
>          }
>      } else if (CacheSizeTest(pdev, surf)) {
>          CacheImage *cache_image;
> -        EngAcquireSemaphore(pdev->Res->image_cache_sem);
>          cache_image = AllocCacheImage(pdev);
>          ImageCacheRemove(pdev, cache_image);
>          cache_image->key = key;
> @@ -2532,8 +2415,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
>          cache_image->width = surf->sizlBitmap.cx;
>          cache_image->height = surf->sizlBitmap.cy;
>          ImageCacheAdd(pdev, cache_image);
> -        RingAdd(pdev, &pdev->Res->cache_image_lru, &cache_image->lru_link);
> -        EngReleaseSemaphore(pdev->Res->image_cache_sem);
> +        RingAdd(pdev, &pdev->cache_image_lru, &cache_image->lru_link);
>          DEBUG_PRINT((pdev, 11, "%s: ImageCacheAdd %u\n", __FUNCTION__, key));
>      }
>  
> @@ -2619,7 +2501,7 @@ BOOL QXLGetMask(PDev *pdev, QXLDrawable *drawable, QXLQMask *qxl_mask, SURFOBJ *
>  
>  static void FreeBuf(PDev *pdev, Resource *res)
>  {
> -    ONDBG(pdev->Res->num_buf_pages--);
> +    ONDBG(pdev->num_buf_pages--);
>      FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
>  }
>  
> @@ -2634,7 +2516,7 @@ UINT8 *QXLGetBuf(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *buf_phys, UINT3
>      }
>  
>      buf_res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, sizeof(Resource) + size);
> -    ONDBG(pdev->Res->num_buf_pages++);
> +    ONDBG(pdev->num_buf_pages++);
>      buf_res->refs = 1;
>      buf_res->free = FreeBuf;
>      RESOURCE_TYPE(buf_res, RESOURCE_TYPE_BUF);
> @@ -2659,26 +2541,26 @@ void UpdateArea(PDev *pdev, RECTL *area, UINT32 surface_id)
>      output->num_res = 0;
>      updat_cmd = (QXLUpdateCmd *)output->data;
>      updat_cmd->release_info.id = (UINT64)output;
> -    ONDBG(pdev->Res->num_outputs++); //todo: atomic
> +    ONDBG(pdev->num_outputs++); //todo: atomic
>  
>      CopyRect(&updat_cmd->area, area);
> -    updat_cmd->update_id = ++pdev->Res->update_id;
> +    updat_cmd->update_id = ++pdev->update_id;
>      updat_cmd->surface_id = surface_id;
>  
> -    EngAcquireSemaphore(pdev->Res->cmd_sem);
> +    EngAcquireSemaphore(pdev->cmd_sem);
>      WaitForCmdRing(pdev);
>      cmd = SPICE_RING_PROD_ITEM(pdev->cmd_ring);
>      cmd->type = QXL_CMD_UPDATE;
>      cmd->data = PA(pdev, updat_cmd, pdev->main_mem_slot);
>      PUSH_CMD(pdev);
> -    EngReleaseSemaphore(pdev->Res->cmd_sem);
> +    EngReleaseSemaphore(pdev->cmd_sem);
>      do {
>  #ifdef DBG
>          {
>              LARGE_INTEGER timeout; // 1 => 100 nanoseconds
>              timeout.QuadPart = -1 * (1000 * 1000 * 10); //negative  => relative // 1s
>              WAIT_FOR_EVENT(pdev, pdev->display_event, &timeout);
> -            if (*pdev->dev_update_id != pdev->Res->update_id) {
> +            if (*pdev->dev_update_id != pdev->update_id) {
>                  DEBUG_PRINT((pdev, 0, "%s: 0x%lx: timeout\n", __FUNCTION__, pdev));
>              }
>          }
> @@ -2686,7 +2568,7 @@ void UpdateArea(PDev *pdev, RECTL *area, UINT32 surface_id)
>          WAIT_FOR_EVENT(pdev, pdev->display_event, NULL);
>  #endif // DEBUG
>          mb();
> -    } while (*pdev->dev_update_id != pdev->Res->update_id);
> +    } while (*pdev->dev_update_id != pdev->update_id);
>  }
>  
>  #else
> @@ -2718,7 +2600,7 @@ static _inline void add_rast_glyphs(PDev *pdev, QXLString *str, ULONG count, GLY
>          UINT32 stride;
>  
>          if (end - now < sizeof(*glyph)) {
> -            NEW_DATA_CHUNK(&pdev->Res->num_glyphs_pages, PAGE_SIZE);
> +            NEW_DATA_CHUNK(&pdev->num_glyphs_pages, PAGE_SIZE);
>          }
>  
>          glyph = (QXLRasterGlyph *)now;
> @@ -2758,7 +2640,7 @@ static _inline void add_rast_glyphs(PDev *pdev, QXLString *str, ULONG count, GLY
>                  UINT8 val;
>                  int i;
>                  if (end - now < sizeof(*bits_pos)) {
> -                    NEW_DATA_CHUNK(&pdev->Res->num_glyphs_pages, PAGE_SIZE);
> +                    NEW_DATA_CHUNK(&pdev->num_glyphs_pages, PAGE_SIZE);
>                  }
>                  *(UINT8 *)now = *bits_pos;
>                  now += sizeof(*bits_pos);
> @@ -2794,11 +2676,11 @@ static void FreeSring(PDev *pdev, Resource *res)
>          QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
>          chunk_phys = chunk->next_chunk;
>          FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
> -        ONDBG(pdev->Res->num_glyphs_pages--);
> +        ONDBG(pdev->num_glyphs_pages--);
>      }
>  
>      FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
> -    ONDBG(pdev->Res->num_glyphs_pages--);
> +    ONDBG(pdev->num_glyphs_pages--);
>  
>      DEBUG_PRINT((pdev, 14, "%s: done\n", __FUNCTION__));
>  }
> @@ -2822,7 +2704,7 @@ BOOL QXLGetStr(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *str_phys, FONTOBJ
>      DEBUG_PRINT((pdev, 9, "%s\n", __FUNCTION__));
>  
>      str_res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, TEXT_ALLOC_SIZE);
> -    ONDBG(pdev->Res->num_glyphs_pages++);
> +    ONDBG(pdev->num_glyphs_pages++);
>      str_res->refs = 1;
>      str_res->free = FreeSring;
>      RESOURCE_TYPE(str_res, RESOURCE_TYPE_SRING);
> @@ -2907,7 +2789,7 @@ QXLCursorCmd *CursorCmd(PDev *pdev)
>      RESOURCE_TYPE(output, RESOURCE_TYPE_CURSOR);
>      cursor_cmd = (QXLCursorCmd *)output->data;
>      cursor_cmd->release_info.id = (UINT64)output;
> -    ONDBG(pdev->Res->num_outputs++); //todo: atomic
> +    ONDBG(pdev->num_outputs++); //todo: atomic
>      DEBUG_PRINT((pdev, 8, "%s: done\n", __FUNCTION__));
>      return cursor_cmd;
>  }
> @@ -2917,13 +2799,13 @@ void PushCursorCmd(PDev *pdev, QXLCursorCmd *cursor_cmd)
>      QXLCommand *cmd;
>  
>      DEBUG_PRINT((pdev, 6, "%s\n", __FUNCTION__));
> -    EngAcquireSemaphore(pdev->Res->cursor_sem);
> +    EngAcquireSemaphore(pdev->cursor_sem);
>      WaitForCursorRing(pdev);
>      cmd = SPICE_RING_PROD_ITEM(pdev->cursor_ring);
>      cmd->type = QXL_CMD_CURSOR;
>      cmd->data = PA(pdev, cursor_cmd, pdev->main_mem_slot);
>      PUSH_CURSOR_CMD(pdev);
> -    EngReleaseSemaphore(pdev->Res->cursor_sem);
> +    EngReleaseSemaphore(pdev->cursor_sem);
>      DEBUG_PRINT((pdev, 8, "%s: done\n", __FUNCTION__));
>  }
>  
> @@ -2938,7 +2820,6 @@ typedef struct InternalCursor {
>  
>  #define CURSOR_HASH_VAL(hsurf) (HSURF_HASH_VAL(hsurf) & CURSOR_HASH_NASKE)
>  
> -/* Called with cursor_cache_sem held */
>  static void CursorCacheRemove(PDev *pdev, InternalCursor *cursor)
>  {
>      InternalCursor **internal;
> @@ -2947,7 +2828,7 @@ static void CursorCacheRemove(PDev *pdev, InternalCursor *cursor)
>      DEBUG_PRINT((pdev, 12, "%s\n", __FUNCTION__));
>  
>      ASSERT(pdev, cursor->unique);
> -    internal = &pdev->Res->cursor_cache[CURSOR_HASH_VAL(cursor->hsurf)];
> +    internal = &pdev->cursor_cache[CURSOR_HASH_VAL(cursor->hsurf)];
>  
>      while (*internal) {
>          if ((*internal)->hsurf == cursor->hsurf) {
> @@ -2963,7 +2844,7 @@ static void CursorCacheRemove(PDev *pdev, InternalCursor *cursor)
>  
>      RingRemove(pdev, &cursor->lru_link);
>      RELEASE_RES(pdev, (Resource *)((UINT8 *)cursor - sizeof(Resource)));
> -    pdev->Res->num_cursors--;
> +    pdev->num_cursors--;
>  
>      if (!found) {
>          DEBUG_PRINT((pdev, 0, "%s: Error: cursor 0x%x isn't in cache \n", __FUNCTION__, cursor));
> @@ -2977,13 +2858,11 @@ static void CursorCacheRemove(PDev *pdev, InternalCursor *cursor)
>  static void CursorCacheClear(PDev *pdev)
>  {
>      DEBUG_PRINT((pdev, 1, "%s\n", __FUNCTION__));
> -    EngAcquireSemaphore(pdev->Res->cursor_cache_sem);
> -    while (pdev->Res->num_cursors) {
> -        ASSERT(pdev, RingGetTail(pdev, &pdev->Res->cursors_lru));
> -        CursorCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->Res->cursors_lru),
> +    while (pdev->num_cursors) {
> +        ASSERT(pdev, RingGetTail(pdev, &pdev->cursors_lru));
> +        CursorCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->cursors_lru),
>                                              InternalCursor, lru_link));
>      }
> -    EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
>  }
>  
>  static void CursorCacheAdd(PDev *pdev, InternalCursor *cursor)
> @@ -2996,21 +2875,19 @@ static void CursorCacheAdd(PDev *pdev, InternalCursor *cursor)
>          return;
>      }
>  
> -    EngAcquireSemaphore(pdev->Res->cursor_cache_sem);
> -    if (pdev->Res->num_cursors == CURSOR_CACHE_SIZE) {
> -        ASSERT(pdev, RingGetTail(pdev, &pdev->Res->cursors_lru));
> -        CursorCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->Res->cursors_lru),
> +    if (pdev->num_cursors == CURSOR_CACHE_SIZE) {
> +        ASSERT(pdev, RingGetTail(pdev, &pdev->cursors_lru));
> +        CursorCacheRemove(pdev, CONTAINEROF(RingGetTail(pdev, &pdev->cursors_lru),
>                                              InternalCursor, lru_link));
>      }
>  
>      key = CURSOR_HASH_VAL(cursor->hsurf);
> -    cursor->next = pdev->Res->cursor_cache[key];
> -    pdev->Res->cursor_cache[key] = cursor;
> +    cursor->next = pdev->cursor_cache[key];
> +    pdev->cursor_cache[key] = cursor;
>  
> -    RingAdd(pdev, &pdev->Res->cursors_lru, &cursor->lru_link);
> +    RingAdd(pdev, &pdev->cursors_lru, &cursor->lru_link);
>      GET_RES((Resource *)((UINT8 *)cursor - sizeof(Resource)));
> -    pdev->Res->num_cursors++;
> -    EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
> +    pdev->num_cursors++;
>  }
>  
>  static InternalCursor *CursorCacheGet(PDev *pdev, HSURF hsurf, UINT32 unique)
> @@ -3022,15 +2899,13 @@ static InternalCursor *CursorCacheGet(PDev *pdev, HSURF hsurf, UINT32 unique)
>          return NULL;
>      }
>  
> -    EngAcquireSemaphore(pdev->Res->cursor_cache_sem);
> -    internal = &pdev->Res->cursor_cache[CURSOR_HASH_VAL(hsurf)];
> +    internal = &pdev->cursor_cache[CURSOR_HASH_VAL(hsurf)];
>      while (*internal) {
>          InternalCursor *now = *internal;
>          if (now->hsurf == hsurf) {
>              if (now->unique == unique) {
>                  RingRemove(pdev, &now->lru_link);
> -                RingAdd(pdev, &pdev->Res->cursors_lru, &now->lru_link);
> -                EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
> +                RingAdd(pdev, &pdev->cursors_lru, &now->lru_link);
>                  return now;
>              }
>              CursorCacheRemove(pdev, now);
> @@ -3038,7 +2913,6 @@ static InternalCursor *CursorCacheGet(PDev *pdev, HSURF hsurf, UINT32 unique)
>          }
>          internal = &now->next;
>      }
> -    EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
>      return NULL;
>  }
>  
> @@ -3052,11 +2926,11 @@ static void FreeCursor(PDev *pdev, Resource *res)
>          QXLDataChunk *chunk = (QXLDataChunk *)VA(pdev, chunk_phys, pdev->main_mem_slot);
>          chunk_phys = chunk->next_chunk;
>          FreeMem(pdev, MSPACE_TYPE_DEVRAM, chunk);
> -        ONDBG(pdev->Res->num_cursor_pages--);
> +        ONDBG(pdev->num_cursor_pages--);
>      }
>  
>      FreeMem(pdev, MSPACE_TYPE_DEVRAM, res);
> -    ONDBG(pdev->Res->num_cursor_pages--);
> +    ONDBG(pdev->num_cursor_pages--);
>  
>      DEBUG_PRINT((pdev, 13, "%s: done\n", __FUNCTION__));
>  }
> @@ -3136,7 +3010,7 @@ static BOOL GetCursorCommon(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_
>  
>      ASSERT(pdev, sizeof(Resource) + sizeof(InternalCursor) < CURSOR_ALLOC_SIZE);
>      res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, CURSOR_ALLOC_SIZE);
> -    ONDBG(pdev->Res->num_cursor_pages++);
> +    ONDBG(pdev->num_cursor_pages++);
>      res->refs = 1;
>      res->free = FreeCursor;
>      RESOURCE_TYPE(res, RESOURCE_TYPE_CURSOR);
> @@ -3148,9 +3022,7 @@ static BOOL GetCursorCommon(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_
>  
>      cursor = info->cursor = &internal->cursor;
>      cursor->header.type = type;
> -    EngAcquireSemaphore(pdev->Res->cursor_cache_sem);
> -    cursor->header.unique = unique ? ++pdev->Res->last_cursor_id : 0;
> -    EngReleaseSemaphore(pdev->Res->cursor_cache_sem);
> +    cursor->header.unique = unique ? ++pdev->last_cursor_id : 0;
>      cursor->header.width = (UINT16)local_surf->sizlBitmap.cx;
>      cursor->header.height = (type == SPICE_CURSOR_TYPE_MONO) ? (UINT16)local_surf->sizlBitmap.cy >> 1 :
>                              (UINT16)local_surf->sizlBitmap.cy;
> @@ -3194,7 +3066,7 @@ static BOOL GetCursorCommon(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_
>      src_end = src + (local_surf->lDelta * local_surf->sizlBitmap.cy);
>      for (; src != src_end; src += local_surf->lDelta) {
>          PutBytes(pdev, &info->chunk, &info->now, &info->end, src, line_size,
> -                 &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
> +                 &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
>      }
>  
>      CursorCacheAdd(pdev, internal);
> @@ -3313,14 +3185,14 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
>  
>              if (pdev->bitmap_format == BMF_32BPP) {
>                  PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)color_trans->pulXlate,
> -                         256 << 2, &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
> +                         256 << 2, &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
>              } else {
>                  int i;
>  
>                  for (i = 0; i < 256; i++) {
>                      UINT32 ent = _16bppTo32bpp(color_trans->pulXlate[i]);
>                      PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)&ent,
> -                             4, &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
> +                             4, &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
>                  }
>              }
>              info.cursor->data_size += 256 << 2;
> @@ -3333,14 +3205,14 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
>  
>              if (pdev->bitmap_format == BMF_32BPP) {
>                  PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)color_trans->pulXlate,
> -                         16 << 2, &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
> +                         16 << 2, &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
>              } else {
>                  int i;
>  
>                  for (i = 0; i < 16; i++) {
>                      UINT32 ent = _16bppTo32bpp(color_trans->pulXlate[i]);
>                      PutBytes(pdev, &info.chunk, &info.now, &info.end, (UINT8 *)&ent,
> -                             4, &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
> +                             4, &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
>                  }
>              }
>              info.cursor->data_size += 16 << 2;
> @@ -3356,7 +3228,7 @@ BOOL GetColorCursor(PDev *pdev, QXLCursorCmd *cmd, LONG hot_x, LONG hot_y, SURFO
>  
>          for (; src != src_end; src += mask->lDelta) {
>              PutBytes(pdev, &info.chunk, &info.now, &info.end, src, line_size,
> -                     &pdev->Res->num_cursor_pages, PAGE_SIZE, FALSE);
> +                     &pdev->num_cursor_pages, PAGE_SIZE, FALSE);
>          }
>      }
>  
> @@ -3374,7 +3246,7 @@ BOOL GetTransparentCursor(PDev *pdev, QXLCursorCmd *cmd)
>      ASSERT(pdev, sizeof(Resource) + sizeof(InternalCursor) < PAGE_SIZE);
>  
>      res = (Resource *)AllocMem(pdev, MSPACE_TYPE_DEVRAM, sizeof(Resource) + sizeof(InternalCursor));
> -    ONDBG(pdev->Res->num_cursor_pages++);
> +    ONDBG(pdev->num_cursor_pages++);
>      res->refs = 1;
>      res->free = FreeCursor;
>      RESOURCE_TYPE(res, RESOURCE_TYPE_CURSOR);
> diff --git a/display/res.h b/display/res.h
> index d447cee..d69986e 100644
> --- a/display/res.h
> +++ b/display/res.h
> @@ -73,6 +73,5 @@ void CheckAndSetSSE2();
>  void EmptyReleaseRing(PDev *pdev);
>  void InitDeviceMemoryResources(PDev *pdev);
>  void ReleaseCacheDeviceMemoryResources(PDev *pdev);
> -extern DevRes **global_res;
>  
>  #endif
> diff --git a/display/surface.c b/display/surface.c
> index 8422cd3..60bbd99 100644
> --- a/display/surface.c
> +++ b/display/surface.c
> @@ -208,14 +208,15 @@ VOID DeleteDeviceBitmap(PDev *pdev, UINT32 surface_id, UINT8 allocation_type)
>      FreeDrawArea(drawarea);
>  
>      if (allocation_type != DEVICE_BITMAP_ALLOCATION_TYPE_SURF0 &&
> -        pdev->Res->surfaces_info[surface_id].draw_area.base_mem != NULL) {
> +        pdev->surfaces_info[surface_id].draw_area.base_mem != NULL) {
>  
>          if (allocation_type == DEVICE_BITMAP_ALLOCATION_TYPE_RAM) {
>              /* server side this surface is already destroyed, just free it here */
> -            ASSERT(pdev, pdev->Res->surfaces_info[surface_id].draw_area.base_mem ==
> -                pdev->Res->surfaces_info[surface_id].copy);
> -            QXLDelSurface(pdev, pdev->Res->surfaces_info[surface_id].draw_area.base_mem,
> -                allocation_type);
> +            ASSERT(pdev, pdev->surfaces_info[surface_id].draw_area.base_mem ==
> +                         pdev->surfaces_info[surface_id].copy);
> +            QXLDelSurface(pdev,
> +                          pdev->surfaces_info[surface_id].draw_area.base_mem,
> +                          allocation_type);
>              FreeSurfaceInfo(pdev, surface_id);
>          } else {
>              QXLSurfaceCmd *surface_cmd;
> @@ -286,7 +287,7 @@ int MoveAllSurfacesToVideoRam(PDev *pdev)
>      SurfaceInfo *surface_info;
>  
>      /* brute force implementation - alternative is to keep an updated used_surfaces list */
> -    DEBUG_PRINT((pdev, 3, "%s\n", __FUNCTION__));
> +    DEBUG_PRINT((pdev, 3, "%s %p\n", __FUNCTION__, pdev));
>  
>      for (surface_id = 1 ; surface_id < pdev->n_surfaces ; ++surface_id) {
>          surface_info = GetSurfaceInfo(pdev, surface_id);
> diff --git a/display/surface.h b/display/surface.h
> index d770884..c3e5a47 100644
> --- a/display/surface.h
> +++ b/display/surface.h
> @@ -26,7 +26,7 @@ static _inline UINT32 GetSurfaceIdFromInfo(SurfaceInfo *info)
>    if (info == &pdev->surface0_info) {
>      return 0;
>    }
> -  return (UINT32)(info - pdev->Res->surfaces_info);
> +  return (UINT32)(info - pdev->surfaces_info);
>  }
>  
>  static _inline SurfaceInfo *GetSurfaceInfo(PDev *pdev, UINT32 id)
> @@ -34,7 +34,7 @@ static _inline SurfaceInfo *GetSurfaceInfo(PDev *pdev, UINT32 id)
>    if (id == 0) {
>      return &pdev->surface0_info;
>    }
> -  return &pdev->Res->surfaces_info[id];
> +  return &pdev->surfaces_info[id];
>  }
>  
>  static _inline UINT32 GetSurfaceId(SURFOBJ *surf)
> @@ -55,42 +55,34 @@ static _inline void FreeSurfaceInfo(PDev *pdev, UINT32 surface_id)
>      if (surface_id == 0) {
>          return;
>      }
> -    EngAcquireSemaphore(pdev->Res->surface_sem);
>  
>      DEBUG_PRINT((pdev, 9, "%s: %p: %d\n", __FUNCTION__, pdev, surface_id));
> -    surface = &pdev->Res->surfaces_info[surface_id];
> +    surface = &pdev->surfaces_info[surface_id];
>      if (surface->draw_area.base_mem == NULL) {
>          DEBUG_PRINT((pdev, 9, "%s: %p: %d: double free. safely ignored\n", __FUNCTION__,
> -            pdev, surface_id));
> -        EngReleaseSemaphore(pdev->Res->surface_sem);
> +                     pdev, surface_id));
>          return;
>      }
>      surface->draw_area.base_mem = NULL; /* Mark as not used */
> -    surface->u.next_free = pdev->Res->free_surfaces;
> -    pdev->Res->free_surfaces = surface;
> -
> -    EngReleaseSemaphore(pdev->Res->surface_sem);
> +    surface->u.next_free = pdev->free_surfaces;
> +    pdev->free_surfaces = surface;
>  }
>  
> -
>  static UINT32 GetFreeSurface(PDev *pdev)
>  {
>      UINT32 x, id;
>      SurfaceInfo *surface;
>  
> -    EngAcquireSemaphore(pdev->Res->surface_sem);
> -
> -    surface = pdev->Res->free_surfaces;
> +    ASSERT(pdev, pdev->enabled);
> +    surface = pdev->free_surfaces;
>      if (surface == NULL) {
>          id = 0;
>      } else {
> -      pdev->Res->free_surfaces = surface->u.next_free;
> +      pdev->free_surfaces = surface->u.next_free;
>  
> -      id = (UINT32)(surface - pdev->Res->surfaces_info);
> +      id = (UINT32)(surface - pdev->surfaces_info);
>      }
>  
> -    EngReleaseSemaphore(pdev->Res->surface_sem);
> -
>      return id;
>  }
>  
> -- 
> 1.7.4.4
> 


More information about the Spice-devel mailing list