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