From b86ad3f837d0fb6f510570c1a037bdb2436ddf66 Mon Sep 17 00:00:00 2001 From: Mike Miller Date: Thu, 4 Jan 2024 14:48:00 -0800 Subject: [PATCH] o Rewrote portions of syslog() handling o Added syscall 422 (sys_futex_time64) o Other tweaks --- debug.h | 4 +- fs/poll.c | 3 +- .../xcdebugger/Breakpoints_v2.xcbkptlist | 43 --------- kernel/calls.c | 3 + kernel/futex.c | 34 +++++++ kernel/log.c | 95 ++++++++----------- kernel/task.c | 6 +- main.c | 2 +- util/sync.c | 49 +++------- 9 files changed, 102 insertions(+), 137 deletions(-) diff --git a/debug.h b/debug.h index 8062fc193d..7a416f418b 100644 --- a/debug.h +++ b/debug.h @@ -3,8 +3,8 @@ #include #include -#define WAIT_SLEEP 200 // Was 25 for a long time. -mke -#define WAIT_MAX_UPPER 55500 +#define WAIT_SLEEP 2500 // Was 25 for a long time. -mke +#define WAIT_MAX_UPPER 555000 void ish_printk(const char *msg, ...); void ish_vprintk(const char *msg, va_list args); diff --git a/fs/poll.c b/fs/poll.c index 7be8137b0e..4c285f481d 100644 --- a/fs/poll.c +++ b/fs/poll.c @@ -342,7 +342,8 @@ void poll_destroy(struct poll *poll) { free(poll_fd); } - while(task_ref_cnt_get(current, 0) > 1) { + while(task_ref_cnt_get(current, 0) > 2) { + struct task* foo = current; nanosleep(&lock_pause, NULL); } diff --git a/iSH-AOK.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist b/iSH-AOK.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist index cfe6f76140..410d3cdbc6 100644 --- a/iSH-AOK.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/iSH-AOK.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist @@ -3,47 +3,4 @@ uuid = "6E8E3717-3660-4400-9A7C-07FA89334909" type = "4" version = "2.0"> - - - - - - - - - - - - - - - - - - diff --git a/kernel/calls.c b/kernel/calls.c index 90a20d02b8..7b4f12a89a 100644 --- a/kernel/calls.c +++ b/kernel/calls.c @@ -9,6 +9,8 @@ extern bool isGlibC; +extern dword_t sys_futex_time64(addr_t uaddr, dword_t op, dword_t val, addr_t timeout_or_val2, addr_t uaddr2, dword_t val3); + dword_t syscall_stub(void) { STRACE("syscall_stub()"); // I should probably do a prink here. Not sure why I removed it @@ -276,6 +278,7 @@ syscall_t syscall_table[] = { [407] = (syscall_t) sys_clock_nanosleep_time64, // clock_nanosleep_time64 [412] = (syscall_t) sys_utimensat64, // utimensat_time64 [414] = (syscall_t) sys_ppoll_time64, + [422] = (syscall_t) sys_futex_time64, [424] = (syscall_t) syscall_stub, // pidfd_send_signal? [436] = (syscall_t) syscall_stub, [439] = (syscall_t) sys_faccessat, // faccessat2 diff --git a/kernel/futex.c b/kernel/futex.c index 5a0f6a1e56..4fd298c970 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -124,6 +124,8 @@ static int futex_load(struct futex *futex, dword_t *out) { return 0; } + + static int futex_wait(addr_t uaddr, dword_t val, struct timespec *timeout) { struct futex *futex = futex_get(uaddr); int err = 0; @@ -148,6 +150,38 @@ static int futex_wait(addr_t uaddr, dword_t val, struct timespec *timeout) { return err; } +static int futex_wait_time64(addr_t uaddr, dword_t val, struct timespec64 *timeout64) { + // Convert struct timespec64 to struct timespec if needed + struct timespec timeout; + timeout.tv_sec = (time_t)timeout64->tv_sec; + timeout.tv_nsec = (long)timeout64->tv_nsec; + + // Call the existing futex_wait with the converted timespec + return futex_wait(uaddr, val, &timeout); +} + +dword_t sys_futex_time64(addr_t uaddr, dword_t op, dword_t val, addr_t timeout_or_val2, addr_t uaddr2, dword_t val3) { + if (!(op & FUTEX_PRIVATE_FLAG_)) { + STRACE("!FUTEX_PRIVATE "); + } + + // Check for FUTEX_WAIT_BITSET operation + if ((op & FUTEX_CMD_MASK_) == FUTEX_WAIT_BITSET_) { + STRACE("futex(FUTEX_WAIT_BITSET_TIME64, %#x, %d, 0x%x) = ...\n", uaddr, val, timeout_or_val2); + + // Get the timespec64 from user space + struct timespec64 timeout64; + if (user_get(timeout_or_val2, timeout64)) + return _EFAULT; + + // Call the futex_wait_time64 function + return futex_wait_time64(uaddr, val, &timeout64); + } + + // Handle other futex operations (possibly by calling sys_futex) + return sys_futex(uaddr, op, val, timeout_or_val2, uaddr2, val3); +} + static int futex_wakelike(int op, addr_t uaddr, dword_t wake_max, dword_t requeue_max, addr_t requeue_addr) { struct futex *futex = futex_get(uaddr); diff --git a/kernel/log.c b/kernel/log.c index 8e1edd9d45..a646f496e1 100644 --- a/kernel/log.c +++ b/kernel/log.c @@ -30,81 +30,67 @@ static lock_t log_lock = LOCK_INITIALIZER; #define SYSLOG_ACTION_SIZE_UNREAD_ 9 #define SYSLOG_ACTION_SIZE_BUFFER_ 10 -static size_t syslog_read(addr_t buf_addr, size_t len, int flags) { - if (len < 0) +static size_t syslog_read(addr_t buf_addr, size_t len, int flags, char* buffer, size_t buffer_size) { + if (len == 0 || buffer_size == 0) return _EINVAL; - if (flags & FIFO_LAST) { - if ((size_t) len > log_max_since_clear) - len = log_max_since_clear; - } else { - if ((size_t) len > fifo_capacity(&log_buf)) - len = fifo_capacity(&log_buf); - } - char *buf = malloc(len + 1); - fifo_read(&log_buf, buf, len, flags); - - // Here we will split on \n and do one entry per line - // Keep printing tokens while one of the - // delimiters present - addr_t pointer = buf_addr; // Where we are in the buffer - char *token = strtok(buf, "\n"); // Get the first line - - if(user_write(pointer, "\n", 1)) { // Positive return value = fail - free(buf); - return _EFAULT; - } - - pointer++; - + + // Limit the read length to the size of the passed buffer + if (len > buffer_size - 1) + len = buffer_size - 1; + + // Read from the log buffer + size_t read_len = fifo_read(&log_buf, buffer, len, flags); + buffer[read_len] = '\0'; // Ensure null-termination + + // Write line by line to the user space, splitting on '\n' + addr_t pointer = buf_addr; + char *token = strtok(buffer, "\n"); while (token != NULL) { size_t length = strlen(token); - if(user_write(pointer, token, length)) { // Positive return value = fail - free(buf); + if (user_write(pointer, token, length)) // Check for write failure return _EFAULT; - } - pointer += length; - - if(user_write(pointer, "\n", 1)) { // Positive return value = fail - free(buf); + + if (user_write(pointer, "\n", 1)) // Check for write failure return _EFAULT; - } - pointer++; - if(pointer < (buf_addr + (len -1))) { - token = strtok(NULL, "\n"); // Grab next token, deal with when back at top of while loop. -mke - } else { - token = NULL; - } + + if (pointer < (buf_addr + len - 1)) + token = strtok(NULL, "\n"); + else + break; // Reached the end of the buffer } - free(buf); - - return len; + return pointer - buf_addr; // Return the number of bytes written } static size_t do_syslog(int type, addr_t buf_addr, int_t len) { - int res; + // Define a buffer size based on your requirements + const size_t BUFFER_SIZE = 8192; + char buffer[BUFFER_SIZE]; + switch (type) { case SYSLOG_ACTION_READ_: - return syslog_read(buf_addr, len, 0); + return syslog_read(buf_addr, len, 0, buffer, BUFFER_SIZE); case SYSLOG_ACTION_READ_ALL_: - return syslog_read(buf_addr, len, FIFO_LAST | FIFO_PEEK); - - case SYSLOG_ACTION_READ_CLEAR_: - res = (int)syslog_read(buf_addr, len, FIFO_LAST | FIFO_PEEK); - if (res < 0) - return res; - fallthrough; + return syslog_read(buf_addr, len, FIFO_LAST | FIFO_PEEK, buffer, BUFFER_SIZE); + + case SYSLOG_ACTION_READ_CLEAR_: { + size_t res = syslog_read(buf_addr, len, FIFO_LAST | FIFO_PEEK, buffer, BUFFER_SIZE); + if (res < 0) + return res; + // fall through to clear + } case SYSLOG_ACTION_CLEAR_: log_max_since_clear = 0; return 0; case SYSLOG_ACTION_SIZE_UNREAD_: - return (int)fifo_size(&log_buf); + return fifo_size(&log_buf); case SYSLOG_ACTION_SIZE_BUFFER_: - return (int)fifo_capacity(&log_buf); + return fifo_capacity(&log_buf); + // Other actions remain unchanged case SYSLOG_ACTION_CLOSE_: case SYSLOG_ACTION_OPEN_: case SYSLOG_ACTION_CONSOLE_OFF_: @@ -115,6 +101,7 @@ static size_t do_syslog(int type, addr_t buf_addr, int_t len) { return _EINVAL; } } + size_t sys_syslog(int_t type, addr_t buf_addr, int_t len) { lock(&log_lock, 0); size_t retval = do_syslog(type, buf_addr, len); @@ -202,7 +189,7 @@ _Noreturn void die(const char *msg, ...); void die(const char *msg, ...) { va_list args; va_start(args, msg); - char buf[4096]; + char buf[8192]; vsprintf(buf, msg, args); die_handler(buf); abort(); diff --git a/kernel/task.c b/kernel/task.c index e0de943386..00e23408b2 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -125,8 +125,10 @@ dword_t get_count_of_blocked_tasks(void) { struct pid *pid_entry; complex_lockt(&pids_lock, 0); list_for_each_entry(&alive_pids_list, pid_entry, alive) { - if (pid_entry->task->io_block) { - res++; + if(pid_entry->task != NULL) { + if (pid_entry->task->io_block) { + res++; + } } } // task_ref_cnt_mod(current, -1); diff --git a/main.c b/main.c index 155417d4db..d7cbfddd62 100644 --- a/main.c +++ b/main.c @@ -56,7 +56,7 @@ int main(int argc, char *const argv[]) { sa.sa_flags = SA_SIGINFO; if(sigaction(/*SIGBUS*/SIGSEGV, &sa, NULL) == -1) { - printf("sigaction fails.\n"); + printk("sigaction fails.\n"); return 0; } diff --git a/util/sync.c b/util/sync.c index 90df48e697..99214bb961 100644 --- a/util/sync.c +++ b/util/sync.c @@ -59,41 +59,20 @@ int wait_for_ignore_signals(cond_t *cond, lock_t *lock, struct timespec *timeout current->waiting_lock = lock; unlock(¤t->waiting_cond_lock); } + int rc = 0; - char saveme[16]; - strncpy(saveme, lock->lname, 16); // Save for later -#if LOCK_DEBUG - struct lock_debug lock_tmp = lock->debug; - lock->debug = (struct lock_debug) { .initialized = lock->debug.initialized }; -#endif - if (!timeout) { // We timeout anyway after fifteen seconds. It appears the process wakes up briefly before returning here if there is nothing else pending. This is KLUGE. -mke - struct timespec trigger_time; - trigger_time.tv_sec = 15; - trigger_time.tv_nsec = 0; - lock->wait4 = true; - - if(current->uid == 501) { // This is here for testing of the process lockup issue. -mke - rc = pthread_cond_timedwait_relative_np(&cond->cond, &lock->m, &trigger_time); - // if((rc == ETIMEDOUT) && current->parent != NULL) { - if(rc == ETIMEDOUT) { - if(current->children.next != NULL) { - notify(cond); // This is a terrible hack that seems to avoid processes getting stuck. - // return 0; - } - } - - rc = 0; - - } else { - pthread_cond_wait(&cond->cond, &lock->m); - } + + if (!timeout) { + // Standard wait on the condition variable without a timeout + rc = pthread_cond_wait(&cond->cond, &lock->m); } else { + // Timed wait on the condition variable #if __linux__ struct timespec abs_timeout; clock_gettime(CLOCK_MONOTONIC, &abs_timeout); abs_timeout.tv_sec += timeout->tv_sec; abs_timeout.tv_nsec += timeout->tv_nsec; - if (abs_timeout.tv_nsec > 1000000000) { + if (abs_timeout.tv_nsec >= 1000000000) { abs_timeout.tv_sec++; abs_timeout.tv_nsec -= 1000000000; } @@ -101,12 +80,9 @@ int wait_for_ignore_signals(cond_t *cond, lock_t *lock, struct timespec *timeout #elif __APPLE__ rc = pthread_cond_timedwait_relative_np(&cond->cond, &lock->m, timeout); #else -#error Unimplemented pthread_cond_wait relative timeout. +#error "Platform not supported for pthread_cond_timedwait." #endif } -#if LOCK_DEBUG - lock->debug = lock_tmp; -#endif if(current) { lock(¤t->waiting_cond_lock, 0); @@ -115,9 +91,14 @@ int wait_for_ignore_signals(cond_t *cond, lock_t *lock, struct timespec *timeout unlock(¤t->waiting_cond_lock); } lock->wait4 = false; - if(rc == ETIMEDOUT) + + // Convert the return code from pthreads to the application-specific format + if (rc == ETIMEDOUT) return _ETIMEDOUT; - return 0; + else if (rc == 0) + return 0; + else + return _EINTR; // or an appropriate error code for other errors } void notify(cond_t *cond) {