mali_scheduler_mask mali_soft_job_system_activate_job(struct mali_soft_job *job)
{
	mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;

	MALI_DEBUG_ASSERT_POINTER(job);
	MALI_DEBUG_ASSERT_POINTER(job->system);
	MALI_DEBUG_ASSERT_POINTER(job->system->session);

	MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeline activation for soft job %u (0x%08X).\n", job->id, job));

	mali_soft_job_system_lock(job->system);

	if (unlikely(job->system->session->is_aborting)) {
		MALI_DEBUG_PRINT(3, ("Mali Soft Job: Soft job %u (0x%08X) activated while session is aborting.\n", job->id, job));

		mali_soft_job_system_unlock(job->system);

		/* Since we are in shutdown, we can ignore the scheduling bitmask. */
		mali_timeline_tracker_release(&job->tracker);
		mali_soft_job_destroy(job);
		return schedule_mask;
	}

	/* Send activated notification. */
	mali_soft_job_send_activated_notification(job);

	/* Wake up sleeping signaler. */
	job->activated = MALI_TRUE;

	/* If job type is self signaled, release tracker, move soft job to free list, and scheduler at once */
	if (MALI_SOFT_JOB_TYPE_SELF_SIGNALED == job->type) {
		MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state);

		job->state = MALI_SOFT_JOB_STATE_SIGNALED;
		mali_soft_job_system_unlock(job->system);

		schedule_mask |= mali_timeline_tracker_release(&job->tracker);

		mali_soft_job_destroy(job);
	} else {
		_mali_osk_wait_queue_wake_up(job->tracker.system->wait_queue);

		mali_soft_job_system_unlock(job->system);
	}

	return schedule_mask;
}
Beispiel #2
0
_mali_osk_errcode_t mali_soft_job_system_signal_job(struct mali_soft_job_system *system, u32 job_id)
{
	struct mali_soft_job *job;
	struct mali_timeline_system *timeline_system;
	mali_scheduler_mask schedule_mask;

	MALI_DEBUG_ASSERT_POINTER(system);

	mali_soft_job_system_lock(system);

	job = mali_soft_job_system_lookup_job(system, job_id);

	if ((NULL == job) || (MALI_SOFT_JOB_TYPE_USER_SIGNALED != job->type)
	    || !(MALI_SOFT_JOB_STATE_STARTED == job->state || MALI_SOFT_JOB_STATE_TIMED_OUT == job->state)) {
		mali_soft_job_system_unlock(system);
		MALI_PRINT_ERROR(("Mali Soft Job: invalid soft job id %u", job_id));
		return _MALI_OSK_ERR_ITEM_NOT_FOUND;
	}

	if (MALI_SOFT_JOB_STATE_TIMED_OUT == job->state) {
		job->state = MALI_SOFT_JOB_STATE_SIGNALED;
		mali_soft_job_system_unlock(system);

		MALI_DEBUG_ASSERT(MALI_TRUE == job->activated);
		MALI_DEBUG_PRINT(4, ("Mali Soft Job: soft job %u (0x%08X) was timed out\n", job->id, job));
		mali_soft_job_destroy(job);

		return _MALI_OSK_ERR_TIMEOUT;
	}

	MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state);

	job->state = MALI_SOFT_JOB_STATE_SIGNALED;
	mali_soft_job_system_unlock(system);

	/* Since the job now is in signaled state, timeouts from the timeline system will be
	 * ignored, and it is not possible to signal this job again. */

	timeline_system = system->session->timeline_system;
	MALI_DEBUG_ASSERT_POINTER(timeline_system);

	/* Wait until activated. */
	_mali_osk_wait_queue_wait_event(timeline_system->wait_queue, mali_soft_job_is_activated, (void *) job);

	MALI_DEBUG_PRINT(4, ("Mali Soft Job: signaling soft job %u (0x%08X)\n", job->id, job));

	schedule_mask = mali_timeline_tracker_release(&job->tracker);
	mali_scheduler_schedule_from_mask(schedule_mask, MALI_FALSE);

	mali_soft_job_destroy(job);

	return _MALI_OSK_ERR_OK;
}
Beispiel #3
0
void mali_soft_job_system_abort(struct mali_soft_job_system *system)
{
	struct mali_soft_job *job, *tmp;
	_MALI_OSK_LIST_HEAD_STATIC_INIT(jobs);

	MALI_DEBUG_ASSERT_POINTER(system);
	MALI_DEBUG_ASSERT_POINTER(system->session);
	MALI_DEBUG_ASSERT(system->session->is_aborting);

	MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting soft job system for session 0x%08X.\n", system->session));

	mali_soft_job_system_lock(system);

	_MALI_OSK_LIST_FOREACHENTRY(job, tmp, &system->jobs_used, struct mali_soft_job, system_list) {
		MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED   == job->state ||
				  MALI_SOFT_JOB_STATE_TIMED_OUT == job->state);

		if (MALI_SOFT_JOB_STATE_STARTED == job->state) {
			/* If the job has been activated, we have to release the tracker and destroy
			 * the job.  If not, the tracker will be released and the job destroyed when
			 * it is activated. */
			if (MALI_TRUE == job->activated) {
				MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting unsignaled soft job %u (0x%08X).\n", job->id, job));

				job->state = MALI_SOFT_JOB_STATE_SIGNALED;
				_mali_osk_list_move(&job->system_list, &jobs);
			}
		} else if (MALI_SOFT_JOB_STATE_TIMED_OUT == job->state) {
			MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting timed out soft job %u (0x%08X).\n", job->id, job));

			/* We need to destroy this soft job. */
			_mali_osk_list_move(&job->system_list, &jobs);
		}
	}

	mali_soft_job_system_unlock(system);

	/* Release and destroy jobs. */
	_MALI_OSK_LIST_FOREACHENTRY(job, tmp, &jobs, struct mali_soft_job, system_list) {
		MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_SIGNALED  == job->state ||
				  MALI_SOFT_JOB_STATE_TIMED_OUT == job->state);

		if (MALI_SOFT_JOB_STATE_SIGNALED == job->state) {
			mali_timeline_tracker_release(&job->tracker);
		}

		/* Move job back to used list before destroying. */
		_mali_osk_list_move(&job->system_list, &system->jobs_used);

		mali_soft_job_destroy(job);
	}
}
Beispiel #4
0
mali_scheduler_mask mali_soft_job_system_timeout_job(struct mali_soft_job *job)
{
	mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;

	MALI_DEBUG_ASSERT_POINTER(job);
	MALI_DEBUG_ASSERT_POINTER(job->system);
	MALI_DEBUG_ASSERT_POINTER(job->system->session);
	MALI_DEBUG_ASSERT(MALI_TRUE == job->activated);

	MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeline timeout for soft job %u (0x%08X).\n", job->id, job));

	mali_soft_job_system_lock(job->system);

	MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED  == job->state ||
			  MALI_SOFT_JOB_STATE_SIGNALED == job->state);

	if (unlikely(job->system->session->is_aborting)) {
		/* The session is aborting.  This job will be released and destroyed by @ref
		 * mali_soft_job_system_abort(). */
		mali_soft_job_system_unlock(job->system);

		return MALI_SCHEDULER_MASK_EMPTY;
	}

	if (MALI_SOFT_JOB_STATE_STARTED != job->state) {
		MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_SIGNALED == job->state);

		/* The job is about to be signaled, ignore timeout. */
		MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeout on soft job %u (0x%08X) in signaled state.\n", job->id, job));
		mali_soft_job_system_unlock(job->system);
		return schedule_mask;
	}

	MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state);

	job->state = MALI_SOFT_JOB_STATE_TIMED_OUT;
	_mali_osk_atomic_inc(&job->refcount);

	mali_soft_job_system_unlock(job->system);

	schedule_mask = mali_timeline_tracker_release(&job->tracker);

	mali_soft_job_destroy(job);

	return schedule_mask;
}
void mali_timeline_sync_fence_activate(struct mali_timeline_sync_fence_tracker *sync_fence_tracker)
{
	mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;

	MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker);
	MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker->flag);

	MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for sync fence tracker\n"));

	/* Signal flag and release reference. */
	mali_sync_flag_signal(sync_fence_tracker->flag, 0);
	mali_sync_flag_put(sync_fence_tracker->flag);

	/* Nothing can wait on this tracker, so nothing to schedule after release. */
	schedule_mask = mali_timeline_tracker_release(&sync_fence_tracker->tracker);
	MALI_DEBUG_ASSERT(MALI_SCHEDULER_MASK_EMPTY == schedule_mask);

	_mali_osk_free(sync_fence_tracker);
}
/**
 * Check if fence has been signaled.
 *
 * @param system Timeline system.
 * @param fence Timeline fence.
 * @return MALI_TRUE if fence is signaled, MALI_FALSE if not.
 */
static mali_bool mali_timeline_fence_wait_check_status(struct mali_timeline_system *system, struct mali_timeline_fence *fence)
{
	int i;
	u32 tid = _mali_osk_get_tid();
	mali_bool ret = MALI_TRUE;
#if defined(CONFIG_SYNC)
	struct sync_fence *sync_fence = NULL;
#endif

	MALI_DEBUG_ASSERT_POINTER(system);
	MALI_DEBUG_ASSERT_POINTER(fence);

	mali_spinlock_reentrant_wait(system->spinlock, tid);

	for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
		struct mali_timeline *timeline;
		mali_timeline_point   point;

		point = fence->points[i];

		if (likely(MALI_TIMELINE_NO_POINT == point)) {
			/* Fence contains no point on this timeline. */
			continue;
		}

		timeline = system->timelines[i];
		MALI_DEBUG_ASSERT_POINTER(timeline);

		if (unlikely(!mali_timeline_is_point_valid(timeline, point))) {
			MALI_PRINT_ERROR(("Mali Timeline: point %d is not valid (oldest=%d, next=%d)\n", point, timeline->point_oldest, timeline->point_next));
		}

		if (!mali_timeline_is_point_released(timeline, point)) {
			ret = MALI_FALSE;
			goto exit;
		}
	}

#if defined(CONFIG_SYNC)
	if (-1 != fence->sync_fd) {
		sync_fence = sync_fence_fdget(fence->sync_fd);
		if (likely(NULL != sync_fence)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
			if (0 == sync_fence->status) {
#else
			if (0 == atomic_read(&sync_fence->status)) {
#endif
				ret = MALI_FALSE;
			}
		} else {
			MALI_PRINT_ERROR(("Mali Timeline: failed to get sync fence from fd %d\n", fence->sync_fd));
		}
	}
#endif /* defined(CONFIG_SYNC) */

exit:
	mali_spinlock_reentrant_signal(system->spinlock, tid);

#if defined(CONFIG_SYNC)
	if (NULL != sync_fence) {
		sync_fence_put(sync_fence);
	}
#endif /* defined(CONFIG_SYNC) */

	return ret;
}

mali_bool mali_timeline_fence_wait(struct mali_timeline_system *system, struct mali_timeline_fence *fence, u32 timeout)
{
	struct mali_timeline_fence_wait_tracker *wait;
	mali_timeline_point point;
	mali_bool ret;

	MALI_DEBUG_ASSERT_POINTER(system);
	MALI_DEBUG_ASSERT_POINTER(fence);

	MALI_DEBUG_PRINT(4, ("Mali Timeline: wait on fence\n"));

	if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY == timeout) {
		return mali_timeline_fence_wait_check_status(system, fence);
	}

	wait = mali_timeline_fence_wait_tracker_alloc();
	if (unlikely(NULL == wait)) {
		MALI_PRINT_ERROR(("Mali Timeline: failed to allocate data for fence wait\n"));
		return MALI_FALSE;
	}

	wait->activated = MALI_FALSE;
	wait->system = system;

	/* Initialize refcount to two references.  The reference first will be released by this
	 * function after the wait is over.  The second reference will be released when the tracker
	 * is activated. */
	_mali_osk_atomic_init(&wait->refcount, 2);

	/* Add tracker to timeline system, but not to a timeline. */
	mali_timeline_tracker_init(&wait->tracker, MALI_TIMELINE_TRACKER_WAIT, fence, wait);
	point = mali_timeline_system_add_tracker(system, &wait->tracker, MALI_TIMELINE_NONE);
	MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT == point);
	MALI_IGNORE(point);

	/* Wait for the tracker to be activated or time out. */
	if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER == timeout) {
		_mali_osk_wait_queue_wait_event(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait);
	} else {
		_mali_osk_wait_queue_wait_event_timeout(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait, timeout);
	}

	ret = wait->activated;

	if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) {
		mali_timeline_fence_wait_tracker_free(wait);
	}

	return ret;
}

void mali_timeline_fence_wait_activate(struct mali_timeline_fence_wait_tracker *wait)
{
	mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;

	MALI_DEBUG_ASSERT_POINTER(wait);
	MALI_DEBUG_ASSERT_POINTER(wait->system);

	MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for fence wait tracker\n"));

	MALI_DEBUG_ASSERT(MALI_FALSE == wait->activated);
	wait->activated = MALI_TRUE;

	_mali_osk_wait_queue_wake_up(wait->system->wait_queue);

	/* Nothing can wait on this tracker, so nothing to schedule after release. */
	schedule_mask = mali_timeline_tracker_release(&wait->tracker);
	MALI_DEBUG_ASSERT(MALI_SCHEDULER_MASK_EMPTY == schedule_mask);
	MALI_IGNORE(schedule_mask);

	if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) {
		mali_timeline_fence_wait_tracker_free(wait);
	}
}