Path: blob/21.2-virgl/src/gallium/frontends/clover/core/event.cpp
4572 views
//1// Copyright 2012 Francisco Jerez2//3// Permission is hereby granted, free of charge, to any person obtaining a4// copy of this software and associated documentation files (the "Software"),5// to deal in the Software without restriction, including without limitation6// the rights to use, copy, modify, merge, publish, distribute, sublicense,7// and/or sell copies of the Software, and to permit persons to whom the8// Software is furnished to do so, subject to the following conditions:9//10// The above copyright notice and this permission notice shall be included in11// all copies or substantial portions of the Software.12//13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19// OTHER DEALINGS IN THE SOFTWARE.20//2122#include "core/event.hpp"23#include "pipe/p_screen.h"2425using namespace clover;2627event::event(clover::context &ctx, const ref_vector<event> &deps,28action action_ok, action action_fail) :29context(ctx), _wait_count(1), _status(0),30action_ok(action_ok), action_fail(action_fail) {31for (auto &ev : deps)32ev.chain(*this);33}3435event::~event() {36}3738std::vector<intrusive_ref<event>>39event::trigger_self() {40std::lock_guard<std::mutex> lock(mutex);41std::vector<intrusive_ref<event>> evs;4243if (_wait_count && !--_wait_count)44std::swap(_chain, evs);4546cv.notify_all();47return evs;48}4950void51event::trigger() try {52if (wait_count() == 1)53action_ok(*this);5455for (event &ev : trigger_self())56ev.trigger();57} catch (error &e) {58abort(e.get());59}6061std::vector<intrusive_ref<event>>62event::abort_self(cl_int status) {63std::lock_guard<std::mutex> lock(mutex);64std::vector<intrusive_ref<event>> evs;6566_status = status;67_wait_count = 0;68std::swap(_chain, evs);6970cv.notify_all();71return evs;72}7374void75event::abort(cl_int status) {76action_fail(*this);7778for (event &ev : abort_self(status))79ev.abort(status);80}8182unsigned83event::wait_count() const {84std::lock_guard<std::mutex> lock(mutex);85return _wait_count;86}8788bool89event::signalled() const {90return !wait_count();91}9293cl_int94event::status() const {95std::lock_guard<std::mutex> lock(mutex);96return _status;97}9899void100event::chain(event &ev) {101std::unique_lock<std::mutex> lock(mutex, std::defer_lock);102std::unique_lock<std::mutex> lock_ev(ev.mutex, std::defer_lock);103std::lock(lock, lock_ev);104105if (_wait_count) {106ev._wait_count++;107_chain.push_back(ev);108}109ev.deps.push_back(*this);110}111112void113event::wait_signalled() const {114std::unique_lock<std::mutex> lock(mutex);115cv.wait(lock, [=]{ return !_wait_count; });116}117118void119event::wait() const {120std::vector<intrusive_ref<event>> evs;121std::swap(deps, evs);122123for (event &ev : evs)124ev.wait();125126wait_signalled();127}128129hard_event::hard_event(command_queue &q, cl_command_type command,130const ref_vector<event> &deps, action action) :131event(q.context(), deps, profile(q, action), [](event &ev){}),132_queue(q), _command(command), _fence(NULL) {133if (q.profiling_enabled())134_time_queued = timestamp::current(q);135136q.sequence(*this);137trigger();138}139140hard_event::~hard_event() {141pipe_screen *screen = queue()->device().pipe;142screen->fence_reference(screen, &_fence, NULL);143}144145cl_int146hard_event::status() const {147pipe_screen *screen = queue()->device().pipe;148149if (event::status() < 0)150return event::status();151152else if (!_fence)153return CL_QUEUED;154155else if (!screen->fence_finish(screen, NULL, _fence, 0))156return CL_SUBMITTED;157158else159return CL_COMPLETE;160}161162command_queue *163hard_event::queue() const {164return &_queue();165}166167cl_command_type168hard_event::command() const {169return _command;170}171172void173hard_event::wait() const {174pipe_screen *screen = queue()->device().pipe;175176event::wait();177178if (status() == CL_QUEUED)179queue()->flush();180181if (!_fence ||182!screen->fence_finish(screen, NULL, _fence, PIPE_TIMEOUT_INFINITE))183throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);184}185186const lazy<cl_ulong> &187hard_event::time_queued() const {188return _time_queued;189}190191const lazy<cl_ulong> &192hard_event::time_submit() const {193return _time_submit;194}195196const lazy<cl_ulong> &197hard_event::time_start() const {198return _time_start;199}200201const lazy<cl_ulong> &202hard_event::time_end() const {203return _time_end;204}205206void207hard_event::fence(pipe_fence_handle *fence) {208assert(fence);209pipe_screen *screen = queue()->device().pipe;210screen->fence_reference(screen, &_fence, fence);211deps.clear();212}213214event::action215hard_event::profile(command_queue &q, const action &action) const {216if (q.profiling_enabled()) {217return [&q, action] (event &ev) {218auto &hev = static_cast<hard_event &>(ev);219220hev._time_submit = timestamp::current(q);221hev._time_start = timestamp::query(q);222223action(ev);224225hev._time_end = timestamp::query(q);226};227228} else {229return action;230}231}232233soft_event::soft_event(clover::context &ctx, const ref_vector<event> &deps,234bool _trigger, action action) :235event(ctx, deps, action, action) {236if (_trigger)237trigger();238}239240cl_int241soft_event::status() const {242if (event::status() < 0)243return event::status();244245else if (!signalled() ||246any_of([](const event &ev) {247return ev.status() != CL_COMPLETE;248}, deps))249return CL_SUBMITTED;250251else252return CL_COMPLETE;253}254255command_queue *256soft_event::queue() const {257return NULL;258}259260cl_command_type261soft_event::command() const {262return CL_COMMAND_USER;263}264265void266soft_event::wait() const {267event::wait();268269if (status() != CL_COMPLETE)270throw error(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);271}272273274