aboutsummaryrefslogtreecommitdiffstats
path: root/src/cpulimit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpulimit.c')
-rw-r--r--src/cpulimit.c166
1 files changed, 45 insertions, 121 deletions
diff --git a/src/cpulimit.c b/src/cpulimit.c
index 300d320..394b132 100644
--- a/src/cpulimit.c
+++ b/src/cpulimit.c
@@ -61,8 +61,7 @@
#include <sys/resource.h>
#include <sys/wait.h>
-#include "process.h"
-#include "procutils.h"
+#include "process_group.h"
#include "list.h"
//some useful macro
@@ -83,7 +82,7 @@
/* GLOBAL VARIABLES */
//the "family"
-struct process_family pf;
+struct process_group pgroup;
//pid of cpulimit
pid_t cpulimit_pid;
//name of this program (maybe cpulimit...)
@@ -99,35 +98,16 @@ int verbose = 0;
//lazy mode (exits if there is no process)
int lazy = 0;
-static void *memrchr(const void *s, int c, size_t n)
-{
- const unsigned char *start = (const unsigned char*)s;
- const unsigned char *end = (const unsigned char*)s;
-
- end+=n-1;
-
- while(end>=start) {
- if(*end==c)
- return (void *)end;
- else
- end--;
- }
-
- return NULL;
-}
-
//SIGINT and SIGTERM signal handler
static void quit(int sig)
{
//let all the processes continue if stopped
struct list_node *node = NULL;
- for (node=pf.members.first; node!= NULL; node=node->next) {
+ for (node=pgroup.proclist->first; node!= NULL; node=node->next) {
struct process *p = (struct process*)(node->data);
kill(p->pid, SIGCONT);
- process_close(p);
}
- //free all the memory
- cleanup_process_family(&pf);
+ close_process_group(&pgroup);
//fix ^C little problem
printf("\r");
fflush(stdout);
@@ -185,22 +165,7 @@ static int get_ncpu() {
return ncpu;
}
-#ifdef __linux__
-
-#include <sys/vfs.h>
-
-static int check_proc()
-{
- struct statfs mnt;
- if (statfs("/proc", &mnt) < 0)
- return 0;
- if (mnt.f_type!=0x9fa0)
- return 0;
- return 1;
-}
-#endif
-
-void limit_process(pid_t pid, double limit, int ignore_children)
+void limit_process(pid_t pid, double limit, int include_children)
{
//slice of the slot in which the process is allowed to run
struct timespec twork;
@@ -226,39 +191,17 @@ void limit_process(pid_t pid, double limit, int ignore_children)
increase_priority();
//build the family
- create_process_family(&pf, pid);
- if (ignore_children) {
- //delete any process with a different pid than the father
- for (node=pf.members.first; node!=NULL; node=node->next) {
- struct process *proc = (struct process*)(node->data);
- if (proc->pid != pid)
- remove_process_from_family(&pf, proc->pid);
- }
- }
-
- if (!ignore_children && verbose) printf("Members in the family owned by %d: %d\n", pf.father, pf.members.count);
+ init_process_group(&pgroup, pid, include_children);
+
+ if (verbose) printf("Members in the process group owned by %d: %d\n", pgroup.target_pid, pgroup.proclist->count);
//rate at which we are keeping active the processes (range 0-1)
//1 means that the process are using all the twork slice
double workingrate = -1;
while(1) {
- if (!ignore_children && c%10==0) {
- //update the process family (checks only for new members)
- int new_children = update_process_family(&pf);
- if (verbose && new_children) {
- printf("%d new children processes detected (", new_children);
- int j;
- node = pf.members.last;
- for (j=0; j<new_children; j++) {
- printf("%d", ((struct process*)(node->data))->pid);
- if (j<new_children-1) printf(" ");
- node = node->previous;
- }
- printf(")\n");
- }
- }
+ update_process_group(&pgroup);
- if (pf.members.count==0) {
+ if (pgroup.proclist->count==0) {
if (verbose) printf("No more processes.\n");
break;
}
@@ -268,24 +211,12 @@ void limit_process(pid_t pid, double limit, int ignore_children)
double pcpu = -1;
//estimate how much the controlled processes are using the cpu in the working interval
- for (node=pf.members.first; node!=NULL; node=node->next) {
+ for (node = pgroup.proclist->first; node != NULL; node = node->next) {
struct process *proc = (struct process*)(node->data);
- if (proc->is_zombie) {
- //process is zombie, remove it from family
- fprintf(stderr,"Process %d is zombie!\n", proc->pid);
- remove_process_from_family(&pf, proc->pid);
+ if (proc->cpu_usage < 0) {
continue;
}
- if (process_monitor(proc) != 0) {
- //process is dead, remove it from family
- if (verbose) fprintf(stderr,"Process %d dead!\n", proc->pid);
- remove_process_from_family(&pf, proc->pid);
- continue;
- }
- if (proc->cpu_usage<0) {
- continue;
- }
- if (pcpu<0) pcpu = 0;
+ if (pcpu < 0) pcpu = 0;
pcpu += proc->cpu_usage;
}
@@ -294,52 +225,52 @@ void limit_process(pid_t pid, double limit, int ignore_children)
//it's the 1st cycle, initialize workingrate
pcpu = limit;
workingrate = limit;
- twork.tv_nsec = TIME_SLOT*limit*1000;
+ twork.tv_nsec = TIME_SLOT * limit * 1000;
}
else {
//adjust workingrate
workingrate = MIN(workingrate / pcpu * limit, 1);
- twork.tv_nsec = TIME_SLOT*1000*workingrate;
+ twork.tv_nsec = TIME_SLOT * 1000 * workingrate;
}
- tsleep.tv_nsec = TIME_SLOT*1000-twork.tv_nsec;
+ tsleep.tv_nsec = TIME_SLOT * 1000 - twork.tv_nsec;
if (verbose) {
if (c%200==0)
printf("\n%%CPU\twork quantum\tsleep quantum\tactive rate\n");
if (c%10==0 && c>0)
- printf("%0.2lf%%\t%6ld us\t%6ld us\t%0.2lf%%\n",pcpu*100,twork.tv_nsec/1000,tsleep.tv_nsec/1000,workingrate*100);
+ printf("%0.2lf%%\t%6ld us\t%6ld us\t%0.2lf%%\n", pcpu*100, twork.tv_nsec/1000, tsleep.tv_nsec/1000, workingrate*100);
}
//resume processes
- for (node=pf.members.first; node!=NULL; node=node->next) {
+ for (node = pgroup.proclist->first; node != NULL; node = node->next) {
struct process *proc = (struct process*)(node->data);
if (kill(proc->pid,SIGCONT)!=0) {
//process is dead, remove it from family
- if (verbose) fprintf(stderr,"Process %d dead!\n", proc->pid);
- remove_process_from_family(&pf, proc->pid);
+ if (verbose) fprintf(stderr, "Process %d dead!\n", proc->pid);
+ //remove_process_from_family(&pf, proc->pid);
}
}
//now processes are free to run (same working slice for all)
gettimeofday(&startwork, NULL);
- nanosleep(&twork,NULL);
+ nanosleep(&twork, NULL);
gettimeofday(&endwork, NULL);
- workingtime = timediff(&endwork,&startwork);
+ workingtime = timediff(&endwork, &startwork);
- long delay = workingtime-twork.tv_nsec/1000;
+ long delay = workingtime - twork.tv_nsec/1000;
if (c>0 && delay>10000) {
//delay is too much! signal to user?
//fprintf(stderr, "%d %ld us\n", c, delay);
}
if (tsleep.tv_nsec>0) {
- //stop only if tsleep>0, instead it's useless
- for (node=pf.members.first; node!=NULL; node=node->next) {
+ //stop only if tsleep>0
+ for (node = pgroup.proclist->first; node != NULL; node = node->next) {
struct process *proc = (struct process*)(node->data);
if (kill(proc->pid,SIGSTOP)!=0) {
//process is dead, remove it from family
if (verbose) fprintf(stderr,"Process %d dead!\n", proc->pid);
- remove_process_from_family(&pf, proc->pid);
+ //remove_process_from_family(&pf, proc->pid);
}
}
//now the processes are sleeping
@@ -347,7 +278,7 @@ void limit_process(pid_t pid, double limit, int ignore_children)
}
c++;
}
- cleanup_process_family(&pf);
+ close_process_group(&pgroup);
}
int main(int argc, char **argv) {
@@ -361,8 +292,8 @@ int main(int argc, char **argv) {
int ignore_children = 0;
//get program name
- char *p=(char*)memrchr(argv[0],(unsigned int)'/',strlen(argv[0]));
- program_name = p==NULL?argv[0]:(p+1);
+ char *p = (char*)memrchr(argv[0], (unsigned int)'/', strlen(argv[0]));
+ program_name = p==NULL ? argv[0] : (p+1);
//get current pid
cpulimit_pid = getpid();
//get cpu count
@@ -422,12 +353,12 @@ int main(int argc, char **argv) {
}
} while(next_option != -1);
- if (pid_ok && (pid<=1 || pid>=65536)) {
+ if (pid_ok && (pid <= 1 || pid >= 65536)) {
fprintf(stderr,"Error: Invalid value for argument PID\n");
print_usage(stderr, 1);
exit(1);
}
- if (pid!=0) {
+ if (pid != 0) {
lazy = 1;
}
@@ -436,14 +367,14 @@ int main(int argc, char **argv) {
print_usage(stderr, 1);
exit(1);
}
- double limit = perclimit/100.0;
+ double limit = perclimit / 100.0;
if (limit<0 || limit >NCPU) {
fprintf(stderr,"Error: limit must be in the range 0-%d00\n", NCPU);
print_usage(stderr, 1);
exit(1);
}
- int command_mode = optind<argc;
+ int command_mode = optind < argc;
if (exe_ok + pid_ok + command_mode == 0) {
fprintf(stderr,"Error: You must specify one target process, either by name, pid, or command line\n");
print_usage(stderr, 1);
@@ -463,19 +394,12 @@ int main(int argc, char **argv) {
//print the number of available cpu
if (verbose) printf("%d cpu detected\n", NCPU);
-#ifdef __linux__
- if (!check_proc()) {
- fprintf(stderr, "procfs is not mounted!\nAborting\n");
- exit(-2);
- }
-#endif
-
if (command_mode) {
int i;
//executable file
const char *cmd = argv[optind];
//command line arguments
- char **cmd_args = (char**)malloc((argc-optind+1)*sizeof(char*));
+ char **cmd_args = (char**)malloc((argc-optind + 1) * sizeof(char*));
if (cmd_args==NULL) exit(2);
for (i=0; i<argc-optind; i++) {
cmd_args[i] = argv[i+optind];
@@ -494,7 +418,14 @@ int main(int argc, char **argv) {
if (child < 0) {
exit(EXIT_FAILURE);
}
- else if (child > 0) {
+ else if (child == 0) {
+ //target process code
+ int ret = execvp(cmd, cmd_args);
+ //if we are here there was an error, show it
+ perror("Error");
+ exit(ret);
+ }
+ else {
//parent code
free(cmd_args);
int limiter = fork();
@@ -521,13 +452,6 @@ int main(int argc, char **argv) {
exit(0);
}
}
- else {
- //target process code
- int ret = execvp(cmd, cmd_args);
- //if we are here there was an error, show it
- perror("Error");
- exit(ret);
- }
}
while(1) {
@@ -535,7 +459,7 @@ int main(int argc, char **argv) {
pid_t ret = 0;
if (pid_ok) {
//search by pid
- ret = look_for_process_by_pid(pid);
+ ret = find_process_by_pid(pid);
if (ret == 0) {
printf("No process found\n");
}
@@ -545,7 +469,7 @@ int main(int argc, char **argv) {
}
else {
//search by file or path name
- ret = look_for_process_by_name(exe);
+ ret = find_process_by_name(exe);
if (ret == 0) {
printf("No process found\n");
}
@@ -558,7 +482,7 @@ int main(int argc, char **argv) {
}
if (ret > 0) {
if (ret == cpulimit_pid) {
- printf("Process %d is cpulimit itself! Aborting to avoid deadlock\n", ret);
+ printf("Target process %d is cpulimit itself! Aborting because it makes no sense\n", ret);
exit(1);
}
printf("Process %d found\n", pid);
Un proyecto texto-plano.xyz