From e7e500366aa7b892070bf41500c64cb3f8a98f88 Mon Sep 17 00:00:00 2001 From: Bjoern Brandenburg Date: Wed, 16 May 2012 19:04:36 +0200 Subject: C++: Break out the phase-fair RW locks code Part of refactoring sharedres.cpp. --- native/src/blocking/rw-phase-fair.cpp | 223 ++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 native/src/blocking/rw-phase-fair.cpp (limited to 'native/src/blocking') diff --git a/native/src/blocking/rw-phase-fair.cpp b/native/src/blocking/rw-phase-fair.cpp new file mode 100644 index 0000000..65b85b4 --- /dev/null +++ b/native/src/blocking/rw-phase-fair.cpp @@ -0,0 +1,223 @@ +#include "sharedres.h" +#include "blocking.h" + +#include "stl-helper.h" + + +static Interference pf_writer_fifo( + const TaskInfo& tsk, const ClusterResources& writes, + const unsigned int num_writes, + const unsigned int num_reads, + const unsigned int res_id, + const unsigned int procs_per_cluster, + const int dedicated_irq) +{ + const unsigned int per_src_wlimit = num_reads + num_writes; + const unsigned long interval = tsk.get_response(); + ClusterLimits limits; + int idx; + + limits.reserve(writes.size()); + enumerate(writes, ct, idx) + { + unsigned int total, parallelism = procs_per_cluster; + + if (idx == dedicated_irq) + parallelism--; + + if (parallelism && (int) tsk.get_cluster() == idx) + parallelism--; + + // At most one blocking request per remote CPU in + // cluster per request. + if (parallelism) + total = num_reads + num_writes * parallelism; + else + // No interference from writers if we are hogging + // the only available CPU. + total = 0; + + limits.push_back(ClusterLimit(total, per_src_wlimit)); + } + + Interference blocking; + blocking = bound_blocking_all_clusters(writes, + limits, + res_id, + interval, + &tsk); + return blocking; + +} + +static Interference pf_reader_all( + const TaskInfo& tsk, + const Resources& all_reads, + const unsigned int num_writes, + const unsigned int num_wblock, + const unsigned int num_reads, + const unsigned int res_id, + const unsigned int procs_per_cluster, + const unsigned int num_procs) +{ + const unsigned long interval = tsk.get_response(); + Interference blocking; + unsigned int rlimit = std::min(num_wblock + num_writes, + num_reads + num_writes * (num_procs - 1)); + blocking = bound_blocking(all_reads[res_id], + interval, + rlimit, + rlimit, + // exclude all if c == 1 + procs_per_cluster == 1, + &tsk); + return blocking; +} + +BlockingBounds* clustered_rw_omlp_bounds(const ResourceSharingInfo& info, + unsigned int procs_per_cluster, + int dedicated_irq) +{ + // split everything by partition + Clusters clusters; + + split_by_cluster(info, clusters); + + // split each partition by resource + ClusterResources resources; + + split_by_resource(clusters, resources); + + // split all by resource + Resources all_task_reqs, all_reads, __all_writes; + split_by_resource(info, all_task_reqs); + split_by_type(all_task_reqs, all_reads, __all_writes); + + // sort each contention set by request length + sort_by_request_length(resources); + sort_by_request_length(all_reads); + + // split by type --- sorted order is maintained + ClusterResources __reads, writes; + split_by_type(resources, __reads, writes); + + + // We need for each task the maximum request span. We also need the + // maximum direct blocking from remote partitions for each request. We + // can determine both in one pass. + + const unsigned int num_procs = procs_per_cluster * clusters.size(); + unsigned int i; + + // direct blocking results + BlockingBounds* _results = new BlockingBounds(info); + BlockingBounds& results = *_results; + + for (i = 0; i < info.get_tasks().size(); i++) + { + const TaskInfo& tsk = info.get_tasks()[i]; + RWCounts rwcounts; + Interference bterm; + + merge_rw_requests(tsk, rwcounts); + + foreach(rwcounts, jt) + { + const RWCount& rw = *jt; + + // skip placeholders + if (!rw.num_reads && !rw.num_writes) + continue; + + Interference wblocking, rblocking; + + wblocking = pf_writer_fifo(tsk, writes, rw.num_writes, + rw.num_reads, rw.res_id, + procs_per_cluster, + dedicated_irq); + + rblocking = pf_reader_all(tsk, all_reads, rw.num_writes, + wblocking.count, rw.num_reads, + rw.res_id, procs_per_cluster, + num_procs); + + //**** SINGLE WRITE + Interference rblocking_w1, wblocking_w1; + + // Keep track of maximum request span. + // Is this already a single-issue request? + if (rw.num_writes && + (rw.num_writes != 1 || rw.num_reads != 0)) + { + wblocking_w1 = pf_writer_fifo(tsk, writes, 1, 0, + rw.res_id, procs_per_cluster, + dedicated_irq); + + rblocking_w1 = pf_reader_all( + tsk, all_reads, 1, + wblocking_w1.count, 0, + rw.res_id, procs_per_cluster, + num_procs); + } + else if (rw.num_writes) + { + wblocking_w1 = wblocking; + rblocking_w1 = rblocking; + } + // else: zero, nothing to do + + //**** SINGLE READ + + Interference rblocking_r1, wblocking_r1; + + + if (rw.num_reads && + (rw.num_reads != 1 || rw.num_writes != 0)) + { + wblocking_r1 = pf_writer_fifo(tsk, writes, 0, 1, + rw.res_id, procs_per_cluster, + dedicated_irq); + + rblocking_r1 = pf_reader_all( + tsk, all_reads, 0, + wblocking_r1.count, 1, + rw.res_id, procs_per_cluster, + num_procs); + } + else if (rw.num_reads) + { + wblocking_r1 = wblocking; + rblocking_r1 = rblocking; + } + + // else: zero, nothing to do + + // The span includes our own request. + if (rw.num_writes) + { + wblocking_w1.total_length += rw.wlength; + wblocking_w1.count += 1; + } + if (rw.num_reads) + { + rblocking_r1.total_length += rw.rlength; + wblocking_r1.count += 1; + } + + // combine + wblocking_w1 += rblocking_w1; + wblocking_r1 += rblocking_r1; + wblocking += rblocking; + + results.raise_request_span(i, wblocking_w1); + results.raise_request_span(i, wblocking_r1); + bterm += wblocking; + } + results[i] = bterm; + } + + // This is the initial delay due to priority donation. + charge_arrival_blocking(info, results); + + return _results; +} -- cgit v1.2.2