make vfs & filesystems use failable copying
[minix3.git] / kernel / system / do_cprofile.c
blobb9f01d9f3bd365cb87b874e9669a18e9417c8c48
1 /* The kernel call that is implemented in this file:
2 * m_type: SYS_CPROFILE
4 * The parameters for this kernel call are:
5 * m7_i1: PROF_ACTION (get/reset profiling data)
6 * m7_i2: PROF_MEM_SIZE (available memory for data)
7 * m7_i4: PROF_ENDPT (endpoint of caller)
8 * m7_p1: PROF_CTL_PTR (location of info struct)
9 * m7_p2: PROF_MEM_PTR (location of memory for data)
11 * Changes:
12 * 14 Aug, 2006 Created (Rogier Meurs)
15 #include "kernel/system.h"
17 #include <string.h>
19 #if CPROFILE
21 static struct cprof_ctl_s cprof_ctl_inst;
22 static struct cprof_tbl_s cprof_tbl_inst;
24 /*===========================================================================*
25 * do_cprofile *
26 *===========================================================================*/
27 int do_cprofile(struct proc * caller, message * m_ptr)
29 int proc_nr, i;
30 phys_bytes len;
31 vir_bytes vir_dst;
33 switch (m_ptr->PROF_ACTION) {
35 case PROF_RESET:
37 /* Reset profiling tables. */
39 cprof_ctl_inst.reset = 1;
41 printf("CPROFILE notice: resetting tables:");
43 for (i=0; i<cprof_procs_no; i++) {
45 printf(" %s", cprof_proc_info[i].name);
47 /* Test whether proc still alive. */
48 if (!isokendpt(cprof_proc_info[i].endpt, &proc_nr)) {
49 printf("endpt not valid %u (%s)\n",
50 cprof_proc_info[i].endpt, cprof_proc_info[i].name);
51 continue;
54 /* Set reset flag. */
55 data_copy(KERNEL, (vir_bytes) &cprof_ctl_inst.reset,
56 cprof_proc_info[i].endpt, cprof_proc_info[i].ctl_v,
57 sizeof(cprof_ctl_inst.reset));
59 printf("\n");
61 return OK;
63 case PROF_GET:
65 /* Get profiling data.
67 * Calculate physical addresses of user pointers. Copy to user
68 * program the info struct. Copy to user program the profiling
69 * tables of the profiled processes.
72 if(!isokendpt(m_ptr->PROF_ENDPT, &proc_nr))
73 return EINVAL;
75 cprof_mem_size = m_ptr->PROF_MEM_SIZE;
77 printf("CPROFILE notice: getting tables:");
79 /* Copy control structs of profiled processes to calculate total
80 * nr of bytes to be copied to user program and find out if any
81 * errors happened. */
82 cprof_info.mem_used = 0;
83 cprof_info.err = 0;
85 for (i=0; i<cprof_procs_no; i++) {
87 printf(" %s", cprof_proc_info[i].name);
89 /* Test whether proc still alive. */
90 if (!isokendpt(cprof_proc_info[i].endpt, &proc_nr)) {
91 printf("endpt not valid %u (%s)\n",
92 cprof_proc_info[i].endpt, cprof_proc_info[i].name);
93 continue;
96 /* Copy control struct from proc to local variable. */
97 data_copy(cprof_proc_info[i].endpt, cprof_proc_info[i].ctl_v,
98 KERNEL, (vir_bytes) &cprof_ctl_inst,
99 sizeof(cprof_ctl_inst));
101 /* Calculate memory used. */
102 cprof_proc_info[i].slots_used = cprof_ctl_inst.slots_used;
103 cprof_info.mem_used += CPROF_PROCNAME_LEN;
104 cprof_info.mem_used += sizeof(cprof_proc_info_inst.slots_used);
105 cprof_info.mem_used += cprof_proc_info[i].slots_used *
106 sizeof(cprof_tbl_inst);
107 /* Collect errors. */
108 cprof_info.err |= cprof_ctl_inst.err;
110 printf("\n");
112 /* Do we have the space available? */
113 if (cprof_mem_size < cprof_info.mem_used) cprof_info.mem_used = -1;
115 /* Copy the info struct to the user process. */
116 data_copy(KERNEL, (vir_bytes) &cprof_info,
117 m_ptr->PROF_ENDPT, (vir_bytes) m_ptr->PROF_CTL_PTR,
118 sizeof(cprof_info));
120 /* If there is no space or errors occurred, don't bother copying. */
121 if (cprof_info.mem_used == -1 || cprof_info.err) return OK;
123 /* For each profiled process, copy its name, slots_used and profiling
124 * table to the user process. */
125 vir_dst = (vir_bytes) m_ptr->PROF_MEM_PTR;
126 for (i=0; i<cprof_procs_no; i++) {
127 len = (phys_bytes) strlen(cprof_proc_info[i].name);
128 data_copy(KERNEL, (vir_bytes) cprof_proc_info[i].name,
129 m_ptr->PROF_ENDPT, vir_dst, len);
130 vir_dst += CPROF_PROCNAME_LEN;
132 len = (phys_bytes) sizeof(cprof_ctl_inst.slots_used);
133 data_copy(cprof_proc_info[i].endpt,
134 cprof_proc_info[i].ctl_v + sizeof(cprof_ctl_inst.reset),
135 m_ptr->PROF_ENDPT, vir_dst, len);
136 vir_dst += len;
138 len = (phys_bytes)
139 (sizeof(cprof_tbl_inst) * cprof_proc_info[i].slots_used);
140 data_copy(cprof_proc_info[i].endpt, cprof_proc_info[i].buf_v,
141 m_ptr->PROF_ENDPT, vir_dst, len);
142 vir_dst += len;
145 return OK;
147 default:
148 return EINVAL;
152 #endif /* CPROFILE */