sp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
        const sp<Fence>& f2) {
    ATRACE_CALL();
    int result;
    // Merge the two fences.  In the case where one of the fences is not a
    // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so
    // that a new fence with the given name is created.
    if (f1->isValid() && f2->isValid()) {
        result = sync_merge(name.string(), f1->mFenceFd, f2->mFenceFd);
    } else if (f1->isValid()) {
        result = sync_merge(name.string(), f1->mFenceFd, f1->mFenceFd);
    } else if (f2->isValid()) {
        result = sync_merge(name.string(), f2->mFenceFd, f2->mFenceFd);
    } else {
        return NO_FENCE;
    }
    if (result == -1) {
        status_t err = -errno;
        ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
                name.string(), f1->mFenceFd, f2->mFenceFd,
                strerror(-err), err);
        return NO_FENCE;
    }
    return sp<Fence>(new Fence(result));
}
Example #2
0
int test_fence_multi_timeline_wait(void)
{
	int timelineA, timelineB, timelineC;
	int fenceA, fenceB, fenceC, merged;
	int valid, active, signaled, ret;

	timelineA = sw_sync_timeline_create();
	timelineB = sw_sync_timeline_create();
	timelineC = sw_sync_timeline_create();

	fenceA = sw_sync_fence_create(timelineA, "fenceA", 5);
	fenceB = sw_sync_fence_create(timelineB, "fenceB", 5);
	fenceC = sw_sync_fence_create(timelineC, "fenceC", 5);

	merged = sync_merge("mergeFence", fenceB, fenceA);
	merged = sync_merge("mergeFence", fenceC, merged);

	valid = sw_sync_fence_is_valid(merged);
	ASSERT(valid, "Failure merging fence from various timelines\n");

	/* Confirm fence isn't signaled */
	active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
	ASSERT(active == 3, "Fence signaled too early!\n");

	ret = sync_wait(merged, 0);
	ASSERT(ret == 0,
	       "Failure waiting on fence until timeout\n");

	ret = sw_sync_timeline_inc(timelineA, 5);
	active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
	signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
	ASSERT(active == 2 && signaled == 1,
	       "Fence did not signal properly!\n");

	ret = sw_sync_timeline_inc(timelineB, 5);
	active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
	signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
	ASSERT(active == 1 && signaled == 2,
	       "Fence did not signal properly!\n");

	ret = sw_sync_timeline_inc(timelineC, 5);
	active = sync_fence_count_with_status(merged, FENCE_STATUS_ACTIVE);
	signaled = sync_fence_count_with_status(merged, FENCE_STATUS_SIGNALED);
	ASSERT(active == 0 && signaled == 3,
	       "Fence did not signal properly!\n");

	/* confirm you can successfully wait */
	ret = sync_wait(merged, 100);
	ASSERT(ret > 0, "Failure waiting on signaled fence\n");

	sw_sync_fence_destroy(merged);
	sw_sync_fence_destroy(fenceC);
	sw_sync_fence_destroy(fenceB);
	sw_sync_fence_destroy(fenceA);
	sw_sync_timeline_destroy(timelineC);
	sw_sync_timeline_destroy(timelineB);
	sw_sync_timeline_destroy(timelineA);

	return 0;
}
sp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
        const sp<Fence>& f2) {
    ATRACE_CALL();
    int result = sync_merge(name.string(), f1->mFenceFd, f2->mFenceFd);
    if (result == -1) {
        status_t err = -errno;
        ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
                name.string(), f1->mFenceFd, f2->mFenceFd,
                strerror(-err), err);
        return NO_FENCE;
    }
    return sp<Fence>(new Fence(result));
}
static int mpcs_consumer_thread(void)
{
	int fence, merged, tmp, valid, it, i;
	int *producer_timelines = test_data_mpsc.producer_timelines;
	int consumer_timeline = test_data_mpsc.consumer_timeline;
	int iterations = test_data_mpsc.iterations;
	int n = test_data_mpsc.threads;

	for (it = 1; it <= iterations; it++) {
		fence = sw_sync_fence_create(producer_timelines[0], "name", it);
		for (i = 1; i < n; i++) {
			tmp = sw_sync_fence_create(producer_timelines[i],
						   "name", it);
			merged = sync_merge("name", tmp, fence);
			sw_sync_fence_destroy(tmp);
			sw_sync_fence_destroy(fence);
			fence = merged;
		}

		valid = sw_sync_fence_is_valid(fence);
		ASSERT(valid, "Failure merging fences\n");

		/*
		 * Make sure we see an increment from every producer thread.
		 * Vary the means by which we wait.
		 */
		if (iterations % 8 != 0) {
			ASSERT(sync_wait(fence, -1) > 0,
			       "Producers did not increment as expected\n");
		} else {
			ASSERT(busy_wait_on_fence(fence) == 0,
			       "Producers did not increment as expected\n");
		}

		ASSERT(test_data_mpsc.counter == n * it,
		       "Counter value mismatch!\n");

		/* Release the producer threads */
		ASSERT(sw_sync_timeline_inc(consumer_timeline, 1) == 0,
		       "Failure releasing producer threads\n");

		sw_sync_fence_destroy(fence);
	}

	return 0;
}
Example #5
0
void
FenceHandle::Merge(const FenceHandle& aFenceHandle)
{
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
  if (!aFenceHandle.IsValid()) {
    return;
  }

  if (!IsValid()) {
    mFence = aFenceHandle.mFence;
  } else {
    int result = sync_merge("FenceHandle", mFence->mFd, aFenceHandle.mFence->mFd);
    if (result == -1) {
      mFence = aFenceHandle.mFence;
    } else {
      mFence = new FdObj(result);
    }
  }
#endif
}
Example #6
0
static void
test_sync_file_fences(struct pipe_context *ctx)
{
   struct pipe_screen *screen = ctx->screen;
   bool pass = true;
   enum pipe_fd_type fd_type = PIPE_FD_TYPE_NATIVE_SYNC;

   if (!screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD))
      return;

   struct cso_context *cso = cso_create_context(ctx, 0);
   struct pipe_resource *buf =
      pipe_buffer_create(screen, 0, PIPE_USAGE_DEFAULT, 1024 * 1024);
   struct pipe_resource *tex =
      util_create_texture2d(screen, 4096, 1024, PIPE_FORMAT_R8_UNORM, 0);
   struct pipe_fence_handle *buf_fence = NULL, *tex_fence = NULL;

   /* Run 2 clears, get fencess. */
   uint32_t value = 0;
   ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value));
   ctx->flush(ctx, &buf_fence, PIPE_FLUSH_FENCE_FD);

   struct pipe_box box;
   u_box_2d(0, 0, tex->width0, tex->height0, &box);
   ctx->clear_texture(ctx, tex, 0, &box, &value);
   ctx->flush(ctx, &tex_fence, PIPE_FLUSH_FENCE_FD);
   pass = pass && buf_fence && tex_fence;

   /* Export fences. */
   int buf_fd = screen->fence_get_fd(screen, buf_fence);
   int tex_fd = screen->fence_get_fd(screen, tex_fence);
   pass = pass && buf_fd >= 0 && tex_fd >= 0;

   /* Merge fences. */
   int merged_fd = sync_merge("test", buf_fd, tex_fd);
   pass = pass && merged_fd >= 0;

   /* (Re)import all fences. */
   struct pipe_fence_handle *re_buf_fence = NULL, *re_tex_fence = NULL;
   struct pipe_fence_handle *merged_fence = NULL;
   ctx->create_fence_fd(ctx, &re_buf_fence, buf_fd, fd_type);
   ctx->create_fence_fd(ctx, &re_tex_fence, tex_fd, fd_type);
   ctx->create_fence_fd(ctx, &merged_fence, merged_fd, fd_type);
   pass = pass && re_buf_fence && re_tex_fence && merged_fence;

   /* Run another clear after waiting for everything. */
   struct pipe_fence_handle *final_fence = NULL;
   ctx->fence_server_sync(ctx, merged_fence);
   value = 0xff;
   ctx->clear_buffer(ctx, buf, 0, buf->width0, &value, sizeof(value));
   ctx->flush(ctx, &final_fence, PIPE_FLUSH_FENCE_FD);
   pass = pass && final_fence;

   /* Wait for the last fence. */
   int final_fd = screen->fence_get_fd(screen, final_fence);
   pass = pass && final_fd >= 0;
   pass = pass && sync_wait(final_fd, -1) == 0;

   /* Check that all fences are signalled. */
   pass = pass && sync_wait(buf_fd, 0) == 0;
   pass = pass && sync_wait(tex_fd, 0) == 0;
   pass = pass && sync_wait(merged_fd, 0) == 0;

   pass = pass && screen->fence_finish(screen, NULL, buf_fence, 0);
   pass = pass && screen->fence_finish(screen, NULL, tex_fence, 0);
   pass = pass && screen->fence_finish(screen, NULL, re_buf_fence, 0);
   pass = pass && screen->fence_finish(screen, NULL, re_tex_fence, 0);
   pass = pass && screen->fence_finish(screen, NULL, merged_fence, 0);
   pass = pass && screen->fence_finish(screen, NULL, final_fence, 0);

   /* Cleanup. */
#ifndef PIPE_OS_WINDOWS
   if (buf_fd >= 0)
      close(buf_fd);
   if (tex_fd >= 0)
      close(tex_fd);
   if (merged_fd >= 0)
      close(merged_fd);
   if (final_fd >= 0)
      close(final_fd);
#endif

   screen->fence_reference(screen, &buf_fence, NULL);
   screen->fence_reference(screen, &tex_fence, NULL);
   screen->fence_reference(screen, &re_buf_fence, NULL);
   screen->fence_reference(screen, &re_tex_fence, NULL);
   screen->fence_reference(screen, &merged_fence, NULL);
   screen->fence_reference(screen, &final_fence, NULL);

   cso_destroy_context(cso);
   pipe_resource_reference(&buf, NULL);
   pipe_resource_reference(&tex, NULL);

   util_report_result(pass);
}