sys_proc_create() can dup FGRPs (XCC)
[akaros.git] / kern / include / ros / procinfo.h
1 /* See COPYRIGHT for copyright information. */
2
3 #ifndef ROS_PROCINFO_H
4 #define ROS_PROCINFO_H
5
6 #include <ros/memlayout.h>
7 #include <ros/common.h>
8 #include <ros/resource.h>
9 #include <ros/atomic.h>
10 #include <ros/arch/arch.h>
11 #include <string.h>
12
13 /* Process creation flags */
14 #define PROC_DUP_FGRP                   1
15
16 #define PROCINFO_MAX_ARGP 32
17 #define PROCINFO_ARGBUF_SIZE 3072
18
19 #ifdef ROS_KERNEL
20 #include <sys/queue.h>
21 #endif /* ROS_KERNEL */
22
23 /* Not necessary to expose all of this, but it doesn't hurt, and is convenient
24  * for the kernel.  Need to do some acrobatics for the TAILQ_ENTRY. */
25 struct vcore;
26 struct vcore {
27 #ifdef ROS_KERNEL
28         TAILQ_ENTRY(vcore)      list;
29 #else /* userspace */
30         void                            *dummy_ptr1;
31         void                            *dummy_ptr2;
32 #endif /* ROS_KERNEL */
33         uint32_t                        pcoreid;
34         bool                            valid;
35         uint32_t                        nr_preempts_sent;       /* these two differ when a preempt*/
36         uint32_t                        nr_preempts_done;       /* is in flight. */
37         uint64_t                        preempt_pending;
38         /* A process can see cumulative runtime as of the last resume, and can also
39          * calculate runtime in this interval, by adding (ns - resume) + total. */
40         uint64_t                        resume_ticks;           /* TSC at resume time */
41         uint64_t                        total_ticks;            /* ticks up to last offlining */
42 };
43
44 struct pcore {
45         uint32_t                        vcoreid;
46         bool                            valid;
47 };
48
49 typedef struct procinfo {
50         pid_t pid;
51         pid_t ppid;
52         size_t max_vcores;      /* TODO: change to a uint32_t */
53         uint64_t tsc_freq;
54         uint64_t timing_overhead;
55         void *heap_bottom;
56         /* for traditional forks, these two need to be memcpy'd over: */
57         char *argp[PROCINFO_MAX_ARGP];
58         char argbuf[PROCINFO_ARGBUF_SIZE];
59         /* glibc relies on stuff above this point.  if you change it, you need to
60          * rebuild glibc. */
61         bool is_mcp;                    /* is in multi mode */
62         unsigned long           res_grant[MAX_NUM_RESOURCES];
63         struct vcore            vcoremap[MAX_NUM_CPUS];
64         uint32_t                        num_vcores;
65         struct pcore            pcoremap[MAX_NUM_CPUS];
66         seq_ctr_t                       coremap_seqctr;
67 } procinfo_t;
68 #define PROCINFO_NUM_PAGES  ((sizeof(procinfo_t)-1)/PGSIZE + 1) 
69
70 static int
71 procinfo_pack_args(procinfo_t* p, char* const* argv, char* const* envp)
72 {
73         int nargv = 0, nenvp = 0;
74         if(argv) while(argv[nargv]) nargv++;
75         if(envp) while(envp[nenvp]) nenvp++;
76
77         if(nargv+nenvp+2 > PROCINFO_MAX_ARGP)
78                 return -1;
79
80         int pos = 0;
81         int i;
82         for(i = 0; i < nargv; i++)
83         {
84                 int len = strlen(argv[i])+1;
85                 if(pos+len > PROCINFO_ARGBUF_SIZE)
86                         return -1;
87                 p->argp[i] = ((procinfo_t*)UINFO)->argbuf+pos;
88                 memcpy(p->argbuf+pos,argv[i],len);
89                 pos += len;
90         }
91         p->argp[nargv] = 0;
92
93         for(i = 0; i < nenvp; i++)
94         {
95                 int len = strlen(envp[i])+1;
96                 if(pos+len > PROCINFO_ARGBUF_SIZE)
97                         return -1;
98                 p->argp[nargv+1+i] = ((procinfo_t*)UINFO)->argbuf+pos;
99                 memcpy(p->argbuf+pos,envp[i],len);
100                 pos += len;
101         }
102         p->argp[nargv+nenvp+1] = 0;
103         
104         return 0;
105 }
106
107 // this is how user programs access the procinfo page
108 #ifndef ROS_KERNEL
109 # define __procinfo (*(procinfo_t*)UINFO)
110
111 #include <ros/common.h>
112 #include <ros/atomic.h>
113 #include <ros/syscall.h>
114
115 /* Figure out what your vcoreid is from your pcoreid and procinfo.  Only low
116  * level or debugging code should call this. */
117 static inline uint32_t __get_vcoreid_from_procinfo(void)
118 {
119         /* The assumption is that any IPIs/KMSGs would knock userspace into the
120          * kernel before it could read the closing of the seqctr.  Put another way,
121          * there is a 'memory barrier' between the IPI write and the seqctr write.
122          * I think this is true. */
123         uint32_t kpcoreid, kvcoreid;
124         seq_ctr_t old_seq;
125         do {
126                 cmb();
127                 old_seq = __procinfo.coremap_seqctr;
128                 kpcoreid = __ros_syscall_noerrno(SYS_getpcoreid, 0, 0, 0, 0, 0, 0);
129                 if (!__procinfo.pcoremap[kpcoreid].valid)
130                         continue;
131                 kvcoreid = __procinfo.pcoremap[kpcoreid].vcoreid;
132         } while (seqctr_retry(old_seq, __procinfo.coremap_seqctr));
133         return kvcoreid;
134 }
135
136 static inline uint32_t __get_vcoreid(void)
137 {
138         /* since sys_getvcoreid could lie (and might never change) */
139         return __get_vcoreid_from_procinfo();
140 }
141
142 #endif /* ifndef ROS_KERNEL */
143
144 #endif // !ROS_PROCDATA_H