Abort all syscalls using a particular FD (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 13 May 2014 23:25:07 +0000 (16:25 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 13 May 2014 23:27:57 +0000 (16:27 -0700)
This will abort any syscalls currently blocked on a rendez that operate on a
given FD.  It is possible that some syscalls are still in progress and haven't
rendezed, and those will not be aborted.

kern/include/kthread.h
kern/include/ros/bits/syscall.h
kern/include/syscall.h
kern/src/kthread.c
kern/src/syscall.c
user/parlib/include/parlib.h
user/parlib/syscall.c

index 3f9ec4d..529d8d7 100644 (file)
@@ -114,6 +114,7 @@ void cv_broadcast_irqsave(struct cond_var *cv, int8_t *irq_state);
 
 bool abort_sysc(struct proc *p, struct syscall *sysc);
 void abort_all_sysc(struct proc *p);
+int abort_all_sysc_fd(struct proc *p, int fd);
 void __reg_abortable_cv(struct cv_lookup_elm *cle, struct cond_var *cv);
 void dereg_abortable_cv(struct cv_lookup_elm *cle);
 bool should_abort(struct cv_lookup_elm *cle);
index 7f1569b..b42510f 100644 (file)
@@ -43,6 +43,7 @@
 #define SYS_poke_ksched                                30
 #define SYS_abort_sysc                         31
 #define SYS_populate_va                                32
+#define SYS_abort_sysc_fd                      33
 
 /* FS Syscalls */
 #define SYS_read                               100
index f4be19a..cdcbe2a 100644 (file)
@@ -63,4 +63,7 @@ int systrace_dereg(bool all, struct proc *p);
 void systrace_print(bool all, struct proc *p);
 void systrace_clear_buffer(void);
 
+/* Utility */
+bool syscall_uses_fd(struct syscall *sysc, int fd);
+
 #endif /* !ROS_KERN_SYSCALL_H */
index eab09d7..012c178 100644 (file)
@@ -744,16 +744,20 @@ bool abort_sysc(struct proc *p, struct syscall *sysc)
        return TRUE;
 }
 
-/* This will abort any abortabls at the time the call was started.  New
- * abortables could be registered concurrently.  The main caller I see for this
- * is proc_destroy(), so DYING will be set, and new abortables will quickly
- * abort and dereg when they see their proc is DYING. */
-void abort_all_sysc(struct proc *p)
+/* This will abort any abortables at the time the call was started for which
+ * should_abort(cle, arg) returns true.  New abortables could be registered
+ * concurrently.  The original for this is proc_destroy(), so DYING will be set,
+ * and new abortables will quickly abort and dereg when they see their proc is
+ * DYING. */
+static int __abort_all_sysc(struct proc *p,
+                            bool (*should_abort)(struct cv_lookup_elm*, void*),
+                            void *arg)
 {
        struct cv_lookup_elm *cle;
        int8_t irq_state = 0;
        struct cv_lookup_tailq abortall_list;
        struct proc *old_proc = switch_to(p);
+       int ret = 0;
        /* Concerns: we need to not remove them from their original list, since
         * concurrent wake ups will cause a dereg, which will remove from the list.
         * We also can't touch freed memory, so we need a refcnt to keep cles
@@ -761,13 +765,37 @@ void abort_all_sysc(struct proc *p)
        TAILQ_INIT(&abortall_list);
        spin_lock_irqsave(&p->abort_list_lock);
        TAILQ_FOREACH(cle, &p->abortable_sleepers, link) {
+               if (!should_abort(cle, arg))
+                       continue;
                atomic_inc(&cle->abort_in_progress);
                TAILQ_INSERT_HEAD(&abortall_list, cle, abortall_link);
+               ret++;
        }
        spin_unlock_irqsave(&p->abort_list_lock);
        TAILQ_FOREACH(cle, &abortall_list, abortall_link)
                __abort_and_release_cle(cle);
        switch_back(p, old_proc);
+       return ret;
+}
+
+static bool always_abort(struct cv_lookup_elm *cle, void *arg)
+{
+       return TRUE;
+}
+
+void abort_all_sysc(struct proc *p)
+{
+       __abort_all_sysc(p, always_abort, 0);
+}
+
+static bool sysc_uses_fd(struct cv_lookup_elm *cle, void *fd)
+{
+       return syscall_uses_fd(cle->sysc, (int)(long)fd);
+}
+
+int abort_all_sysc_fd(struct proc *p, int fd)
+{
+       return __abort_all_sysc(p, sysc_uses_fd, (void*)(long)fd);
 }
 
 /* Being on the abortable list means that the CLE, KTH, SYSC, and CV are valid
index 61efccc..a1a7806 100644 (file)
@@ -1027,6 +1027,13 @@ static int sys_abort_sysc(struct proc *p, struct syscall *sysc)
        return abort_sysc(p, sysc);
 }
 
+static int sys_abort_sysc_fd(struct proc *p, int fd)
+{
+       /* Consider checking for a bad fd.  Doesn't matter now, since we only look
+        * for actual syscalls blocked that had used fd. */
+       return abort_all_sysc_fd(p, fd);
+}
+
 static unsigned long sys_populate_va(struct proc *p, uintptr_t va,
                                      unsigned long nr_pgs)
 {
@@ -1790,6 +1797,7 @@ const struct sys_table_entry syscall_table[] = {
        [SYS_change_to_m] = {(syscall_t)sys_change_to_m, "change_to_m"},
        [SYS_poke_ksched] = {(syscall_t)sys_poke_ksched, "poke_ksched"},
        [SYS_abort_sysc] = {(syscall_t)sys_abort_sysc, "abort_sysc"},
+       [SYS_abort_sysc_fd] = {(syscall_t)sys_abort_sysc_fd, "abort_sysc_fd"},
        [SYS_populate_va] = {(syscall_t)sys_populate_va, "populate_va"},
 
        [SYS_read] = {(syscall_t)sys_read, "read"},
@@ -2076,3 +2084,27 @@ void systrace_clear_buffer(void)
        memset(systrace_buffer, 0, sizeof(struct systrace_record) * MAX_SYSTRACES);
        spin_unlock_irqsave(&systrace_lock);
 }
+
+bool syscall_uses_fd(struct syscall *sysc, int fd)
+{
+       switch (sysc->num) {
+               case (SYS_read):
+               case (SYS_write):
+               case (SYS_close):
+               case (SYS_fstat):
+               case (SYS_fcntl):
+               case (SYS_llseek):
+               case (SYS_nmount):
+               case (SYS_fd2path):
+                       if (sysc->arg0 == fd)
+                               return TRUE;
+                       return FALSE;
+               case (SYS_mmap):
+                       /* mmap always has to be special. =) */
+                       if (sysc->arg4 == fd)
+                               return TRUE;
+                       return FALSE;
+               default:
+                       return FALSE;
+       }
+}
index 11f69c2..6e576e1 100644 (file)
@@ -55,6 +55,7 @@ int         sys_change_vcore(uint32_t vcoreid, bool enable_my_notif);
 int         sys_change_to_m(void);
 int         sys_poke_ksched(int pid, unsigned int res_type);
 int         sys_abort_sysc(struct syscall *sysc);
+int         sys_abort_sysc_fd(int fd);
 
 long           syscall_async(struct syscall *sysc, unsigned long num, ...);
 
index f5e4e5d..d958dba 100644 (file)
@@ -167,6 +167,11 @@ int sys_abort_sysc(struct syscall *sysc)
        return ros_syscall(SYS_abort_sysc, sysc, 0, 0, 0, 0, 0);
 }
 
+int sys_abort_sysc_fd(int fd)
+{
+       return ros_syscall(SYS_abort_sysc_fd, fd, 0, 0, 0, 0, 0);
+}
+
 long syscall_async(struct syscall *sysc, unsigned long num, ...)
 {
        va_list args;