1 #include <stdio.h>
2 #include <pthread.h>
3 
4 // simulated system
5 struct app {
6   long PC;
7   bool simulating;
8 } sys;
9 
10 // locks
11 pthread_mutex_t simulation_lock;
12 pthread_mutex_t application_lock;
13 
14 
15 pthread_t sim_th;
16 
17 struct sim_args {
18   long int steps2go;
19 };
20 
21 void
step_start(void)22 step_start(void)
23 {
24   pthread_mutex_lock(&application_lock);
25 }
26 
27 void
step_end(void)28 step_end(void)
29 {
30   pthread_mutex_unlock(&application_lock);
31 }
32 
33 void *
sim_thread(void * arg)34 sim_thread(void *arg)
35 {
36   printf("Sim: thread started, now trying lock...\n");
37   pthread_mutex_lock(&simulation_lock);
38   printf("Sim: got lock, now run\n");
39   struct sim_args *args= (struct sim_args *)arg;
40   bool done= 0;
41   long steps2go= args->steps2go, steps= steps2go;
42   while (!done)
43     {
44       step_start();
45       sys.PC++;
46       if (steps2go > 0)
47 	{
48 	  steps--;
49 	  if (done= steps == 0)
50 	    printf("Sim: %s steps done\n", steps2go);
51 	}
52       else if (steps2go == 0)
53 	{
54 	}
55       /*else if (steps2go < 0)
56 	{*/
57 	  if (done= !sys.simulating)
58 	    printf("Sim: requested to stop\n");
59 	  /*}*/
60       step_end();
61     }
62   printf("Sim: finished, releasing lock...\n");
63   pthread_mutex_unlock(&simulation_lock);
64   printf("Sim: done\n");
65   return(NULL);
66 }
67 
68 
69 void
start_command(void)70 start_command(void)
71 {
72   pthread_mutex_lock(&application_lock);
73 }
74 
75 void
end_command(void)76 end_command(void)
77 {
78   pthread_mutex_unlock(&application_lock);
79 }
80 
81 
82 void
g_cmd(FILE * fin,FILE * fout)83 g_cmd(FILE *fin, FILE *fout)
84 {
85   start_command();
86   fprintf(fout, "PC=%ld, simulating=%d\n", sys.PC, sys.simulating);
87   end_command();
88 }
89 
90 void
s_cmd(FILE * fin,FILE * fout)91 s_cmd(FILE *fin, FILE *fout)
92 {
93   start_command();
94   fscanf(fin, " %ld", &sys.PC);
95   fprintf(fout, "PC=%ld\n", sys.PC);
96   end_command();
97 }
98 
99 void
start_simulation(int steps)100 start_simulation(int steps)
101 {
102   struct sim_args sargs;
103   sargs.steps2go= steps;
104   sys.simulating= 1;
105   pthread_attr_t ta;
106   pthread_attr_init(&ta);
107   pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
108   pthread_create(&sim_th, &ta, sim_thread, &sargs);
109   pthread_attr_destroy(&ta);
110 }
111 
112 void
r_cmd(FILE * fin,FILE * fout)113 r_cmd(FILE *fin, FILE *fout)
114 {
115   start_command();
116   if (pthread_mutex_trylock(&simulation_lock) != 0)
117     {
118       fprintf(fout, "Simulation already runing\n");
119     }
120   else
121     {
122       fprintf(fout, "Run from PC=%ld\n", sys.PC);
123       start_simulation(-1);
124       pthread_mutex_unlock(&simulation_lock);
125     }
126   end_command();
127 }
128 
129 void
S_cmd(FILE * fin,FILE * fout)130 S_cmd(FILE *fin, FILE *fout)
131 {
132   fprintf(fout, "Trying to get app lock...\n");
133   start_command();
134   fprintf(fout, "OK, lock is ours, set stopper flag...\n");
135   sys.simulating= 0;
136   fprintf(fout, "Release lock, to give chance of stop\n");
137   end_command();
138   fprintf(fout, "Wait for stop...\n");
139   pthread_mutex_lock(&simulation_lock);
140   fprintf(fout, "We got sim lock, so it stopped\n");
141   pthread_mutex_unlock(&simulation_lock);
142   fprintf(fout, "Stopped at PC=%ld\n", sys.PC);
143 }
144 
145 
146 struct input_args {
147   int nr;
148   char *fin_name;
149   char *fout_name;
150 };
151 
152 void *
input_thread(void * arg)153 input_thread(void *arg)
154 {
155   struct input_args *args= (struct input_args *)arg;
156   FILE *fin, *fout;
157   if (args->fin_name)
158     fin= fopen(args->fin_name, "r");
159   else
160     fin= stdin;
161   if (args->fout_name)
162     fout= fopen(args->fout_name, "w");
163   else
164     fout= stdout;
165   bool done= 0;
166   while (!done)
167     {
168       char cmd[100];
169       fprintf(fout, "%d> ", args->nr); fflush(fout);
170       fscanf(fin, " %99s", &cmd[0]);
171       fprintf(fout, "%d Got command: %c\n", args->nr, cmd[0]);
172       switch (cmd[0])
173 	{
174 	case 'q':
175 	  done= 1;
176 	  break;
177 	case 'g':
178 	  g_cmd(fin, fout);
179 	  break;
180 	case 's':
181 	  s_cmd(fin, fout);
182 	  break;
183 	case 'r':
184 	  r_cmd(fin, fout);
185 	  break;
186 	case 'S':
187 	  S_cmd(fin, fout);
188 	  break;
189 	default:
190 	  fprintf(fout, "%d Unknown command\n", args->nr);
191 	  break;
192 	}
193     }
194   fprintf(fout, "%d Console finished\n", args->nr);
195   fclose(fin);
196   fclose(fout);
197   return(NULL);
198 }
199 
200 
201 int
main(int argc,char * argv[])202 main(int argc, char *argv[])
203 {
204   pthread_t input_th[3];
205   int threads= 0;
206 
207   pthread_mutex_init(&simulation_lock, NULL);
208   pthread_mutex_init(&application_lock, NULL);
209 
210   struct input_args iargs= { 0, NULL, NULL };
211   pthread_create(&input_th[0], NULL, input_thread, &iargs);
212   threads++;
213   if (argc > 1)
214     {
215       struct input_args iargs= { 1, argv[1], argv[1] };
216       pthread_create(&input_th[1], NULL, input_thread, &iargs);
217       threads++;
218     }
219   if (argc > 2)
220     {
221       struct input_args iargs= { 2, argv[2], argv[2] };
222       pthread_create(&input_th[2], NULL, input_thread, &iargs);
223       threads++;
224     }
225   int i;
226   for (i= 0; i < threads; i++)
227     {
228       void *ret;
229       pthread_join(input_th[i], &ret);
230     }
231   return(0);
232 }
233