-
Notifications
You must be signed in to change notification settings - Fork 0
/
state_printer.c
397 lines (320 loc) · 14.4 KB
/
state_printer.c
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
/****************************************************************************
state_printer.c
Read Appendix D - output generation - in order to understand how
to use these routines.
The first portion of this file is SCHEDULER_PRINTER.
Revision History:
1.1 December 1990 Initial release
2.1 April 2001 Added memory_printer
2.2 July 2002 Make code appropriate for undergrads.
3.0 August 2004: Modified to support memory mapped IO
3.60 August 2012: Used student supplied code to add support
for Mac machines
4.10 December 2013: Remove SP_setup_file and SP_setup_action
Roll SP_ACTION_MODE into the routine SP_setup
Define some new states.
****************************************************************************/
#include "global.h"
#include "syscalls.h"
#include "z502.h"
#include "protos.h"
#include "stdio.h"
#include "string.h"
#if defined LINUX || defined MAC
#include <unistd.h>
#endif
INT16 SP_target_pid = -1;
INT16 SP_pid_states[SP_NUMBER_OF_STATES][SP_MAX_NUMBER_OF_PIDS];
INT16 SP_number_of_pids[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
INT32 SP_time = -1;
char SP_action[ SP_LENGTH_OF_ACTION + 1 ] = { '\0' };
FILE *SP_file_ptr;
char *mode_name[] = {"NEW:", "RUNNING:", "READY :",
"SUS-PRC:", "SUS-TMR:", "SUS-DSK:", "TERM'D: " };
//
// This string is printed out when requested as the header
#define SP_HEADER_STRING \
" Time Target Action Run New Done State Populations \n"
short SP_do_output( char *text ); // Prototype
/****************************************************************************
SP_setup_action
This routine allows the caller to set up a string indicating
the action that will be performed.
****************************************************************************/
short SP_setup_action( INT16 mode, char *data ) {
if ( mode != SP_ACTION_MODE ) {
printf( "Illegal mode specified in SP_setup_action.\n" );
return 1;
}
if ( strlen( data) > SP_LENGTH_OF_ACTION ) {
printf( "Too many characters in string entered in SP_setup.\n" );
return 1;
}
(void)strncpy( SP_action, data, SP_LENGTH_OF_ACTION);
return 0;
} // End of SP_setup_action
/****************************************************************************
SP_setup
This routine allows the caller to set up all the information
that will eventually be printed.
NOTE: The meaning of data passed in here depends on the mode specified.
****************************************************************************/
short SP_setup( INT16 mode, INT32 data ) {
INT16 index;
switch( mode ) {
case SP_ACTION_MODE:
printf("Illegal use of SP_ACTION_MODE for SP_setup\n");
break;
case SP_TIME_MODE:
if ( data < 0 ) {
printf( "Negative TIME entered in SP_setup.\n" );
return 1;
}
SP_time = (INT32)data % 1000000L;
break;
case SP_TARGET_MODE:
if ( data < 0 || data > 99 ) {
printf( "Expected PID not in range 0 - 99 in SP_setup.\n" );
return 1;
}
SP_target_pid = (INT16)data;
break;
case SP_NEW_MODE:
case SP_RUNNING_MODE:
case SP_READY_MODE:
case SP_PROCESS_SUSPENDED_MODE:
case SP_TIMER_SUSPENDED_MODE:
case SP_DISK_SUSPENDED_MODE:
case SP_TERMINATED_MODE:
if ( data < 0 || data > 99 ) {
printf( "Expected PID not in range 0 - 99 in SP_setup.\n" );
return 1;
}
index = SP_number_of_pids[mode - SP_STATE_MODE_START];
if ( index >= SP_MAX_NUMBER_OF_PIDS ) {
printf( "Too many (more than %d) PIDs ", SP_MAX_NUMBER_OF_PIDS );
printf( "for this mode entered in SP_setup.\n" );
return 1;
}
SP_pid_states[mode - SP_STATE_MODE_START][index] = (INT16)data;
SP_number_of_pids[ mode - SP_STATE_MODE_START ]++;
break;
default:
printf( "ERROR - illegal mode used in SP_setup\n" );
}
return 0;
} /* End of SP_setup */
/****************************************************************************
SP_print_line
SP_print_line prints out all the data that has been sent to the
routine via various SP_setup commands. After the print is complete,
the setup data is deleted.
****************************************************************************/
short SP_print_line( void ) {
char output_line[400];
char temp[12];
INT16 index;
INT16 ind;
INT16 pos;
BOOL mode_print_done;
INT32 current_time;
// print out the header
SP_do_output( SP_HEADER_STRING );
sprintf( output_line, "%5d", SP_time ); /* Time */
if ( SP_time == -1 ) {
MEM_READ( Z502ClockStatus, ¤t_time );
sprintf( output_line, "%5d", current_time % 100000 );
}
sprintf( temp, " %3d ", SP_target_pid ); /* Target Pid */
if ( SP_target_pid < 0 )
sprintf( temp, "%s", " " );
(void)strcat( output_line, temp );
sprintf( temp, " %8s", SP_action ); /* Action */
(void)strcat( output_line, temp );
index = SP_RUNNING_MODE - SP_STATE_MODE_START; /* Running proc.*/
if ( SP_number_of_pids[ index ] > 0 )
sprintf( temp, " %3d", SP_pid_states[index][0] );
else
sprintf( temp, " " );
(void)strcat( output_line, temp );
index = SP_NEW_MODE - SP_STATE_MODE_START; /* New proc.*/
if ( SP_number_of_pids[ index ] > 0 )
sprintf( temp, " %3d ", SP_pid_states[index][0] );
else
sprintf( temp, " " );
(void)strcat( output_line, temp );
index = SP_TERMINATED_MODE - SP_STATE_MODE_START; /* Done proc.*/
if ( SP_number_of_pids[ index ] > 0 )
sprintf( temp, "%3d ", SP_pid_states[index][0] );
else
sprintf( temp, " " );
(void)strcat( output_line, temp );
SP_do_output( output_line );
strcpy( output_line, "" );
mode_print_done = FALSE;
for ( ind = SP_READY_MODE; ind <= SP_TERMINATED_MODE; ind++ ) {
index = ind - SP_STATE_MODE_START;
if ( SP_number_of_pids[ index ] > 0 ) {
(void)strcat( output_line, mode_name[ index ] );
for (pos = 0; pos < SP_number_of_pids[index]; pos++ ) {
sprintf( temp, " %d", SP_pid_states[index][pos] );
(void)strcat( output_line, temp );
}
mode_print_done = TRUE;
(void)strcat( output_line, "\n" );
SP_do_output( output_line );
strcpy( output_line, " " );
} /* End of if */
} /* End of for*/
if ( mode_print_done == FALSE )
SP_do_output( "\n" );
/* Initialize everything */
SP_time = -1;
strcpy( SP_action, "" );
SP_target_pid = -1;
for ( index = 0 ; index <= SP_NUMBER_OF_STATES; index++ )
SP_number_of_pids[ index ] = 0;
return 0;
} /* End of SP_print_line */
/****************************************************************************
SP_do_output
This little routine simply directs output Cto the screen.
****************************************************************************/
short SP_do_output( char *text ) {
printf( "%s", text );
return 0;
} /* End of SP_do_output */
/****************************************************************************
Read Appendix D - output generation - in order to understand how
to use these routines.
The second portion of this file is MEMORY_PRINTER.
This is the definition of the table we will produce here.
A Frame 0000000000111111111122222222223333333333444444444455555555556666
B Frame 0123456789012345678901234567890123456789012345678901234567890123
C PID 0000000001111
D VPN 0000000110000
E VPN 0000111000000
F VPN 0000000220000
G VPN 0123567230123
H VMR 7775555447777
The rows mean the following:
A - B: The frame number. Note how the first column is "00" and the
last column is "63".
C: The Process ID of the process having it's virtual page in the
frame table.
D - G: The virtual page number of the process that's mapped to that
frame. Again the number (from 0 to 1023 possible) is written
vertically.
H: The state of the page. Valid = 4, Modified = 2,
Referenced = 1. These are OR'd (or added) together.
Example: The page in frame 6 is virtual page 107 in process 0. That
page has been made valid and has been referenced.
****************************************************************************/
/****************************************************************************
Here's the structure we're going to fill in containing all the info to
be printed.
****************************************************************************/
typedef struct {
INT32 contains_data;
INT32 pid;
INT32 logical_page;
INT32 state;
}MP_FRAME_ENTRY;
typedef struct {
MP_FRAME_ENTRY entry[PHYS_MEM_PGS];
}MP_FRAME_TABLE;
MP_FRAME_TABLE MP_ft;
void MP_initialize( void );
/****************************************************************************
MP_setup
This routine allows the caller to set up all the information
that will eventually be printed.
The type of data passed in here depends on the mode specified.
****************************************************************************/
short MP_setup( INT32 frame, INT32 pid, INT32 logical_page, INT32 state ) {
short static first_time = TRUE;
if ( first_time == TRUE ) {
MP_initialize( );
first_time = FALSE;
}
if ( frame < 0 || frame >= PHYS_MEM_PGS ) {
printf( "Frame value %d is not in the range 0 - %d in MP_setup\n",
frame, PHYS_MEM_PGS - 1 );
return 1;
}
if ( pid < 0 || pid > 9 ) {
printf( "Input PID %d not in range 0 - 9 in MP_setup.\n", pid );
return 1;
}
if ( logical_page < 0 || logical_page >= VIRTUAL_MEM_PAGES ) {
printf( "Input logical page (%d) not in range 0 - %d in MP_setup.\n",
logical_page, VIRTUAL_MEM_PAGES - 1 );
return 1;
}
if ( state < 0 || state > 7 ) {
printf( "Input state %d not in range 0 - 7 in MP_setup\n", state );
return 1;
}
if ( logical_page > 0 || pid > 0 || state > 0 ) { // Check there's data 2014
MP_ft.entry[frame].contains_data = TRUE;
MP_ft.entry[frame].logical_page = logical_page;
MP_ft.entry[frame].pid = pid;
MP_ft.entry[frame].state = state;
}
return 0;
}
/****************************************************************************
MP_print_line
Outputs everything we know about the state of the physical memory.
****************************************************************************/
short MP_print_line( void ) {
INT32 index;
INT32 temp;
char output_line3[PHYS_MEM_PGS+5];
char output_line4[PHYS_MEM_PGS+5];
char output_line5[PHYS_MEM_PGS+5];
char output_line6[PHYS_MEM_PGS+5];
char output_line7[PHYS_MEM_PGS+5];
char output_line8[PHYS_MEM_PGS+5];
// Header Line
SP_do_output("\n PHYSICAL MEMORY STATE\n");
// First Line
SP_do_output("Frame 0000000000111111111122222222223333333333444444444455555555556666\n");
// Second Line
SP_do_output("Frame 0123456789012345678901234567890123456789012345678901234567890123\n");
// Third - Eighth Line
strcpy( output_line3, " \n" );
strcpy( output_line4, " \n" );
strcpy( output_line5, " \n" );
strcpy( output_line6, " \n" );
strcpy( output_line7, " \n" );
strcpy( output_line8, " \n" );
for ( index = 0; index < PHYS_MEM_PGS; index++ ) {
if ( MP_ft.entry[index].contains_data == TRUE ) {
output_line3[index] = (char)(MP_ft.entry[index].pid + 48);
temp = MP_ft.entry[index].logical_page;
output_line4[index] = (char)(temp / 1000 ) +48;
output_line5[index] = (char)((temp / 100 ) % 10) +48;
output_line6[index] = (char)((temp / 10 ) % 10) +48;
output_line7[index] = (char)((temp ) % 10) +48;
output_line8[index] = (char)MP_ft.entry[index].state +48;
}
}
SP_do_output( "PID " ); SP_do_output( output_line3 );
SP_do_output( "VPN " ); SP_do_output( output_line4 );
SP_do_output( "VPN " ); SP_do_output( output_line5 );
SP_do_output( "VPN " ); SP_do_output( output_line6 );
SP_do_output( "VPN " ); SP_do_output( output_line7 );
SP_do_output( "VMR " ); SP_do_output( output_line8 );
MP_initialize( );
return 0;
}
/****************************************************************************
MP_initialize
Simply zero out the structure used for holding data.
****************************************************************************/
void MP_initialize( void ) {
short index;
for ( index = 0; index < PHYS_MEM_PGS; index++ )
MP_ft.entry[index].contains_data = FALSE;
}