Pipes (XCC)
[akaros.git] / kern / include / ros / procinfo.h
index b403f12..9b69de4 100644 (file)
@@ -5,40 +5,58 @@
 
 #include <ros/memlayout.h>
 #include <ros/common.h>
+#include <ros/resource.h>
+#include <ros/atomic.h>
 #include <ros/arch/arch.h>
+#include <string.h>
 
 #define PROCINFO_MAX_ARGP 32
 #define PROCINFO_ARGBUF_SIZE 3072
 
-// TODO: move me to an atomic header, and give me some support functions.
-#ifndef __TMP_SEQ_CTR
-#define __TMP_SEQ_CTR
-typedef uint8_t seq_ctr_t;
-#endif
+#ifdef ROS_KERNEL
+#include <sys/queue.h>
+#endif /* ROS_KERNEL */
 
 /* Not necessary to expose all of this, but it doesn't hurt, and is convenient
- * for the kernel. */
+ * for the kernel.  Need to do some acrobatics for the TAILQ_ENTRY. */
+struct vcore;
 struct vcore {
+#ifdef ROS_KERNEL
+       TAILQ_ENTRY(vcore)      list;
+#else /* userspace */
+       void                            *dummy_ptr1;
+       void                            *dummy_ptr2;
+#endif /* ROS_KERNEL */
        uint32_t                        pcoreid;
        bool                            valid;
-       bool                            preempt_served;
+       uint32_t                        nr_preempts_sent;       /* these two differ when a preempt*/
+       uint32_t                        nr_preempts_done;       /* is in flight. */
        uint64_t                        preempt_pending;
-       struct trapframe        *tf_to_run;
+};
+
+struct pcore {
+       uint32_t                        vcoreid;
+       bool                            valid;
 };
 
 typedef struct procinfo {
        pid_t pid;
        pid_t ppid;
-       size_t max_harts;
+       size_t max_vcores;      /* TODO: change to a uint32_t */
        uint64_t tsc_freq;
-       void* heap_bottom;
-       char* argp[PROCINFO_MAX_ARGP];
+       uint64_t timing_overhead;
+       void *heap_bottom;
+       /* for traditional forks, these two need to be memcpy'd over: */
+       char *argp[PROCINFO_MAX_ARGP];
        char argbuf[PROCINFO_ARGBUF_SIZE];
        /* glibc relies on stuff above this point.  if you change it, you need to
         * rebuild glibc. */
+       bool is_mcp;                    /* is in multi mode */
+       unsigned long           res_grant[MAX_NUM_RESOURCES];
        struct vcore            vcoremap[MAX_NUM_CPUS];
        uint32_t                        num_vcores;
-       seq_ctr_t                       coremap_edit;
+       struct pcore            pcoremap[MAX_NUM_CPUS];
+       seq_ctr_t                       coremap_seqctr;
 } procinfo_t;
 #define PROCINFO_NUM_PAGES  ((sizeof(procinfo_t)-1)/PGSIZE + 1)        
 
@@ -53,7 +71,8 @@ procinfo_pack_args(procinfo_t* p, char* const* argv, char* const* envp)
                return -1;
 
        int pos = 0;
-       for(int i = 0; i < nargv; i++)
+       int i;
+       for(i = 0; i < nargv; i++)
        {
                int len = strlen(argv[i])+1;
                if(pos+len > PROCINFO_ARGBUF_SIZE)
@@ -64,7 +83,7 @@ procinfo_pack_args(procinfo_t* p, char* const* argv, char* const* envp)
        }
        p->argp[nargv] = 0;
 
-       for(int i = 0; i < nenvp; i++)
+       for(i = 0; i < nenvp; i++)
        {
                int len = strlen(envp[i])+1;
                if(pos+len > PROCINFO_ARGBUF_SIZE)
@@ -81,6 +100,38 @@ procinfo_pack_args(procinfo_t* p, char* const* argv, char* const* envp)
 // this is how user programs access the procinfo page
 #ifndef ROS_KERNEL
 # define __procinfo (*(procinfo_t*)UINFO)
-#endif
+
+#include <ros/common.h>
+#include <ros/atomic.h>
+#include <ros/syscall.h>
+
+/* Figure out what your vcoreid is from your pcoreid and procinfo.  Only low
+ * level or debugging code should call this. */
+static inline uint32_t __get_vcoreid_from_procinfo(void)
+{
+       /* The assumption is that any IPIs/KMSGs would knock userspace into the
+        * kernel before it could read the closing of the seqctr.  Put another way,
+        * there is a 'memory barrier' between the IPI write and the seqctr write.
+        * I think this is true. */
+       uint32_t kpcoreid, kvcoreid;
+       seq_ctr_t old_seq;
+       do {
+               cmb();
+               old_seq = __procinfo.coremap_seqctr;
+               kpcoreid = __ros_syscall_noerrno(SYS_getpcoreid, 0, 0, 0, 0, 0, 0);
+               if (!__procinfo.pcoremap[kpcoreid].valid)
+                       continue;
+               kvcoreid = __procinfo.pcoremap[kpcoreid].vcoreid;
+       } while (seqctr_retry(old_seq, __procinfo.coremap_seqctr));
+       return kvcoreid;
+}
+
+static inline uint32_t __get_vcoreid(void)
+{
+       /* since sys_getvcoreid could lie (and might never change) */
+       return __get_vcoreid_from_procinfo();
+}
+
+#endif /* ifndef ROS_KERNEL */
 
 #endif // !ROS_PROCDATA_H