Skip to content

Commit 48e1b27

Browse files
committed
update
1 parent 3138ca6 commit 48e1b27

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2234
-604
lines changed

common/dl-utils-lite.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <time.h>
2323
#include <unistd.h>
2424
#include <dirent.h>
25-
#include <tuple>
2625

2726
#include "common/server/crash-dump.h"
2827
#include "common/stats/provider.h"
@@ -50,9 +49,9 @@ double dl_time() {
5049
}
5150

5251
void dl_print_backtrace(void **trace, int trace_size) {
53-
std::ignore = write (2, "\n------- Stack Backtrace -------\n", 33);
52+
write (2, "\n------- Stack Backtrace -------\n", 33);
5453
backtrace_symbols_fd (trace, trace_size, 2);
55-
std::ignore = write (2, "-------------------------------\n", 32);
54+
write (2, "-------------------------------\n", 32);
5655
}
5756

5857
void dl_print_backtrace() {
@@ -72,7 +71,7 @@ void dl_print_backtrace_gdb() {
7271
name_buf[res] = 0;
7372
int child_pid = fork();
7473
if (child_pid < 0) {
75-
std::ignore = write (2, "Can't fork() to run gdb\n", 24);
74+
write (2, "Can't fork() to run gdb\n", 24);
7675
_exit (0);
7776
}
7877
if (!child_pid) {
@@ -84,7 +83,7 @@ void dl_print_backtrace_gdb() {
8483
waitpid (child_pid, nullptr, 0);
8584
}
8685
} else {
87-
std::ignore = write (2, "can't get name of executable file to pass to gdb\n", 49);
86+
write (2, "can't get name of executable file to pass to gdb\n", 49);
8887
}
8988
}
9089

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
set(RUNTIME_ALLOCATOR_SRC
2-
${BASE_DIR}/runtime-light/allocator/runtime-light-allocator.cpp)
1+
set(RUNTIME_ALLOCATOR_SRC allocator/runtime-light-allocator.cpp)

runtime-light/allocator/runtime-light-allocator.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55
#include <cstddef>
66
#include <cstring>
77

8-
#include "runtime-core/runtime-core.h"
8+
#include "runtime-core/utils/kphp-assert-core.h"
99
#include "runtime-light/component/component.h"
10-
#include "runtime-light/utils/panic.h"
1110

1211
namespace {
1312
// TODO: make it depend on max chunk size, e.g. MIN_EXTRA_MEM_SIZE = f(MAX_CHUNK_SIZE);
@@ -136,4 +135,4 @@ void *RuntimeAllocator::realloc_global_memory(void *mem, size_t new_size, size_t
136135

137136
void RuntimeAllocator::free_global_memory(void *mem, size_t) noexcept {
138137
get_platform_context()->allocator.free(mem);
139-
}
138+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
prepend(RUNTIME_COMPONENT_SRC component/ component.cpp)

runtime-light/component/component.cpp

Lines changed: 117 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,64 +3,140 @@
33
// Distributed under the GPL v3 License, see LICENSE.notice.txt
44

55
#include "runtime-light/component/component.h"
6+
7+
#include <chrono>
8+
#include <cstdint>
9+
#include <utility>
10+
11+
#include "runtime-core/utils/kphp-assert-core.h"
612
#include "runtime-light/core/globals/php-init-scripts.h"
13+
#include "runtime-light/header.h"
14+
#include "runtime-light/scheduler/scheduler.h"
15+
#include "runtime-light/utils/context.h"
716

8-
void ComponentState::resume_if_was_rescheduled() {
9-
if (poll_status == PollStatus::PollReschedule) {
10-
// If component was suspended by please yield and there is no awaitable streams
11-
main_thread();
12-
}
17+
void ComponentState::init_script_execution() noexcept {
18+
kphp_core_context.init();
19+
init_php_scripts_in_each_worker(php_script_mutable_globals_singleton, main_task);
20+
scheduler.suspend(std::make_pair(main_task.get_handle(), WaitEvent::Rechedule{}));
1321
}
1422

15-
bool ComponentState::is_stream_already_being_processed(uint64_t stream_d) {
16-
return opened_streams.contains(stream_d);
17-
}
23+
void ComponentState::process_platform_updates() noexcept {
24+
const auto &platform_ctx{*get_platform_context()};
25+
26+
for (;;) {
27+
// check if platform asked for yield
28+
if (static_cast<bool>(platform_ctx.please_yield.load())) { // tell the scheduler that we are about to yield
29+
php_debug("platform asked for yield");
30+
const auto schedule_status{scheduler.schedule(ScheduleEvent::Yield{})};
31+
poll_status = schedule_status == ScheduleStatus::Error ? PollStatus::PollFinishedError : PollStatus::PollReschedule;
32+
return;
33+
}
1834

19-
void ComponentState::resume_if_wait_stream(uint64_t stream_d, StreamStatus status) {
20-
if (is_stream_timer(stream_d)) {
21-
process_timer(stream_d);
22-
} else {
23-
process_stream(stream_d, status);
35+
// try taking update from the platform
36+
if (uint64_t stream_d{}; static_cast<bool>(platform_ctx.take_update(std::addressof(stream_d)))) {
37+
if (opened_streams_.contains(stream_d)) { // update on opened stream
38+
php_debug("took update on stream %" PRIu64, stream_d);
39+
switch (scheduler.schedule(ScheduleEvent::UpdateOnStream{.stream_d = stream_d})) {
40+
case ScheduleStatus::Resumed: { // scheduler's resumed a coroutine waiting for update
41+
break;
42+
}
43+
case ScheduleStatus::Skipped: { // no one is waiting for the event yet, so just save it
44+
pending_updates_.insert(stream_d);
45+
break;
46+
}
47+
case ScheduleStatus::Error: { // something bad's happened, stop execution
48+
poll_status = PollStatus::PollFinishedError;
49+
return;
50+
}
51+
}
52+
} else { // update on incoming stream
53+
php_debug("got new incoming stream %" PRIu64, stream_d);
54+
if (standard_stream_ != INVALID_PLATFORM_DESCRIPTOR) {
55+
php_warning("skip new incoming stream since previous one is not closed");
56+
release_stream(stream_d);
57+
continue;
58+
} // TODO: multiple incoming streams (except for http queries)
59+
standard_stream_ = stream_d;
60+
incoming_streams_.push_back(stream_d);
61+
opened_streams_.insert(stream_d);
62+
if (const auto schedule_status{scheduler.schedule(ScheduleEvent::IncomingStream{.stream_d = stream_d})}; schedule_status == ScheduleStatus::Error) {
63+
poll_status = PollStatus::PollFinishedError;
64+
return;
65+
}
66+
}
67+
} else { // we'are out of updates so let the scheduler do whatever it wants
68+
switch (scheduler.schedule(ScheduleEvent::NoEvent{})) {
69+
case ScheduleStatus::Resumed: { // scheduler's resumed some coroutine, so let's continue scheduling
70+
break;
71+
}
72+
case ScheduleStatus::Skipped: { // scheduler's done nothing, so it's either scheduled all coroutines or is waiting for events
73+
poll_status = scheduler.done() ? PollStatus::PollFinishedOk : PollStatus::PollBlocked;
74+
return;
75+
}
76+
case ScheduleStatus::Error: { // something bad's happened, stop execution
77+
poll_status = PollStatus::PollFinishedError;
78+
return;
79+
}
80+
}
81+
}
2482
}
83+
// unreachable code
84+
poll_status = PollStatus::PollFinishedError;
2585
}
2686

27-
void ComponentState::process_new_input_stream(uint64_t stream_d) {
28-
bool already_pending = std::find(incoming_pending_queries.begin(), incoming_pending_queries.end(), stream_d) != incoming_pending_queries.end();
29-
if (!already_pending) {
30-
php_debug("got new pending query %lu", stream_d);
31-
incoming_pending_queries.push_back(stream_d);
32-
}
33-
if (wait_incoming_stream) {
34-
php_debug("start process pending query %lu", stream_d);
35-
main_thread();
87+
uint64_t ComponentState::take_incoming_stream() noexcept {
88+
if (incoming_streams_.empty()) {
89+
php_warning("can't take incoming stream cause we don't have them");
90+
return INVALID_PLATFORM_DESCRIPTOR;
3691
}
92+
const auto stream_d{incoming_streams_.front()};
93+
incoming_streams_.pop_front();
94+
php_debug("take incoming stream %" PRIu64, stream_d);
95+
return stream_d;
3796
}
3897

39-
void ComponentState::init_script_execution() {
40-
kphp_core_context.init();
41-
init_php_scripts_in_each_worker(php_script_mutable_globals_singleton, k_main);
42-
main_thread = k_main.get_handle();
98+
uint64_t ComponentState::open_stream(const string &component_name) noexcept {
99+
uint64_t stream_d{};
100+
if (const auto open_stream_res{get_platform_context()->open(component_name.size(), component_name.c_str(), std::addressof(stream_d))};
101+
open_stream_res != OpenStreamResult::OpenStreamOk) {
102+
php_warning("can't open stream to %s", component_name.c_str());
103+
return INVALID_PLATFORM_DESCRIPTOR;
104+
}
105+
opened_streams_.insert(stream_d);
106+
php_debug("opened a stream %" PRIu64 " to %s", stream_d, component_name.c_str());
107+
return stream_d;
43108
}
44109

45-
bool ComponentState::is_stream_timer(uint64_t stream_d) {
46-
return timer_callbacks.contains(stream_d);
110+
uint64_t ComponentState::set_timer(std::chrono::nanoseconds duration) noexcept {
111+
uint64_t timer_d{};
112+
if (const auto set_timer_res{get_platform_context()->set_timer(std::addressof(timer_d), static_cast<uint64_t>(duration.count()))};
113+
set_timer_res != SetTimerResult::SetTimerOk) {
114+
php_warning("can't set timer for %.9f sec", std::chrono::duration<double>(duration).count());
115+
return INVALID_PLATFORM_DESCRIPTOR;
116+
}
117+
opened_streams_.insert(timer_d);
118+
php_debug("set timer %" PRIu64 " for %.9f sec", timer_d, std::chrono::duration<double>(duration).count());
119+
return timer_d;
47120
}
48121

49-
void ComponentState::process_timer(uint64_t stream_d) {
122+
void ComponentState::release_stream(uint64_t stream_d) noexcept {
123+
if (stream_d == standard_stream_) {
124+
standard_stream_ = INVALID_PLATFORM_DESCRIPTOR;
125+
}
126+
opened_streams_.erase(stream_d);
127+
pending_updates_.erase(stream_d); // also erase pending updates if exists
50128
get_platform_context()->free_descriptor(stream_d);
51-
timer_callbacks[stream_d]();
52-
timer_callbacks.erase(stream_d);
53-
opened_streams.erase(stream_d);
129+
php_debug("released a stream %" PRIu64, stream_d);
54130
}
55131

56-
void ComponentState::process_stream(uint64_t stream_d, StreamStatus status) {
57-
auto expected_status = opened_streams[stream_d];
58-
if ((expected_status == StreamRuntimeStatus::WBlocked && status.write_status != IOBlocked)
59-
|| (expected_status == StreamRuntimeStatus::RBlocked && status.read_status != IOBlocked)) {
60-
php_debug("resume on waited query %lu", stream_d);
61-
auto suspend_point = awaiting_coroutines[stream_d];
62-
awaiting_coroutines.erase(stream_d);
63-
php_assert(awaiting_coroutines.empty());
64-
suspend_point();
132+
void ComponentState::release_all_streams() noexcept {
133+
const auto &platform_ctx{*get_platform_context()};
134+
standard_stream_ = INVALID_PLATFORM_DESCRIPTOR;
135+
for (const auto stream_d : opened_streams_) {
136+
platform_ctx.free_descriptor(stream_d);
137+
php_debug("released a stream %" PRIu64, stream_d);
65138
}
139+
opened_streams_.clear();
140+
pending_updates_.clear();
141+
incoming_streams_.clear();
66142
}

runtime-light/component/component.h

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,78 +4,87 @@
44

55
#pragma once
66

7-
#include <coroutine>
7+
#include <chrono>
88
#include <csetjmp>
99
#include <cstddef>
10-
#include <functional>
11-
#include <queue>
10+
#include <cstdint>
1211

1312
#include "runtime-core/memory-resource/resource_allocator.h"
1413
#include "runtime-core/memory-resource/unsynchronized_pool_resource.h"
1514
#include "runtime-core/runtime-core.h"
16-
1715
#include "runtime-light/core/globals/php-script-globals.h"
1816
#include "runtime-light/coroutine/task.h"
19-
#include "runtime-light/stdlib/output-control.h"
17+
#include "runtime-light/header.h"
18+
#include "runtime-light/scheduler/scheduler.h"
19+
#include "runtime-light/stdlib/fork/fork-context.h"
20+
#include "runtime-light/stdlib/output/output-buffer.h"
2021
#include "runtime-light/stdlib/rpc/rpc-context.h"
21-
#include "runtime-light/stdlib/superglobals.h"
22-
#include "runtime-light/streams/streams.h"
23-
#include "runtime-light/utils/context.h"
22+
23+
constexpr uint64_t INVALID_PLATFORM_DESCRIPTOR = 0;
24+
25+
// Coroutine scheduler type. Change it here if you want to use another scheduler
26+
using CoroutineScheduler = SimpleCoroutineScheduler;
27+
static_assert(CoroutineSchedulerConcept<CoroutineScheduler>);
2428

2529
struct ComponentState {
26-
template<typename Key, typename Value>
27-
using unordered_map = memory_resource::stl::unordered_map<Key, Value, memory_resource::unsynchronized_pool_resource>;
30+
template<typename T>
31+
using unordered_set = memory_resource::stl::unordered_set<T, memory_resource::unsynchronized_pool_resource>;
32+
2833
template<typename T>
2934
using deque = memory_resource::stl::deque<T, memory_resource::unsynchronized_pool_resource>;
30-
static constexpr auto INIT_RUNTIME_ALLOCATOR_SIZE = static_cast<size_t>(512U * 1024U); // 512KB
3135

32-
ComponentState()
36+
ComponentState() noexcept
3337
: runtime_allocator(INIT_RUNTIME_ALLOCATOR_SIZE, 0)
38+
, scheduler(runtime_allocator.memory_resource)
39+
, fork_component_context(runtime_allocator.memory_resource)
3440
, php_script_mutable_globals_singleton(runtime_allocator.memory_resource)
35-
, opened_streams(unordered_map<uint64_t, StreamRuntimeStatus>::allocator_type{runtime_allocator.memory_resource})
36-
, awaiting_coroutines(unordered_map<uint64_t, std::coroutine_handle<>>::allocator_type{runtime_allocator.memory_resource})
37-
, timer_callbacks(unordered_map<uint64_t, std::function<void()>>::allocator_type{runtime_allocator.memory_resource})
38-
, incoming_pending_queries(deque<uint64_t>::allocator_type{runtime_allocator.memory_resource})
39-
, rpc_component_context(runtime_allocator.memory_resource) {}
41+
, rpc_component_context(runtime_allocator.memory_resource)
42+
, incoming_streams_(deque<uint64_t>::allocator_type{runtime_allocator.memory_resource})
43+
, opened_streams_(unordered_set<uint64_t>::allocator_type{runtime_allocator.memory_resource})
44+
, pending_updates_(unordered_set<uint64_t>::allocator_type{runtime_allocator.memory_resource}) {}
4045

4146
~ComponentState() = default;
4247

43-
bool not_finished() const noexcept {
44-
return poll_status != PollStatus::PollFinishedOk && poll_status != PollStatus::PollFinishedError;
45-
}
46-
47-
void resume_if_was_rescheduled();
48-
49-
bool is_stream_already_being_processed(uint64_t stream_d);
50-
51-
void resume_if_wait_stream(uint64_t stream_d, StreamStatus status);
48+
void init_script_execution() noexcept;
49+
void process_platform_updates() noexcept;
5250

53-
void process_new_input_stream(uint64_t stream_d);
54-
55-
void init_script_execution();
51+
bool stream_updated(uint64_t stream_d) const noexcept {
52+
return pending_updates_.contains(stream_d);
53+
}
54+
const unordered_set<uint64_t> &opened_streams() const noexcept {
55+
return opened_streams_;
56+
}
57+
const deque<uint64_t> &incoming_streams() const noexcept {
58+
return incoming_streams_;
59+
}
60+
uint64_t standard_stream() const noexcept {
61+
return standard_stream_;
62+
}
63+
uint64_t take_incoming_stream() noexcept;
64+
uint64_t open_stream(const string &) noexcept;
65+
uint64_t set_timer(std::chrono::nanoseconds) noexcept;
66+
void release_stream(uint64_t) noexcept;
67+
void release_all_streams() noexcept;
5668

5769
RuntimeAllocator runtime_allocator;
58-
task_t<void> k_main;
59-
Response response;
60-
PhpScriptMutableGlobals php_script_mutable_globals_singleton;
6170

71+
CoroutineScheduler scheduler;
72+
ForkComponentContext fork_component_context;
6273
PollStatus poll_status = PollStatus::PollReschedule;
63-
uint64_t standard_stream = 0;
64-
std::coroutine_handle<> main_thread;
65-
bool wait_incoming_stream = false;
6674

67-
unordered_map<uint64_t, StreamRuntimeStatus> opened_streams; // подумать про необходимость opened_streams. Объединить с awaiting_coroutines
68-
unordered_map<uint64_t, std::coroutine_handle<>> awaiting_coroutines;
69-
unordered_map<uint64_t, std::function<void()>> timer_callbacks;
70-
deque<uint64_t> incoming_pending_queries;
75+
Response response;
76+
PhpScriptMutableGlobals php_script_mutable_globals_singleton;
7177

7278
KphpCoreContext kphp_core_context;
7379
RpcComponentContext rpc_component_context;
7480

7581
private:
76-
bool is_stream_timer(uint64_t stream_d);
82+
task_t<void> main_task;
7783

78-
void process_timer(uint64_t stream_d);
84+
uint64_t standard_stream_{INVALID_PLATFORM_DESCRIPTOR};
85+
deque<uint64_t> incoming_streams_;
86+
unordered_set<uint64_t> opened_streams_;
87+
unordered_set<uint64_t> pending_updates_;
7988

80-
void process_stream(uint64_t stream_d, StreamStatus status);
89+
static constexpr auto INIT_RUNTIME_ALLOCATOR_SIZE = static_cast<size_t>(512U * 1024U); // 512KB
8190
};

runtime-light/core/core.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
prepend(RUNTIME_LANGUAGE_SRC ${BASE_DIR}/runtime-light/core/globals/
1+
prepend(RUNTIME_LANGUAGE_SRC core/globals/
22
php-script-globals.cpp)
33

4-
prepend(RUNTIME_KPHP_CORE_CONTEXT_SRC ${BASE_DIR}/runtime-light/core/kphp-core-impl/
4+
prepend(RUNTIME_KPHP_CORE_CONTEXT_SRC core/kphp-core-impl/
55
kphp-core-context.cpp)
66

77

runtime-light/core/globals/php-init-scripts.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#pragma once
66

7-
#include <cstddef>
7+
#include "runtime-light/coroutine/task.h"
88

99
class PhpScriptMutableGlobals;
1010

0 commit comments

Comments
 (0)