Browse Source

Merge remote-tracking branch 'origin/hw7' into hw7

Lorenz 7 years ago
parent
commit
31528a103f

+ 22
- 2
hw7/simu1/ANSWERS.md View File

17
 
17
 
18
 Hier wird der Lock durch das Vertauschen des Wertes in `mutex` mit dem Register `ax` gesetzt. Aufgehoben wird der Lock, in dem eine `0` in die Mutex-Variable (`mutex`) geschrieben wird.
18
 Hier wird der Lock durch das Vertauschen des Wertes in `mutex` mit dem Register `ax` gesetzt. Aufgehoben wird der Lock, in dem eine `0` in die Mutex-Variable (`mutex`) geschrieben wird.
19
 
19
 
20
-1. Das Programm liefert nun immer den erwarteten Wert. Sowohl mit `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -i 1 -a ax=40:bx=40,ax=40:bx=40` als auch mit nur `-i 1000` steht am Ende der Wert `80` in `count`.
20
+1. Das Programm liefert nun immer den erwarteten Wert. Sowohl mit `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -i 1 -a bx=40,bx=40` als auch mit nur `-i 1000` steht am Ende der Wert `80` in `count`.
21
 
21
 
22
-2. Die mit der Flag `-P` ausgeführten Tests laufen fehlerfrei. Beispielsweise liefern `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -a ax=5:bx=5,ax=5:bx=5 -P 0011` und `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -a ax=5:bx=5,ax=5:bx=5 -P 001000000000001` beide das erwartete Ergebnis (`10`).
22
+### `peterson.s`
23
+
24
+1. Trotz unterschiedlicher Interruptfrequenzen (`-i 1`, `-i 5`, `-i 10`, `-i 20`...) funktioniert der Code fehlerfrei.
25
+
26
+2. Mit beispielsweise `./x86.py -p peterson.s -M count,flag,turn -R ax,bx,cx,fx -a ax=5:bx=0,ax=5:bx=1 -P 11111111000000001000111111111111111` lassen sich mögliche Race Conditions ausschließen, da zwischen dem Testen auf einen Wert und dem zugehörigen Sprung jeweils ein Interrupt stattfindet. Das Endergebnis bleibt davon jedoch unbeeinflusst, was auf fehlerfreien Code schließen lässt.
27
+
28
+### `ticket.s`
29
+
30
+1. Die Wartezeit der Threads ist abhängig von der Interrupt-Häufigkeit. Wenn nur selten ein Interrupt stattfindet, beispielsweise mit `-i 10000`, hängen die einzelnen Threads sehr lange in der `.aquire`-Schleife fest.
31
+
32
+2. Eine größere Threadzahl macht im Gegensatz zur Interrupthäufigkeit keinen Unterschied. Die einzelnen Threads warten zwar dennoch länger, das liegt jedoch daran, dass mehr Tickets vergeben wurden und somit die Wartezeit auch höher ist.
33
+
34
+### `yield.s`
35
+
36
+1. Beim Aufruf von `./x86.py -p test-and-set.s -M mutex,count -R ax,bx -a ax=5:bx=5,ax=5:bx=5` bzw. `./x86.py -p yield.s -M mutex,count -R ax,bx -a ax=5:bx=5,ax=5:bx=5` ist der Unterschied deutlich zu merken. Der zweite Thread hängt in `test-and-set.s` in einer Schleife beim holen des Locks, und loopt bis zum nächsten Interrupt. `yield.s` tut hier was es soll, und spart somit ca. 50 Zyklen (bzw. etwas weniger als die Interruptrate). Die Einsparung von Zyklen tritt immer dann auf, wenn Thread 1 den Lock hat, dann ein Interrupt kommt und Thread 2 auf den Lock warten muss. Mit `test-and-set.s` wird in diesem Fall ewig geloopt, mit `yield.s` wird die CPU direkt wieder für den ersten Thread freigegeben.
37
+
38
+### `test-and-test-and-set.s`
39
+
40
+1. Dieser Lock tut dasselbe wie in `test-and-set.s`, nur wird beim holen des Locks ein zweiter Test durchgeführt.
41
+
42
+2. Im Vergleich mit `test-and-set.s` muss mit dieser Konfiguration kein atomarer Tausch der Werte in `%ax` und `mutex` ausgeführt werden, wenn der mutex nicht sowieso frei ist. Nur wenn der mutex auch verfügbar ist, wird dieser Tausch durchgeführt.

+ 2
- 1
hw7/task1/src/hash256.rs View File

1
 use hasher_sha256::{Hasher, HashResult};
1
 use hasher_sha256::{Hasher, HashResult};
2
 use hasher_sha256::Sha256;
2
 use hasher_sha256::Sha256;
3
 
3
 
4
-
4
+/// Dieser Datentyp beschreibt die Lösung des Hashverfahrens.
5
 pub struct Solution {
5
 pub struct Solution {
6
     pub number: usize,
6
     pub number: usize,
7
     pub hash: String,
7
     pub hash: String,
8
 }
8
 }
9
 
9
 
10
+/// `verify_product` dient der Verifikation eines gefundenen Hashes.
10
 pub fn verify_product(base: usize, number: usize, difficulty: &String) -> Option<Solution> {
11
 pub fn verify_product(base: usize, number: usize, difficulty: &String) -> Option<Solution> {
11
     let sol = base * number;
12
     let sol = base * number;
12
     let input = sol.to_string();
13
     let input = sol.to_string();

+ 2
- 0
hw7/task1/src/main.rs View File

7
 mod hasher_sha256;
7
 mod hasher_sha256;
8
 mod hash256;
8
 mod hash256;
9
 
9
 
10
+/// Hauptfunktion zum Starten des Hashers.
10
 pub fn main() {
11
 pub fn main() {
11
     let matches = create_app().get_matches();
12
     let matches = create_app().get_matches();
12
     let base = matches.value_of("base").unwrap_or("1");
13
     let base = matches.value_of("base").unwrap_or("1");
54
     };
55
     };
55
 }
56
 }
56
 
57
 
58
+/// Diese Funktion dient der Konfiguration der App mit dem Paket **Clap**.
57
 fn create_app<'a, 'b>() -> App<'a, 'b> {
59
 fn create_app<'a, 'b>() -> App<'a, 'b> {
58
     App::new("Hash256")
60
     App::new("Hash256")
59
         .version("1.0")
61
         .version("1.0")

+ 7
- 0
hw7/task2/src/errortype.rs View File

1
+/// Dieser Datentyp beschreibt die in der Shell auftretenden Fehler.
2
+#[derive(Debug, PartialEq)]
3
+pub enum ErrorType {
4
+    PathError,
5
+    BrokenPipeError,
6
+    ForkError,
7
+}

+ 42
- 46
hw7/task2/src/lib.rs View File

3
 use std::io::{BufRead, Write};
3
 use std::io::{BufRead, Write};
4
 use std::str::FromStr;
4
 use std::str::FromStr;
5
 use std::env;
5
 use std::env;
6
-use std::str::Split;
7
-use std::os::unix::io::RawFd;
8
 use std::ffi::{OsString, CString};
6
 use std::ffi::{OsString, CString};
9
 use nix::unistd::ForkResult::{Child, Parent};
7
 use nix::unistd::ForkResult::{Child, Parent};
10
-use nix::sys::wait::{wait, WaitStatus};
11
-use nix::unistd::dup2;
12
-use nix::unistd::close;
13
-use nix::unistd::{execvp, fork, pipe, read, write};
8
+use nix::sys::wait::wait;
9
+use nix::unistd::{dup2, close, execvp, fork, pipe};
14
 
10
 
15
-mod shellerror;
11
+mod errortype;
16
 
12
 
17
-use shellerror::ShellError;
13
+use errortype::ErrorType;
18
 
14
 
19
 #[derive(PartialEq, Debug)]
15
 #[derive(PartialEq, Debug)]
20
 pub enum Command {
16
 pub enum Command {
25
 }
21
 }
26
 
22
 
27
 impl FromStr for Command {
23
 impl FromStr for Command {
28
-    type Err = ShellError;
24
+    type Err = ErrorType;
29
     fn from_str(s: &str) -> Result<Self, Self::Err> {
25
     fn from_str(s: &str) -> Result<Self, Self::Err> {
30
 
26
 
31
         let mut parts = s.split_whitespace();
27
         let mut parts = s.split_whitespace();
93
     }
89
     }
94
     /// Initializes the Shell Loop.
90
     /// Initializes the Shell Loop.
95
     /// Starts the shell.
91
     /// Starts the shell.
96
-    pub fn start(&mut self) -> Result<(), &str> {
92
+    pub fn start(&mut self) -> Result<(), ErrorType> {
97
         self.shell_loop()
93
         self.shell_loop()
98
     }
94
     }
99
 
95
 
100
     /// Loops while exit hasn't been called.
96
     /// Loops while exit hasn't been called.
101
     /// When *prompt()* returns (the user hit enter) a Command is created through the FromStr-Trait.
97
     /// When *prompt()* returns (the user hit enter) a Command is created through the FromStr-Trait.
102
     /// If the Command-creation succeeds, run the command.
98
     /// If the Command-creation succeeds, run the command.
103
-    fn shell_loop(&mut self) -> Result<(), &str> {
99
+    fn shell_loop(&mut self) -> Result<(), ErrorType> {
104
         while !self.should_exit {
100
         while !self.should_exit {
105
             if let Ok(Some(line)) = self.prompt() {
101
             if let Ok(Some(line)) = self.prompt() {
106
                 let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
102
                 let _ = Command::from_str(&line).and_then(|cmd| self.run(cmd));
111
 
107
 
112
     /// Prints the shell prompt.
108
     /// Prints the shell prompt.
113
     /// Waits for user input and returns the read line.
109
     /// Waits for user input and returns the read line.
114
-    pub fn prompt(&mut self) -> Result<Option<String>, &str> {
110
+    pub fn prompt(&mut self) -> Result<Option<String>, ErrorType> {
115
         match env::current_dir() {
111
         match env::current_dir() {
116
             Ok(pwd) => {
112
             Ok(pwd) => {
117
                 let _ = self.writer.write(
113
                 let _ = self.writer.write(
127
                     Err(_) => Ok(None),
123
                     Err(_) => Ok(None),
128
                 }
124
                 }
129
             }
125
             }
130
-            Err(_) => return Err("Path Error"),
126
+            Err(_) => return Err(ErrorType::PathError),
131
         }
127
         }
132
     }
128
     }
133
 
129
 
134
     /// Runs a command.
130
     /// Runs a command.
135
     /// Currently only `cd` and `exit` are working.
131
     /// Currently only `cd` and `exit` are working.
136
-    fn run(&mut self, command: Command) -> Result<(), ShellError> {
132
+    fn run(&mut self, command: Command) -> Result<(), ErrorType> {
137
 
133
 
138
         match command {
134
         match command {
139
             Command::Empty => {},
135
             Command::Empty => {},
140
             Command::Program(cmd) => {
136
             Command::Program(cmd) => {
141
 
137
 
142
-                let mut commands = cmd.split('|');
138
+                let commands = cmd.split('|');
143
                 let commands_vec: Vec<&str> = commands.collect();
139
                 let commands_vec: Vec<&str> = commands.collect();
144
-                
140
+
145
                 let needs_pipe = commands_vec.len() == 2;
141
                 let needs_pipe = commands_vec.len() == 2;
146
 
142
 
147
-                if let Ok((reader, writer)) = pipe() {
148
 
143
 
149
                     let fi = fork();
144
                     let fi = fork();
150
                     match fi {
145
                     match fi {
151
-                        Ok(Parent { .. }) => {
152
-                            wait();
153
-                        }
154
-                        Ok(Child) => {
155
-                            if let Some(first) = commands_vec.get(0) {
156
-                                if needs_pipe {
157
-                                    close(reader).unwrap();
158
-                                    dup2(writer, 1).unwrap();
159
-                                }
160
-                                self.execute(first);
161
-                            }
162
-                        }
163
-                        Err(_) => println!("Fatal error: Fork failed"),
164
-                    }
165
-
146
+                        Ok(Parent { child: _child }) => {
147
+                            let _ = wait();
166
 
148
 
167
-                    let sec = fork();
168
-                    match sec {
169
-                        Ok(Parent { .. }) => {
170
-                            wait();
171
                         }
149
                         }
172
                         Ok(Child) => {
150
                         Ok(Child) => {
173
-                            if let Some(second) = commands_vec.get(1) {
174
-                                close(1).unwrap();
175
-                                close(writer).unwrap();
176
-                                dup2(reader, 0).unwrap();
177
-                                self.execute(second);
151
+                            if let Ok((reader, writer)) = pipe() {
152
+                                let sec = fork();
153
+                                match sec {
154
+                                    Ok(Parent { child: _child }) => {
155
+                                        let _ = wait();
156
+                                        if let Some(second) = commands_vec.get(1) {
157
+                                            match close(writer) {
158
+                                                Ok(_) => {},
159
+                                                Err(_) => return Err(ErrorType::BrokenPipeError),
160
+                                            }
161
+                                            dup2(reader, 0).unwrap();
162
+                                            self.execute(second);
163
+                                        }
164
+                                    }
165
+                                    Ok(Child) => {
166
+                                        if let Some(first) = commands_vec.get(0) {
167
+                                            if needs_pipe {
168
+                                                close(reader).unwrap();
169
+                                                dup2(writer, 1).unwrap();
170
+                                            }
171
+                                            self.execute(first);
172
+                                        }
173
+                                    }
174
+                                    Err(_) => return Err(ErrorType::ForkError),
175
+                                }
178
                             }
176
                             }
179
                         }
177
                         }
180
-                        Err(_) => println!("Fatal error: Fork failed"),
178
+                        Err(_) => return Err(ErrorType::ForkError),
181
                     }
179
                     }
182
 
180
 
183
-                }
184
-
185
             },
181
             },
186
             Command::Exit => self.should_exit = true,
182
             Command::Exit => self.should_exit = true,
187
             Command::Cd(_) => {
183
             Command::Cd(_) => {
192
     }
188
     }
193
 
189
 
194
     fn execute(&self, cmd: &str){
190
     fn execute(&self, cmd: &str){
195
-        let mut parts:Vec<&str> = cmd.split_whitespace().collect();
191
+        let parts:Vec<&str> = cmd.split_whitespace().collect();
196
         let args:Vec<CString> = parts.iter().map(|f| CString::new(*f).unwrap()).collect();
192
         let args:Vec<CString> = parts.iter().map(|f| CString::new(*f).unwrap()).collect();
197
         let t = args.into_boxed_slice();
193
         let t = args.into_boxed_slice();
198
 
194
 
199
-        execvp(&t[0], &t);
195
+        execvp(&t[0], &t).unwrap();
200
     }
196
     }
201
 }
197
 }
202
 
198
 

+ 4
- 0
hw7/task2/src/main.rs View File

4
 use std::io;
4
 use std::io;
5
 use task2::Shell;
5
 use task2::Shell;
6
 
6
 
7
+
8
+/// Diese Funktion startet die Shell durch Aufruf
9
+/// von `Shell::new()`.
7
 fn main() {
10
 fn main() {
8
     let stdin = io::stdin();
11
     let stdin = io::stdin();
9
     let stdout = io::stdout();
12
     let stdout = io::stdout();
10
 
13
 
11
     let mut s = Shell::new(stdin.lock(), stdout.lock(), "schell".to_string());
14
     let mut s = Shell::new(stdin.lock(), stdout.lock(), "schell".to_string());
15
+    // Kontrolliertes bzw. unkontrolliertes Beenden der Shell
12
     match s.start() {
16
     match s.start() {
13
         Ok(_) => process::exit(0),
17
         Ok(_) => process::exit(0),
14
         Err(_) => process::exit(1),
18
         Err(_) => process::exit(1),

+ 0
- 2
hw7/task2/src/shellerror.rs View File

1
-#[derive(PartialEq, Debug)]
2
-pub struct ShellError;

Loading…
Cancel
Save