diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-04-02 08:36:14 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-04-02 09:49:53 +0100 |
commit | f98b2e164637292c2425f6e6d2c22bd9a2800f8e (patch) | |
tree | 5c9aa6320cb7057f1b3af81244896e71b6b9a431 | |
parent | a926d9f68231ac0f2a1f54c7a722979a8ed6e9e1 (diff) |
sna: Prevent signal re-entrancy into cursor update routines
As we may need to allocate from within the cursor update, we are prone
to re-entrancy issues within malloc()/free(). To avoid these we need to
block SigIO (for pointer updates) whilst in the critical section.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna.h | 1 | ||||
-rw-r--r-- | src/sna/sna_display.c | 115 |
2 files changed, 68 insertions, 48 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h index 00175828..3d0b1cfa 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -290,6 +290,7 @@ struct sna { unsigned serial; uint32_t fg, bg; + int size; int last_x; int last_y; diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index b186c988..8657dabf 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -107,7 +107,7 @@ struct sna_crtc { int dpms_mode; PixmapPtr scanout_pixmap; struct kgem_bo *bo, *shadow_bo; - uint32_t cursor; + struct sna_cursor *cursor; uint32_t sprite; bool shadow; bool fallback_shadow; @@ -1585,6 +1585,7 @@ retry: /* Attach per-crtc pixmap or direct */ if (saved_bo) kgem_bo_destroy(&sna->kgem, saved_bo); + sna_crtc->cursor = NULL; /* reattach cursor on next update */ sna_crtc_randr(crtc); if (sna_crtc->shadow) sna_crtc_damage(crtc); @@ -3067,9 +3068,10 @@ rotate_coord_back(Rotation rotation, int w, int h, int *x, int *y) } } -static struct sna_cursor *__sna_create_cursor(struct sna *sna, unsigned size) +static struct sna_cursor *__sna_create_cursor(struct sna *sna) { struct sna_cursor *c; + int size = sna->cursor.size; __DBG(("%s(size=%d)\n", __FUNCTION__, size)); @@ -3106,14 +3108,25 @@ static struct sna_cursor *__sna_create_cursor(struct sna *sna, unsigned size) static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc) { struct sna_cursor *cursor; - Rotation rotation; - int width, height, size; - int i, x, y; uint32_t *src; + int width, height, size, x, y; + Rotation rotation; if (sna->cursor.ref == NULL || sna->cursor.ref->bits == NULL) return NULL; + cursor = to_sna_crtc(crtc)->cursor; + __DBG(("%s: current cursor handle=%d, serial=%d [expected %d]\n", + __FUNCTION__, + cursor ? cursor->handle : 0, + cursor ? cursor->serial : 0, + sna->cursor.serial)); + if (cursor && cursor->serial == sna->cursor.serial) { + assert(cursor->size == sna->cursor.size); + assert(cursor->rotation == crtc->transform_in_use ? crtc->rotation : RR_Rotate_0); + return cursor; + } + __DBG(("%s: cursor=%dx%d, serial=%d\n", __FUNCTION__, sna->cursor.ref->bits->width, sna->cursor.ref->bits->height, @@ -3124,21 +3137,12 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc) if (cursor->serial == sna->cursor.serial && cursor->rotation == rotation) { __DBG(("%s: reusing handle=%d, serial=%d, rotation=%d, size=%d\n", __FUNCTION__, cursor->handle, cursor->serial, cursor->rotation, cursor->size)); -#if HAS_DEBUG_FULL - i = MAX(sna->cursor.ref->bits->width, sna->cursor.ref->bits->height); - for (size = 64; size < i; size <<= 1) - ; - assert(cursor->size == size); -#endif + assert(cursor->size == sna->cursor.size); return cursor; } } - i = MAX(sna->cursor.ref->bits->width, sna->cursor.ref->bits->height); - for (size = 64; size < i; size <<= 1) - ; - assert(size <= sna->cursor.max_size); - + size = sna->cursor.size; for (cursor = sna->cursor.cursors; cursor; cursor = cursor->next) { if (cursor->alloc >= 4*size*size && cursor->serial != sna->cursor.serial) { __DBG(("%s: stealing handle=%d, serial=%d, rotation=%d, alloc=%d\n", @@ -3148,7 +3152,7 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc) } if (cursor == NULL) { - cursor = __sna_create_cursor(sna, size); + cursor = __sna_create_cursor(sna); if (cursor == NULL) return NULL; } @@ -3237,6 +3241,7 @@ sna_show_cursors(ScrnInfoPtr scrn) __DBG(("%s\n", __FUNCTION__)); + OsBlockSIGIO(); for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; struct sna_crtc *sna_crtc = to_sna_crtc(crtc); @@ -3252,17 +3257,15 @@ sna_show_cursors(ScrnInfoPtr scrn) if (!crtc->cursor_in_range) continue; - cursor = __sna_get_cursor(sna, crtc); - if (cursor == NULL) { - assert(sna_crtc->cursor == 0); + if (sna_crtc->cursor) continue; - } - if (sna_crtc->cursor == cursor->handle) + cursor = __sna_get_cursor(sna, crtc); + if (cursor == NULL) continue; - __DBG(("%s: CRTC:%d, handle=%d->%d\n", __FUNCTION__, - sna_crtc->id, sna_crtc->cursor, cursor->handle)); + __DBG(("%s: CRTC:%d, handle->%d\n", __FUNCTION__, + sna_crtc->id, cursor->handle)); VG_CLEAR(arg); arg.flags = DRM_MODE_CURSOR_BO; @@ -3271,8 +3274,9 @@ sna_show_cursors(ScrnInfoPtr scrn) arg.handle = cursor->handle; if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) - sna_crtc->cursor = cursor->handle; + sna_crtc->cursor = cursor; } + OsReleaseSIGIO(); } static void @@ -3305,6 +3309,7 @@ sna_hide_cursors(ScrnInfoPtr scrn) __DBG(("%s\n", __FUNCTION__)); + OsBlockSIGIO(); for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; struct sna_crtc *sna_crtc = to_sna_crtc(crtc); @@ -3313,13 +3318,10 @@ sna_hide_cursors(ScrnInfoPtr scrn) if (!sna_crtc) break; - if (!crtc->enabled) - continue; - if (!sna_crtc->cursor) continue; - __DBG(("%s: CRTC:%d, handle=%d\n", __FUNCTION__, sna_crtc->id, sna_crtc->cursor)); + __DBG(("%s: CRTC:%d, handle=%d\n", __FUNCTION__, sna_crtc->id, sna_crtc->cursor->handle)); VG_CLEAR(arg); arg.flags = DRM_MODE_CURSOR_BO; @@ -3327,8 +3329,8 @@ sna_hide_cursors(ScrnInfoPtr scrn) arg.width = arg.height = 0; arg.handle = 0; - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) - sna_crtc->cursor = 0; + (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg); + sna_crtc->cursor = NULL; } while (sna->cursor.cursors) { @@ -3338,6 +3340,7 @@ sna_hide_cursors(ScrnInfoPtr scrn) gem_close(sna->kgem.fd, cursor->handle); free(cursor); } + OsReleaseSIGIO(); } static void @@ -3349,6 +3352,7 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y) __DBG(("%s(%d, %d)\n", __FUNCTION__, x, y)); + OsBlockSIGIO(); sna->cursor.last_x = x; sna->cursor.last_y = y; @@ -3372,10 +3376,6 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y) if (!crtc->enabled) goto disable; - cursor = __sna_get_cursor(sna, crtc); - if (cursor == NULL) - goto disable; - if (crtc->transform_in_use) { int xhot = sna->cursor.ref->bits->xhot; int yhot = sna->cursor.ref->bits->yhot; @@ -3396,33 +3396,40 @@ sna_set_cursor_position(ScrnInfoPtr scrn, int x, int y) arg.y = y - crtc->y; } - if (arg.x < crtc->mode.HDisplay && arg.x > -cursor->size && - arg.y < crtc->mode.VDisplay && arg.y > -cursor->size) { - arg.flags = DRM_MODE_CURSOR_MOVE; - arg.handle = cursor->handle; + if (arg.x < crtc->mode.HDisplay && arg.x > -sna->cursor.size && + arg.y < crtc->mode.VDisplay && arg.y > -sna->cursor.size) { + cursor = __sna_get_cursor(sna, crtc); + if (cursor == NULL) { + __DBG(("%s: failed to grab cursor, disabling\n", + __FUNCTION__)); + goto disable; + } - if (sna_crtc->cursor != arg.handle) { + arg.handle = cursor->handle; + if (sna_crtc->cursor != cursor) { arg.flags |= DRM_MODE_CURSOR_BO; arg.width = arg.height = cursor->size; } + arg.flags |= DRM_MODE_CURSOR_MOVE; crtc->cursor_in_range = true; } else { disable: crtc->cursor_in_range = false; if (sna_crtc->cursor) { arg.flags = DRM_MODE_CURSOR_BO; - arg.width = arg.height = arg.handle = 0; + arg.width = arg.height = 0; } } - __DBG(("%s: CRTC:%d (%d, %d), handle=%d\n", - __FUNCTION__, sna_crtc->id, arg.x, arg.y, arg.handle)); + __DBG(("%s: CRTC:%d (%d, %d), handle=%d, flags=%x (old cursor handle=%d)\n", + __FUNCTION__, sna_crtc->id, arg.x, arg.y, arg.handle, arg.flags, sna_crtc->cursor ? sna_crtc->cursor->handle : 0)); if (arg.flags && drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_CURSOR, &arg) == 0) - sna_crtc->cursor = arg.handle; + sna_crtc->cursor = arg.handle ? cursor : NULL; } + OsReleaseSIGIO(); } static void @@ -3435,6 +3442,17 @@ sna_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src) { } +static int __cursor_size(CursorPtr cursor) +{ + int i, size; + + i = MAX(cursor->bits->width, cursor->bits->height); + for (size = 64; size < i; size <<= 1) + ; + + return size; +} + static Bool sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor) { @@ -3448,16 +3466,17 @@ sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor) if (sna->cursor.ref) FreeCursor(sna->cursor.ref, None); sna->cursor.ref = cursor; + sna->cursor.size = __cursor_size(cursor); sna->cursor.serial++; - __DBG(("%s(%dx%d): ARGB?=%d, serial->%d\n", __FUNCTION__, + __DBG(("%s(%dx%d): ARGB?=%d, serial->%d, size->%d\n", __FUNCTION__, cursor->bits->width, cursor->bits->height, cursor->bits->argb!=NULL, - sna->cursor.serial)); + sna->cursor.serial, + sna->cursor.size)); - return (cursor->bits->width <= sna->cursor.max_size && - cursor->bits->height <= sna->cursor.max_size); + return sna->cursor.size <= sna->cursor.max_size; } static void |