Skip to content

Commit 1577c90

Browse files
committed
smp: Structures for running tasks on a specific CPU
1 parent 4170fbc commit 1577c90

4 files changed

Lines changed: 72 additions & 22 deletions

File tree

api/smp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,13 @@ public:
114114
// execute @func on another CPU core
115115
// call @done back on main CPU when task returns
116116
// use signal() to broadcast work should begin
117-
static void add_task(task_func func, done_func done);
118-
static void add_task(task_func func);
117+
static void add_task(task_func func, done_func done, int cpu = -1);
118+
static void add_task(task_func func, int cpu = -1);
119+
// execute a function on the main cpu
120+
static void add_bsp_task(done_func func);
119121

120122
// call this to signal that tasks are queued up
121-
static void signal();
123+
static void signal(int cpu = -1);
122124

123125
// trigger interrupt on specified CPU
124126
static void unicast(int cpu, uint8_t intr);

src/platform/x86_pc/apic_revenant.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "apic.hpp"
44
#include "apic_timer.hpp"
55
#include <kernel/irq_manager.hpp>
6+
#include <kernel/rng.hpp>
67
#include <kprint>
78

89
extern "C" int get_cpu_id();
@@ -12,30 +13,32 @@ extern "C" void lapic_exception_handler();
1213

1314
using namespace x86;
1415
smp_stuff smp;
16+
SMP_ARRAY<smp_stuff> smp_local;
1517

16-
static bool revenant_task_doer()
18+
static bool revenant_task_doer(smp_stuff& system)
1719
{
1820
// grab hold on task list
19-
lock(smp.tlock);
21+
lock(system.tlock);
2022

21-
if (smp.tasks.empty()) {
22-
unlock(smp.tlock);
23+
if (system.tasks.empty()) {
24+
unlock(system.tlock);
2325
// try again
2426
return false;
2527
}
2628

2729
// get copy of shared task
28-
auto task = std::move(smp.tasks.front());
29-
smp.tasks.pop_front();
30+
auto task = std::move(system.tasks.front());
31+
system.tasks.pop_front();
3032

31-
unlock(smp.tlock);
33+
unlock(system.tlock);
3234

3335
// execute actual task
3436
task.func();
3537

3638
// add done function to completed list (only if its callable)
3739
if (task.done)
3840
{
41+
// NOTE: specifically pushing to 'smp' here, and not 'system'
3942
lock(smp.flock);
4043
smp.completed.push_back(std::move(task.done));
4144
unlock(smp.flock);
@@ -48,7 +51,11 @@ static void revenant_task_handler()
4851
{
4952
bool work_done = false;
5053
while (true) {
51-
bool did_something = revenant_task_doer();
54+
// global tasks
55+
bool did_something = revenant_task_doer(smp);
56+
work_done = work_done || did_something;
57+
// cpu-specific tasks
58+
did_something = revenant_task_doer(PER_CPU(smp_local));
5259
work_done = work_done || did_something;
5360
if (did_something == false) break;
5461
}
@@ -74,9 +81,11 @@ void revenant_main(int cpu)
7481
IRQ_manager::enable_interrupts();
7582
// init timer system
7683
APIC_Timer::init();
77-
84+
// subscribe to task and timer interrupts
7885
IRQ_manager::get().subscribe(0, revenant_task_handler);
7986
IRQ_manager::get().subscribe(1, APIC_Timer::start_timers);
87+
// seed RNG
88+
RNG::init();
8089

8190
// allow programmers to do stuff on each core at init
8291
::SMP::init_task();

src/platform/x86_pc/apic_revenant.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,6 @@ struct smp_stuff
4545
std::deque<SMP::done_func> completed;
4646
};
4747
extern smp_stuff smp;
48+
extern SMP_ARRAY<smp_stuff> smp_local;
4849

4950
#endif

src/platform/x86_pc/smp.cpp

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,31 +151,69 @@ void ::SMP::init_task()
151151
/* do nothing */
152152
}
153153

154-
void ::SMP::add_task(smp_task_func task, smp_done_func done)
154+
void ::SMP::add_task(smp_task_func task, smp_done_func done, int cpu)
155155
{
156156
#ifdef INCLUDEOS_SINGLE_THREADED
157+
assert(cpu == -1 || cpu == 0);
157158
task(); done();
158159
#else
159-
lock(smp.tlock);
160-
smp.tasks.emplace_back(std::move(task), std::move(done));
161-
unlock(smp.tlock);
160+
if (cpu == -1)
161+
{
162+
lock(smp.tlock);
163+
smp.tasks.emplace_back(std::move(task), std::move(done));
164+
unlock(smp.tlock);
165+
}
166+
else {
167+
lock(smp_local[cpu].tlock);
168+
smp_local[cpu].tasks.emplace_back(std::move(task), std::move(done));
169+
unlock(smp_local[cpu].tlock);
170+
}
162171
#endif
163172
}
164-
void ::SMP::add_task(smp_task_func task)
173+
void ::SMP::add_task(smp_task_func task, int cpu)
165174
{
166175
#ifdef INCLUDEOS_SINGLE_THREADED
176+
assert(cpu == -1 || cpu == 0);
167177
task();
168178
#else
169-
lock(smp.tlock);
170-
smp.tasks.emplace_back(std::move(task), nullptr);
171-
unlock(smp.tlock);
179+
if (cpu == -1)
180+
{
181+
lock(smp.tlock);
182+
smp.tasks.emplace_back(std::move(task), nullptr);
183+
unlock(smp.tlock);
184+
}
185+
else {
186+
lock(smp_local[cpu].tlock);
187+
smp_local[cpu].tasks.emplace_back(std::move(task), nullptr);
188+
unlock(smp_local[cpu].tlock);
189+
}
172190
#endif
173191
}
174-
void ::SMP::signal()
192+
void ::SMP::add_bsp_task(smp_done_func task)
193+
{
194+
#ifdef INCLUDEOS_SINGLE_THREADED
195+
task();
196+
#else
197+
lock(smp.flock);
198+
smp.completed.push_back(std::move(task));
199+
unlock(smp.flock);
200+
x86::APIC::get().send_bsp_intr();
201+
#endif
202+
}
203+
204+
void ::SMP::signal(int cpu)
175205
{
176206
#ifndef INCLUDEOS_SINGLE_THREADED
177207
// broadcast that there is work to do
178-
x86::APIC::get().bcast_ipi(0x20);
208+
// -1: Broadcast to everyone except BSP
209+
if (cpu == -1)
210+
x86::APIC::get().bcast_ipi(0x20);
211+
// 1-xx: Unicast specific vCPU
212+
else if (cpu != 0)
213+
x86::APIC::get().send_ipi(cpu, 0x20);
214+
// 0: BSP unicast
215+
else
216+
x86::APIC::get().send_bsp_intr();
179217
#endif
180218
}
181219

0 commit comments

Comments
 (0)