commit - ace583b69a3b05ca805707befbc795a4db603773
commit + 56248200cb9b36d2cb2c595655895b7e03abd637
blob - 416363d99565971384e28d9bc1ff3f4f05d0f431
blob + 0a4afde5d0435523b7baf038d00578fd27b6d917
--- kernel/ipc/block_service.c
+++ kernel/ipc/block_service.c
#include "mm/kmem.h"
#include "sys/diag.h"
#include "arch/smp.h"
+#include "time/timer.h"
#include "sync/spinlock.h"
#define BLOCK_SERVICE_MAX_PENDING 64U
struct block_service_pending *slot;
struct ipc_block_service_request tmp;
struct ringbuf *ringbuf;
- uint64_t spins = 0;
bool warned = false;
uint32_t cpu;
block_state.next_token = 1;
tmp = *req;
tmp.token = slot->token;
+ if ((tmp.flags & IPC_BLOCK_SERVICE_F_WRITE) != 0 &&
+ tmp.blocks > 0 && tmp.data_len == 0) {
+ static uint32_t zero_write_log;
+ if (zero_write_log < 4) {
+ printk("[diag][block] WARN: write with zero data len dev=");
+ printk_dec((uint64_t)tmp.device);
+ printk(" lba=");
+ printk_dec(tmp.lba);
+ printk(" blocks=");
+ printk_dec((uint64_t)tmp.blocks);
+ printk(" task=");
+ printk(sched_task_name(slot->client));
+ printk("\n");
+ zero_write_log++;
+ }
+ }
block_diag_log_request(&tmp);
block_trace_record_submit(&tmp);
if (ipc_portal_send(block_state.portal, &tmp, sizeof(tmp)) != 0) {
}
perf_counter_inc(PERF_COUNTER_BLOCK_REQUESTS, 1);
- /*
- * Optimized IPC wait: significantly reduced spin limit from 100M to 1M
- * to minimize CPU waste on busy-waiting. With sched_yield() called every
- * iteration, 1M yields is still ~1-10ms depending on scheduler congestion.
- */
- uint64_t spin_limit = 1000000;
+ uint64_t start_ticks = timer_ticks();
+ uint64_t timeout_ticks = timer_get_hz() * 5; /* 5s */
while (!__atomic_load_n(&slot->ready, __ATOMIC_ACQUIRE)) {
if (block_state.server == NULL || slot->client == NULL ||
- ++spins > spin_limit) {
+ (timeout_ticks > 0 &&
+ (timer_ticks() - start_ticks) > timeout_ticks)) {
if (ringbuf != NULL && slot->resp_offset != 0) {
ringbuf_data_free(ringbuf, slot->resp_offset,
sizeof(*slot->resp));
block_diag_log("[diag][block] block_service_issue timed out\n");
return -1;
}
- if (!warned && diag_flag_enabled(DIAG_FLAG_BLOCK) && spins > 100000) {
+ if (!warned && diag_flag_enabled(DIAG_FLAG_BLOCK) &&
+ (timer_ticks() - start_ticks) > (timer_get_hz() / 10)) {
block_diag_log("[diag][block] waiting for daemon response\n");
warned = true;
}
blob - 252ba42f51af5d58dc705c59d057e1ede786cea9
blob + 93dd9e7027c73eb4c00f3f7be3f0ab7049c6ff1e
--- kernel/ipc/mailbox.c
+++ kernel/ipc/mailbox.c
{
struct ipc_message *msg;
const uint8_t *src = buf;
+ static uint32_t quota_log_count;
if (mbox == NULL || len == 0 || buf == NULL)
return -1;
/* Check payload quota early if enabled */
if (mbox->quota_enabled && len > mbox->payload_quota) {
mbox->quota_violations++;
+ if (quota_log_count < 4) {
+ printk("[ipc] mailbox payload quota hit owner=");
+ if (mbox->owner != NULL && sched_task_name(mbox->owner) != NULL)
+ printk(sched_task_name(mbox->owner));
+ else
+ printk("(none)");
+ printk(" len=");
+ printk_dec(len);
+ printk("\n");
+ quota_log_count++;
+ }
return -1; /* ENOBUFS semantics */
}
mailbox_unlock(mbox);
kmem_free(msg);
mbox->quota_violations++;
+ if (quota_log_count < 4) {
+ printk("[ipc] mailbox depth quota hit owner=");
+ if (mbox->owner != NULL && sched_task_name(mbox->owner) != NULL)
+ printk(sched_task_name(mbox->owner));
+ else
+ printk("(none)");
+ printk(" depth=");
+ printk_dec(mbox->depth);
+ printk("\n");
+ quota_log_count++;
+ }
return -1; /* ENOBUFS: quota exceeded */
}
if (mbox->tail == NULL) {
blob - e6901397160b25456a90ad6fb7921363705ae7ea
blob + 348a7cedef6fea351da9d46bd3a49d96992afe08
--- kernel/kmain.c
+++ kernel/kmain.c
boot_log_result("vfs", rc == 0);
}
- // rc = user_netd_server_prepare();
- // #ifdef LENIX_DEBUG
- // boot_log_result("Preparing netd...", rc == 0);
- // #endif
- // if (rc == 0) {
- // rc = user_netd_server_launch();
- // boot_log_result("netd", rc == 0);
- // }
+ rc = user_netd_server_prepare();
+ #ifdef LENIX_DEBUG
+ boot_log_result("Preparing netd...", rc == 0);
+ #endif
+ if (rc == 0) {
+ rc = user_netd_server_launch();
+ boot_log_result("netd", rc == 0);
+ }
- // rc = user_sock_udp_server_prepare();
- // #ifdef LENIX_DEBUG
- // boot_log_result("Preparing sock.udp...", rc == 0);
- // #endif
- // if (rc == 0) {
- // rc = user_sock_udp_server_launch();
- // boot_log_result("sock.udp", rc == 0);
- // }
+ rc = user_sock_udp_server_prepare();
+ #ifdef LENIX_DEBUG
+ boot_log_result("Preparing sock.udp...", rc == 0);
+ #endif
+ if (rc == 0) {
+ rc = user_sock_udp_server_launch();
+ boot_log_result("sock.udp", rc == 0);
+ }
- // rc = user_sock_tcp_server_prepare();
- // #ifdef LENIX_DEBUG
- // boot_log_result("Preparing sock.tcp...", rc == 0);
- // #endif
- // if (rc == 0) {
- // rc = user_sock_tcp_server_launch();
- // boot_log_result("sock.tcp", rc == 0);
- // }
+ rc = user_sock_tcp_server_prepare();
+ #ifdef LENIX_DEBUG
+ boot_log_result("Preparing sock.tcp...", rc == 0);
+ #endif
+ if (rc == 0) {
+ rc = user_sock_tcp_server_launch();
+ boot_log_result("sock.tcp", rc == 0);
+ }
rc = user_tty_server_prepare();
#ifdef LENIX_DEBUG
blob - c70f34d454452e243e82515ff0ab386f67fb9db5
blob + 33b6a1766a033676c6ba050604869de169ea45b4
--- kernel/sched/task.c
+++ kernel/sched/task.c
static struct ipc_mailbox *sched_mailbox_create(struct sched_task *task);
static void sched_mailbox_destroy(struct sched_task *task);
+static bool name_equals(const char *a, const char *b);
+#if defined(LENIX_DEBUG_EXIT)
+/* Enable LENIX_DEBUG_EXIT_VERBOSE to re-enable noisy exit/wait logging. */
+#endif
#if defined(__x86_64__)
struct switch_frame {
sched_task_exit_status_consume(uint64_t caller_pid, uint64_t pid,
int *status_out)
{
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
static uint32_t wait_consume_miss_dump_count;
static uint32_t wait_consume_parent_mismatch_log;
bool did_dump = false;
if (!exit_status_table[i].in_use)
continue;
if (exit_status_table[i].parent_pid == 0) {
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
serial_write("[wait_consume_stale] caller=",
sizeof("[wait_consume_stale] caller=") - 1);
debug_serial_write_u64(caller_pid);
continue;
}
if (exit_status_table[i].parent_pid != caller_pid) {
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
if (wait_consume_parent_mismatch_log < 8) {
serial_write("[wait_consume_mismatch] caller=",
sizeof("[wait_consume_mismatch] caller=") - 1);
if (status_out != NULL)
*status_out = exit_status_table[i].status;
uint64_t found = exit_status_table[i].pid;
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
int log_status = (status_out != NULL) ? *status_out : 0;
serial_write("[wait_consume] caller=",
sizeof("[wait_consume] caller=") - 1);
exit_status_table[i].status = 0;
return (int)found;
}
-#ifdef LENIX_DEBUG_EXIT
- serial_write("[wait_consume_miss] caller=",
- sizeof("[wait_consume_miss] caller=") - 1);
- debug_serial_write_u64(caller_pid);
- serial_write(" pid=", sizeof(" pid=") - 1);
- debug_serial_write_u64(pid);
- serial_write(" -> ECHILD\n", sizeof(" -> ECHILD\n") - 1);
- if (!did_dump && wait_consume_miss_dump_count < 8) {
- serial_write("[wait_consume_table] in_use entries:\n",
- sizeof("[wait_consume_table] in_use entries:\n") - 1);
- for (size_t i = 0; i < (sizeof(exit_status_table) /
- sizeof(exit_status_table[0])); i++) {
- if (!exit_status_table[i].in_use)
- continue;
- serial_write(" slot=", sizeof(" slot=") - 1);
- debug_serial_write_u64(i);
- serial_write(" pid=", sizeof(" pid=") - 1);
- debug_serial_write_u64(exit_status_table[i].pid);
- serial_write(" parent=", sizeof(" parent=") - 1);
- debug_serial_write_u64(exit_status_table[i].parent_pid);
- serial_write(" status=", sizeof(" status=") - 1);
- debug_serial_write_i64(exit_status_table[i].status);
- serial_write("\n", 1);
- }
- wait_consume_miss_dump_count++;
- did_dump = true;
- }
-#endif
return -SYSCALL_ECHILD;
}
result = true;
break;
}
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
serial_write("[child_exists] caller=",
sizeof("[child_exists] caller=") - 1);
debug_serial_write_u64(parent_pid);
{
uint64_t want_pid = 0;
int rc;
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
static uint64_t wait_spin_counter;
static uint32_t wait_return_log_count;
#endif
rc = sched_task_exit_status_consume(caller_pid, want_pid,
status_out);
if (rc >= 0) {
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
if (wait_return_log_count < 64) {
serial_write("[wait_return] caller=",
sizeof("[wait_return] caller=") - 1);
return rc;
}
if (rc == -SYSCALL_ECHILD) {
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
exit_status_table_dump("[wait_echild_table]\n");
exit_status_table_dump("[wait_echild_table]\n");
#endif
/* Child still exists but no status yet; keep waiting */
} else if (!sched_task_child_exists(caller_pid, pid)) {
rc = -SYSCALL_ECHILD;
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
if (wait_return_log_count < 32) {
serial_write("[wait_return] caller=",
sizeof("[wait_return] caller=") - 1);
wait_spin_debug++;
}
#endif
-#ifdef LENIX_DEBUG_EXIT
+#if defined(LENIX_DEBUG_EXIT_VERBOSE)
wait_spin_counter++;
if ((wait_spin_counter % 1000ULL) == 0) {
serial_write("[wait_spin] caller=",
}
}
-#ifdef LENIX_DEBUG_EXIT
-static void
+static void __attribute__((unused))
exit_status_table_dump(const char *tag)
{
size_t len = 0;
serial_write("\n", 1);
}
}
-#endif
void
sched_task_set_exit_status(struct sched_task *task, int status)
sched_mailbox_create(struct sched_task *task)
{
struct ipc_mailbox *mbox;
+ const uint32_t depth_limit = 1024; /* available for opt-in quotas */
/* Allocated out of kmem so IPC does not depend on per-arch plumbing. */
mbox = kmem_zalloc(sizeof(*mbox));
ipc_mailbox_init(mbox, task);
if (task != NULL)
ipc_mailbox_set_cpu_hint(mbox, task->last_cpu);
+ /* Quotas remain available but are disabled by default to avoid ENOBUFS. */
+ (void)depth_limit;
return mbox;
}
+static bool
+name_equals(const char *a, const char *b)
+{
+ if (a == NULL || b == NULL)
+ return false;
+ while (*a != '\0' && *b != '\0') {
+ if (*a != *b)
+ return false;
+ a++;
+ b++;
+ }
+ return (*a == '\0' && *b == '\0');
+}
+
static void
sched_mailbox_destroy(struct sched_task *task)
{
blob - 693388275d6526807f6a750396ed81a993f8182e
blob + 37773657b33a89a8d0371eb6f05cbf2e49ad78f2
--- kernel/sys/syscall.c
+++ kernel/sys/syscall.c
{
struct sched_task *task = sched_current_task();
struct sys_fd_table *table;
+ static uint32_t fd_table_alloc_log;
if (task == NULL)
return NULL;
if (table == NULL && create) {
/* Allocate and initialize the FD table */
table = kmem_alloc(sizeof(*table));
- if (table == NULL)
+ if (table == NULL) {
+ if (fd_table_alloc_log < 4) {
+ printk("[sys_fd_table] alloc failed task=");
+ printk_dec((int64_t)sched_task_id(task));
+ printk(" name=");
+ printk(sched_task_name(task));
+ printk("\n");
+ fd_table_alloc_log++;
+ }
return NULL;
+ }
syscall_memset(table, 0, sizeof(*table));
sched_task_sys_private_set(task, table, sys_fd_table_destroy);