forked from google-coral/libedgetpu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsingle_queue_dma_scheduler.h
165 lines (135 loc) · 5.65 KB
/
single_queue_dma_scheduler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DARWINN_DRIVER_SINGLE_QUEUE_DMA_SCHEDULER_H_
#define DARWINN_DRIVER_SINGLE_QUEUE_DMA_SCHEDULER_H_
#include <condition_variable> // NOLINT
#include <list>
#include <memory>
#include <mutex> // NOLINT
#include <queue>
#include <vector>
#include "api/driver.h"
#include "api/watchdog.h"
#include "driver/dma_info.h"
#include "driver/dma_scheduler.h"
#include "driver/tpu_request.h"
#include "port/status.h"
#include "port/std_mutex_lock.h"
#include "port/thread_annotations.h"
namespace platforms {
namespace darwinn {
namespace driver {
// Manages the processing order of DMAs with single queue. All DMAs are
// serialized. Thread-safe.
class SingleQueueDmaScheduler : public DmaScheduler {
public:
SingleQueueDmaScheduler(std::unique_ptr<api::Watchdog> watchdog)
: watchdog_(std::move(watchdog)) {}
~SingleQueueDmaScheduler() override = default;
// Implements DmaScheduler interfaces.
util::Status Open() override LOCKS_EXCLUDED(mutex_);
util::Status Close(api::Driver::ClosingMode mode) override
LOCKS_EXCLUDED(mutex_);
util::Status Submit(std::shared_ptr<TpuRequest> request) override
LOCKS_EXCLUDED(mutex_);
util::StatusOr<DmaDescriptorType> PeekNextDma() const override
LOCKS_EXCLUDED(mutex_);
util::StatusOr<DmaInfo*> GetNextDma() override LOCKS_EXCLUDED(mutex_);
util::Status NotifyDmaCompletion(DmaInfo* dma_info) override
LOCKS_EXCLUDED(mutex_);
util::Status NotifyRequestCompletion() override LOCKS_EXCLUDED(mutex_);
util::Status CancelPendingRequests() override LOCKS_EXCLUDED(mutex_);
util::Status WaitActiveRequests() override LOCKS_EXCLUDED(mutex_);
bool IsEmpty() const override LOCKS_EXCLUDED(mutex_) {
StdMutexLock lock(&mutex_);
return IsEmptyLocked();
}
int64 MaxRemainingCycles() const override LOCKS_EXCLUDED(mutex_);
util::StatusOr<std::shared_ptr<TpuRequest>> GetOldestActiveRequest()
const override LOCKS_EXCLUDED(mutex_);
private:
// A data structure for managing Request and associated DMAs.
struct Task {
Task(std::shared_ptr<TpuRequest> request, std::list<DmaInfo>&& dmas)
: request(std::move(request)), dmas(std::move(dmas)) {}
// This type is movable.
Task(Task&& other)
: request(std::move(other.request)), dmas(std::move(other.dmas)) {}
Task& operator=(Task&& other) {
if (this != &other) {
request = std::move(other.request);
dmas = std::move(other.dmas);
}
return *this;
}
// Returns the associated TpuRequest.
std::shared_ptr<TpuRequest> GetTpuRequest() const {
return request;
}
// Request.
std::shared_ptr<TpuRequest> request;
// DMAs to be performed to serve request. std::list is intentionally used to
// have valid pointers while other members removed.
std::list<DmaInfo> dmas;
};
// A data structure for keeping track of DMA and its associated request.
struct PendingDma {
// DMA.
DmaInfo* info;
// Related request.
TpuRequest* request;
};
// Validates whether in "is_open" state.
util::Status ValidateOpenState(bool is_open) const
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Locked version of IsEmpty().
bool IsEmptyLocked() const EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
return pending_tasks_.empty() && active_tasks_.empty() &&
pending_dmas_.empty();
}
// Handles all completed DMAs related cleanups for given tasks.
util::Status HandleCompletedTasks() LOCKS_EXCLUDED(mutex_);
util::Status HandleActiveTasks() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Waits until all active DMAs are completed.
util::Status CloseActiveDmas() LOCKS_EXCLUDED(mutex_);
// Cancels all the active DMAs and requests.
util::Status CancelActiveRequests() LOCKS_EXCLUDED(mutex_);
// Cancels all the tasks in a provided queue.
util::Status CancelTaskQueue(std::deque<Task>& tasks)
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Guards all the related queues.
mutable std::mutex mutex_;
// A notification to wait for all active requests to complete.
std::condition_variable wait_active_requests_complete_;
// A notification to wait for all active dmas to complete.
std::condition_variable wait_active_dmas_complete_;
// Tracks open state.
bool is_open_ GUARDED_BY(mutex_){false};
// Pending tasks that have not yet performed any DMAs to DarwiNN device.
std::deque<Task> pending_tasks_ GUARDED_BY(mutex_);
// Active tasks that have delivered DMAs fully or partially to DarwiNN device.
std::deque<Task> active_tasks_ GUARDED_BY(mutex_);
// Completed tasks that may have few active on-going DMAs.
std::deque<Task> completed_tasks_ GUARDED_BY(mutex_);
// DMAs belonging to active requests that are not yet served.
std::queue<PendingDma> pending_dmas_ GUARDED_BY(mutex_);
// A watchdog passed down from the driver to keep track of TPU being active.
// DmaScheduler is responsible for activating the watchdog whenever a task
// enters active queue and de-activating it when the queue is empty.
std::unique_ptr<api::Watchdog> watchdog_;
};
} // namespace driver
} // namespace darwinn
} // namespace platforms
#endif // DARWINN_DRIVER_SINGLE_QUEUE_DMA_SCHEDULER_H_