mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01:00
added support for different sched strats + cfs
This commit is contained in:
@@ -4,7 +4,8 @@
|
||||
#include "../uos-intel-gpgpu/driver/gpgpu_driver.h"
|
||||
|
||||
#include "../virt/scheduler.h"
|
||||
extern gpgpu_virt::Scheduler* _global_sched;
|
||||
#include "../virt/strategies/rr.h"
|
||||
extern gpgpu_virt::GPGPUScheduler* _global_sched;
|
||||
|
||||
namespace gpgpu
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "../virt/rpc.h"
|
||||
#include "../virt/scheduler.h"
|
||||
#include "../virt/strategies/rr.h"
|
||||
|
||||
#define GENODE // use genodes stdint header
|
||||
#include "../uos-intel-gpgpu/driver/gpgpu_driver.h"
|
||||
@@ -15,7 +16,7 @@
|
||||
#endif // TEST
|
||||
|
||||
gpgpu::gpgpu_genode* _global_gpgpu_genode;
|
||||
gpgpu_virt::Scheduler* _global_sched;
|
||||
gpgpu_virt::GPGPUScheduler* _global_sched;
|
||||
|
||||
void Component::construct(Genode::Env& e)
|
||||
{
|
||||
@@ -25,7 +26,7 @@ void Component::construct(Genode::Env& e)
|
||||
// init globals
|
||||
static gpgpu::gpgpu_genode gg(e);
|
||||
_global_gpgpu_genode = ≫
|
||||
static gpgpu_virt::Scheduler sched;
|
||||
static gpgpu_virt::GPGPUScheduler sched;
|
||||
_global_sched = &sched;
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
TARGET = gpgpu
|
||||
REQUIRES = x86_64
|
||||
|
||||
SRC_CC = main.cc gpgpu_genode.cc stubs.cc test.cc ../virt/rpc.cc ../virt/scheduler.cc
|
||||
SRC_CC = main.cc gpgpu_genode.cc stubs.cc test.cc ../virt/rpc.cc ../virt/strategies/rr.cc ../virt/strategies/cfs.cc
|
||||
LIBS = base
|
||||
|
||||
UOS_INTEL_GPGPU = uos-intel-gpgpu-link-cxx.o
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
#include <gpgpu_virt/session.h>
|
||||
|
||||
#include "rpc.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
// genode instance
|
||||
#include "../gpgpu/gpgpu_genode.h"
|
||||
extern gpgpu::gpgpu_genode* _global_gpgpu_genode;
|
||||
extern gpgpu_virt::Scheduler* _global_sched;
|
||||
#include "scheduler.h"
|
||||
#include "strategies/rr.h"
|
||||
extern gpgpu_virt::GPGPUScheduler* _global_sched;
|
||||
|
||||
// driver
|
||||
#define GENODE // use genodes stdint header
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
#include "scheduler.h"
|
||||
#include "kernel.h"
|
||||
|
||||
// genode instance
|
||||
#include "../gpgpu/gpgpu_genode.h"
|
||||
extern gpgpu::gpgpu_genode* _global_gpgpu_genode;
|
||||
|
||||
// driver
|
||||
#define GENODE
|
||||
#include "../uos-intel-gpgpu/driver/gpgpu_driver.h"
|
||||
#include "../uos-intel-gpgpu/driver/ppgtt32.h"
|
||||
|
||||
namespace gpgpu_virt
|
||||
{
|
||||
|
||||
void Scheduler::schedule_next()
|
||||
{
|
||||
VGpu* first = nullptr;
|
||||
do
|
||||
{
|
||||
VGpu* next = nullptr;
|
||||
_run_list.dequeue([&next](VGpu& vgpu){
|
||||
next = &vgpu;
|
||||
});
|
||||
if(next != nullptr)
|
||||
{
|
||||
// set vgpu
|
||||
_curr_vgpu = next;
|
||||
|
||||
// add vgpu back to end of list
|
||||
_run_list.enqueue(*next);
|
||||
|
||||
// complete iteration?
|
||||
if(first == next)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// remember start of our search
|
||||
if(first == nullptr)
|
||||
{
|
||||
first = next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_curr_vgpu = nullptr;
|
||||
}
|
||||
}
|
||||
while(_curr_vgpu != nullptr && !_curr_vgpu->has_kernel()); // continue search if we picked a vgpu without kernel
|
||||
}
|
||||
|
||||
void Scheduler::handle_gpu_event()
|
||||
{
|
||||
// reduce frequency
|
||||
GPGPU_Driver& gpgpudriver = GPGPU_Driver::getInstance();
|
||||
gpgpudriver.setMinFreq();
|
||||
|
||||
/* Switch to next vGPU in the run list */
|
||||
schedule_next();
|
||||
|
||||
// If no vGPU to schedule, this means that we don't have any clients with anymore.
|
||||
if(_curr_vgpu == nullptr)
|
||||
{
|
||||
idle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Kernel* next = _curr_vgpu->take_kernel();
|
||||
if(next == nullptr)
|
||||
{
|
||||
idle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
idle = false;
|
||||
|
||||
// switch context
|
||||
dispatch(*_curr_vgpu);
|
||||
|
||||
// set frequency
|
||||
gpgpudriver.setMaxFreq();
|
||||
|
||||
// run gpgpu task
|
||||
gpgpudriver.enqueueRun(*next->get_config());
|
||||
|
||||
// free kernel object
|
||||
// kernel_config will not be freed, just the Queue object!
|
||||
_global_gpgpu_genode->free(next);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +1,35 @@
|
||||
#ifndef SCHEDULER_H
|
||||
#define SCHEDULER_H
|
||||
|
||||
#include <util/fifo.h>
|
||||
#include "vgpu.h"
|
||||
#include "kernel.h"
|
||||
|
||||
#include "strategies/rr.h"
|
||||
|
||||
// genode instance
|
||||
#include "../gpgpu/gpgpu_genode.h"
|
||||
extern gpgpu::gpgpu_genode* _global_gpgpu_genode;
|
||||
|
||||
// driver
|
||||
#define GENODE
|
||||
#include "../uos-intel-gpgpu/driver/gpgpu_driver.h"
|
||||
|
||||
namespace gpgpu_virt {
|
||||
|
||||
class Scheduler
|
||||
template<typename S> class Scheduler
|
||||
{
|
||||
private:
|
||||
S strat;
|
||||
VGpu* _curr_vgpu;
|
||||
Genode::Fifo<VGpu> _run_list;
|
||||
bool idle;
|
||||
|
||||
Scheduler(const Scheduler ©) = delete;
|
||||
Scheduler(Scheduler&&) = delete;
|
||||
Scheduler& operator=(const Scheduler&) = delete;
|
||||
Scheduler& operator=(Scheduler&&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
Scheduler() : _curr_vgpu(nullptr), _run_list(), idle(true) { }
|
||||
|
||||
/**
|
||||
* @brief Select next vGPU from run list
|
||||
* @details At the moment, round-robin is the only implemented strategy.
|
||||
* TODO: Implement interface for strategies and strategies *
|
||||
*/
|
||||
void schedule_next();
|
||||
Scheduler() : strat(), _curr_vgpu(nullptr), idle(true) { }
|
||||
|
||||
/**
|
||||
* @brief Switch to new vGPU's context
|
||||
@@ -41,7 +48,40 @@ namespace gpgpu_virt {
|
||||
* executing kernels. It is the target for interrupts coming from the GPGPU driver, e.g. when
|
||||
* a kernel has finished its execution.
|
||||
*/
|
||||
void handle_gpu_event();
|
||||
void handle_gpu_event()
|
||||
{
|
||||
// reduce frequency
|
||||
GPGPU_Driver& gpgpudriver = GPGPU_Driver::getInstance();
|
||||
gpgpudriver.setMinFreq();
|
||||
|
||||
/* Switch to next vGPU in the run list */
|
||||
_curr_vgpu = strat.nextVGPU();
|
||||
|
||||
// If no vGPU to schedule, this means that we don't have any clients with anymore.
|
||||
if(_curr_vgpu == nullptr)
|
||||
{
|
||||
idle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
idle = false;
|
||||
|
||||
Kernel* next = _curr_vgpu->take_kernel();
|
||||
|
||||
// switch context
|
||||
dispatch(*_curr_vgpu);
|
||||
|
||||
// set frequency
|
||||
gpgpudriver.setMaxFreq();
|
||||
|
||||
// run gpgpu task
|
||||
gpgpudriver.enqueueRun(*next->get_config());
|
||||
|
||||
// free kernel object
|
||||
// kernel_config will not be freed, just the Queue object!
|
||||
_global_gpgpu_genode->free(next);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
@@ -50,7 +90,7 @@ namespace gpgpu_virt {
|
||||
*/
|
||||
void add_vgpu(VGpu* vgpu)
|
||||
{
|
||||
_run_list.enqueue(*vgpu);
|
||||
strat.addVGPU(vgpu);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +100,7 @@ namespace gpgpu_virt {
|
||||
*/
|
||||
void remove_vgpu(VGpu* vgpu)
|
||||
{
|
||||
_run_list.remove(*vgpu);
|
||||
strat.removeVGPU(vgpu);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,6 +114,8 @@ namespace gpgpu_virt {
|
||||
return idle;
|
||||
}
|
||||
};
|
||||
|
||||
using GPGPUScheduler = Scheduler<gpgpu_virt::RoundRobin>;
|
||||
}
|
||||
|
||||
#endif // SCHEDULER_H
|
||||
|
||||
40
repos/dde_uos-intel-gpgpu/src/virt/strategie.h
Normal file
40
repos/dde_uos-intel-gpgpu/src/virt/strategie.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef STRATEGIE_H
|
||||
#define STRATEGIE_H
|
||||
|
||||
#include "vgpu.h"
|
||||
|
||||
namespace gpgpu_virt {
|
||||
|
||||
class Strategie
|
||||
{
|
||||
private:
|
||||
Strategie(const Strategie ©) = delete;
|
||||
|
||||
public:
|
||||
Strategie() {};
|
||||
virtual ~Strategie() {};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param vgpu
|
||||
*/
|
||||
virtual void addVGPU(VGpu* vgpu) = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param vgpu
|
||||
*/
|
||||
virtual void removeVGPU(VGpu* vgpu) = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @return VGpu*
|
||||
*/
|
||||
virtual VGpu* nextVGPU() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // STRATEGIE_H
|
||||
70
repos/dde_uos-intel-gpgpu/src/virt/strategies/cfs.cc
Normal file
70
repos/dde_uos-intel-gpgpu/src/virt/strategies/cfs.cc
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "cfs.h"
|
||||
|
||||
// genode instance
|
||||
#include "../../gpgpu/gpgpu_genode.h"
|
||||
extern gpgpu::gpgpu_genode* _global_gpgpu_genode;
|
||||
|
||||
namespace gpgpu_virt
|
||||
{
|
||||
|
||||
static unsigned long long int rdtsc()
|
||||
{
|
||||
unsigned long long int ret = 0;
|
||||
unsigned int cycles_lo;
|
||||
unsigned int cycles_hi;
|
||||
|
||||
__asm__ volatile ("RDTSC" : "=a" (cycles_lo), "=d" (cycles_hi));
|
||||
ret = (unsigned long long int)cycles_hi << 32 | cycles_lo;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CompletlyFair::addVGPU(VGpu* vgpu)
|
||||
{
|
||||
cfs_entry* ce = new (_global_gpgpu_genode->getAlloc()) cfs_entry(vgpu);
|
||||
_run_list.enqueue(*ce);
|
||||
}
|
||||
|
||||
void CompletlyFair::removeVGPU(VGpu* vgpu)
|
||||
{
|
||||
_run_list.for_each([&vgpu, this](cfs_entry& ce){
|
||||
if(ce.vgpu == vgpu)
|
||||
{
|
||||
_run_list.remove(ce);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
VGpu* CompletlyFair::nextVGPU()
|
||||
{
|
||||
// update cfs entry
|
||||
_curr->runtime += rdtsc() - _curr->ts;
|
||||
|
||||
// list empty?
|
||||
if(_run_list.empty())
|
||||
return nullptr;
|
||||
|
||||
cfs_entry* min = nullptr;
|
||||
_run_list.head([&min](cfs_entry& ce){
|
||||
min = &ce;
|
||||
});
|
||||
|
||||
_run_list.for_each([&min](cfs_entry& ce){
|
||||
if(ce.runtime < min->runtime && ce.vgpu->has_kernel())
|
||||
{
|
||||
min = &ce;
|
||||
}
|
||||
});
|
||||
|
||||
if(min->vgpu->has_kernel()) // in case this is still the head
|
||||
{
|
||||
_curr = min;
|
||||
_curr->ts = rdtsc();
|
||||
return min->vgpu;
|
||||
}
|
||||
|
||||
// no vgpu with kernel found
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
55
repos/dde_uos-intel-gpgpu/src/virt/strategies/cfs.h
Normal file
55
repos/dde_uos-intel-gpgpu/src/virt/strategies/cfs.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef CFS_H
|
||||
#define CFS_H
|
||||
|
||||
#include <util/fifo.h>
|
||||
#include "../strategie.h"
|
||||
|
||||
namespace gpgpu_virt {
|
||||
|
||||
class CompletlyFair : Strategie
|
||||
{
|
||||
class cfs_entry : public Genode::Fifo<cfs_entry>::Element
|
||||
{
|
||||
public:
|
||||
VGpu* vgpu;
|
||||
unsigned long runtime;
|
||||
unsigned long ts;
|
||||
cfs_entry(VGpu* vg) : vgpu(vg), runtime(0), ts(0) {}
|
||||
};
|
||||
|
||||
private:
|
||||
Genode::Fifo<cfs_entry> _run_list; // TODO: Red Black Tree
|
||||
cfs_entry* _curr;
|
||||
|
||||
CompletlyFair(const CompletlyFair ©) = delete;
|
||||
CompletlyFair(CompletlyFair&&) = delete;
|
||||
CompletlyFair& operator=(const CompletlyFair&) = delete;
|
||||
CompletlyFair& operator=(CompletlyFair&&) = delete;
|
||||
|
||||
public:
|
||||
CompletlyFair() : _run_list(), _curr(nullptr) {};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param vgpu
|
||||
*/
|
||||
void addVGPU(VGpu* vgpu) override;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param vgpu
|
||||
*/
|
||||
void removeVGPU(VGpu* vgpu) override;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @return VGpu*
|
||||
*/
|
||||
VGpu* nextVGPU() override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CFS_H
|
||||
57
repos/dde_uos-intel-gpgpu/src/virt/strategies/rr.cc
Normal file
57
repos/dde_uos-intel-gpgpu/src/virt/strategies/rr.cc
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "rr.h"
|
||||
|
||||
namespace gpgpu_virt
|
||||
{
|
||||
|
||||
void RoundRobin::addVGPU(VGpu* vgpu)
|
||||
{
|
||||
_run_list.enqueue(*vgpu);
|
||||
}
|
||||
|
||||
void RoundRobin::removeVGPU(VGpu* vgpu)
|
||||
{
|
||||
_run_list.remove(*vgpu);
|
||||
}
|
||||
|
||||
VGpu* RoundRobin::nextVGPU()
|
||||
{
|
||||
// list empty?
|
||||
if(_run_list.empty())
|
||||
return nullptr;
|
||||
|
||||
VGpu* first = nullptr;
|
||||
VGpu* next = nullptr;
|
||||
for(;;)
|
||||
{
|
||||
// get next vgpu
|
||||
_run_list.dequeue([&next](VGpu& vgpu){
|
||||
next = &vgpu;
|
||||
});
|
||||
|
||||
// add vgpu back to end of list
|
||||
_run_list.enqueue(*next);
|
||||
|
||||
// check if it has kernel?
|
||||
if(next->has_kernel())
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
// complete iteration?
|
||||
if(first == next)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// set start of search
|
||||
if(first == nullptr)
|
||||
{
|
||||
first = next;
|
||||
}
|
||||
}
|
||||
|
||||
// no vgpu with kernel found
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
40
repos/dde_uos-intel-gpgpu/src/virt/strategies/rr.h
Normal file
40
repos/dde_uos-intel-gpgpu/src/virt/strategies/rr.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef RR_H
|
||||
#define RR_H
|
||||
|
||||
#include <util/fifo.h>
|
||||
#include "../strategie.h"
|
||||
|
||||
namespace gpgpu_virt {
|
||||
|
||||
class RoundRobin : Strategie
|
||||
{
|
||||
private:
|
||||
Genode::Fifo<VGpu> _run_list;
|
||||
|
||||
public:
|
||||
RoundRobin() : _run_list() {};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param vgpu
|
||||
*/
|
||||
void addVGPU(VGpu* vgpu) override;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param vgpu
|
||||
*/
|
||||
void removeVGPU(VGpu* vgpu) override;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @return VGpu*
|
||||
*/
|
||||
VGpu* nextVGPU() override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // RR_H
|
||||
@@ -36,7 +36,6 @@ namespace gpgpu_virt {
|
||||
void add_kernel(Kernel* kernel) {
|
||||
kernel->get_config()->ctx = ctx; // set context
|
||||
ready_list.enqueue(*kernel);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user