SYS_notify and SYS_self_notify
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 7 Apr 2010 05:14:51 +0000 (22:14 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:41 +0000 (17:35 -0700)
Processes can notify themselves (pick a vcore) or another process (which
will check the notif_methods for the vcoreid and if the notif is
wanted).  Example code in mhello.

You'll need to update your kernel headers (though you won't need a full
glibc recompile).

kern/include/process.h
kern/include/ros/bits/syscall.h
kern/src/process.c
kern/src/syscall.c
tests/mhello.c
user/include/parlib.h
user/parlib/syscall.c

index dacd79d..0213b10 100644 (file)
@@ -11,6 +11,7 @@
 #define ROS_KERN_PROCESS_H
 
 #include <ros/common.h>
+#include <ros/notification.h>
 #include <trap.h>
 #include <atomic.h>
 
@@ -81,6 +82,9 @@ void proc_run(struct proc *SAFE p);
 void proc_restartcore(struct proc *SAFE p, trapframe_t *SAFE tf);
 void proc_destroy(struct proc *SAFE p);
 void proc_yield(struct proc *SAFE p);
+void do_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
+               struct notif_event *ne);
+void proc_notify(struct proc *p, unsigned int notif, struct notif_event *ne);
 
 /* Exposed for sys_getvcoreid(), til it's unnecessary */
 uint32_t proc_get_vcoreid(struct proc *SAFE p, uint32_t pcoreid);
index 62908d9..67d78f1 100644 (file)
 #define SYS_shared_page_alloc          22
 #define SYS_shared_page_free           23
 #define SYS_resource_req                       24
+#define SYS_notify                                     25
+#define SYS_self_notify                                26
+
 /* Platform specific syscalls */
-#define SYS_serial_read                                25
-#define SYS_serial_write                       26
-#define SYS_eth_read                           27
-#define SYS_eth_write                          28
-#define SYS_eth_get_mac_addr                   29
-#define SYS_eth_recv_check                     30
+#define SYS_serial_read                                75
+#define SYS_serial_write                       76
+#define SYS_eth_read                           77
+#define SYS_eth_write                          78
+#define SYS_eth_get_mac_addr           79
+#define SYS_eth_recv_check                     80
 
 #define SYS_read                               100
 #define SYS_write                              101
index 67c14c8..c9e8e50 100644 (file)
@@ -702,6 +702,9 @@ void do_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
                struct notif_event *ne)
 {
        assert(notif < MAX_NR_NOTIF);
+       if (ne)
+               assert(notif == ne->ne_type);
+
        struct notif_method *nm = &p->procdata->notif_methods[notif];
        struct preempt_data *vcpd = &p->procdata->vcore_preempt_data[vcoreid];
 
@@ -741,17 +744,21 @@ void do_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
  * just determines where the notif should be sent, other checks, etc.
  * Specifically, it handles the parameters of notif_methods.  If you happen to
  * notify yourself, make sure you process routine kmsgs. */
-void proc_notify(struct proc *p, unsigned int notif)
+void proc_notify(struct proc *p, unsigned int notif, struct notif_event *ne)
 {
        assert(notif < MAX_NR_NOTIF); // notifs start at 0
        struct notif_method *nm = &p->procdata->notif_methods[notif];
-       struct notif_event ne;
+       struct notif_event local_ne;
        
-       ne.ne_type = notif;
+       /* Caller can opt to not send an NE, in which case we use the notif */
+       if (!ne) {
+               ne = &local_ne;
+               ne->ne_type = notif;
+       }
 
        if (!(nm->flags & NOTIF_WANTED))
                return;
-       do_notify(p, nm->vcoreid, notif, &ne);
+       do_notify(p, nm->vcoreid, ne->ne_type, ne);
 }
 
 /* Global version of the helper, for sys_get_vcoreid (might phase that syscall
index d62c1f5..5589b7c 100644 (file)
@@ -5,6 +5,7 @@
 #endif
 
 #include <ros/common.h>
+#include <ros/notification.h>
 #include <arch/types.h>
 #include <arch/arch.h>
 #include <arch/mmu.h>
@@ -558,10 +559,60 @@ static int sys_shared_page_free(env_t* p1, void*DANGEROUS addr, pid_t p2)
 }
 
 
-/************** Resource Request Syscalls **************/
-
 /* sys_resource_req(): called directly from dispatch table. */
 
+/* Will notify the target on the given vcore, if the caller controls the target.
+ * Will honor the target's wanted/vcoreid.  u_ne can be NULL. */
+static int sys_notify(struct proc *p, int target_pid, unsigned int notif,
+                      struct notif_event *u_ne)
+{
+       struct notif_event local_ne;
+       struct proc *target = pid2proc(target_pid);
+
+       if (!target) {
+               set_errno(current_tf, EBADPROC);
+               return -1;
+       }
+       if (!proc_controls(p, target)) {
+               proc_decref(target, 1);
+               set_errno(current_tf, EPERM);
+               return -1;
+       }
+       /* if the user provided a notif_event, copy it in and use that */
+       if (u_ne) {
+               if (memcpy_from_user(p, &local_ne, u_ne, sizeof(struct notif_event))) {
+                       proc_decref(target, 1);
+                       set_errno(current_tf, EINVAL);
+                       return -1;
+               }
+               proc_notify(target, local_ne.ne_type, &local_ne);
+       } else {
+               proc_notify(target, notif, 0);
+       }
+       proc_decref(target, 1);
+       return 0;
+}
+
+/* Will notify the calling process on the given vcore, independently of WANTED
+ * or advertised vcoreid. */
+static int sys_self_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
+                           struct notif_event *u_ne)
+{
+       struct notif_event local_ne;
+
+       /* if the user provided a notif_event, copy it in and use that */
+       if (u_ne) {
+               if (memcpy_from_user(p, &local_ne, u_ne, sizeof(struct notif_event))) {
+                       set_errno(current_tf, EINVAL);
+                       return -1;
+               }
+               do_notify(p, vcoreid, local_ne.ne_type, &local_ne);
+       } else {
+               do_notify(p, vcoreid, notif, 0);
+       }
+       return 0;
+}
+
 /************** Platform Specific Syscalls **************/
 
 //Read a buffer over the serial port
@@ -999,6 +1050,8 @@ intreg_t syscall(struct proc *p, uintreg_t syscallno, uintreg_t a1,
                [SYS_shared_page_alloc] = (syscall_t)sys_shared_page_alloc,
                [SYS_shared_page_free] = (syscall_t)sys_shared_page_free,
                [SYS_resource_req] = (syscall_t)resource_req,
+               [SYS_notify] = (syscall_t)sys_notify,
+               [SYS_self_notify] = (syscall_t)sys_self_notify,
        #ifdef __CONFIG_SERIAL_IO__
                [SYS_serial_read] = (syscall_t)sys_serial_read,
                [SYS_serial_write] = (syscall_t)sys_serial_write,
index 029a059..a7cc0c6 100644 (file)
@@ -52,7 +52,19 @@ int main(int argc, char** argv)
                retval = hart_request(2); // doesn't do what you think.  this gives 3.
                //debug("retval = %d\n", retval);
        }
-       printf("Vcore %d Done!\n", vcoreid);
+
+       /* test notifying my vcore2 */
+       udelay(5000000);
+       printf("Vcore 0 self-notifying vcore 2 with notif 4!\n");
+       struct notif_event ne;
+       ne.ne_type = 4;
+       sys_self_notify(2, 4, &ne);
+       udelay(5000000);
+       printf("Vcore 0 notifying itself with notif 3!\n");
+       ne.ne_type = 3;
+       sys_notify(sys_getpid(), 3, &ne);
+       udelay(1000000);
+
        /* test loop for restarting a notif_tf */
        if (vcoreid == 0) {
                int ctr = 0;
@@ -62,6 +74,7 @@ int main(int argc, char** argv)
                }
        }
 
+       printf("Vcore %d Done!\n", vcoreid);
        hart_barrier_wait(&b,hart_self());
 
        printf("All Cores Done!\n", vcoreid);
index 3f5e1dd..e693dc5 100644 (file)
@@ -46,6 +46,9 @@ void        sys_reboot();
 int         gettimeofday(struct timeval* tp, void* tzp);
 void *COUNT(length) sys_mmap(void *SNT addr, size_t length, int prot, int flags,
                              int fd, size_t offset);
+int         sys_notify(int pid, unsigned int notif, struct notif_event *ne);
+int         sys_self_notify(uint32_t vcoreid, unsigned int notif,
+                            struct notif_event *ne);
 
 #endif // !ASSEMBLER
 
index aa24fa7..ecc7bed 100644 (file)
@@ -134,3 +134,13 @@ void *CT(length) sys_mmap(void *SNT addr, size_t length, int prot, int flags,
                                               prot, &extra_args, 0));
 }
 
+int sys_notify(int pid, unsigned int notif, struct notif_event *ne)
+{
+       return ros_syscall(SYS_notify, pid, notif, ne, 0, 0);
+}
+
+int sys_self_notify(uint32_t vcoreid, unsigned int notif,
+                    struct notif_event *ne)
+{
+       return ros_syscall(SYS_self_notify, vcoreid, notif, ne, 0, 0);
+}