Skip to content

Commit

Permalink
refactor hash table implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
HiGarfield committed Sep 1, 2024
1 parent 0a578f7 commit 9d2eb6e
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 73 deletions.
109 changes: 39 additions & 70 deletions src/process_group.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "process_group.h"
#include "list.h"
#include "util.h"
#include "process_table.h"

/* look for a process by pid
search_pid : pid of the wanted process
Expand Down Expand Up @@ -114,7 +115,12 @@ pid_t find_process_by_name(char *process_name)
int init_process_group(struct process_group *pgroup, pid_t target_pid, int include_children)
{
/* hashtable initialization */
memset(&pgroup->proctable, 0, sizeof(pgroup->proctable));
pgroup->proccache = (struct process_table *)malloc(sizeof(struct process_table));
if (pgroup->proccache == NULL)
{
exit(-1);
}
process_table_init(pgroup->proccache, 2048);
pgroup->target_pid = target_pid;
pgroup->include_children = include_children;
pgroup->proclist = (struct list *)malloc(sizeof(struct list));
Expand All @@ -133,32 +139,32 @@ int init_process_group(struct process_group *pgroup, pid_t target_pid, int inclu

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;
}
}
process_table_destroy(pgroup->proccache);
free(pgroup->proccache);
clear_list(pgroup->proclist);
free(pgroup->proclist);
pgroup->proclist = NULL;
return 0;
}

static struct process *dump_process(struct process *proc)
{
struct process *p = (struct process *)malloc(sizeof(struct process));
if (p == NULL)
{
exit(-1);
}
return memcpy(p, proc, sizeof(struct process));
}

/* parameter in range 0-1 */
#define ALPHA 0.08
#define MIN_DT 20

void update_process_group(struct process_group *pgroup)
{
struct process_iterator it;
struct process tmp_process;
struct process tmp_process, *p;
struct process_filter filter;
struct timespec now;
double dt;
Expand All @@ -176,63 +182,34 @@ void update_process_group(struct process_group *pgroup)

while (get_next_process(&it, &tmp_process) != -1)
{
int hashkey = pid_hashfn(tmp_process.pid);
if (pgroup->proctable[hashkey] == NULL)
p = process_table_find(pgroup->proccache, &tmp_process);
if (p == NULL)
{
/* empty bucket */
struct process *new_process = (struct process *)malloc(sizeof(struct process));
if (new_process == NULL)
{
exit(-1);
}
pgroup->proctable[hashkey] = (struct list *)malloc(sizeof(struct list));
if (pgroup->proctable[hashkey] == NULL)
{
exit(-1);
}
/* process is new. add it */
tmp_process.cpu_usage = -1;
memcpy(new_process, &tmp_process, sizeof(struct process));
init_list(pgroup->proctable[hashkey], sizeof(pid_t));
add_elem(pgroup->proctable[hashkey], new_process);
add_elem(pgroup->proclist, new_process);
p = dump_process(&tmp_process);
process_table_add(pgroup->proccache, p);
add_elem(pgroup->proclist, p);
}
else
{
/* existing bucket */
struct process *p = (struct process *)locate_elem(pgroup->proctable[hashkey], &tmp_process);
if (p == NULL)
double sample;
add_elem(pgroup->proclist, p);
if (dt < MIN_DT)
continue;
/* process exists. update CPU usage */
sample = (tmp_process.cputime - p->cputime) / dt;
if (p->cpu_usage < 0)
{
/* process is new. add it */
struct process *new_process = (struct process *)malloc(sizeof(struct process));
if (new_process == NULL)
{
exit(-1);
}
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);
/* initialization */
p->cpu_usage = sample;
}
else
{
double sample;
add_elem(pgroup->proclist, p);
if (dt < MIN_DT)
continue;
/* process exists. update CPU usage */
sample = (tmp_process.cputime - p->cputime) / dt;
if (p->cpu_usage < 0)
{
/* initialization */
p->cpu_usage = sample;
}
else
{
/* usage adjustment */
p->cpu_usage = (1.0 - ALPHA) * p->cpu_usage + ALPHA * sample;
}
p->cputime = tmp_process.cputime;
/* usage adjustment */
p->cpu_usage = (1.0 - ALPHA) * p->cpu_usage + ALPHA * sample;
}
p->cputime = tmp_process.cputime;
}
}
close_process_iterator(&it);
Expand All @@ -243,13 +220,5 @@ void update_process_group(struct process_group *pgroup)

int remove_process(struct process_group *pgroup, pid_t pid)
{
int hashkey = pid_hashfn(pid);
struct list_node *node;
if (pgroup->proctable[hashkey] == NULL)
return 1; /* nothing to delete */
node = (struct list_node *)locate_node(pgroup->proctable[hashkey], &pid);
if (node == NULL)
return 2;
delete_node(pgroup->proctable[hashkey], node);
return 0;
return process_table_del_pid(pgroup->proccache, pid);
}
2 changes: 1 addition & 1 deletion src/process_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
struct process_group
{
/* hashtable with all the processes (array of struct list of struct process) */
struct list *proctable[PIDHASH_SZ];
struct process_table *proccache;
struct list *proclist;
pid_t target_pid;
int include_children;
Expand Down
83 changes: 83 additions & 0 deletions src/process_table.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <stdlib.h>
#include <string.h>
#include "process_table.h"

void process_table_init(struct process_table *pt, int hashsize)
{
pt->hashsize = hashsize;
pt->table = (struct list **)malloc(sizeof(struct list *) * pt->hashsize);
if (pt->table == NULL)
{
exit(1);
}
memset(pt->table, 0, sizeof(struct list *) * pt->hashsize);
}

static int proc_hash(struct process_table *pt, struct process *p)
{
return p->pid % pt->hashsize;
}

struct process *process_table_find(struct process_table *pt, struct process *p)
{
int idx = proc_hash(pt, p);
if (pt->table[idx] == NULL)
{
return NULL;
}
return (struct process *)locate_elem(pt->table[idx], p);
}

void process_table_add(struct process_table *pt, struct process *p)
{
int idx = proc_hash(pt, p);
if (pt->table[idx] == NULL)
{
pt->table[idx] = (struct list *)malloc(sizeof(struct list));
if (pt->table[idx] == NULL)
{
exit(-1);
}
init_list(pt->table[idx], sizeof(pid_t));
}
add_elem(pt->table[idx], p);
}

int process_table_del(struct process_table *pt, struct process *p)
{
struct list_node *node;
int idx = proc_hash(pt, p);
if (pt->table[idx] == NULL)
{
return 1; /* nothing to delete */
}
node = (struct list_node *)locate_node(pt->table[idx], p);
if (node == NULL)
{
return 2; /* nothing to delete */
}
delete_node(pt->table[idx], node);
return 0;
}

int process_table_del_pid(struct process_table *pt, pid_t pid)
{
struct process p;
p.pid = pid;
return process_table_del(pt, &p);
}

void process_table_destroy(struct process_table *pt)
{
int i;
for (i = 0; i < pt->hashsize; i++)
{
if (pt->table[i] != NULL)
{
destroy_list(pt->table[i]);
free(pt->table[i]);
}
}
free(pt->table);
pt->table = NULL;
}
25 changes: 25 additions & 0 deletions src/process_table.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef __PROCESS_TABLE_H
#define __PROCESS_TABLE_H

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

struct process_table
{
struct list **table;
int hashsize;
};

void process_table_init(struct process_table *pt, int hashsize);

struct process *process_table_find(struct process_table *pt, struct process *p);

void process_table_add(struct process_table *pt, struct process *p);

int process_table_del(struct process_table *pt, struct process *p);

int process_table_del_pid(struct process_table *pt, pid_t pid);

void process_table_destroy(struct process_table *pt);

#endif
4 changes: 2 additions & 2 deletions tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ override CFLAGS := $(filter-out -std=% -ansi -W%,$(CFLAGS)) \
TARGETS = busy process_iterator_test
SRC = ../src
SYSLIBS ?= -lpthread $(SRC)/util.c
LIBS := $(SRC)/list.c $(SRC)/process_iterator.c \
$(SRC)/process_group.c $(SRC)/util.c
LIBS := $(SRC)/list.c $(SRC)/process_iterator.c $(SRC)/process_group.c \
$(SRC)/process_table.c $(SRC)/util.c

UNAME ?= $(shell uname)
ifeq ($(UNAME), FreeBSD)
Expand Down

0 comments on commit 9d2eb6e

Please sign in to comment.