Пример #1
0
void
test_and ()
{
  v = init;

  atomic_fetch_and (&v, 0);
  if (v != 0)
    abort ();

  v = init;
  atomic_fetch_and_explicit (&v, init, memory_order_consume);
  if (v != init)
    abort ();

  atomic_fetch_and (&v, 0);
  if (v != 0)
    abort ();

  v = ~v;
  atomic_fetch_and_explicit (&v, init, memory_order_release);
  if (v != init)
    abort ();

  atomic_fetch_and (&v, 0);
  if (v != 0)
    abort ();

  v = ~v;
  atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst);
  if (v != 0)
    abort ();
}
Пример #2
0
void
test_fetch_and ()
{
  v = init;

  if (atomic_fetch_and_explicit (&v, 0, memory_order_relaxed) != init)
    abort ();

  if (atomic_fetch_and_explicit (&v, init, memory_order_consume) != 0)
    abort ();

  if (atomic_fetch_and_explicit (&v, 0, memory_order_acquire) != 0)
    abort ();

  v = ~v;
  if (atomic_fetch_and_explicit (&v, init, memory_order_release) != init)
    abort ();

  if (atomic_fetch_and_explicit (&v, 0, memory_order_acq_rel) != init)
    abort ();

  if (atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst) != 0)
    abort ();

  if (atomic_fetch_and (&v, 0) != 0)
    abort ();
}
Пример #3
0
static void __icache_sync_action(struct linkedentry *entry)
{
	struct inode *node = entry->obj;
	if(node->flags & INODE_DIRTY)
		fs_callback_inode_push(node);
	linkedlist_do_remove(ic_dirty, &node->dirty_item);
	atomic_fetch_and(&node->flags, ~INODE_DIRTY);
}
Пример #4
0
bool bitmap_test_and_clear_atomic(unsigned long *map, long start, long nr)
{
    unsigned long *p = map + BIT_WORD(start);
    const long size = start + nr;
    int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
    unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
    unsigned long dirty = 0;
    unsigned long old_bits;

    /* First word */
    if (nr - bits_to_clear > 0) {
        old_bits = atomic_fetch_and(p, ~mask_to_clear);
        dirty |= old_bits & mask_to_clear;
        nr -= bits_to_clear;
        bits_to_clear = BITS_PER_LONG;
        mask_to_clear = ~0UL;
        p++;
    }

    /* Full words */
    if (bits_to_clear == BITS_PER_LONG) {
        while (nr >= BITS_PER_LONG) {
            if (*p) {
                old_bits = atomic_xchg(p, 0);
                dirty |= old_bits;
            }
            nr -= BITS_PER_LONG;
            p++;
        }
    }

    /* Last word */
    if (nr) {
        mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
        old_bits = atomic_fetch_and(p, ~mask_to_clear);
        dirty |= old_bits & mask_to_clear;
    } else {
        if (!dirty) {
            smp_mb();
        }
    }

    return dirty != 0;
}
Пример #5
0
/* read an inode from the filesystem */
int fs_inode_pull(struct inode *node)
{
	int r = 0;
	if(node->flags & INODE_NEEDREAD) {
		r = fs_callback_inode_pull(node);
		if(!r) {
			atomic_fetch_and(&node->flags, ~INODE_NEEDREAD);
		}
	}
	fs_inode_init_kdev(node);
	return r;
}
Пример #6
0
/* drop a reference to an inode. */
void vfs_icache_put(struct inode *node)
{
	assert(node->count > 0);
	mutex_acquire(ic_lock);
	if(atomic_fetch_sub(&node->count, 1) == 1) {
		if(node->flags & INODE_PERSIST) {
			if(node->nlink != 0) {
				mutex_release(ic_lock);
				return;
			}
		}
		assert(node->flags & INODE_INUSE);
		atomic_fetch_and(&node->flags, ~INODE_INUSE);
		if(node->filesystem) {
			atomic_fetch_sub(&node->filesystem->usecount, 1);
		}

		linkedlist_remove(ic_inuse, &node->inuse_item);
		queue_enqueue_item(ic_lru, &node->lru_item, node);
	}
	mutex_release(ic_lock);
}
Пример #7
0
 void atomic_and(volatile T * const dest, const T val) {
   atomic_fetch_and(dest, val);
 }
Пример #8
0
KOKKOS_INLINE_FUNCTION
void atomic_and(volatile T * const dest, const T src) {
    (void)atomic_fetch_and(dest,src);
}
Пример #9
0
TEST(stdatomic, atomic_fetch_and) {
  atomic_int i = ATOMIC_VAR_INIT(0x123);
  ASSERT_EQ(0x123, atomic_fetch_and(&i, 0x00f));
  ASSERT_EQ(0x003, atomic_fetch_and_explicit(&i, 0x2, memory_order_relaxed));
  ASSERT_EQ(0x002, atomic_load(&i));
}
Пример #10
0
void
atomic_clearbits_int(__volatile unsigned int *uip, unsigned int v)
{
	atomic_fetch_and((atomic_uint *)uip, ~v);
}
Пример #11
0
/* indicates that an inode no longer needs to be written to the filesystem */
void vfs_inode_unset_dirty(struct inode *node)
{
	assert(node->flags & INODE_DIRTY);
	linkedlist_remove(ic_dirty, &node->dirty_item);
	atomic_fetch_and(&node->flags, ~INODE_DIRTY);
}
Пример #12
0
static bool recreate_dispmanx(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;
    int display_nr = 0;
    int layer = 0;

    MP_VERBOSE(ctx, "Recreating DISPMANX state...\n");

    destroy_dispmanx(ctx);

    p->display = vc_dispmanx_display_open(display_nr);
    p->update = vc_dispmanx_update_start(0);
    if (!p->display || !p->update) {
        MP_FATAL(ctx, "Could not get DISPMANX objects.\n");
        goto fail;
    }

    uint32_t dispw, disph;
    if (graphics_get_display_size(0, &dispw, &disph) < 0) {
        MP_FATAL(ctx, "Could not get display size.\n");
        goto fail;
    }
    p->w = dispw;
    p->h = disph;

    if (ctx->vo->opts->fullscreen) {
        p->x = p->y = 0;
    } else {
        struct vo_win_geometry geo;
        struct mp_rect screenrc = {0, 0, p->w, p->h};

        vo_calc_window_geometry(ctx->vo, &screenrc, &geo);

        mp_rect_intersection(&geo.win, &screenrc);

        p->x = geo.win.x0;
        p->y = geo.win.y0;
        p->w = geo.win.x1 - geo.win.x0;
        p->h = geo.win.y1 - geo.win.y0;
    }

    // dispmanx is like a neanderthal version of Wayland - you can add an
    // overlay any place on the screen.
    VC_RECT_T dst = {.x = p->x, .y = p->y, .width = p->w, .height = p->h};
    VC_RECT_T src = {.width = p->w << 16, .height = p->h << 16};
    VC_DISPMANX_ALPHA_T alpha = {
        .flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE,
        .opacity = 0xFF,
    };
    p->window = vc_dispmanx_element_add(p->update, p->display, layer, &dst, 0,
                                        &src, DISPMANX_PROTECTION_NONE, &alpha,
                                        0, 0);
    if (!p->window) {
        MP_FATAL(ctx, "Could not add DISPMANX element.\n");
        goto fail;
    }

    vc_dispmanx_update_submit_sync(p->update);
    p->update = vc_dispmanx_update_start(0);

    p->egl_window = (EGL_DISPMANX_WINDOW_T){
        .element = p->window,
        .width = p->w,
        .height = p->h,
    };
    p->egl_surface = eglCreateWindowSurface(p->egl_display, p->egl_config,
                                            &p->egl_window, NULL);

    if (p->egl_surface == EGL_NO_SURFACE) {
        MP_FATAL(ctx, "Could not create EGL surface!\n");
        goto fail;
    }

    if (!eglMakeCurrent(p->egl_display, p->egl_surface, p->egl_surface,
                        p->egl_context))
    {
        MP_FATAL(ctx, "Failed to set context!\n");
        goto fail;
    }

    p->display_fps = 0;
    TV_GET_STATE_RESP_T tvstate;
    TV_DISPLAY_STATE_T tvstate_disp;
    if (!vc_tv_get_state(&tvstate) && !vc_tv_get_display_state(&tvstate_disp)) {
        if (tvstate_disp.state & (VC_HDMI_HDMI | VC_HDMI_DVI)) {
            p->display_fps = tvstate_disp.display.hdmi.frame_rate;

            HDMI_PROPERTY_PARAM_T param = {
                .property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE,
            };
            if (!vc_tv_hdmi_get_property(&param) &&
                param.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC)
                p->display_fps = p->display_fps / 1.001;
        } else {
            p->display_fps = tvstate_disp.display.sdtv.frame_rate;
        }
    }

    p->win_params[0] = display_nr;
    p->win_params[1] = layer;
    p->win_params[2] = p->x;
    p->win_params[3] = p->y;

    ctx->vo->dwidth = p->w;
    ctx->vo->dheight = p->h;
    ra_gl_ctx_resize(ctx->swapchain, p->w, p->h, 0);

    ctx->vo->want_redraw = true;

    vo_event(ctx->vo, VO_EVENT_WIN_STATE);
    return true;

fail:
    destroy_dispmanx(ctx);
    return false;
}

static void rpi_swap_buffers(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;
    eglSwapBuffers(p->egl_display, p->egl_surface);
}

static bool rpi_init(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);

    bcm_host_init();

    vc_tv_register_callback(tv_callback, ctx);

    p->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (!eglInitialize(p->egl_display, NULL, NULL)) {
        MP_FATAL(ctx, "EGL failed to initialize.\n");
        goto fail;
    }

    if (!mpegl_create_context(ctx, p->egl_display, &p->egl_context, &p->egl_config))
        goto fail;

    if (recreate_dispmanx(ctx) < 0)
        goto fail;

    mpegl_load_functions(&p->gl, ctx->log);

    struct ra_gl_ctx_params params = {
        .swap_buffers = rpi_swap_buffers,
        .native_display_type = "MPV_RPI_WINDOW",
        .native_display = p->win_params,
    };

    if (!ra_gl_ctx_init(ctx, &p->gl, params))
        goto fail;

    return true;

fail:
    rpi_uninit(ctx);
    return false;
}

static bool rpi_reconfig(struct ra_ctx *ctx)
{
    return recreate_dispmanx(ctx);
}

static struct mp_image *take_screenshot(struct ra_ctx *ctx)
{
    struct priv *p = ctx->priv;

    if (!p->display)
        return NULL;

    struct mp_image *img = mp_image_alloc(IMGFMT_BGR0, p->w, p->h);
    if (!img)
        return NULL;

    DISPMANX_RESOURCE_HANDLE_T resource =
        vc_dispmanx_resource_create(VC_IMAGE_ARGB8888,
                                    img->w | ((img->w * 4) << 16), img->h,
                                    &(int32_t){0});
    if (!resource)
        goto fail;

    if (vc_dispmanx_snapshot(p->display, resource, 0))
        goto fail;

    VC_RECT_T rc = {.width = img->w, .height = img->h};
    if (vc_dispmanx_resource_read_data(resource, &rc, img->planes[0], img->stride[0]))
        goto fail;

    vc_dispmanx_resource_delete(resource);
    return img;

fail:
    vc_dispmanx_resource_delete(resource);
    talloc_free(img);
    return NULL;
}

static int rpi_control(struct ra_ctx *ctx, int *events, int request, void *arg)
{
    struct priv *p = ctx->priv;

    switch (request) {
    case VOCTRL_SCREENSHOT_WIN:
        *(struct mp_image **)arg = take_screenshot(ctx);
        return VO_TRUE;
    case VOCTRL_FULLSCREEN:
        recreate_dispmanx(ctx);
        return VO_TRUE;
    case VOCTRL_CHECK_EVENTS:
        if (atomic_fetch_and(&p->reload_display, 0)) {
            MP_WARN(ctx, "Recovering from display mode switch...\n");
            recreate_dispmanx(ctx);
        }
        return VO_TRUE;
    case VOCTRL_GET_DISPLAY_FPS:
        *(double *)arg = p->display_fps;
        return VO_TRUE;
    }

    return VO_NOTIMPL;
}

const struct ra_ctx_fns ra_ctx_rpi = {
    .type           = "opengl",
    .name           = "rpi",
    .reconfig       = rpi_reconfig,
    .control        = rpi_control,
    .init           = rpi_init,
    .uninit         = rpi_uninit,
};