ladybird/Kernel/WorkQueue.h
Liav A 0810c1b972 Kernel/Storage: Introduce basic abstraction layer for ATA components
This abstraction layer is mainly for ATA ports (AHCI ports, IDE ports).
The goal is to create a convenient and flexible framework so it's
possible to expand to support other types of controller (e.g. Intel PIIX
and ICH IDE controllers) and to abstract operations that are possible on
each component.

Currently only the ATA IDE code is affected by this, making it much
cleaner and readable - the ATA bus mastering code is moved to the
ATAPort code so more implementations in the near future can take
advantage of such functionality easily.

In addition to that, the hierarchy of the ATA IDE code resembles more of
the SATA AHCI code now, which means the IDEChannel class is solely
responsible for getting interrupts, passing them for further processing
in the ATAPort code to take care of the rest of the handling logic.
2022-07-19 11:07:34 +01:00

70 lines
1.6 KiB
C++

/*
* Copyright (c) 2021, the SerenityOS developers.
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Error.h>
#include <AK/IntrusiveList.h>
#include <Kernel/Forward.h>
#include <Kernel/Locking/SpinlockProtected.h>
#include <Kernel/WaitQueue.h>
namespace Kernel {
extern WorkQueue* g_io_work;
extern WorkQueue* g_ata_work;
class WorkQueue {
AK_MAKE_NONCOPYABLE(WorkQueue);
AK_MAKE_NONMOVABLE(WorkQueue);
public:
static void initialize();
ErrorOr<void> try_queue(void (*function)(void*), void* data = nullptr, void (*free_data)(void*) = nullptr)
{
auto item = new (nothrow) WorkItem; // TODO: use a pool
if (!item)
return Error::from_errno(ENOMEM);
item->function = [function, data, free_data] {
function(data);
if (free_data)
free_data(data);
};
do_queue(*item);
return {};
}
template<typename Function>
ErrorOr<void> try_queue(Function function)
{
auto item = new (nothrow) WorkItem; // TODO: use a pool
if (!item)
return Error::from_errno(ENOMEM);
item->function = Function(function);
do_queue(*item);
return {};
}
private:
explicit WorkQueue(StringView);
struct WorkItem {
public:
IntrusiveListNode<WorkItem> m_node;
Function<void()> function;
};
void do_queue(WorkItem&);
RefPtr<Thread> m_thread;
WaitQueue m_wait_queue;
SpinlockProtected<IntrusiveList<&WorkItem::m_node>> m_items;
};
}