blob: bf2e26d42cdefa92c36360ba45b4890582826dd1 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <io-scheduler/worker.h>
#include <stdio.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#include <io-scheduler/io-scheduler.h>
namespace ioscheduler {
zx_status_t Worker::Create(Scheduler* sched, uint32_t id, fbl::unique_ptr<Worker>* out) {
fbl::AllocChecker ac;
fbl::unique_ptr<Worker> worker(new (&ac) Worker(sched, id));
if (!ac.check()) {
fprintf(stderr, "Failed to allocate worker.\n");
return ZX_ERR_NO_MEMORY;
}
if (thrd_create(&worker->thread_, worker->ThreadEntry, worker.get()) != ZX_OK) {
fprintf(stderr, "Failed to create worker thread.\n");
return ZX_ERR_NO_MEMORY;
}
worker->thread_started_ = true;
*out = std::move(worker);
return ZX_OK;
}
Worker::Worker(Scheduler* sched, uint32_t id) : sched_(sched), id_(id) { }
Worker::~Worker() {
if (thread_started_) {
thrd_join(thread_, nullptr);
}
}
int Worker::ThreadEntry(void* arg) {
Worker* w = static_cast<Worker*>(arg);
w->WorkerLoop();
return 0;
}
void Worker::WorkerLoop() {
const size_t max_ops = 10;
SchedulerClient* client = sched_->client();
zx_status_t status;
for ( ; ; ) {
size_t actual_count = 0;
SchedulerOp* op_list[max_ops];
status = client->Acquire(op_list, max_ops, &actual_count, true);
if (status == ZX_ERR_CANCELED) {
// Cancel received, no more ops to read. Drain the streams and exit.
break;
}
if (status != ZX_OK) {
fprintf(stderr, "Unexpected return status from Acquire() %d\n", status);
client->Fatal();
break;
}
// Dummy issue loop. In the future, ops will be added to the scheduler.
for (size_t i = 0; i < actual_count; i++) {
status = client->Issue(op_list[i]);
ZX_DEBUG_ASSERT(status == ZX_OK); // Require synchronous completion, for now.
client->Release(op_list[i]);
}
}
}
} // namespace ioscheduler