-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
196 lines (177 loc) · 6.3 KB
/
main.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
/**
* CS 537 Programming Assignment 4 (Fall 2020)
* @authors Michael Noguera and Julien de Castelnau
* @date 11/22/2020
* @file main.c
* @brief parses command line arguments & coordinates main simulation loop
* @version FINAL
*/
#define _GNU_SOURCE
#include "intervaltree.h"
#include "memory.h"
#include "process.h"
#include "replace.h"
#include "simulator.h"
#include "stat.h"
#include "trace_parser.h"
#include <errno.h>
#include <getopt.h>
#include <string.h>
/**
* Parses args, validates memory size and page size
* @param[in] argc from main
* @param[in] argv from main
* @param[out] memsize total size of memory in bytes
* @param[out] pagesize size of one page in bytes
* @param[out] filename provided trace file name
* @returns values via the parameter fields labeled "out", or exits with an error if invalid input provided.
* */
inline static void parseArgs(int argc, char** argv, int* memsize, int* pagesize,
char** filename) {
// use getopt to handle input
int opt = 0;
while ((opt = getopt(argc, argv, "-p:m:h")) != -1) {
switch ((char)opt) {
case 'm':
assert(optarg != NULL);
errno = 0;
*memsize = (int)strtol(optarg, NULL, 10);
if (errno != 0) {
fprintf(stderr,
"Error parsing -m, must be a valid integer.\n");
exit(EXIT_FAILURE);
}
break;
case 'p':
assert(optarg != NULL);
errno = 0;
*pagesize = (int)strtol(optarg, NULL, 10);
if (errno != 0) {
fprintf(stderr,
"Error parsing -p, must be a valid integer.\n");
exit(EXIT_FAILURE);
}
break;
case 'h':
// help message printed by '-h'
printf("Usage:\n");
printf(
" ./pfsim-lru [-m real memory size] [-p page size] "
"<tracefile>\n");
printf(
" ./pfsim-fifo [-m real memory size] [-p page size] "
"<tracefile>\n");
printf(
" ./pfsim-clock [-m real memory size] [-p page size] "
"<tracefile>\n");
printf(
" ./pfsim-random [-m real memory size] [-p page size] "
"<tracefile>\n");
printf("\nOptions:\n");
printf(" -h\t");
printf("Prints this message.\n");
printf(" -m\t");
printf(
"Amount of physical memory avaliable, in megabytes. "
"Defaults to 1 MB.\n");
printf(" -p\t");
printf(
"Page size as a number of bytes, must be a power of two. "
"Defaults to 4096 bytes.\n");
exit(EXIT_FAILURE);
break;
case '?':
// error message directs user to call '-h'
if (argv != NULL && argv[0] != NULL) {
printf("Try '%s -h' for more information.\n",
basename(argv[0]));
} else {
fprintf(stderr, "Could not recognize executable name.");
printf("Specify '-h' for more information.\n");
}
exit(EXIT_FAILURE);
break;
default:
*filename = optarg;
break;
}
}
// validate page size
if (*pagesize && *pagesize % 2 != 0) {
fprintf(stderr, "ERROR: page size must be a power of two\n");
exit(EXIT_FAILURE);
} else if (*pagesize < 0) {
fprintf(stderr, "ERROR: page size must be positive\n");
exit(EXIT_FAILURE);
} else if (*pagesize == 0) {
fprintf(
stderr,
"\x1B[2mWARN: page size (-p) not specified, defaulting to 4096 bytes\x1B[0m\n");
*pagesize = 4096;
}
// validate and calculate memory size
if (*memsize < 0) {
fprintf(stderr, "ERROR: memory size must be positive\n");
exit(EXIT_FAILURE);
} else if (*memsize == 0) {
fprintf(stderr,
"\x1B[2mWARN: memory size (-m) not specified, defaulting to 1 MB\x1B[0m\n");
*memsize = 1;
}
*memsize *= 0x100000; // MB -> bytes
// make sure that pages fit in memory
if (*pagesize > *memsize) {
fprintf(stderr,
"ERROR: specified page size is larger than memory size\n");
exit(EXIT_FAILURE);
}
// filename is required
if (*filename == NULL) {
fprintf(stderr,
"ERROR: must specify valid file name on command line\n");
exit(EXIT_FAILURE);
}
}
/**
* Main method, coordinates simulation
* @param argc # of cmdline args
* @param argv cmdline args
* @see simulator.c for main loop of simulation
* @return EXIT_SUCCESS on success and EXIT_FAILURE on failure
*/
int main(int argc, char** argv) {
// 1. Parse command line arguments
int memsize = 0;
int pagesize = 0;
char* filename = NULL;
parseArgs(argc, argv, &memsize, &pagesize, &filename);
assert(memsize > 0);
assert(pagesize > 0);
assert(filename != NULL);
int numberOfPhysicalPages = memsize / pagesize;
assert(numberOfPhysicalPages > 0);
// 2. Open tracefile
FILE* tracefile = NULL;
tracefile = fopen(filename, "r");
if (tracefile == NULL) {
fprintf(stderr, "ERROR: error opening specified trace file\n");
exit(EXIT_FAILURE);
}
printf("\x1B[1m\x1B[7m%s\x1B[0m\n"," PARAMETERS ");
printf(" \x1B[1m%s\x1B[0m\n", filename);
printf(" page size: %i B\n", pagesize);
printf(" memory size: %i MB\n", memsize/0x100000);
printf(" = %i pages\n", numberOfPhysicalPages);
// 3. Initialize helper modules
Memory_init(numberOfPhysicalPages);
Replace_initReplacementModule(numberOfPhysicalPages);
Stat_init();
ProcessQueues_init();
// 4. Read "first pass", ennumerating pids and building interval tree
first_pass(tracefile);
// 5. Run the simulation
unsigned long exit_time = Simulator_runSimulation(tracefile);
// 6. Output results
Stat_printStats(exit_time);
return EXIT_SUCCESS;
}