aboutsummaryrefslogtreecommitdiffstats
path: root/src/process_group.c
blob: 043ee6992f950209b6c6ae969f244a9faa52c446 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/time.h>

#include <assert.h>

#include "process_iterator.h"
#include "process_group.h"
#include "list.h"

int init_process_group(struct process_group *pgroup, int target_pid, int include_children)
{
	//hashtable initialization
	memset(&pgroup->proctable, 0, sizeof(pgroup->proctable));
	pgroup->target_pid = target_pid;
	pgroup->include_children = include_children;
	pgroup->proclist = (struct list*)malloc(sizeof(struct list));
	init_list(pgroup->proclist, 4);
	memset(&pgroup->last_update, 0, sizeof(pgroup->last_update));
	return 0;
}

int close_process_group(struct process_group *pgroup)
{
	int i;
	int size = sizeof(pgroup->proctable) / sizeof(struct process*);
	for (i=0; i<size; i++) {
		if (pgroup->proctable[i] != NULL) {
			//free() history for each process
			destroy_list(pgroup->proctable[i]);
			free(pgroup->proctable[i]);
			pgroup->proctable[i] = NULL;
		}
	}
	clear_list(pgroup->proclist);
	free(pgroup->proclist);
	pgroup->proclist = NULL;
	return 0;
}

void remove_terminated_processes(struct process_group *pgroup)
{
	//TODO
}

//return t1-t2 in microseconds (no overflow checks, so better watch out!)
static inline unsigned long timediff(const struct timeval *t1,const struct timeval *t2)
{
	return (t1->tv_sec - t2->tv_sec) * 1000000 + (t1->tv_usec - t2->tv_usec);
}

//parameter in range 0-1
#define ALFA 0.08

int process_monitor(struct process *proc)
{
	// int j = get_jiffies(proc);
	// if (j<0) return -1; //error retrieving jiffies count (maybe the process is dead)
	// struct timeval now;
	// gettimeofday(&now, NULL);
	// if (proc->last_jiffies==-1) {
	// 	//store current time
	// 	proc->last_sample = now;
	// 	//store current jiffies
	// 	proc->last_jiffies = j;
	// 	//it's the first sample, cannot figure out the cpu usage
	// 	proc->cpu_usage = -1;
	// 	return 0;
	// }
	// //time from previous sample (in ns)
	// long dt = timediff(&now, &(proc->last_sample));
	// //how many jiffies in dt?
	// double max_jiffies = dt * HZ / 1000000.0;
	// double sample = (j - proc->last_jiffies) / max_jiffies;
	// if (proc->cpu_usage == -1) {
	// 	//initialization
	// 	proc->cpu_usage = sample;
	// }
	// else {
	// 	//usage adjustment
	// 	proc->cpu_usage = (1-ALFA) * proc->cpu_usage + ALFA * sample;
	// }
	// //store current time
	// proc->last_sample = now;
	// //store current jiffies
	// proc->last_jiffies = j;	
	return 0;
}

void update_process_group(struct process_group *pgroup)
{
	struct process_iterator it;
	struct process tmp_process;
	struct process_filter filter;
	filter.pid = pgroup->target_pid;
	filter.include_children = pgroup->include_children;
	init_process_iterator(&it, &filter);
	clear_list(pgroup->proclist);
	init_list(pgroup->proclist, 4);
	struct timeval now;
	gettimeofday(&now, NULL);
	//time elapsed from previous sample (in ms)
	long dt = timediff(&now, &pgroup->last_update) / 1000;
	while (get_next_process(&it, &tmp_process) != -1)
	{
		// printf("Read process %d\n", tmp_process.pid);
		// printf("Parent %d\n", tmp_process.ppid);
		// printf("Starttime %d\n", tmp_process.starttime);
		// printf("CPU time %d\n", tmp_process.cputime);
		int hashkey = pid_hashfn(tmp_process.pid + tmp_process.starttime);
		if (pgroup->proctable[hashkey] == NULL)
		{
			//empty bucket
			pgroup->proctable[hashkey] = malloc(sizeof(struct list));
			struct process *new_process = malloc(sizeof(struct process));
			tmp_process.cpu_usage = -1;
			memcpy(new_process, &tmp_process, sizeof(struct process));
			init_list(pgroup->proctable[hashkey], 4);
			add_elem(pgroup->proctable[hashkey], new_process);
			add_elem(pgroup->proclist, new_process);
		}
		else
		{
			//existing bucket
			struct process *p = (struct process*)locate_elem(pgroup->proctable[hashkey], &tmp_process);
			if (p == NULL)
			{
				//process is new. add it
				struct process *new_process = malloc(sizeof(struct process));
				tmp_process.cpu_usage = -1;
				memcpy(new_process, &tmp_process, sizeof(struct process));
				add_elem(pgroup->proctable[hashkey], new_process);
				add_elem(pgroup->proclist, new_process);
			}
			else
			{
				assert(tmp_process.pid == p->pid);
				assert(tmp_process.ppid == p->ppid);
				assert(tmp_process.starttime == p->starttime);
				//process exists. update CPU usage
				double sample = (tmp_process.cputime - p->cputime) / dt;
				if (p->cpu_usage == -1) {
					//initialization
					p->cpu_usage = sample;
				}
				else {
					//usage adjustment
					p->cpu_usage = (1-ALFA) * p->cpu_usage + ALFA * sample;
				}
				p->cpu_usage = (1-ALFA) * p->cpu_usage + ALFA * sample;
				p->cputime = tmp_process.cputime;
				add_elem(pgroup->proclist, p);
			}
		}
	}
	close_process_iterator(&it);
	pgroup->last_update = now;
}
Un proyecto texto-plano.xyz