diff --git a/app/AppDelegate.m b/app/AppDelegate.m index 4acce7501f..ecccb63bfc 100644 --- a/app/AppDelegate.m +++ b/app/AppDelegate.m @@ -53,8 +53,8 @@ static void ios_handle_exit(struct task *task, int code) { return; // pid should be saved now since task would be freed pid_t pid = task->pid; - if(pids_lock.pid == pid) - unlock(&pids_lock); + // if(pids_lock.pid == pid) + // unlock(&pids_lock); // while((critical_region_count(task)) || (locks_held_count(task))) { // Wait for now, task is in one or more critical sections, and/or has locks // nanosleep(&lock_pause, NULL); // } diff --git a/app/UserPreferences.m b/app/UserPreferences.m index c7916a7b93..c6761e9b0d 100644 --- a/app/UserPreferences.m +++ b/app/UserPreferences.m @@ -448,7 +448,7 @@ - (BOOL)validateShouldEnableExtraLocking:(id *)value error:(NSError **)error { // Should set task->critical_region.count to 0 for all active processes when this is set to false. Otherwise stuff blows up. -mke if(doEnableExtraLocking == true) { // This needs to be the opposite of what you would expect because of reasons. -mke complex_lockt(&pids_lock, 0, __FILE__, __LINE__); - dword_t res = zero_critical_regions_count(); + zero_critical_regions_count(); unlock(&pids_lock); } return [*value isKindOfClass:NSNumber.class]; diff --git a/emu/memory.c b/emu/memory.c index 3bb610a2a8..517317dca7 100644 --- a/emu/memory.c +++ b/emu/memory.c @@ -358,8 +358,6 @@ void *mem_ptr(struct mem *mem, addr_t addr, int type) { #endif // if page is cow, ~~milk~~ copy it - if(doEnableExtraLocking) - extra_lockf(0, __FILE__, __LINE__); if (entry->flags & P_COW) { lock(¤t->general_lock, 0); // prevent elf_exec from doing mm_release while we are in flight? -mke @@ -380,9 +378,6 @@ void *mem_ptr(struct mem *mem, addr_t addr, int type) { } - if(doEnableExtraLocking) - extra_unlockf(0, __FILE__, __LINE__); - } void *ptr = mem_ptr_nofault(mem, addr, type); diff --git a/fs/dir.c b/fs/dir.c index 73815ffcf8..8f4c7d6661 100644 --- a/fs/dir.c +++ b/fs/dir.c @@ -15,6 +15,7 @@ static unsigned long fd_telldir(struct fd *fd) { static void fd_seekdir(struct fd *fd, unsigned long off) { fd->offset = off; + if (fd->ops->seekdir) fd->ops->seekdir(fd, off); } @@ -72,6 +73,8 @@ int_t sys_getdents_common(fd_t f, addr_t dirents, dword_t count, int printed = 0; while (true) { ptr = fd_telldir(fd); + extern time_t boot_time; + fd->stat.atime = (dword_t)boot_time; struct dir_entry entry; err = fd->ops->readdir(fd, &entry); if (err < 0) @@ -81,6 +84,7 @@ int_t sys_getdents_common(fd_t f, addr_t dirents, dword_t count, size_t max_reclen = sizeof(struct linux_dirent64_) + strlen(entry.name) + 4; char dirent_data[max_reclen]; + dirent_data[0] = 0; ino_t inode = entry.inode; off_t_ offset = fd_telldir(fd); const char *name = entry.name; diff --git a/fs/fd.c b/fs/fd.c index 3a4dfc2290..079be56a88 100644 --- a/fs/fd.c +++ b/fs/fd.c @@ -18,6 +18,7 @@ struct fd *fd_create(const struct fd_ops *ops) { fd->flags = 0; fd->mount = NULL; fd->offset = 0; + fd->stat.ctime = (dword_t)time(NULL); list_init(&fd->poll_fds); lock_init(&fd->poll_lock); lock_init(&fd->lock); @@ -49,6 +50,8 @@ int fd_close(struct fd *fd) { mount_release(fd->mount); free(fd); } + if(fd->inode != NULL) + fd->stat.atime = (dword_t)time(NULL); return err; } diff --git a/fs/pipe.c b/fs/pipe.c index ff900e6cd4..a64d6d54eb 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -13,6 +13,7 @@ static fd_t pipe_f_create(int pipe_fd, int flags) { fd->stat.mode = S_IFIFO | 0660; fd->stat.uid = current->uid; fd->stat.gid = current->gid; + fd->stat.ctime = (dword_t)time(NULL); return f_install(fd, flags); } diff --git a/fs/proc.c b/fs/proc.c index 00bb5b1184..e4e66135c7 100644 --- a/fs/proc.c +++ b/fs/proc.c @@ -78,10 +78,14 @@ static int proc_getpath(struct fd *fd, char *buf) { static int proc_stat(struct mount *UNUSED(mount), const char *path, struct statbuf *stat) { struct proc_entry entry = {0}; + extern time_t boot_time; int err = proc_lookup(path, &entry); if (err < 0) return err; int ret = proc_entry_stat(&entry, stat); + stat->atime = (dword_t)time(NULL); + stat->mtime = (dword_t)boot_time; + stat->ctime = (dword_t)boot_time; proc_entry_cleanup(&entry); return ret; } diff --git a/jit/gadgets-aarch64/gadgets.h b/jit/gadgets-aarch64/gadgets.h index 67ab5e875a..f7983b6ff7 100644 --- a/jit/gadgets-aarch64/gadgets.h +++ b/jit/gadgets-aarch64/gadgets.h @@ -31,6 +31,7 @@ _xaddr .req x3 .endm .macro gret pop=0 ldr x8, [_ip, \pop*8]! + dmb ishld /* Jason Conway's Re Ordering patch (upstream PR #1944 */ add _ip, _ip, 8 /* TODO get rid of this */ br x8 .endm diff --git a/kernel/calls.c b/kernel/calls.c index 33564872b4..984e5ebad0 100644 --- a/kernel/calls.c +++ b/kernel/calls.c @@ -11,7 +11,6 @@ extern bool isGlibC; dword_t syscall_stub(void) { STRACE("syscall_stub()"); - //STRACE("syscall_stub()"); return _ENOSYS; } dword_t syscall_stub_silent(void) { @@ -271,7 +270,9 @@ syscall_t syscall_table[] = { [383] = (syscall_t) syscall_stub_silent, // statx [384] = (syscall_t) sys_arch_prctl, [403] = (syscall_t) syscall_stub, // clock_gettime64 + [406] = (syscall_t) syscall_stub, // clock_getres_time64 [407] = (syscall_t) syscall_stub, // clock_nanosleep_time64 + [412] = (syscall_t) syscall_stub, // utimensat_time64 [436] = (syscall_t) syscall_stub, [439] = (syscall_t) sys_faccessat, // faccessat2 }; diff --git a/kernel/exit.c b/kernel/exit.c index 36e2277416..58e231b162 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -62,7 +62,11 @@ noreturn void do_exit(int status) { bool signal_pending = !!(current->pending & ~current->blocked); // has to happen before mm_release - while((critical_region_count(current) > 1) || (locks_held_count(current)) || (current->process_info_being_read) || (signal_pending)) { // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight + + while((critical_region_count(current) > 1) || + (locks_held_count(current)) || + (current->process_info_being_read) || + (signal_pending)) { // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight nanosleep(&lock_pause, NULL); signal_pending = !!(current->pending & ~current->blocked); } @@ -77,17 +81,28 @@ noreturn void do_exit(int status) { do { nanosleep(&lock_pause, NULL); signal_pending = !!(current->pending & ~current->blocked); - } while((critical_region_count(current) > 1) || (locks_held_count(current)) || (current->process_info_being_read) || (signal_pending)); // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight + } while((critical_region_count(current) > 1) || + (locks_held_count(current)) || + (current->process_info_being_read) || + (signal_pending)); // Wait for now, task is in one or more critical mm_release(current->mm); current->mm = NULL; + signal_pending = !!(current->pending & ~current->blocked); - while((critical_region_count(current) > 1) || (locks_held_count(current)) || (current->process_info_being_read) || (signal_pending)) { // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight + while((critical_region_count(current) > 1) || + (locks_held_count(current)) || + (current->process_info_being_read) || + (signal_pending)) { // Wait for now, task is in one or more critical // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight nanosleep(&lock_pause, NULL); signal_pending = !!(current->pending & ~current->blocked); } fdtable_release(current->files); current->files = NULL; - while((critical_region_count(current) > 1) || (locks_held_count(current)) || (current->process_info_being_read) || (signal_pending)) { // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight + + while((critical_region_count(current) > 1) || + (locks_held_count(current)) || + (current->process_info_being_read) || + (signal_pending)) { // Wait for now, task is in one or more critical // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight nanosleep(&lock_pause, NULL); signal_pending = !!(current->pending & ~current->blocked); } @@ -97,8 +112,10 @@ noreturn void do_exit(int status) { // sighand must be released below so it can be protected by pids_lock // since it can be accessed by other threads - //while(critical_region_count(current)) { - while((critical_region_count(current) > 1) || (locks_held_count(current)) || (current->process_info_being_read) || (signal_pending)) { // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight + while((critical_region_count(current) > 1) || + (locks_held_count(current)) || + (current->process_info_being_read) || + (signal_pending)) { // Wait for now, task is in one or more critical// Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight nanosleep(&lock_pause, NULL); signal_pending = !!(current->pending & ~current->blocked); } @@ -115,7 +132,10 @@ noreturn void do_exit(int status) { complex_lockt(&pids_lock, 0, __FILE__, __LINE__); // release the sighand signal_pending = !!(current->pending & ~current->blocked); - while((critical_region_count(current) > 2) || (locks_held_count(current)) || (current->process_info_being_read) || (signal_pending)) { // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight + while((critical_region_count(current) > 2) || + (locks_held_count(current)) || + (current->process_info_being_read) || + (signal_pending)) { // Wait for now, task is in one or more critical // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight nanosleep(&lock_pause, NULL); signal_pending = !!(current->pending & ~current->blocked); } @@ -139,7 +159,10 @@ noreturn void do_exit(int status) { signal_pending = !!(current->pending & ~current->blocked); - while((critical_region_count(current) > 2) || (locks_held_count(current)) || (current->process_info_being_read) || (signal_pending)) { // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight + while((critical_region_count(current) > 2) || + (locks_held_count(current)) || + (current->process_info_being_read) || + (signal_pending)) { // Wait for now, task is in one or more critical // Wait for now, task is in one or more critical sections, and/or has locks, or signals in flight nanosleep(&lock_pause, NULL); signal_pending = !!(current->pending & ~current->blocked); } @@ -263,8 +286,13 @@ dword_t sys_exit_group(dword_t status) { static bool reap_if_zombie(struct task *task, struct siginfo_ *info_out, struct rusage_ *rusage_out, int options) { if (!task->zombie) return false; - while((critical_region_count(task) > 1) || (locks_held_count(task))) { // Wait for now, task is in one or more critical sections, and/or has locks + bool signal_pending = !!(task->pending & ~task->blocked); + while(((signal_pending) || + (critical_region_count(task) > 1) || + (locks_held_count(task))) && + (task->pid > 10)) { nanosleep(&lock_pause, NULL); + signal_pending = !!(task->pending & ~task->blocked); } complex_lockt(&task->group->lock, 0, __FILE__, __LINE__); @@ -292,26 +320,58 @@ static bool reap_if_zombie(struct task *task, struct siginfo_ *info_out, struct // lock(&pids_lock); //mkemkemke Doesn't work //if(doEnableExtraLocking) //mke Doesn't work // extra_lockf(task->pid); - while((critical_region_count(task) > 1) || (locks_held_count(task))) { // Wait for now, task is in one or more critical sections, and/or has locks + + signal_pending = !!(task->pending & ~task->blocked); + while(((signal_pending) || + (critical_region_count(task) > 1) || + (locks_held_count(task))) && + (task->pid > 10)) { nanosleep(&lock_pause, NULL); + signal_pending = !!(task->pending & ~task->blocked); } cond_destroy(&task->group->child_exit); - while((critical_region_count(task) > 1) || (locks_held_count(task))) { // Wait for now, task is in one or more critical sections, and/or has locks + + signal_pending = !!(task->pending & ~task->blocked); + while(((signal_pending) || + (critical_region_count(task) > 1) || + (locks_held_count(task))) && + (task->pid > 10)) { nanosleep(&lock_pause, NULL); + signal_pending = !!(task->pending & ~task->blocked); } task_leave_session(task); - while((critical_region_count(task) > 1) || (locks_held_count(task))) { // Wait for now, task is in one or more critical sections, and/or has locks + + signal_pending = !!(task->pending & ~task->blocked); + while(((signal_pending) || + (critical_region_count(task) > 1) || + (locks_held_count(task))) && + (task->pid > 10)) { nanosleep(&lock_pause, NULL); + signal_pending = !!(task->pending & ~task->blocked); } list_remove(&task->group->pgroup); - while((critical_region_count(task) > 1) || (locks_held_count(task))) { // Wait for now, task is in one or more critical sections, and/or has locks + + signal_pending = !!(task->pending & ~task->blocked); + while(((signal_pending) || + (critical_region_count(task) > 1) || + (locks_held_count(task))) && + (task->pid > 10)) { nanosleep(&lock_pause, NULL); + signal_pending = !!(task->pending & ~task->blocked); } free(task->group); - while((critical_region_count(task) > 1) || (locks_held_count(task))) { // Wait for now, task is in one or more critical sections, and/or has locks + + signal_pending = !!(task->pending & ~task->blocked); + while(((signal_pending) || + (critical_region_count(task) > 1) || + (locks_held_count(task))) && + (task->pid > 10)) { nanosleep(&lock_pause, NULL); + signal_pending = !!(task->pending & ~task->blocked); } + //complex_lockt(&pids_lock, 0, __FILE__, __LINE__); task_destroy(task); + //unlock(&pids_lock); return true; } diff --git a/kernel/fs.c b/kernel/fs.c index cf3febff7a..491a3bf8bc 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -120,7 +120,7 @@ dword_t sys_readlinkat(fd_t at_f, addr_t path_addr, addr_t buf_addr, dword_t buf if (user_write(buf_addr, buf, size)) return _EFAULT; } - return size; + return (dword_t)size; } dword_t sys_readlink(addr_t path_addr, addr_t buf_addr, dword_t bufsize) { diff --git a/kernel/mmap.c b/kernel/mmap.c index 9e644d73ec..b103117409 100644 --- a/kernel/mmap.c +++ b/kernel/mmap.c @@ -49,15 +49,11 @@ void mm_release(struct mm *mm) { nanosleep(&lock_pause, NULL); } - if(doEnableExtraLocking) - extra_lockf(0, __FILE__, __LINE__); mem_destroy(&mm->mem); while((critical_region_count(current) > 1) || (current->process_info_being_read)) { // Wait for now, task is in one or more critical sections nanosleep(&lock_pause, NULL); } free(mm); - if(doEnableExtraLocking) - extra_unlockf(0, __FILE__, __LINE__); } } @@ -65,7 +61,7 @@ static addr_t do_mmap(addr_t addr, dword_t len, dword_t prot, dword_t flags, fd_ int err; pages_t pages = PAGE_ROUND_UP(len); if (!pages) return _EINVAL; - page_t page; + page_t page = 0; if (addr != 0) { if (PGOFFSET(addr) != 0) return _EINVAL; diff --git a/kernel/resource_locking.h b/kernel/resource_locking.h index 386d502d10..4c067c2a2c 100644 --- a/kernel/resource_locking.h +++ b/kernel/resource_locking.h @@ -6,4 +6,5 @@ extern unsigned critical_region_count(struct task*); extern void modify_critical_region_counter(struct task*, int, char*, int); extern unsigned locks_held_count(struct task*); extern void modify_locks_held_count(struct task*, int); +extern bool current_is_valid(void); diff --git a/kernel/task.c b/kernel/task.c index 86584486be..36632576eb 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -17,17 +17,13 @@ pthread_mutex_t multicore_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t extra_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t delay_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t atomic_l_lock = PTHREAD_MUTEX_INITIALIZER; +time_t boot_time; // Store the boot time. -mke -dword_t extra_lock_pid = -1; -char extra_lock_comm[16] = ""; -bool extra_lock_held = false; -time_t newest_extra_lock_time = 0; -unsigned maxl = 10; // Max age of an extra_lock bool BOOTING = true; bool doEnableMulticore; // Enable multicore if toggled, should default to false bool isGlibC = false; // Try to guess if we're running a non musl distro. -mke -bool doEnableExtraLocking; // Enable extra locking if toggled, should default to false +bool doEnableExtraLocking; // Enable extra locking if toggled, should default to true unsigned doLockSleepNanoseconds; // How many nanoseconds should __lock() sleep between retries __thread struct task *current; @@ -88,13 +84,11 @@ dword_t get_count_of_blocked_tasks() { return res; } -dword_t zero_critical_regions_count(void) { // If doEnableExtraLocking is changed to false, we need to zero out critical_region.count for active processes - dword_t res = 0; +void zero_critical_regions_count(void) { // If doEnableExtraLocking is changed to false, we need to zero out critical_region.count for active processes struct pid *pid_entry; list_for_each_entry(&alive_pids_list, pid_entry, alive) { pid_entry->task->critical_region.count = 0; // Bad things happen if this isn't done. -mke } - return 0; } dword_t get_count_of_alive_tasks() { @@ -219,6 +213,11 @@ void run_at_boot(void) { // Stuff we run only once, at boot time. do_uname(&uts); unsigned short ncpu = get_cpu_count(); printk("iSH-AOK %s booted on %d emulated %s CPU(s)\n",uts.release, ncpu, uts.arch); + // Get boot time + extern time_t boot_time; + + boot_time = time(NULL); + //printk("Seconds since January 1, 1970 = %ld\n", boot_time); BOOTING = false; } @@ -294,120 +293,3 @@ void update_thread_name() { pthread_setname_np(pthread_self(), name); #endif } - -/* Let me be clear here. The following two functions (extra_lockf() & extra_unlockf() are horrible hacks. - If I were a better programmer I'd actually figure out and fix the problems they are mitigating. After a couple of - years of trying the better programmer approach on and off I've given up and gone full on kludge King. -mke */ -int extra_lockf(dword_t pid, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { - return 0; // Disabled for now -mke - //if(current != NULL) - ////modify_critical_region_counter(current, 1, __FILE__, __LINE__); - //pthread_mutex_lock(&extra_lock); - //extra_lock_pid = pid; - //extra_lock_pid = current->pid; - extra_lock_held = true; // - //if(current != NULL) - ////modify_critical_region_counter(current, -1, __FILE__, __LINE__); - //return 0; - - time_t now; - time(&now); - - if(!newest_extra_lock_time) - time(&newest_extra_lock_time); // Initialize - - unsigned int count = 0; - int random_wait = WAIT_SLEEP + rand() % WAIT_SLEEP; - struct timespec mylock_pause = {0 /*secs*/, random_wait /*nanosecs*/}; - long count_max = (WAIT_MAX_UPPER - WAIT_SLEEP); // As sleep time increases, decrease acceptable loops. -mke - - if((now - newest_extra_lock_time > maxl) && (extra_lock_held)) { // If we have a lock, and there has been no activity for awhile, kill it - printk("ERROR: The newest_extra_lock time(extra_lockf) has exceeded %d seconds (%d). (%s:%d) Resetting\n", maxl, now - newest_extra_lock_time, file, line); - pthread_mutex_unlock(&extra_lock); - - while(pthread_mutex_trylock(&extra_lock)) { - count++; - nanosleep(&mylock_pause, NULL); - //mylock_pause.tv_nsec+=10; - if(count > count_max) { - printk("ERROR: Possible deadlock(extra_lockf(), aborted lock attempt(PID: %d Process: %s) (%s:%d)\n", current_pid(), current_comm(), file, line ); - extra_lock_pid = 0; - strcpy(extra_lock_comm, ""); - pthread_mutex_unlock(&extra_lock); - return 1; - } - // Loop until lock works. Maybe this will help make the multithreading work? -mke - } - - extra_lock_pid = pid; - extra_lock_held = true; // - time(&newest_extra_lock_time); // Update time - current->locks_held.count++; - return 0; - } - - while(pthread_mutex_trylock(&extra_lock)) { - count++; - nanosleep(&mylock_pause, NULL); - //mylock_pause.tv_nsec+=10; - if(count > count_max) { - printk("ERROR: Possible deadlock(extra_lockf), aborted lock attempt(PID: %d) (%s:%d)\n", extra_lock_pid, file, line); - extra_lock_pid = 0; - pthread_mutex_unlock(&extra_lock); - strcpy(extra_lock_comm, ""); - return 1; - } - // Loop until lock works. Maybe this will help make the multithreading work? -mke - } - - if(count > count_max * .90) { - //printk("WARNING: large lock attempt count(Function: extra_lockf(%d) PID: %d Process: %s)\n",count, current->pid, current->comm); - printk("WARNING: large lock attempt count(Function: extra_lockf(%x) PID: %d) (%s:%d)\n",count, extra_lock_pid, file, line); - } - - time(&newest_extra_lock_time); // Update time - extra_lock_pid = pid; //Save, we may need it later to make sure the lock gets removed if the pid is killed - extra_lock_held = true; // - return 0; -} - -void extra_unlockf(dword_t pid, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { - return; // Disabled for now. -mke - if(current != NULL) - modify_critical_region_counter(current, 1, __FILE__, __LINE__); - pthread_mutex_unlock(&extra_lock); - if(current != NULL) - modify_critical_region_counter(current, -1, __FILE__, __LINE__); - extra_lock_held = false; - return; - - /* time_t now; - time(&now); - if((now - newest_extra_lock_time > maxl) && (extra_lock_held)) { // If we have a lock, and there has been no activity for awhile, kill it - printk("ERROR: The newest_extra_lock time(unlockf) has exceeded %d seconds (%d) (%d). Resetting\n", maxl, now, newest_extra_lock_time); - pthread_mutex_unlock(&extra_lock); - current->locks_held.count--; - extra_lock_pid = 0; - strcpy(extra_lock_comm, ""); - extra_lock_held = false; - return; - } - - if((pid_get(extra_lock_pid) == NULL) && (extra_lock_pid)) { - printk("WARNING: Previous extra_lock() PID(%d) missing\n", extra_lock_pid); // It will be zero if not relevant - } - - if(pid) - // Placeholder - if(!extra_lock_held) { - printk("WARNING: Trying to extra_unlockf() when no lock exists\n"); - return; - } - pthread_mutex_unlock(&extra_lock); - extra_lock_pid = 0; - strcpy(extra_lock_comm, ""); - extra_lock_held = false; // - current->locks_held.count--; - return; - */ -} diff --git a/kernel/task.h b/kernel/task.h index 980d96b574..fd767e6b5e 100644 --- a/kernel/task.h +++ b/kernel/task.h @@ -204,7 +204,7 @@ struct task *pid_get_task_zombie(dword_t id); // don't return null if the task e dword_t get_count_of_blocked_tasks(void); dword_t get_count_of_alive_tasks(void); -dword_t zero_critical_regions_count(void); +void zero_critical_regions_count(void); #define MAX_PID (1 << 15) // oughta be enough @@ -220,10 +220,6 @@ extern void (*exit_hook)(struct task *task, int code); // Will ensure that the -pid part always fits, then will fit as much of comm as possible. void update_thread_name(void); -// Functions to implement additional locking and unlocking -mke -int extra_lockf(dword_t pid, __attribute__((unused)) const char *file, __attribute__((unused)) int line); -void extra_unlockf(dword_t pid, __attribute__((unused)) const char *file, __attribute__((unused)) int line); - // To collect statics on which tasks are blocked we need to proccess areas // of code which could block our task (e.g reads or writes). Before executing // of functions which can block the task, we mark our task as blocked and diff --git a/kernel/time.c b/kernel/time.c index c71f06e0bd..2f6a9f97b5 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -36,16 +36,16 @@ static struct timer_spec timer_spec_to_real(struct itimerspec_ itspec) { static struct itimerspec_ timer_spec_from_real(struct timer_spec spec) { struct itimerspec_ itspec = { - .value.sec = spec.value.tv_sec, - .value.nsec = spec.value.tv_nsec, - .interval.sec = spec.interval.tv_sec, - .interval.nsec = spec.interval.tv_nsec, + .value.sec = (dword_t)spec.value.tv_sec, + .value.nsec = (dword_t)spec.value.tv_nsec, + .interval.sec = (dword_t)spec.interval.tv_sec, + .interval.nsec = (dword_t)spec.interval.tv_nsec, }; return itspec; }; dword_t sys_time(addr_t time_out) { - dword_t now = time(NULL); + dword_t now = (dword_t)time(NULL); if (time_out != 0) if (user_put(time_out, now)) return _EFAULT; @@ -73,8 +73,9 @@ dword_t sys_clock_gettime(dword_t clock, addr_t tp) { return errno_map(); } struct timespec_ t; - t.sec = ts.tv_sec; - t.nsec = ts.tv_nsec; + t.sec = (dword_t)ts.tv_sec; + t.nsec = (dword_t)ts.tv_nsec; + if (user_put(tp, t)) return _EFAULT; STRACE(" {%lds %ldns}", t.sec, t.nsec); @@ -91,8 +92,8 @@ dword_t sys_clock_getres(dword_t clock, addr_t res_addr) { if (err < 0) return errno_map(); struct timespec_ t; - t.sec = res.tv_sec; - t.nsec = res.tv_nsec; + t.sec = (dword_t)res.tv_sec; + t.nsec = (dword_t)res.tv_nsec; if (user_put(res_addr, t)) return _EFAULT; return 0; @@ -111,7 +112,7 @@ static void itimer_notify(struct task *task) { ////modify_critical_region_counter(task, -1, __FILE__, __LINE__); } -static int itimer_set(struct tgroup *group, int which, struct timer_spec spec, struct timer_spec *old_spec) { +static long itimer_set(struct tgroup *group, int which, struct timer_spec spec, struct timer_spec *old_spec) { if (which != ITIMER_REAL_) { FIXME("unimplemented setitimer %d", which); return _EINVAL; @@ -127,7 +128,7 @@ static int itimer_set(struct tgroup *group, int which, struct timer_spec spec, s return timer_set(group->itimer, spec, old_spec); } -int_t sys_setitimer(int_t which, addr_t new_val_addr, addr_t old_val_addr) { +long sys_setitimer(int_t which, addr_t new_val_addr, addr_t old_val_addr) { struct itimerval_ val; if (user_get(new_val_addr, val)) return _EFAULT; @@ -143,17 +144,17 @@ int_t sys_setitimer(int_t which, addr_t new_val_addr, addr_t old_val_addr) { struct tgroup *group = current->group; lock(&group->lock, 0); - int err = itimer_set(group, which, spec, &old_spec); + long err = itimer_set(group, which, spec, &old_spec); unlock(&group->lock); if (err < 0) return err; if (old_val_addr != 0) { struct itimerval_ old_val; - old_val.interval.sec = old_spec.interval.tv_sec; - old_val.interval.usec = old_spec.interval.tv_nsec / 1000; - old_val.value.sec = old_spec.value.tv_sec; - old_val.value.usec = old_spec.value.tv_nsec / 1000; + old_val.interval.sec = (dword_t)old_spec.interval.tv_sec; + old_val.interval.usec = (dword_t)old_spec.interval.tv_nsec / 1000; + old_val.value.sec = (dword_t)old_spec.value.tv_sec; + old_val.value.usec = (dword_t)old_spec.value.tv_nsec / 1000; if (user_put(old_val_addr, old_val)) return _EFAULT; } @@ -161,7 +162,7 @@ int_t sys_setitimer(int_t which, addr_t new_val_addr, addr_t old_val_addr) { return 0; } -uint_t sys_alarm(uint_t seconds) { +long sys_alarm(uint_t seconds) { STRACE("alarm(%d)", seconds); struct timer_spec spec = { .value.tv_sec = seconds, @@ -170,13 +171,13 @@ uint_t sys_alarm(uint_t seconds) { struct tgroup *group = current->group; lock(&group->lock, 0); - int err = itimer_set(group, ITIMER_REAL_, spec, &old_spec); + long err = itimer_set(group, ITIMER_REAL_, spec, &old_spec); unlock(&group->lock); if (err < 0) return err; // Round up, and make sure to not return 0 if old_spec is > 0 - seconds = old_spec.value.tv_sec; + seconds = (dword_t)old_spec.value.tv_sec; if (old_spec.value.tv_nsec >= 500000000) seconds++; if (seconds == 0 && !timespec_is_zero(old_spec.value)) @@ -203,8 +204,8 @@ dword_t sys_nanosleep(addr_t req_addr, addr_t rem_addr) { return errno_map(); if (rem_addr != 0) { struct timespec_ rem_ts; - rem_ts.sec = rem.tv_sec; - rem_ts.nsec = rem.tv_nsec; + rem_ts.sec = (dword_t)rem.tv_sec; + rem_ts.nsec = (dword_t)rem.tv_nsec; if (user_put(rem_addr, rem_ts)) return _EFAULT; } @@ -235,8 +236,8 @@ dword_t sys_gettimeofday(addr_t tv, addr_t tz) { } struct timeval_ tv_; struct timezone_ tz_; - tv_.sec = timeval.tv_sec; - tv_.usec = timeval.tv_usec; + tv_.sec = (dword_t)timeval.tv_sec; + tv_.usec = (dword_t)timeval.tv_usec; tz_.minuteswest = timezone.tz_minuteswest; tz_.dsttime = timezone.tz_dsttime; if ((tv && user_put(tv, tv_)) || (tz && user_put(tz, tz_))) { diff --git a/kernel/time.h b/kernel/time.h index d906e50e7c..307ff0bc35 100644 --- a/kernel/time.h +++ b/kernel/time.h @@ -49,8 +49,8 @@ struct tms_ { clock_t_ tms_cstime; /* system time of children */ }; -int_t sys_setitimer(int_t which, addr_t new_val, addr_t old_val); -uint_t sys_alarm(uint_t seconds); +long sys_setitimer(int_t which, addr_t new_val, addr_t old_val); +long sys_alarm(uint_t seconds); int_t sys_timer_create(dword_t clock, addr_t sigevent_addr, addr_t timer_addr); int_t sys_timer_settime(dword_t timer, int_t flags, addr_t new_value_addr, addr_t old_value_addr); int_t sys_timer_delete(dword_t timer_id); diff --git a/kernel/uname.c b/kernel/uname.c index eb9e9d3650..6d3e1e5555 100644 --- a/kernel/uname.c +++ b/kernel/uname.c @@ -10,12 +10,13 @@ #endif const char *uname_version = "iSH-AOK"; -const char *uname_hostname_override = NULL; +char *uname_hostname_override = NULL; + void do_uname(struct uname *uts) { struct utsname real_uname; uname(&real_uname); - const char *hostname = real_uname.nodename; + char *hostname = real_uname.nodename; if (uname_hostname_override) hostname = uname_hostname_override; @@ -44,8 +45,18 @@ dword_t sys_uname(addr_t uts_addr) { return 0; } -dword_t sys_sethostname(addr_t UNUSED(hostname_addr), dword_t UNUSED(hostname_len)) { - return _EPERM; +dword_t sys_sethostname(addr_t hostname_addr, dword_t hostname_len) { + if(current->uid != 0) { + return _EPERM; + } else { + free(uname_hostname_override); + uname_hostname_override = malloc(hostname_len + 1); + int result = 0; + // user_read(addr, &(var), sizeof(var)) + result = user_read(hostname_addr, uname_hostname_override, hostname_len + 1); + + return result; + } } #if __APPLE__ @@ -55,7 +66,7 @@ static uint64_t get_total_ram() { return total_ram; } static void sysinfo_specific(struct sys_info *info) { - info->totalram = get_total_ram(); + info->totalram = (dword_t)get_total_ram(); // TODO: everything else } #elif __linux__ @@ -77,10 +88,10 @@ static void sysinfo_specific(struct sys_info *info) { dword_t sys_sysinfo(addr_t info_addr) { struct sys_info info = {0}; struct uptime_info uptime = get_uptime(); - info.uptime = uptime.uptime_ticks; - info.loads[0] = uptime.load_1m; - info.loads[1] = uptime.load_5m; - info.loads[2] = uptime.load_15m; + info.uptime = (dword_t)uptime.uptime_ticks; + info.loads[0] = (dword_t)uptime.load_1m; + info.loads[1] = (dword_t)uptime.load_5m; + info.loads[2] = (dword_t)uptime.load_15m; sysinfo_specific(&info); if (user_put(info_addr, info)) diff --git a/kernel/user.c b/kernel/user.c index b7be6f243d..e793d93c61 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -31,11 +31,20 @@ static int __user_write_task(struct task *task, addr_t addr, const void *buf, si while (p < addr + count) { addr_t chunk_end = (PAGE(p) + 1) << PAGE_BITS; if (chunk_end > addr + count) - chunk_end = addr + count; + chunk_end = addr + (addr_t)count; char *ptr = mem_ptr(task->mem, p, ptrace ? MEM_WRITE_PTRACE : MEM_WRITE); if (ptr == NULL) return 1; memcpy(ptr, &cbuf[p - addr], chunk_end - p); + /* if(!strcmp(task->comm, "ls")) { // Turns out this code mostly deals with linked libraries, at least in the case of ls. -mke + char foo[500] = {}; + memcpy(foo, &cbuf[p - addr], 50); + int a = 0; + printk("INFO: FOO: %s\n", foo); + memcpy(ptr, &cbuf[p - addr], chunk_end - p); + } else { + memcpy(ptr, &cbuf[p - addr], chunk_end - p); + } */ p = chunk_end; } return 0; diff --git a/platform/darwin.c b/platform/darwin.c index 673377cf5b..cad0ee2fbd 100644 --- a/platform/darwin.c +++ b/platform/darwin.c @@ -70,6 +70,7 @@ struct uptime_info get_uptime() { sysctlbyname("kern.boottime", &kern_boottime, &size, NULL, 0); struct timeval now; gettimeofday(&now, NULL); + extern time_t boot_time; struct { uint32_t ldavg[3]; @@ -88,7 +89,8 @@ struct uptime_info get_uptime() { struct uptime_info uptime = { //.uptime_ticks = now.tv_sec - kern_boottime[0], - .uptime_ticks = getSystemUptime() * 100, // This works but shouldn't. -mke + .uptime_ticks = (now.tv_sec - boot_time) * 100, // Note that busybox uptime doesn't like the multiplier. -mke + //.uptime_ticks = getSystemUptime() * 100, // This works but shouldn't. -mke .load_1m = vm_loadavg.ldavg[0], .load_5m = vm_loadavg.ldavg[1], .load_15m = vm_loadavg.ldavg[2], diff --git a/util/sync.c b/util/sync.c index 9e3b613e6f..141f930d16 100644 --- a/util/sync.c +++ b/util/sync.c @@ -52,16 +52,17 @@ void modify_critical_region_counter(struct task *task, int value, __attribute__( if(!task->critical_region.count && (value < 0)) { // Prevent our unsigned value attempting to go negative. -mke //int skipme = strcmp(task->comm, "init"); //if((task->pid > 2) && (skipme != 0)) // Why ask why? -mke - printk("ERROR: Attempt to decrement critical_region count when it is already zero, ignoring(%s:%d) (%s:%d)\n", task->comm, task->pid, file, line); + if(task->pid > 10) + printk("ERROR: Attempt to decrement critical_region count when it is already zero, ignoring(%s:%d) (%s:%d)\n", task->comm, task->pid, file, line); return; } - if((strcmp(task->comm, "easter_egg") == 0) && ( !noprintk)) { // Extra logging for the some command + /* if((strcmp(task->comm, "easter_egg") == 0) && ( !noprintk)) { // Extra logging for the some command noprintk = 1; // Avoid recursive logging -mke printk("INFO: MCRC(%d(%s):%s:%d:%d:%d)\n", task->pid, task->comm, file, line, value, task->critical_region.count + value); noprintk = 0; - } + } */ task->critical_region.count = task->critical_region.count + value; @@ -118,9 +119,8 @@ int wait_for_ignore_signals(cond_t *cond, lock_t *lock, struct timespec *timeout unlock(¤t->waiting_cond_lock); } - modify_critical_region_counter(current, 1,__FILE__, __LINE__); - int savepid = current->pid; - + modify_critical_region_counter(current, 1, __FILE__, __LINE__); + int rc = 0; #if LOCK_DEBUG struct lock_debug lock_tmp = lock->debug; @@ -128,6 +128,7 @@ int wait_for_ignore_signals(cond_t *cond, lock_t *lock, struct timespec *timeout #endif unsigned attempts = 0; if (!timeout) { + unsigned save_pid = lock->pid; if(current->pid <= 20) { pthread_cond_wait(&cond->cond, &lock->m); goto SKIP; @@ -139,25 +140,62 @@ int wait_for_ignore_signals(cond_t *cond, lock_t *lock, struct timespec *timeout current->waiting_lock = NULL; unlock(¤t->waiting_cond_lock); //return _ETIMEDOUT; - printk("ERROR: Locking PID is gone in wait_for_ignore_signals() (%s:%d). Attempting recovery\n", current->comm, current->pid); + if(!strcmp("go", current->comm)) // go causes this a lot. To no particularly positive effect -mke + printk("ERROR: Locking PID is gone in wait_for_ignore_signals() (%s:%d). Attempting recovery\n", current->comm, current->pid); unlock(lock); modify_critical_region_counter(current, -1,__FILE__, __LINE__); return 0; // Weird } - struct timespec trigger_time; - clock_gettime(CLOCK_MONOTONIC, &trigger_time); - trigger_time.tv_sec = trigger_time.tv_sec + 6; - trigger_time.tv_nsec = 0; + if((lock->pid == -1) && (lock->comm[0] == 0)) { // Something has gone wrong. -mke goto AGAIN; // Ugh. -mke } - rc = pthread_cond_timedwait_relative_np(&cond->cond, &lock->m, &trigger_time); + + struct timespec trigger_time; + clock_gettime(CLOCK_REALTIME, &trigger_time); + trigger_time.tv_sec += 6; + trigger_time.tv_nsec = 0; + + if(lock->pid != -1) { + lock->pid = -33; + + if((pthread_mutex_trylock(&lock->m) == EBUSY)) { // Be sure lock is still held. -mke + rc = pthread_cond_timedwait_relative_np(&cond->cond, &lock->m, &trigger_time); + } else { + printk("ERROR: Locking PID is gone in wait_for_ignore_signals() (%s:%d). Attempting recovery\n", current->comm, current->pid); + lock(¤t->waiting_cond_lock, 0); + current->waiting_cond = NULL; + current->waiting_lock = NULL; + unlock(¤t->waiting_cond_lock); + modify_critical_region_counter(current, -1,__FILE__, __LINE__); + unlock(lock); + lock->pid = save_pid; + //pthread_mutex_unlock(&lock->m); + return 0; // Process that held lock exited. Bad, but what can you do? -mke + } + //pthread_mutex_unlock(&lock->m); + } else { + lock(¤t->waiting_cond_lock, 0); + current->waiting_cond = NULL; + current->waiting_lock = NULL; + unlock(¤t->waiting_cond_lock); + modify_critical_region_counter(current, -1,__FILE__, __LINE__); + unlock(lock); + lock->pid = save_pid; + return 0; // More Kludgery. -mke + } + if(rc == ETIMEDOUT) { attempts++; if(attempts <= 6) // We are likely deadlocked if more than ten attempts -mke goto AGAIN; printk("ERROR: Deadlock in wait_for_ignore_signals() (%s:%d). Attempting recovery\n", current->comm, current->pid); + lock(¤t->waiting_cond_lock, 0); + current->waiting_cond = NULL; + current->waiting_lock = NULL; + unlock(¤t->waiting_cond_lock); + lock->pid = save_pid; unlock(lock); modify_critical_region_counter(current, -1,__FILE__, __LINE__); return 0; @@ -224,6 +262,8 @@ unsigned critical_region_count(struct task *task) { unsigned tmp = 0; // pthread_mutex_lock(task->critical_region.lock); // This would make more tmp = task->critical_region.count; + if(tmp > 1000) // Not likely + tmp = 0; // pthread_mutex_unlock(task->critical_region.lock); return tmp; @@ -232,6 +272,14 @@ unsigned critical_region_count(struct task *task) { unsigned critical_region_count_wrapper() { // sync.h can't know about the definition of struct due to recursive include files. -mke return(critical_region_count(current)); } + +bool current_is_valid(void) { + if(current != NULL) + return true; + + return false; +} + unsigned locks_held_count(struct task *task) { // return 0; // Short circuit for now if(task->pid < 10) // Here be monsters. -mke diff --git a/util/sync.h b/util/sync.h index 0879bfac6f..333bb212b6 100644 --- a/util/sync.h +++ b/util/sync.h @@ -23,6 +23,7 @@ extern void modify_critical_region_counter_wrapper(int, const char*, int); extern unsigned locks_held_count_wrapper(void); extern void modify_locks_held_count_wrapper(int); extern struct pid *pid_get(dword_t id); +extern bool current_is_valid(void); extern struct timespec lock_pause; @@ -66,7 +67,7 @@ static inline void atomic_l_lockf(unsigned count, __attribute__((unused)) const pthread_mutex_lock(&atomic_l_lock); modify_locks_held_count_wrapper(1); modify_critical_region_counter_wrapper(-1,__FILE__, __LINE__); - STRACE("atomic_l_lockf(%d)\n", count); + //STRACE("atomic_l_lockf(%d)\n", count); // This is too verbose most of the time } static inline void atomic_l_unlockf(void) { @@ -167,6 +168,11 @@ static inline void __lock(lock_t *lock, int log_lock, __attribute__((unused)) co static inline void unlock(lock_t *lock) { //modify_critical_region_counter_wrapper(1, __FILE__, __LINE__); + unsigned count = 0; + while((lock->pid == -33) && (count < 1000)) { // Pending signal, wait. -mke + nanosleep(&lock_pause, NULL); + count++; + } lock->owner = zero_init(pthread_t); pthread_mutex_unlock(&lock->m); lock->pid = -1; // @@ -195,13 +201,10 @@ typedef struct { char comm[16]; } wrlock_t; - static inline void _read_unlock(wrlock_t *lock, const char*, int); static inline void _write_unlock(wrlock_t *lock, const char*, int); static inline void write_unlock_and_destroy(wrlock_t *lock); - - static inline void loop_lock_read(wrlock_t *lock, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { modify_critical_region_counter_wrapper(1, __FILE__, __LINE__); modify_locks_held_count_wrapper(1); // No, it hasn't been granted yet, but since it can take some time, we set it here to avoid problems. -mke