Release coccinelle-0.1.4
[bpt/coccinelle.git] / tools / distributed / spatch_linux.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 #include <sys/ipc.h>
6 #include <sys/sem.h>
7 #include <errno.h>
8 #include <sys/time.h>
9 #include <signal.h>
10 #include <string.h>
11
12 #define MAX 9
13
14 #define DONE_SEM 0 // index of the semaphore on which to wait for children
15
16 #ifndef HOME
17 #define HOME "/home/julia/coccinelle/tools/distributed/"
18 #endif
19
20 int sem;
21
22 void inc_sem(int sem, int sem_num, int inc) {
23 struct sembuf sops;
24 sops.sem_num = sem_num;
25 sops.sem_op = inc;
26 sops.sem_flg = 0;
27 semop(sem,&sops,1);
28 }
29
30 void dec_sem(int sem, int sem_num) {
31 struct sembuf sops;
32 sops.sem_num = sem_num;
33 sops.sem_op = -1;
34 sops.sem_flg = 0;
35 semop(sem,&sops,1);
36 }
37
38 void wait_sem(int sem, int sem_num) {
39 struct sembuf sops;
40 int err;
41 sops.sem_num = sem_num;
42 sops.sem_op = 0;
43 sops.sem_flg = 0;
44 err = semop(sem,&sops,1);
45 if (err < 0) {printf("error in %d\n",sem);perror("wait_sem");}
46 }
47
48 void exit_sighandler(int x) {
49 semctl(sem,DONE_SEM,IPC_RMID);
50 exit(0);
51 }
52
53 void do_child(int sem, int id, unsigned int argc, char **argv, int max,
54 char *script) {
55 int pid,status;
56 if (!(pid=fork())) {
57 // child
58 int i;
59 char **new_args = malloc(sizeof(char*) * (argc + 5));
60 char string1[50],string2[50];
61 for(i=1; i!=argc; i++) {
62 new_args[i+4] = argv[i];
63 }
64 new_args[i+4] = NULL;
65 new_args[0] = "nothing";
66 new_args[1] = new_args[5]; // cocci file must be first
67 new_args[2] = "-index";
68 sprintf(string1, "%d", id);
69 new_args[3] = string1; // processor number must be third
70 new_args[4] = "-max";
71 sprintf(string2, "%d", max);
72 new_args[5] = string2;
73 execvp(script,new_args);
74 printf("tried to execute %s\n",HOME "spatch_linux_script");
75 perror("exec failure");
76 exit(0);
77 }
78 wait(&status);
79 dec_sem(sem,DONE_SEM); // indicate that this child is done
80 }
81
82 void cleanup(char **argv) {
83 char **new_args = malloc(sizeof(char*) * 3);
84 new_args[0] = "nothing";
85 new_args[1] = argv[1];
86 new_args[2] = NULL;
87 printf ("doing cleanup on %s\n",argv[1]);
88 execvp(HOME "cleanup_script",new_args);
89 }
90
91 int main(unsigned int argc, char **argv) {
92 int pid, i, start=0, max;
93 char script[150];
94 // initialize the semaphore
95 sem = semget(0,1/* only one sem */,(IPC_CREAT|0666));
96 if (sem < 0) { perror("semget"); exit(0); }
97 // set up signal handlers so we can delete the semaphore
98 signal(SIGTERM,exit_sighandler); // kill
99 signal(SIGHUP,exit_sighandler); // kill -HUP / xterm closed
100 signal(SIGINT,exit_sighandler); // Interrupt from keyboard
101 signal(SIGQUIT,exit_sighandler); // Quit from keyboard
102 // interpret the arguments
103 max = MAX;
104 if (!strcmp(argv[1],"-processes")) {max = atoi(argv[2]); start = 2;}
105 if (!strcmp(argv[1],"-script")) {
106 strcpy(script,HOME);
107 strcat(script,argv[2]);
108 start = 2;
109 } else strcpy(script,HOME "spatch_linux_script");
110 if (!strcmp(argv[1],"--help")) {
111 printf("spatch_linux [-processes n] foo.cocci ...\n");
112 exit (0);
113 }
114
115 inc_sem(sem,0,max);
116
117 // run the child processes
118 for(i=0;i!=max;i++) {
119 if (!(pid=fork())) {
120 // child
121 do_child(sem,i,argc-start,&argv[start],max,script);
122 exit(0);
123 }
124 }
125
126 wait_sem(sem,DONE_SEM); // wait for the children to end
127 int err = semctl(sem,DONE_SEM,IPC_RMID);
128 if (err < 0) perror ("couldn't remove");
129 cleanup(&argv[start]);
130 }