├── CNAME ├── languages └── craftinginterpreters │ ├── jlox │ ├── .gitignore │ ├── .idea │ │ ├── .gitignore │ │ ├── description.html │ │ ├── project-template.xml │ │ ├── dictionaries │ │ │ └── sakib.xml │ │ ├── encodings.xml │ │ ├── vcs.xml │ │ ├── modules.xml │ │ └── misc.xml │ ├── class-sample.lox │ ├── src │ │ └── dev │ │ │ └── sakib │ │ │ └── lox │ │ │ ├── LoxCallable.java │ │ │ ├── Return.java │ │ │ ├── RuntimeError.java │ │ │ ├── Token.java │ │ │ ├── TokenType.java │ │ │ ├── LoxInstance.java │ │ │ ├── Environment.java │ │ │ ├── LoxClass.java │ │ │ ├── LoxFunction.java │ │ │ ├── AstPrinter.java │ │ │ ├── Lox.java │ │ │ ├── Stmt.java │ │ │ ├── Expr.java │ │ │ └── Scanner.java │ ├── .run │ │ └── Template Application.run.xml │ ├── jlox.iml │ ├── tool │ │ ├── tool.iml │ │ └── src │ │ │ └── GenerateAst.java │ └── sample.lox │ └── hello.lox ├── _config.yml ├── algorithms ├── README.md └── the-algorithm-design-manual │ └── programming-challenges │ ├── uva10137 │ ├── README.md │ └── uva10137.py │ ├── uva843 │ ├── README.md │ └── uva843.py │ ├── uva10004 │ ├── README.md │ └── uva10004.py │ ├── uva10152 │ ├── README.md │ └── uva10152.py │ ├── uva850 │ ├── README.md │ └── uva850.py │ ├── uva100 │ ├── README.md │ └── uva100.py │ ├── uva10010 │ ├── README.md │ └── uva10010.py │ ├── uva10038 │ ├── README.md │ └── uva10038.py │ ├── uva10041 │ ├── README.md │ └── uva10041.py │ ├── uva10142 │ ├── README.md │ └── uva10142.py │ ├── uva847 │ ├── README.md │ └── uva847.py │ ├── uva10035 │ ├── README.md │ └── uva10035.py │ ├── uva10110 │ ├── README.md │ └── uva10110.py │ ├── uva10037 │ ├── README.md │ └── uva10037.py │ ├── uva10026 │ ├── README.md │ └── uva10026.py │ ├── uva120 │ ├── uva120.py │ └── README.md │ ├── new_uva.py │ └── README.md ├── os └── OSTEP │ ├── 19-tlb │ └── homeworks │ │ ├── chart.png │ │ ├── chart-aws.png │ │ ├── chart-thread-affinity.png │ │ ├── data-v3.csv │ │ ├── run-tlb.sh │ │ ├── data-v2.csv │ │ ├── data-v4.csv │ │ ├── data-v2-aws.csv │ │ ├── data-v4-aws.csv │ │ ├── tlb.c │ │ ├── README.md │ │ └── data-v1.csv │ ├── 21-swapping-mechanisms │ └── homeworks │ │ ├── chart.png │ │ └── README.md │ ├── 06-limited-direct-execution │ └── homeworks │ │ ├── common.h │ │ ├── system_call.c │ │ └── context_switch.c │ ├── 15-address-translation │ ├── p1.c │ └── p1.s │ ├── 22-swapping-policy │ └── homeworks │ │ ├── FIFO, RAND, LRU and CLOCK.png │ │ ├── run.sh │ │ └── README.md │ ├── 29-locked-data-structures │ └── homeworks │ │ ├── Time vs. Threshold.png │ │ ├── common.h │ │ ├── README.md │ │ ├── counter.c │ │ └── sloppycounter.c │ ├── 14-memory-api │ └── homeworks │ │ ├── null.c │ │ ├── array.c │ │ ├── array3.c │ │ ├── array2.c │ │ ├── unfreed.c │ │ └── vector.c │ ├── 05-process-api │ ├── notes.md │ ├── homeworks │ │ ├── p3.c │ │ ├── p2.c │ │ ├── p1.c │ │ ├── p5.c │ │ ├── p7.c │ │ ├── p4.c │ │ ├── p6.c │ │ └── p8.c │ ├── fork.c │ ├── wait.c │ ├── redirect.c │ └── exec.c │ ├── 48-distributed-systems │ └── homeworks │ │ ├── Makefile │ │ ├── server.c │ │ ├── client.c │ │ └── common.h │ ├── 13-address-space │ ├── va.c │ └── homeworks │ │ ├── README.md │ │ └── memory-user.c │ ├── 45-data-integrity-and-protection │ └── homeworks │ │ ├── check-xor.c │ │ ├── check-fletcher.c │ │ ├── create-csum.c │ │ ├── crc.c │ │ ├── README.md │ │ └── check-csum.c │ ├── 04-processes │ ├── memory.c │ ├── system_call.c │ ├── common.h │ ├── thread.c │ └── common_threads.h │ ├── 31-semaphores │ └── homeworks │ │ ├── fork-join.c │ │ ├── rendezvous.c │ │ ├── mutex-nostarve.c │ │ ├── common_threads.h │ │ ├── barrier.c │ │ ├── reader-writer.c │ │ └── reader-writer-nostarve.c │ ├── 27-thread-api │ ├── thread.c │ ├── pi.go │ ├── homeworks │ │ └── README.md │ └── pi.c │ ├── 26-concurrency-and-threads │ ├── thread.c │ └── homeworks │ │ └── README.md │ ├── 41-fast-fs │ └── homeworks │ │ └── README.md │ ├── 20-advanced-page-tables │ └── homeworks │ │ └── README.md │ ├── 39-files-and-directories │ └── homeworks │ │ ├── stat.c │ │ ├── tree.c │ │ ├── ls.c │ │ └── tail.c │ ├── 10-multi-cpu-scheduling │ └── homeworks │ │ └── README.md │ ├── 38-raids │ └── homeworks │ │ └── README.md │ ├── 18-paging │ └── homeworks │ │ └── README.md │ ├── 44-ssd │ └── homeworks │ │ └── README.md │ ├── 33-event-based-concurrency │ └── homeworks │ │ ├── README.md │ │ ├── tcp.c │ │ ├── multi-tcp.c │ │ ├── file-tcp.c │ │ └── aio-file-tcp.c │ ├── 37-hard-disk-drive │ └── homeworks │ │ └── README.md │ ├── 32-concurrency-bugs │ └── homeworks │ │ └── README.md │ ├── 28-locks │ └── homeworks │ │ └── README.md │ ├── 17-freespace │ └── homeworks │ │ └── README.md │ ├── README.md │ ├── 16-segmentation │ └── homeworks │ │ └── README.md │ ├── 42-fsck-and-journaling │ └── homeworks │ │ └── README.md │ ├── 30-condition-variables │ └── homeworks │ │ └── README.md │ ├── 43-lfs │ └── homeworks │ │ └── README.md │ └── 40-fs-implementation │ └── homeworks │ └── README.md ├── .gitignore └── README.md /CNAME: -------------------------------------------------------------------------------- 1 | cs.sakib.dev -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal 2 | 3 | title: cs.sakib.dev 4 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /algorithms/README.md: -------------------------------------------------------------------------------- 1 | [Programming challenges](./the-algorithm-design-manual/programming-challenges/) -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjsakib/cs/HEAD/os/OSTEP/19-tlb/homeworks/chart.png -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/chart-aws.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjsakib/cs/HEAD/os/OSTEP/19-tlb/homeworks/chart-aws.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore all extensionless files 2 | * 3 | !*/ 4 | !*.* 5 | 6 | # output files 7 | *.output 8 | 9 | .vscode 10 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/chart-thread-affinity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjsakib/cs/HEAD/os/OSTEP/19-tlb/homeworks/chart-thread-affinity.png -------------------------------------------------------------------------------- /os/OSTEP/21-swapping-mechanisms/homeworks/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjsakib/cs/HEAD/os/OSTEP/21-swapping-mechanisms/homeworks/chart.png -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.idea/description.html: -------------------------------------------------------------------------------- 1 | Simple Java application that includes a class with main() method -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.idea/project-template.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /os/OSTEP/06-limited-direct-execution/homeworks/common.h: -------------------------------------------------------------------------------- 1 | long get_dt(long s1, long us1, long s2, long us2) { 2 | return (s1-s2)*1e6 + (us1 - us2); 3 | } 4 | -------------------------------------------------------------------------------- /os/OSTEP/15-address-translation/p1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) { 4 | int x = 10; 5 | x+=2; 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /os/OSTEP/22-swapping-policy/homeworks/FIFO, RAND, LRU and CLOCK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjsakib/cs/HEAD/os/OSTEP/22-swapping-policy/homeworks/FIFO, RAND, LRU and CLOCK.png -------------------------------------------------------------------------------- /os/OSTEP/29-locked-data-structures/homeworks/Time vs. Threshold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjsakib/cs/HEAD/os/OSTEP/29-locked-data-structures/homeworks/Time vs. Threshold.png -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/class-sample.lox: -------------------------------------------------------------------------------- 1 | class DevonshireCream { 2 | serveOn() { 3 | return "Scones"; 4 | } 5 | } 6 | 7 | print DevonshireCream; 8 | 9 | print DevonshireCream(); -------------------------------------------------------------------------------- /os/OSTEP/14-memory-api/homeworks/null.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | int *x = NULL; 6 | printf("%d\n", *x); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/notes.md: -------------------------------------------------------------------------------- 1 | ## How do we run a program? 2 | 3 | So, we evoke programs in a shell, the the shell uses `fork`, `exec`, `wait` etc to run the program. But how does the shell itself starts? 4 | -------------------------------------------------------------------------------- /os/OSTEP/48-distributed-systems/homeworks/Makefile: -------------------------------------------------------------------------------- 1 | all: server client 2 | 3 | server: server.c common.h 4 | gcc server.c -o server -Wall 5 | 6 | client: client.c common.h 7 | gcc client.c -o client -Wall 8 | -------------------------------------------------------------------------------- /os/OSTEP/14-memory-api/homeworks/array.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | int *x = malloc(10 * sizeof(int)); 6 | x[10] = 0; 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /os/OSTEP/14-memory-api/homeworks/array3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | int *x = malloc(10 * sizeof(int)); 6 | free(x + 5); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.idea/dictionaries/sakib.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | sakib 5 | 6 | 7 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/data-v3.csv: -------------------------------------------------------------------------------- 1 | Pages, Accessing all of them 100000 times 2 | 1, 398 3 | 2, 203 4 | 4, 197 5 | 8, 192 6 | 16, 475 7 | 32, 929 8 | 64, 845 9 | 128, 853 10 | 256, 818 11 | 512, 810 12 | 1024, 823 13 | 2048, 628 14 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10137/README.md: -------------------------------------------------------------------------------- 1 | # 10137 - The Trip 2 | 3 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10137/uva10137.py) -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva843/README.md: -------------------------------------------------------------------------------- 1 | # UVa 843 - Crypt Kicker 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva843/uva843.py) 3 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10004/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10004 - Bicoloring 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10004/uva10004.py) 3 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10152/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10152 - ShellSort 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10152/uva10152.py) 3 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva850/README.md: -------------------------------------------------------------------------------- 1 | # UVa 850 - Crypt Kicker II 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva850/uva850.py) 3 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /os/OSTEP/14-memory-api/homeworks/array2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | int *x = malloc(10 * sizeof(int)); 6 | free(x); 7 | printf("%d\n", x[5]); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /os/OSTEP/14-memory-api/homeworks/unfreed.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | int *x = (int*) malloc(sizeof(int)); 6 | *x = 10; 7 | printf("%d\n", *x); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva100/README.md: -------------------------------------------------------------------------------- 1 | # UVa 100 - The 3n + 1 problem 2 | 3 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva100/uva100.py) 4 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10010/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10010 - Where's Waldorf? 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10010/uva10010.py) 3 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10038/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10038 - Jolly Jumpers 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10038/uva10038.py) 3 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10041/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10041 - Vito's Family 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10041/uva10041.py) 3 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10142/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10142 - Australian Voting 2 | 3 | [Python code](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10142/uva10142.py) -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva847/README.md: -------------------------------------------------------------------------------- 1 | # UVa 847 - A Multiplication Game 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva847/uva847.py) 3 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10035/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10035 - Primary Arithmetic 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10035/uva10035.py) 3 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10110/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10110 - Light, more light 2 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10110/uva10110.py) 3 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/LoxCallable.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | import java.util.List; 4 | 5 | public interface LoxCallable { 6 | int arity(); 7 | Object call(Interpreter interpreter, List arguments); 8 | } 9 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10041/uva10041.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | input() 4 | 5 | 6 | for line in sys.stdin: 7 | nums = list(sorted(map(int, line.split()[1:]))) 8 | 9 | m = nums[len(nums)//2] 10 | 11 | print(sum(map(lambda x: abs(x-m), nums))) 12 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/Return.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | public class Return extends RuntimeException { 4 | final Object value; 5 | 6 | Return(Object value) { 7 | super(null, null, false, false); 8 | this.value = value; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/RuntimeError.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | class RuntimeError extends RuntimeException { 4 | final Token token; 5 | 6 | RuntimeError(Token token, String message) { 7 | super(message); 8 | this.token = token; 9 | } 10 | } -------------------------------------------------------------------------------- /os/OSTEP/13-address-space/va.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | printf("Location of code: %p\n", main); 6 | printf("Location of heap: %p\n", malloc(100e6)); 7 | int x = 42; 8 | printf("Locatoin of stack: %p\n", &x); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10110/uva10110.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from math import sqrt 3 | 4 | for line in sys.stdin: 5 | n = int(line) 6 | if n == 0: 7 | break 8 | 9 | if (int(sqrt(n))**2 == n): 10 | print('yes') 11 | else: 12 | print('no') 13 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/run-tlb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Pages, Accessing all of them 100000 times" 3 | 4 | i=1 5 | while [ $i -le 63 ] 6 | do 7 | echo "$i, $(./tlb $i)" 8 | i=$(( $i + 1 )); 9 | done 10 | 11 | while [ $i -le 65536 ] 12 | do 13 | echo "$i, $(./tlb $i)" 14 | i=$(( $i * 2 )); 15 | done 16 | -------------------------------------------------------------------------------- /os/OSTEP/45-data-integrity-and-protection/homeworks/check-xor.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) { 4 | unsigned int c; 5 | unsigned char sum = 0; 6 | while ((c = getchar()) != EOF) { 7 | sum^=c; 8 | } 9 | printf("XOR Checksum: %d\n", sum); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10037/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10037 - Bridge 2 | 3 | A simple `n log(n)` works fine. The basic idea is to use the first and second fast person for carrying the flashlight. 4 | 5 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10037/uva10037.py) 6 | -------------------------------------------------------------------------------- /os/OSTEP/29-locked-data-structures/homeworks/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float get_dt(struct timeval *t1, struct timeval *t2) { 4 | return (t2->tv_sec - t1->tv_sec) + (t2->tv_usec - t1->tv_usec) / (float)1e6; 5 | } 6 | 7 | int get_dt_n(struct timeval *t1, struct timeval *t2) { 8 | return (t2->tv_sec - t1->tv_sec)*1e6 + (t2->tv_usec - t1->tv_usec); 9 | } 10 | -------------------------------------------------------------------------------- /os/OSTEP/45-data-integrity-and-protection/homeworks/check-fletcher.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) { 4 | unsigned int c; 5 | unsigned char s1 = 0, s2 = 0; 6 | while ((c = getchar()) != EOF) { 7 | s1 = (s1 + c) % 255; 8 | s2 = (s1 + s2) % 255; 9 | } 10 | printf("Fletcher checksum: (%d, %d)\n", s1, s2); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/homeworks/p3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | int rc = fork(); 6 | if (rc < 0) { 7 | fprintf(stderr, "Fork failed.\n"); 8 | } else if (rc == 0) { 9 | printf("Hello!\n"); 10 | } else { 11 | fopen("xxxx", "w"); 12 | printf("Goodbye!\n"); 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/homeworks/p2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | FILE *fp = fopen("p2.output", "w"); 6 | int rc = fork(); 7 | if (rc < 0) { 8 | fprintf(stderr, "Fork failed.\n"); 9 | } else if (rc ==0) { 10 | fprintf(fp, "Hello from child.\n"); 11 | } else { 12 | fprintf(fp, "Hello from parent.\n"); 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /os/OSTEP/04-processes/memory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "common.h" 5 | 6 | int 7 | main(int argc, char *argv[]) 8 | { 9 | int *p = malloc(sizeof(int)); 10 | assert(p != NULL); 11 | printf("(%d) address pointed to by p: %p\n", getpid(), p); 12 | *p = 0; 13 | while(1) { 14 | Spin(1); 15 | *p = *p + 1; 16 | printf("(%d) p: %d\n", getpid(), *p); 17 | } 18 | return 0; 19 | } -------------------------------------------------------------------------------- /os/OSTEP/04-processes/system_call.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) { 6 | struct timeval t; 7 | gettimeofday(&t, NULL); 8 | long t1 = t.tv_usec; 9 | long sum = 0; 10 | for(int i = 0;i< 100; i++) { 11 | gettimeofday(&t, NULL); 12 | sum += t.tv_usec - t1; 13 | printf("%ld\n", t.tv_usec - t1); 14 | } 15 | printf("Average delay %ld\n", sum/100); 16 | } -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva847/uva847.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | for line in sys.stdin: 5 | n = int(line) 6 | 7 | count = 1 8 | while True: 9 | n /= 9 10 | count += 1 11 | if n <= 1: 12 | break 13 | n /= 2 14 | count += 1 15 | if n <= 1: 16 | break 17 | if count & 1: 18 | print('Ollie wins.') 19 | else: 20 | print('Stan wins.') 21 | -------------------------------------------------------------------------------- /os/OSTEP/48-distributed-systems/homeworks/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "common.h" 3 | 4 | int main(int argc, char** argv) { 5 | int sd = UDP_Open(8000); 6 | struct sockaddr_in addrRcv; 7 | char msg[BUFFER_SIZE]; 8 | while(1) { 9 | UDP_Read(sd, &addrRcv, msg, BUFFER_SIZE); 10 | printf("Received: %s\n", msg); 11 | sprintf(msg, "Hi client!"); 12 | UDP_Write(sd, &addrRcv, msg, BUFFER_SIZE); 13 | } 14 | return 0; 15 | } -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.run/Template Application.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10137/uva10137.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | for line in sys.stdin: 4 | n = int(line) 5 | if n == 0: 6 | break 7 | amounts = [float(input()) for _ in range(n)] 8 | avg = sum(amounts)/n 9 | ans = 0 10 | ansNeg = 0 11 | for amount in amounts: 12 | diff = int((amount - avg)*100)/100 13 | ans += max(diff, 0) 14 | ansNeg += min(diff, 0) 15 | print('${:.2f}'.format(max(ans, -ansNeg))) -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/jlox.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10026/README.md: -------------------------------------------------------------------------------- 1 | # UVa 10026 - Shoemaker's Problem 2 | 3 | When comparing two jobs, if one jobs fine times the other jobs required time is greater than the other jobs fine times the first jobs required time, the first job has to come before the second job. Otherwise the second job has to come first. 4 | 5 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva10026/uva10026.py) 6 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/tool/tool.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /os/OSTEP/48-distributed-systems/homeworks/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "common.h" 3 | 4 | 5 | int main(int argc, char** argv) { 6 | int sd = UDP_Open(8080); 7 | struct sockaddr_in addrSend, addrRcv; 8 | UDP_FillSockAddr(&addrSend, "localhost", 8000); 9 | char msg[BUFFER_SIZE]; 10 | sprintf(msg, "Hello Server!"); 11 | UDP_Write(sd, &addrSend, msg, BUFFER_SIZE); 12 | UDP_Read(sd, &addrRcv, msg, BUFFER_SIZE); 13 | printf("Received: %s\n", msg); 14 | return 0; 15 | } -------------------------------------------------------------------------------- /os/OSTEP/04-processes/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __common_h__ 2 | #define __common_h__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | double GetTime() { 9 | struct timeval t; 10 | int rc = gettimeofday(&t, NULL); 11 | assert(rc == 0); 12 | return (double) t.tv_sec + (double) t.tv_usec/1e6; 13 | } 14 | 15 | void Spin(int howlong) { 16 | double t = GetTime(); 17 | while ((GetTime() - t) < (double) howlong) 18 | ; // do nothing in loop 19 | } 20 | 21 | #endif // __common_h__ 22 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/homeworks/p1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int var; 5 | 6 | int main(int argc, char *argv[]) { 7 | var = 42; 8 | int rc = fork(); 9 | if (rc < 0) { 10 | fprintf(stderr, "Fork failed.\n"); 11 | } else if (rc ==0) { 12 | // var = 41; 13 | printf("var: %d, in child (pid: %d)\n", var, (int) getpid()); 14 | } else { 15 | var = 43; 16 | printf("var: %d, in parent (pid: %d)\n", var, (int) getpid()); 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/Token.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | class Token { 4 | final TokenType type; 5 | final String lexeme; 6 | final Object literal; 7 | final int line; 8 | 9 | Token(TokenType type, String lexeme, Object literal, int line) { 10 | this.type = type; 11 | this.lexeme = lexeme; 12 | this.literal = literal; 13 | this.line = line; 14 | } 15 | 16 | public String toString() { 17 | return type + " " + lexeme + " " + literal; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /os/OSTEP/31-semaphores/homeworks/fork-join.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "common_threads.h" 5 | 6 | sem_t s; 7 | 8 | void *child(void *arg) { 9 | sleep(1); 10 | printf("child\n"); 11 | Sem_post(&s); 12 | return NULL; 13 | } 14 | 15 | int main(int argc, char *argv[]) { 16 | pthread_t p; 17 | printf("parent: begin\n"); 18 | Sem_init(&s, 0); 19 | Pthread_create(&p, NULL, child, NULL); 20 | Sem_wait(&s); 21 | printf("parent: end\n"); 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva100/uva100.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import functools 3 | 4 | @functools.lru_cache(maxsize=None) 5 | def cycle(n): 6 | if n == 1: 7 | return 1 8 | elif n % 2 == 0: 9 | return 1 + cycle(n//2) 10 | else: 11 | return 1 + cycle(3*n+1) 12 | 13 | for line in sys.stdin: 14 | i, j = map(int, line.split()) 15 | ii, jj = i, j 16 | if (i > j): 17 | i, j = j, i 18 | mx = 0 19 | for x in range(i,j+1): 20 | mx = max(mx, cycle(x)) 21 | 22 | print(ii, jj, mx) -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/homeworks/p5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int arc, char *argv[]) { 6 | int rc = fork(); 7 | 8 | if (rc < 0) { 9 | printf("failed to fork\n"); 10 | } else if(rc == 0) { 11 | int child_wait_rc = wait(NULL); 12 | printf("Child child_wait_rc: %d (pid: %d)\n", child_wait_rc, (int) getpid() ); 13 | } else { 14 | int wait_rc = wait(NULL); 15 | printf("Parent, wait_rc: %d (pid: %d)\n", wait_rc, (int) getpid()); 16 | } 17 | 18 | return 0; 19 | 20 | } -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/homeworks/p7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int arc, char *argv[]) { 6 | int rc = fork(); 7 | 8 | if (rc < 0) { 9 | printf("failed to fork\n"); 10 | } else if(rc == 0) { 11 | printf("Child\n"); 12 | // fflush(stdout); 13 | close(STDOUT_FILENO); 14 | printf("Child (pid: %d)\n", (int) getpid() ); 15 | } else { 16 | int wait_rc = wait(NULL); 17 | printf("Parent, wait_rc: %d (pid: %d)\n", wait_rc, (int) getpid()); 18 | } 19 | 20 | return 0; 21 | 22 | } -------------------------------------------------------------------------------- /os/OSTEP/13-address-space/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | * So it turns out it is not possible to invade a lot of memory with just plain integer array because of stack size limitation. So gotta use `malloc`. 3 | 4 | * If one doesn't touch the memory after allocating with `malloc`, the os doesn't actually seem to allocate the memory. 5 | 6 | * There is some kind of limitation how much memory a process can consume. The process `Segmentation fault` after `2048M` even though there is more free memory left. 7 | 8 | ### Tip 9 | `htop` is much easier and convenient than `free` or `top` to keep track of memory. 10 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) { 6 | printf("Hello world! (pid: %d)\n", (int) getpid()); 7 | int rc = fork(); 8 | printf("%d (pid: %d)\n", rc, (int) getpid()); 9 | if (rc < 0) { 10 | fprintf(stderr, "Fork failed\n"); 11 | exit(1); 12 | } else if(rc == 0) { 13 | printf("Hello, I am child (pid: %d)\n", (int) getpid()); 14 | } else { 15 | printf("Hello, I am parent of %d (pid: %d)\n", rc, (int) getpid()); 16 | } 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/TokenType.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | enum TokenType { 4 | // Single-character tokens 5 | LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE, COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR, QUESTION, COLON, 6 | 7 | // One or two character tokens. 8 | BANG, BANG_EQUAL, EQUAL, EQUAL_EQUAL, GREATER, GREATER_EQUAL, LESS, LESS_EQUAL, 9 | 10 | // Literals 11 | IDENTIFIER, STRING, NUMBER, 12 | 13 | // KEYWORDS 14 | AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR, PRINT, SUPER, THIS, TRUE, VAR, WHILE, RETURN, CONTINUE, BREAK, 15 | 16 | EOF 17 | } -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva120/uva120.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from operator import itemgetter 3 | 4 | for line in sys.stdin: 5 | print(line.strip()) 6 | nums = list(map(int, line.split())) 7 | 8 | for i in range(len(nums)-1, 0, -1): 9 | mx, _ = max(enumerate(nums[:i+1]), key=itemgetter(1)) 10 | if mx == i: 11 | continue 12 | if mx != 0: 13 | print(len(nums)-mx, end=' ') 14 | nums = list(reversed(nums[:mx+1])) + nums[mx+1:] 15 | print(len(nums)-i, end=' ') 16 | nums = list(reversed(nums[:i+1])) + nums[i+1:] 17 | print('0') 18 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/wait.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) { 7 | printf("Hello world! (pid: %d)\n", (int) getpid()); 8 | int rc = fork(); 9 | if (rc < 0) { 10 | fprintf(stderr, "Fork failed\n"); 11 | exit(1); 12 | } else if(rc == 0) { 13 | printf("Hello, I am child (pid: %d)\n", (int) getpid()); 14 | } else { 15 | int rc_wait = wait(NULL); 16 | printf("Hello, I am parent of %d (rc_wait: %d) (pid: %d)\n", rc, rc_wait, (int) getpid()); 17 | } 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10038/uva10038.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def is_jolly(arr): 5 | l = len(arr) 6 | if l == 1: 7 | return True 8 | nums = set(range(1,l)) 9 | i = 0 10 | while i < l-1: 11 | x = abs(arr[i] - arr[i+1]) 12 | if x not in nums: 13 | return False 14 | nums.remove(x) 15 | i+=1 16 | if len(nums) == 0: 17 | return True 18 | return False 19 | 20 | 21 | for line in sys.stdin: 22 | n, *arr = map(int, line.split()) 23 | if is_jolly(arr): 24 | print('Jolly') 25 | else: 26 | print('Not jolly') 27 | -------------------------------------------------------------------------------- /os/OSTEP/13-address-space/homeworks/memory-user.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) { 6 | if (argc < 2) { 7 | fprintf(stderr, "Memory amount not provided\n"); 8 | return -1; 9 | } 10 | printf("PID: %d\n",(int) getpid()); 11 | int m = atoi(argv[1]); 12 | int integers = m *((1024*1024) / sizeof(int)); 13 | int *nums = malloc(m * 1024*1024); 14 | for (int i = 0; i < integers; i++) { 15 | nums[i]+=1; 16 | } 17 | while(1) { 18 | // nums[i]+=1; 19 | // i++; 20 | // if (i == integers) i = 0; 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10026/uva10026.py: -------------------------------------------------------------------------------- 1 | nn = int(input()) 2 | 3 | 4 | class Job: 5 | def __init__(self, i, t, f): 6 | self.i = i 7 | self.t = t 8 | self.f = f 9 | 10 | def __lt__(self, other): 11 | return self.f * other.t > self.t * other.f 12 | 13 | def __str__(self): 14 | return f'{self.i}' 15 | 16 | 17 | for ii in range(nn): 18 | input() 19 | if ii != 0: 20 | print('') 21 | 22 | n = int(input()) 23 | 24 | jobs = [] 25 | 26 | for i in range(n): 27 | jobs.append(Job(i+1, *map(int, input().split()))) 28 | 29 | jobs.sort() 30 | 31 | print(*jobs) 32 | -------------------------------------------------------------------------------- /os/OSTEP/27-thread-api/thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef struct {int a; int b;} myarg_t; 7 | typedef struct {int x; int y;} myret_t; 8 | 9 | void *mythread(void *args) { 10 | myarg_t *arg = args; 11 | printf("Received: %d %d\n", arg->a, arg->b); 12 | 13 | myret_t *ret = malloc(sizeof(myret_t)); 14 | return ret; 15 | } 16 | 17 | int main(int argc, char** argv) { 18 | pthread_t p; 19 | myret_t *rvals; 20 | myarg_t args = {10, 20}; 21 | pthread_create(&p, NULL, mythread, &args); 22 | pthread_join(p, (void**) &rvals); 23 | printf("returned: %d %d\n", rvals->x, rvals->y); 24 | return 0; 25 | } -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/homeworks/p4.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) { 8 | char *lsargs[3]; 9 | lsargs[0] = strdup("/bin/ls"); 10 | lsargs[1] = strdup("-l"); 11 | lsargs[2] = NULL; 12 | int rc = fork(); 13 | if (rc == 0) { 14 | // execl(lsargs[0], lsargs[0], lsargs[1], NULL); 15 | // execle(lsargs[0], lsargs[0], lsargs[1], NULL, NULL); 16 | // execlp("ls", lsargs[1], lsargs[1], NULL); 17 | // execv(lsargs[0], lsargs); 18 | // execvp("ls", lsargs); 19 | execvpe("ls", lsargs, NULL); 20 | } else { 21 | return -1; 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10035/uva10035.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | for line in sys.stdin: 4 | a, b = map(int, line.split()) 5 | 6 | if a == 0 and b == 0: 7 | break 8 | count = 0 9 | 10 | if b > a: 11 | a, b = b, a 12 | 13 | carry = 0 14 | 15 | while a or b: 16 | res = a % 10 + b % 10 + carry 17 | # print(a, b, carry, res) 18 | 19 | if res > 9: 20 | count += 1 21 | carry = res // 10 22 | a //= 10 23 | b //= 10 24 | 25 | if count == 0: 26 | print('No carry operation.') 27 | elif count == 1: 28 | print('1 carry operation.') 29 | else: 30 | print(count, 'carry operations.') 31 | -------------------------------------------------------------------------------- /os/OSTEP/45-data-integrity-and-protection/homeworks/create-csum.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define BLOCK_SIZE 4096 5 | 6 | char buff[BLOCK_SIZE]; 7 | 8 | char xor(char* block, int len) { 9 | char sum = 0; 10 | for(int i = 0; i 0) { 23 | fprintf(output, "%c\n", xor(buff, read_count)); 24 | } 25 | fclose(output); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/redirect.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char *argv[]) { 9 | int rc = fork(); 10 | if (rc < 0) { 11 | fprintf(stderr, "Fork failed\n"); 12 | exit(1); 13 | } else if(rc == 0) { 14 | close(STDOUT_FILENO); 15 | open("./redirect.output", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU); 16 | char *myargs[3]; 17 | myargs[0] = strdup("wc"); 18 | myargs[1] = strdup("exec.c"); 19 | myargs[2] = NULL; 20 | execvp(myargs[0], myargs); 21 | } else { 22 | int rc_wait = wait(NULL); 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /os/OSTEP/26-concurrency-and-threads/thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static volatile int counter = 0; 5 | 6 | void *mythread(void *arg) { 7 | printf("%s: begin\n", (char*) arg); 8 | for(int i = 0; i < 1e4; i++) { 9 | counter += 1; 10 | } 11 | printf("%s: done\n", (char*) arg); 12 | 13 | return NULL; 14 | } 15 | 16 | int main(int argc, char **argv) { 17 | pthread_t p1, p2; 18 | printf("main: begin (counter = %d)\n", counter); 19 | pthread_create(&p1, NULL, mythread, "A"); 20 | pthread_create(&p2, NULL, mythread, "B"); 21 | 22 | pthread_join(p1, NULL); 23 | pthread_join(p2, NULL); 24 | 25 | printf("main: done with both (counter = %d)\n", counter); 26 | return 0; 27 | } -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/homeworks/p6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int arc, char *argv[]) { 6 | int rc1 = fork(); 7 | 8 | if (rc1 < 0) { 9 | printf("failed to fork\n"); 10 | } else if(rc1 == 0) { 11 | printf("Child 1 (pid: %d)\n", (int) getpid() ); 12 | } else { 13 | int rc2 = fork(); 14 | 15 | if (rc2 < 0) { 16 | printf("Second fork failed\n"); 17 | } else if (rc2 == 0) { 18 | printf("Child 2 (pid: %d)\n", (int) getpid()); 19 | } else { 20 | waitpid((pid_t) rc2, NULL, WNOHANG); 21 | // wait(NULL); 22 | printf("Parent (pid: %d)\n", (int) getpid()); 23 | } 24 | } 25 | 26 | return 0; 27 | 28 | } -------------------------------------------------------------------------------- /os/OSTEP/29-locked-data-structures/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 29 solution 2 | 3 | ## Question 1 4 | 5 | `gettimeofday` is accurate enough on the machine I am using. 6 | 7 | ## Question 2 8 | 9 | When more threads are used, it takes more time. But when more threads than actual number of CPUs are used, the time stays same. I have 12 CPUs. So 12 threads and 100 threads takes roughly the same amount of time. 10 | 11 | ## Question 3 12 | 13 | As the threshold increase performance doesn't increase like in the book. As the threshold increase exponentially the performance increase linearly and stops at a point (32). On the other hand with a good threshold (32) performance increase as number of threads increase. 14 | 15 | ![Chart](./Time vs. Threshold.png) 16 | -------------------------------------------------------------------------------- /os/OSTEP/45-data-integrity-and-protection/homeworks/crc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define POLY 0x1021 4 | 5 | int main(int argc, char** argv) { 6 | unsigned short crc = 0, first_bit; 7 | int ch; 8 | 9 | while ((ch = getchar()) != EOF) { 10 | for (int i = 0; i < 8; i++) { 11 | first_bit = crc >> 15; 12 | 13 | crc <<= 1; 14 | if (ch & 1 << i) { 15 | crc+=1; 16 | } 17 | 18 | if (first_bit) { 19 | crc ^= POLY; 20 | } 21 | } 22 | } 23 | 24 | for (int i = 0; i < 16; i++) { 25 | first_bit = crc >> 15; 26 | crc <<= 1; 27 | if (first_bit) { 28 | crc ^= POLY; 29 | } 30 | } 31 | printf("CRC: 0x%x\n", crc); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/new_uva.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import sys 3 | import os 4 | 5 | if len(sys.argv) != 2: 6 | raise Exception('Invalid arguments') 7 | 8 | name = sys.argv[1] 9 | 10 | num, title = name.split(' - ') 11 | 12 | short_name = f'uva{num}' 13 | 14 | with open('README.md', 'a') as f: 15 | print(f'\n* [UVa {name}](./uva{num})', file=f) 16 | 17 | os.mkdir(short_name) 18 | 19 | with open(f'./{short_name}/README.md', 'w') as f: 20 | print(f'# UVa {name}', file=f) 21 | print( 22 | f'[Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/{short_name}/{short_name}.py)', file=f) 23 | 24 | open(f'./{short_name}/{short_name}.py', 'w').close() 25 | 26 | os.system(f'code ./{short_name}/{short_name}.py') 27 | -------------------------------------------------------------------------------- /os/OSTEP/04-processes/thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common.h" 4 | #include "common_threads.h" 5 | 6 | volatile int counter = 0; 7 | int loops; 8 | 9 | void *worker(void *arg) { 10 | int i; 11 | for (i = 0; i< loops; i++) { 12 | counter++; 13 | } 14 | return NULL; 15 | } 16 | 17 | int main(int argc, char *argv[]) { 18 | if( argc!= 2) { 19 | fprintf(stderr, "usage: threads \n"); 20 | 21 | } 22 | loops = atoi(argv[1]); 23 | pthread_t p1, p2; 24 | printf("Initial value: %d\n", counter); 25 | Pthread_create(&p1, NULL, worker, NULL); 26 | Pthread_create(&p2, NULL, worker, NULL); 27 | Pthread_join(p1, NULL); 28 | Pthread_join(p2, NULL); 29 | printf("Final value: %d\n", counter); 30 | return 0; 31 | } -------------------------------------------------------------------------------- /languages/craftinginterpreters/hello.lox: -------------------------------------------------------------------------------- 1 | print "Hello world! 2 | "; 3 | 4 | fun sqrt(x) { 5 | var res = x/2; 6 | 7 | while (res*res - x > 0.00001) { 8 | res = res - (res*res - x) / (2*res); 9 | } 10 | 11 | return res; 12 | } 13 | 14 | print "sqrt(99):"; 15 | print sqrt(625); 16 | print " 17 | "; 18 | 19 | fun modulo(x, y) { 20 | while (x >= y) { 21 | x = x - y; 22 | } 23 | return x; 24 | } 25 | print "module(5,2):"; 26 | print modulo(5, 2); 27 | print " 28 | "; 29 | 30 | fun isPrime(x) { 31 | for (var i = 2; i < sqrt(x); i = i+1) { 32 | if (modulo(x, i) == 0) { 33 | return false; 34 | } 35 | } 36 | 37 | return true; 38 | } 39 | 40 | print "isPrime(10):"; 41 | print isPrime(10); 42 | print " 43 | "; 44 | 45 | print "isPrime(67):"; 46 | print isPrime(67); 47 | print " 48 | "; -------------------------------------------------------------------------------- /os/OSTEP/15-address-translation/p1.s: -------------------------------------------------------------------------------- 1 | .file "p1.c" 2 | .text 3 | .globl main 4 | .type main, @function 5 | main: 6 | .LFB0: 7 | .cfi_startproc 8 | endbr64 9 | pushq %rbp 10 | .cfi_def_cfa_offset 16 11 | .cfi_offset 6, -16 12 | movq %rsp, %rbp 13 | .cfi_def_cfa_register 6 14 | movl %edi, -20(%rbp) 15 | movq %rsi, -32(%rbp) 16 | movl $10, -4(%rbp) 17 | addl $2, -4(%rbp) 18 | movl $0, %eax 19 | popq %rbp 20 | .cfi_def_cfa 7, 8 21 | ret 22 | .cfi_endproc 23 | .LFE0: 24 | .size main, .-main 25 | .ident "GCC: (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008" 26 | .section .note.GNU-stack,"",@progbits 27 | .section .note.gnu.property,"a" 28 | .align 8 29 | .long 1f - 0f 30 | .long 4f - 1f 31 | .long 5 32 | 0: 33 | .string "GNU" 34 | 1: 35 | .align 8 36 | .long 0xc0000002 37 | .long 3f - 2f 38 | 2: 39 | .long 0x3 40 | 3: 41 | .align 8 42 | 4: 43 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva120/README.md: -------------------------------------------------------------------------------- 1 | # UVa 120 - Stacks of Flapjacks 2 | 3 | We need to sort a list of numbers with the flip operation mentioned in the problem statement. 4 | 5 | The good news here is that `n` is `<=30` and we don't need to minimize the required steps. So, even a very pythonic `n^2` solution works. Here we traverse the list from last to first. At every step we need to put the largest number up to the current position at current position. For that, we find the largest number position up to current position. Then we do one flip (if necessary) so that the largest number comes at the first position. Then we do another flip so that the first position comes at out current position. 6 | 7 | [Python solution](https://github.com/sjsakib/cs/blob/master/algorithms/the-algorithm-design-manual/programming-challenges/uva120/uva120.py) 8 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) { 8 | printf("Hello world! (pid: %d)\n", (int) getpid()); 9 | int rc = fork(); 10 | if (rc < 0) { 11 | fprintf(stderr, "Fork failed\n"); 12 | exit(1); 13 | } else if(rc == 0) { 14 | printf("Hello, I am child (pid: %d)\n", (int) getpid()); 15 | char *myargs[3]; 16 | myargs[0] = strdup("wc"); 17 | myargs[1] = strdup("exec.c"); 18 | myargs[2] = NULL; 19 | execvp(myargs[0], myargs); 20 | printf("this shouldn't print out"); 21 | 22 | } else { 23 | int rc_wait = wait(NULL); 24 | printf("Hello, I am parent of %d (rc_wait: %d) (pid: %d)\n", rc, rc_wait, (int) getpid()); 25 | } 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10004/uva10004.py: -------------------------------------------------------------------------------- 1 | while True: 2 | n = int(input()) 3 | if n == 0: 4 | break 5 | 6 | l = int(input()) 7 | graph = [[] for _ in range(n)] 8 | for _ in range(l): 9 | u, v = map(int, input().split()) 10 | graph[u].append(v) 11 | graph[v].append(u) 12 | 13 | colors = [-1]*n 14 | 15 | q = [0] 16 | colors[0] = True 17 | 18 | impossible = False 19 | 20 | while q: 21 | u = q.pop() 22 | for v in graph[u]: 23 | if colors[v] == colors[u]: 24 | print('NOT BICOLORABLE.') 25 | impossible = True 26 | break 27 | if colors[v] != -1: 28 | continue 29 | colors[v] = not colors[u] 30 | q.append(v) 31 | if impossible: 32 | break 33 | else: 34 | print('BICOLORABLE.') 35 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/LoxInstance.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class LoxInstance { 7 | private LoxClass klass; 8 | private final Map fields = new HashMap<>(); 9 | 10 | LoxInstance(LoxClass klass) { 11 | this.klass = klass; 12 | } 13 | 14 | Object get(Token name) { 15 | if (fields.containsKey(name.lexeme)) { 16 | return fields.get(name.lexeme); 17 | } 18 | 19 | LoxFunction method = klass.findMethod(name.lexeme); 20 | if (method != null) return method.bind(this); 21 | 22 | throw new RuntimeError(name, "Undefined property '" + name.lexeme + "'"); 23 | } 24 | 25 | public void set(Token name, Object value) { 26 | fields.put(name.lexeme, value); 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return klass.name + " instance"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10152/uva10152.py: -------------------------------------------------------------------------------- 1 | k = int(input()) 2 | 3 | 4 | class T: 5 | def __init__(self, name, i, wi=-1): 6 | self.name = name 7 | self.i = i 8 | self.wi = wi 9 | 10 | def __str__(self): 11 | return self.name 12 | 13 | 14 | for _ in range(k): 15 | n = int(input()) 16 | 17 | d = {} 18 | 19 | for i in range(n): 20 | name = input() 21 | d[name] = T(name, i) 22 | for i in range(n): 23 | d[input()].wi = i 24 | 25 | original = sorted(d.values(), key=lambda t: t.i) 26 | wanted = sorted(original, key=lambda t: t.wi) 27 | 28 | smallest = -1 29 | found = T('', 0, -1) 30 | for t in original: 31 | if t.wi < smallest and t.wi > found.wi: 32 | found = t 33 | if t.wi > smallest: 34 | smallest = t.wi 35 | if found.wi != -1: 36 | for i in range(found.wi, -1, -1): 37 | print(wanted[i].name) 38 | 39 | print('') 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CS 2 | 3 | I decided to teach myself computer science. That's not a new decision of course. But in the past I always kind of tried to learn only the useful or most fun parts in a rush. This time the plan is to learn in depth, using openly available resources. 4 | 5 | I am following the guide at [Teach Yourself CS](https://teachyourselfcs.com/) 6 | 7 | ## OS 8 | 9 | ### Operating Systems: Three Easy Pieces 10 | 11 | This one is really good resource. Wish I could find as as good material for all the CS topics I am about to try. The dialogues gives a feeling of connection to the author, makes one feel he is _actually_ directly teaching them. 12 | 13 | Freely available at: [http://www.ostep.org](http://www.ostep.org/) 14 | 15 | [Homework solutions](./os/OSTEP/) 16 | 17 | ## Algorithms 18 | 19 | ### The Algorithm Design Manual 20 | 21 | I've started reading [The Algorithm Design Manual](http://www.algorist.com/) 22 | 23 | [Programming challenges](./algorithms/the-algorithm-design-manual/programming-challenges) 24 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/data-v2.csv: -------------------------------------------------------------------------------- 1 | Pages, Accessing all of them 100000 times 2 | 1, 205 3 | 2, 193 4 | 3, 202 5 | 4, 222 6 | 5, 219 7 | 6, 199 8 | 7, 197 9 | 8, 230 10 | 9, 229 11 | 10, 312 12 | 11, 511 13 | 12, 482 14 | 13, 590 15 | 14, 534 16 | 15, 470 17 | 16, 556 18 | 17, 477 19 | 18, 488 20 | 19, 526 21 | 20, 560 22 | 21, 600 23 | 22, 567 24 | 23, 627 25 | 24, 641 26 | 25, 638 27 | 26, 736 28 | 27, 952 29 | 28, 916 30 | 29, 869 31 | 30, 880 32 | 31, 842 33 | 32, 868 34 | 33, 858 35 | 34, 853 36 | 35, 858 37 | 36, 840 38 | 37, 866 39 | 38, 885 40 | 39, 843 41 | 40, 880 42 | 41, 869 43 | 42, 870 44 | 43, 858 45 | 44, 878 46 | 45, 860 47 | 46, 870 48 | 47, 844 49 | 48, 842 50 | 49, 857 51 | 50, 867 52 | 51, 855 53 | 52, 862 54 | 53, 862 55 | 54, 856 56 | 55, 857 57 | 56, 848 58 | 57, 859 59 | 58, 840 60 | 59, 876 61 | 60, 873 62 | 61, 859 63 | 62, 817 64 | 63, 816 65 | 64, 821 66 | 128, 822 67 | 256, 843 68 | 512, 845 69 | 1024, 847 70 | 2048, 628 71 | 4096, 1176 72 | 8192, 1650 73 | 16384, 1799 74 | 32768, 1875 75 | 65536, 1896 76 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/data-v4.csv: -------------------------------------------------------------------------------- 1 | Pages, Accessing all of them 100000 times 2 | 1, 254 3 | 2, 242 4 | 3, 192 5 | 4, 216 6 | 5, 202 7 | 6, 192 8 | 7, 189 9 | 8, 201 10 | 9, 239 11 | 10, 418 12 | 11, 364 13 | 12, 462 14 | 13, 566 15 | 14, 497 16 | 15, 560 17 | 16, 449 18 | 17, 472 19 | 18, 488 20 | 19, 512 21 | 20, 571 22 | 21, 547 23 | 22, 567 24 | 23, 621 25 | 24, 610 26 | 25, 636 27 | 26, 754 28 | 27, 928 29 | 28, 909 30 | 29, 857 31 | 30, 886 32 | 31, 841 33 | 32, 863 34 | 33, 849 35 | 34, 839 36 | 35, 869 37 | 36, 840 38 | 37, 876 39 | 38, 849 40 | 39, 839 41 | 40, 861 42 | 41, 851 43 | 42, 845 44 | 43, 839 45 | 44, 858 46 | 45, 855 47 | 46, 850 48 | 47, 843 49 | 48, 853 50 | 49, 854 51 | 50, 848 52 | 51, 853 53 | 52, 850 54 | 53, 842 55 | 54, 826 56 | 55, 922 57 | 56, 860 58 | 57, 856 59 | 58, 848 60 | 59, 848 61 | 60, 851 62 | 61, 850 63 | 62, 848 64 | 63, 852 65 | 64, 847 66 | 128, 845 67 | 256, 824 68 | 512, 815 69 | 1024, 863 70 | 2048, 751 71 | 4096, 1199 72 | 8192, 1573 73 | 16384, 2021 74 | 32768, 1967 75 | 65536, 1917 76 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/data-v2-aws.csv: -------------------------------------------------------------------------------- 1 | 1, 322 2 | 2, 313 3 | 3, 328 4 | 4, 327 5 | 5, 322 6 | 6, 330 7 | 7, 343 8 | 8, 335 9 | 9, 510 10 | 10, 419 11 | 11, 575 12 | 12, 639 13 | 13, 683 14 | 14, 705 15 | 15, 747 16 | 16, 1012 17 | 17, 997 18 | 18, 1029 19 | 19, 1019 20 | 20, 1102 21 | 21, 1018 22 | 22, 1100 23 | 23, 1107 24 | 24, 1009 25 | 25, 1102 26 | 26, 1060 27 | 27, 1125 28 | 28, 1100 29 | 29, 1028 30 | 30, 1117 31 | 31, 1112 32 | 32, 1118 33 | 33, 1120 34 | 34, 1038 35 | 35, 1103 36 | 36, 1100 37 | 37, 1123 38 | 38, 1064 39 | 39, 1068 40 | 40, 1050 41 | 41, 1106 42 | 42, 1104 43 | 43, 1029 44 | 44, 1018 45 | 45, 1072 46 | 46, 1195 47 | 47, 1038 48 | 48, 1158 49 | 49, 1052 50 | 50, 1105 51 | 51, 1021 52 | 52, 1117 53 | 53, 1086 54 | 54, 1047 55 | 55, 1048 56 | 56, 1068 57 | 57, 1152 58 | 58, 1228 59 | 59, 1128 60 | 60, 1132 61 | 61, 1140 62 | 62, 1092 63 | 63, 1123 64 | 64, 1037 65 | 128, 972 66 | 256, 971 67 | 512, 1054 68 | 1024, 948 69 | 2048, 1279 70 | 4096, 1319 71 | 8192, 1782 72 | 16384, 1921 73 | 32768, 1965 74 | 65536, 1916 75 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/data-v4-aws.csv: -------------------------------------------------------------------------------- 1 | 1, 325 2 | 2, 312 3 | 3, 333 4 | 4, 329 5 | 5, 345 6 | 6, 332 7 | 7, 327 8 | 8, 341 9 | 9, 372 10 | 10, 425 11 | 11, 550 12 | 12, 660 13 | 13, 694 14 | 14, 703 15 | 15, 726 16 | 16, 972 17 | 17, 1025 18 | 18, 886 19 | 19, 1041 20 | 20, 1109 21 | 21, 1131 22 | 22, 1117 23 | 23, 1094 24 | 24, 1018 25 | 25, 1062 26 | 26, 1017 27 | 27, 1139 28 | 28, 1072 29 | 29, 1077 30 | 30, 1111 31 | 31, 1107 32 | 32, 1126 33 | 33, 1047 34 | 34, 1093 35 | 35, 1109 36 | 36, 1056 37 | 37, 1099 38 | 38, 1040 39 | 39, 1078 40 | 40, 1069 41 | 41, 1092 42 | 42, 1030 43 | 43, 1078 44 | 44, 1058 45 | 45, 1283 46 | 46, 1059 47 | 47, 993 48 | 48, 1030 49 | 49, 1078 50 | 50, 1216 51 | 51, 1069 52 | 52, 1037 53 | 53, 1056 54 | 54, 1068 55 | 55, 1084 56 | 56, 1031 57 | 57, 1174 58 | 58, 1149 59 | 59, 1138 60 | 60, 1105 61 | 61, 1040 62 | 62, 1000 63 | 63, 1007 64 | 64, 1134 65 | 128, 897 66 | 256, 929 67 | 512, 1029 68 | 1024, 1025 69 | 2048, 1303 70 | 4096, 1300 71 | 8192, 1792 72 | 16384, 1908 73 | 32768, 1902 74 | 65536, 1984 75 | -------------------------------------------------------------------------------- /os/OSTEP/05-process-api/homeworks/p8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int arc, char *argv[]) { 6 | int pfd[2]; 7 | 8 | if (pipe(pfd) < 0) { 9 | fprintf(stderr, "Pipe failed\n"); 10 | } 11 | 12 | int rc1 = fork(); 13 | if (rc1 < 0) { 14 | fprintf(stderr, "failed to fork\n"); 15 | } else if(rc1 == 0) { 16 | close(pfd[0]); 17 | dup2(pfd[1], STDOUT_FILENO); 18 | execlp("grep", "grep", "fork", "p8.c", NULL); 19 | } else { 20 | int rc2 = fork(); 21 | 22 | if (rc2 < 0) { 23 | printf("Second fork failed\n"); 24 | } else if (rc2 == 0) { 25 | close(pfd[1]); 26 | dup2(pfd[0], STDIN_FILENO); 27 | execlp("wc", "wc", "-l", NULL); 28 | } else { 29 | // waitpid((pid_t) rc2, NULL, WUNTRACED); 30 | // wait(NULL); 31 | printf("Parent (pid: %d)\n", (int) getpid()); 32 | } 33 | } 34 | 35 | return 0; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /os/OSTEP/45-data-integrity-and-protection/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 45 solution 2 | 3 | ## Question 1 4 | 5 | Sum: 71 6 | Xor: 51 7 | Fletcher: 73 196 8 | 9 | ## Question 3 10 | 11 | `./checksum.py -D 136,68,34,17 -c` 12 | 13 | It can happen when there is only one `1` in a position in all the bytes. 14 | 15 | ## Question 4 16 | 17 | `./checksum.py -D 134,129,1,8 -c` 18 | 19 | ## Question 5 20 | 21 | Additive checksum will be same for any data set if their summation is same is same. For example 22 | 23 | ``` 24 | ./checksum.py -D 134,129,1,8 -c 25 | ./checksum.py -D 131,130,2,9 -c 26 | ``` 27 | 28 | ## Question 6 29 | 30 | ``` 31 | ./checksum.py -D 88,145,37,168 -c 32 | ./checksum.py -D 216,149,33,40 -c 33 | ``` 34 | 35 | In general it can happen if bit flip happens in a complementary way in any two of the bytes. 36 | 37 | ## Question 7 38 | 39 | Fletcher respects the order of the data unlike the other two. 40 | 41 | ## Question 8 42 | 43 | ``` 44 | ./checksum.py -D 0,1,2,258 -c 45 | ./checksum.py -D 0,1,2,3 -c 46 | ``` 47 | -------------------------------------------------------------------------------- /os/OSTEP/41-fast-fs/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 41 solution 2 | 3 | ## Question 1 4 | 5 | `-L 4` spreads out the file. 6 | 7 | ## Question 2 8 | 9 | `-L 30` gives same result as without `-L` flag because each group can have at most 30 data blocks. 10 | 11 | ## Question 3 12 | 13 | Filespan should decrease as `-L` increase up to 30. 14 | 15 | ## Question 4 16 | 17 | Three groups should be used for the three directories. 18 | 19 | 20 | ## Question 5 21 | 22 | It does pretty well. Can't get better if inodes and data blocks are kept separate. 23 | 24 | ## Question 6 25 | 26 | `dirspan` is affected badly. Besides a lot of data blocks in every group stays unused because small files. 27 | 28 | ## Question 7 29 | 30 | This policy is better for `dirspan` because it prevents from another directory from getting in between a directory and its file inodes. 31 | 32 | ## Question 8 33 | 34 | `i` is spread out in fragments. 35 | 36 | ## Question 9 37 | 38 | `filspan` and `dirspan` is increased. But blocks of a file stays together. 39 | 40 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/tlb.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define PAGESIZE 4096 9 | #define LOOP 100000 10 | 11 | long get_dt(long s1, long u1, long s2, long u2) { 12 | return (s2-s1)*1e6 + (u2-u1); 13 | } 14 | 15 | int main(int argc, char **argv) { 16 | cpu_set_t mask; 17 | CPU_ZERO(&mask); 18 | CPU_SET(0, &mask); 19 | sched_setaffinity(0, sizeof(mask), &mask); 20 | 21 | 22 | int pages = atoi(argv[1]); 23 | int jump = PAGESIZE / sizeof(int); 24 | struct timeval t; 25 | 26 | int *arr = malloc(sizeof(int)*pages*jump); 27 | for(int i = 0; i< pages*jump; i+=jump) 28 | arr[i] = 0; 29 | 30 | gettimeofday(&t, NULL); 31 | long tu = t.tv_usec; 32 | long ts = t.tv_sec; 33 | for(int k = 0; k < LOOP; k++) 34 | for(int i = 0; i< pages*jump; i+=jump) 35 | arr[i]+=1; 36 | 37 | gettimeofday(&t, NULL); 38 | printf("%lu\n", get_dt(ts, tu, t.tv_sec, t.tv_usec)/pages); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /os/OSTEP/45-data-integrity-and-protection/homeworks/check-csum.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define BLOCK_SIZE 4096 6 | 7 | char buff[BLOCK_SIZE]; 8 | 9 | char xor(char* block, int len) { 10 | char sum = 0; 11 | for(int i = 0; i 0) { 27 | scan_count = fscanf(sumfile, "%c\n", &sum); 28 | if (scan_count != 1 || sum != xor(buff, read_count)) { 29 | fprintf(stderr, "Corruption found at block: %d\n", block_count); 30 | exit(-1); 31 | } 32 | block_count++; 33 | } 34 | fclose(sumfile); 35 | printf("No corruption found\n"); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /os/OSTEP/20-advanced-page-tables/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 20 solution 2 | 3 | ## Question 1 4 | 5 | Just one should be enough. Because only address to the first level page directory base address needs to be stored in a register. The page directory entries can point to other page directories or tables. 6 | 7 | ## Question 2 8 | 9 | - `0x611c` -> `0b 11000 01000 11100` 10 | - `0b11000` -> 24, `0b01000` -> 8, `0b11100` -> 28 11 | - `pages[108][24`] -> `0xa1` -> `0b 1 0100001`, valid. 12 | - `0b0100001` -> 33 13 | - `pages[33][8]` -> `0xb5` -> `0b1 0110101`, valid. 14 | - `0b0110101` -> 53 15 | - `pages[53][28]` -> `0x8` -> 8 16 | 17 | So that's three memory access as expected. 18 | 19 | ## Question 3 20 | 21 | If I understand the question correctly, the way multi level page directories work so far, memory references to page tables aren't stored in TLB. TLB stores physical address against VPN. Page directories don't have VPN, they are stored outside the memory space of the current program by the system. 22 | 23 | So every TLB miss will result in two more TLB miss. 24 | -------------------------------------------------------------------------------- /os/OSTEP/31-semaphores/homeworks/rendezvous.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "common_threads.h" 4 | 5 | // If done correctly, each child should print their "before" message 6 | // before either prints their "after" message. Test by adding sleep(1) 7 | // calls in various locations. 8 | 9 | sem_t s1, s2; 10 | 11 | void *child_1(void *arg) { 12 | sleep(1); 13 | printf("child 1: before\n"); 14 | Sem_post(&s1); 15 | Sem_wait(&s2); 16 | printf("child 1: after\n"); 17 | return NULL; 18 | } 19 | 20 | void *child_2(void *arg) { 21 | printf("child 2: before\n"); 22 | Sem_post(&s2); 23 | Sem_wait(&s1); 24 | printf("child 2: after\n"); 25 | return NULL; 26 | } 27 | 28 | int main(int argc, char *argv[]) { 29 | pthread_t p1, p2; 30 | printf("parent: begin\n"); 31 | Sem_init(&s1, 0); 32 | Sem_init(&s2, 0); 33 | Pthread_create(&p1, NULL, child_1, NULL); 34 | Pthread_create(&p2, NULL, child_2, NULL); 35 | Pthread_join(p1, NULL); 36 | Pthread_join(p2, NULL); 37 | printf("parent: end\n"); 38 | return 0; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10010/uva10010.py: -------------------------------------------------------------------------------- 1 | x = int(input()) 2 | 3 | dxs = [-1, 0, 1] 4 | dys = [-1, 0, 1] 5 | 6 | 7 | def find(word): 8 | for i in range(m): 9 | for j in range(n): 10 | for dx in dxs: 11 | for dy in dys: 12 | if dx == 0 and dy == 0: 13 | continue 14 | for k, ch in enumerate(word): 15 | r = i + dx*k 16 | c = j + dy*k 17 | if r < 0 or c < 0 or r >= m or c >= n: 18 | break 19 | if ch != grid[r][c]: 20 | break 21 | else: 22 | return i+1, j+1 23 | 24 | 25 | for xx in range(x): 26 | input() 27 | m, n = map(int, input().split()) 28 | grid = [] 29 | for _ in range(m): 30 | grid.append(input().lower()) 31 | 32 | k = int(input()) 33 | for _ in range(k): 34 | print(*find(input().lower())) 35 | if xx != x-1: 36 | print('') 37 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/README.md: -------------------------------------------------------------------------------- 1 | # Programming Challenges 2 | 3 | ## Chapter 1: Introduction to Algorithm Design 4 | 5 | * [UVa 100 - The 3n + 1 problem](./uva100) 6 | 7 | * [UVa 10137 - The Trip](./uva10137) 8 | 9 | * [UVa 10142 - Australian Voting](./uva10142) 10 | 11 | ## Chapter 2: Algorithm Analysis 12 | 13 | * [UVa 10035 - Primary Arithmetic](./uva10035) 14 | 15 | * [UVa 847 - A Multiplication Game](./uva847) 16 | 17 | * [UVa 10110 - Light, more light](./uva10110) 18 | 19 | ## Chapter 3: Data Structures 20 | 21 | * [UVa 10038 - Jolly Jumpers](./uva10038) 22 | 23 | * [UVa 843 - Crypt Kicker](./uva843) 24 | 25 | * [UVa 850 - Crypt Kicker II](./uva850) 26 | 27 | * [UVa 10010 - Where's Waldorf?](./uva10010) 28 | 29 | ## Chapter 4: Sorting and Searching 30 | 31 | * [UVa 10041 - Vito's Family](./uva10041) 32 | 33 | * [UVa 120 - Stacks of Flapjacks](./uva120) 34 | 35 | * [UVa 10037 - Bridge](./uva10037) 36 | 37 | 38 | * [UVa 10026 - Shoemaker's Problem](./uva10026) 39 | 40 | * [UVa 10152 - ShellSort](./uva10152) 41 | 42 | * [UVa 10004 - Bicoloring](./uva10004) 43 | -------------------------------------------------------------------------------- /os/OSTEP/14-memory-api/homeworks/vector.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Vector { 5 | int size; 6 | int *elements; 7 | }; 8 | 9 | struct Vector* new_vector(int size) { 10 | struct Vector* newVector = malloc(sizeof(struct Vector)); 11 | newVector->size = size; 12 | newVector->elements = malloc(size *sizeof(int)); 13 | return newVector; 14 | } 15 | 16 | int get_element(struct Vector* v, int i) { 17 | return v->elements[i]; 18 | } 19 | void put_element(struct Vector* v, int i, int x) { 20 | v->elements[i] = x; 21 | } 22 | void push_element(struct Vector* v, int x) { 23 | // Could allocate 10 at a time and keep another property for allocated size 24 | v->elements = realloc(v->elements, sizeof(int)*(v->size+1)); 25 | v->elements[v->size] = x; 26 | v->size+=1; 27 | } 28 | int pop_element(struct Vector* v) { 29 | int ret = v->elements[v->size-1]; 30 | v->elements = realloc(v->elements, sizeof(int)*(v->size-1)); 31 | v->size-=1; 32 | return ret; 33 | } 34 | 35 | int main(int argc, char **argv) { 36 | struct Vector* list = new_vector(0); 37 | for(int i = 0; i<100; i++) { 38 | push_element(list, i); 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /os/OSTEP/39-files-and-directories/homeworks/stat.c: -------------------------------------------------------------------------------- 1 | #define _DEFAULT_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | int main(int argc, char** argv) { 11 | if (argc < 2) { 12 | printf("Specify file/directory\n"); 13 | exit(-1); 14 | } 15 | struct stat statbuf; 16 | if (stat(argv[1], &statbuf) < 0) { 17 | printf("Failed to get stats\n"); 18 | exit(-1); 19 | } 20 | printf("Inode : %lu\n", statbuf.st_ino); 21 | printf("Size : %'ld\n", statbuf.st_size); 22 | printf("Type : "); 23 | switch (statbuf.st_mode & S_IFMT) { 24 | case S_IFBLK: printf("block device\n"); break; 25 | case S_IFDIR: printf("directory\n"); break; 26 | case S_IFLNK: printf("symlink\n"); break; 27 | case S_IFREG: printf("regular file\n"); break; 28 | case S_IFSOCK: printf("socket\n"); break; 29 | default: printf("unknown?\n"); break; 30 | } 31 | printf("Link count : %lu\n", statbuf.st_nlink); 32 | return 0; 33 | } -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10037/uva10037.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | for ii in range(int(input())): 5 | if ii != 0: 6 | print('') 7 | input() 8 | n = int(input()) 9 | nums = [] 10 | for _ in range(n): 11 | nums.append(int(input())) 12 | nums.sort() 13 | 14 | if n == 1: 15 | print(nums[0]) 16 | print(nums[0]) 17 | continue 18 | elif n == 2: 19 | print(nums[1]) 20 | print(nums[0], nums[1]) 21 | continue 22 | 23 | i = len(nums)-1 24 | a, b = nums[:2] 25 | total = b+a 26 | 27 | res = f'{a} {b}\n{a}\n' 28 | 29 | while i > 1: 30 | left = i - 1 31 | if 2*b - a > nums[i-1] or left == 1: 32 | total += nums[i] 33 | res += f'{a} {nums[i]}\n' 34 | if left != 1: 35 | total += a 36 | res += f'{a}\n' 37 | 38 | i -= 1 39 | else: 40 | total += nums[i] + b*2 41 | res += f'{nums[i-1]} {nums[i]}\n{b}\n{a} {b}\n' 42 | 43 | if left > 2: 44 | total += a 45 | res += f'{a}\n' 46 | i -= 2 47 | print(total) 48 | print(res, end='') 49 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/Environment.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | class Environment { 7 | final Environment enclosing; 8 | private final ArrayList values = new ArrayList<>(); 9 | 10 | Environment() { 11 | enclosing = null; 12 | } 13 | 14 | Environment(Environment enclosing) { 15 | this.enclosing = enclosing; 16 | } 17 | 18 | void define(Object value) { 19 | values.add(value); 20 | } 21 | 22 | Environment ancestor(int distance) { 23 | Environment environment = this; 24 | for (int i = 0; i < distance; i++) { 25 | environment = environment.enclosing; 26 | } 27 | return environment; 28 | } 29 | 30 | Object getAt(int distance, Integer index) { 31 | return ancestor(distance).values.get(index); 32 | } 33 | 34 | void assignAt(int distance, Integer index, Object value) { 35 | ancestor(distance).values.set(index, value); 36 | } 37 | 38 | void assign(Integer index, Object value) { 39 | values.set(index, value); 40 | } 41 | 42 | Object get(int index) { 43 | return values.get(index); 44 | } 45 | } -------------------------------------------------------------------------------- /os/OSTEP/10-multi-cpu-scheduling/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 10 solution 2 | 3 | ## Question 1 4 | 5 | `./multi.py -n 1 -L a:30:200` 6 | 7 | With one CPU and one job, it should finish in 30 8 | 9 | ## Question 2 10 | 11 | The first 10 cycles will be the same, if `-r` is 2, the next 20 cycles will take ten. 12 | 13 | ## Question 3 14 | 15 | It decrease `-r` times faster with every tick after the CPU is warm. 16 | 17 | ## Question 4 18 | 19 | Works just as expected. Become after `-w` ticks. 20 | 21 | ## Question 5 22 | 23 | `./multi.py -n 2 -L a:100:100,b:100:50,c:100:50` 24 | 25 | The caches cannot hold all three of the working sets. On top of that the quantum is same as the warm up time. As soon as the CPU warms up, job is switched. Sad. 26 | 27 | ## Question 6 28 | 29 | `./multi.py -n 2 -L a:100:100,b:100:50,c:100:50 -A a:0,b:1,c:1` 30 | 31 | I think this combination is as good as it gets. `a` can't be be put put with other jobs in a CPU because of it's big working set. 32 | 33 | ## Question 7 34 | 35 | If we can run a job exclusively on a performance increase much more due to better cache usage. 36 | 37 | ## Question 8 38 | 39 | It works better than manual affinity because of better CPU utilization. Performance increase with lower values of `-P` 40 | -------------------------------------------------------------------------------- /os/OSTEP/38-raids/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 38 solution 2 | 3 | ## Question 1 4 | 5 | The left-symmetric layout seems like a strange way to layout the sectors. Not sure how this is supposed to help. 6 | 7 | ## Question 2 8 | 9 | Using bigger chunk again puts multiple parity blocks in the same disks for level 5. 10 | 11 | ## Question 4 12 | 13 | RAID 4 and 5 will be much more efficient all four of disks are used in single request. The reads can be omitted then. 14 | 15 | ## Question 5 16 | 17 | ``` 18 | ./raid.py -L 0 -t -n 100 -c # 275.7 19 | ./raid.py -L 1 -t -n 100 -c # 278.7 20 | ./raid.py -L 4 -t -n 100 -c # 386.1 21 | ./raid.py -L 5 -t -n 100 -c # 276.5 22 | ``` 23 | 24 | ## Question 6 25 | 26 | ``` 27 | ./raid.py -L 0 -n 100 -t -D 4 -c # 275.7 28 | ./raid.py -L 0 -n 100 -t -D 8 -c # 156.5 29 | ./raid.py -L 0 -n 100 -t -D 16 -c # 86.8 30 | ./raid.py -L 0 -n 100 -t -D 32 -c # 58.6 31 | ``` 32 | 33 | Other levels scales pretty similarly. 34 | 35 | ## Question 7 36 | 37 | Level 4 scales badly. Others scale similarly. 38 | 39 | ## Question 8 40 | 41 | Performance doesn't vary with read and write for sequential workload. But with random workload, using request size larger than `chunk size * number of disks` scales very well with larger requests. 42 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva850/uva850.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | n = int(input()) 4 | input() 5 | 6 | phrase = 'the quick brown fox jumps over the lazy dog' 7 | 8 | 9 | def match(line): 10 | if len(line) != len(phrase): 11 | return False 12 | 13 | for i, c in enumerate(line): 14 | if (c in mapping and mapping[c] != phrase[i]) or (c not in mapping and phrase[i] in mapped): 15 | return False 16 | if c not in mapping: 17 | mapping[c] = phrase[i] 18 | mapped.add(phrase[i]) 19 | return True 20 | 21 | 22 | for i in range(n): 23 | lines = [] 24 | while True: 25 | try: 26 | line = input() 27 | except: 28 | break 29 | if (line): 30 | lines.append(line) 31 | else: 32 | break 33 | found_match = False 34 | for line in lines: 35 | mapping = {' ': ' '} 36 | mapped = set() 37 | found_match = match(line) 38 | if found_match: 39 | break 40 | 41 | if found_match: 42 | for line in lines: 43 | for c in line: 44 | print(mapping[c], end='') 45 | print('') 46 | else: 47 | print('No solution.') 48 | 49 | if i != n-1: 50 | print('') 51 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/LoxClass.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | public class LoxClass implements LoxCallable { 7 | final String name; 8 | private final Map methods; 9 | 10 | LoxClass(String name, Map methods) { 11 | this.name = name; 12 | this.methods = methods; 13 | } 14 | 15 | LoxFunction findMethod(String name) { 16 | if (methods.containsKey(name)) { 17 | return methods.get(name); 18 | } 19 | 20 | return null; 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return name; 26 | } 27 | 28 | @Override 29 | public int arity() { 30 | LoxFunction initializer = findMethod("init"); 31 | if (initializer == null) return 0; 32 | return initializer.arity(); 33 | } 34 | 35 | @Override 36 | public Object call(Interpreter interpreter, List arguments) { 37 | LoxInstance instance = new LoxInstance(this); 38 | 39 | LoxFunction initializer = findMethod("init"); 40 | if (initializer != null) { 41 | initializer.bind(instance).call(interpreter, arguments); 42 | } 43 | 44 | return instance; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /os/OSTEP/27-thread-api/pi.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "math" 7 | "time" 8 | ) 9 | 10 | func term(i int64) float64 { 11 | return (1.0 / float64(i)) * (1.0 / float64(i)) 12 | } 13 | 14 | func segment(i int64, j int64, n int, c chan float64) { 15 | start := time.Now() 16 | sum := new(Float) 17 | for k := i; k <= j; k++ { 18 | sum += term(k) 19 | } 20 | fmt.Printf("Thread #%d finished in %s\n", n, time.Since(start)) 21 | c <- sum 22 | } 23 | 24 | func main() { 25 | threads := flag.Int("threads", 4, "Number of threads") 26 | digits := flag.Int64("digits", 2, "Number of precise digits after decimal point") 27 | flag.Parse() 28 | iterations := int64(math.Pow(10, float64(*digits+1))) 29 | 30 | perThread := iterations / int64(*threads) 31 | 32 | c := make(chan Float) 33 | 34 | start := time.Now() 35 | for i := 0; i < *threads; i++ { 36 | var j int64 = 0 37 | if i == *threads-1 { 38 | j = iterations 39 | } else { 40 | j = int64(i+1) * perThread 41 | } 42 | go segment(int64(i)*perThread+1, j, i, c) 43 | } 44 | var sum float64 = 0 45 | for i := 0; i < *threads; i++ { 46 | sum += <-c 47 | } 48 | pi := math.Sqrt(sum * 6) 49 | fmt.Printf("\nPI: %.*f\n", *digits, pi) 50 | fmt.Println("Threads: ", *threads) 51 | fmt.Println("Iterations: ", iterations) 52 | fmt.Println("Time: ", time.Since(start)) 53 | } 54 | -------------------------------------------------------------------------------- /os/OSTEP/18-paging/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 18 solution 2 | 3 | ## Question 1 4 | 5 | Table size will decrease as page size increase. But the problem with larger page would be internal fragmentation in the pages. 6 | 7 | ## Question 2 8 | 9 | `./paging-linear-translate.py -P 1k -a 16k -p 32k -v -u 0` 10 | 11 | All the addresses are invalid as none of the pages are allocated 12 | 13 | `./paging-linear-translate.py -P 1k -a 16k -p 32k -v -u 25` 14 | 15 | Page size is 1k, `log(1k) = 10` bits are required to describe every address. Address space size is 16k. There can be 16 pages in total, so `log(16) = 4` more bits are required to describe a page number. 16 | 17 | - 14726 -> 0b11100110000110. First four bit 0b1110 -> 14. Page 14 is not valid. So address not valid. 18 | - 11206 -> 0b10101111000110. First four bit 0b1010 -> 10. Page 10 is valid. PPN for page 10 is 0x13 -> 0b10011. So physical address is `0b10011 1111000110` -> 20422 19 | - 7735 -> 0b01111000110111. VPN: 0b0111 -> 7. Not valid. 20 | 21 | ## Question 3 22 | 23 | The first one is unrealistically small. 24 | 25 | ## Question 4 26 | 27 | The program doesn't work when: 28 | 29 | - Physical memory size is less or equal to the address space size. 30 | - Page is is bigger that address space size. 31 | - Page size or address space size is not power of 2. This is because it will result in discountinuous addresses. 32 | - Page or address space size is zero 33 | -------------------------------------------------------------------------------- /os/OSTEP/44-ssd/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 44 solution 2 | 3 | ## Question 1 4 | 5 | `./ssd.py -T log -s 2 -n 10 -q` 6 | 7 | write(58, F) 8 | write(46, 9) 9 | write(31, I) 10 | trim(31) 11 | write(35, g) 12 | read(46) -> 9 13 | read(35) -> g 14 | write(44, 3) 15 | read(58) 16 | write(79, F) 17 | 18 | ## Question 2 19 | 20 | Without overwrites, it is not that hard to figure out. 21 | 22 | ## Question 3 23 | 24 | Some commands try to read uninitialized data, which fails. 25 | 26 | ## Question 4 27 | 28 | `./ssd.py -T log -s 1 -n 10 -C` 29 | 30 | For the first erase 1000 + 160 for four program + 40 for four reads. 31 | 32 | ## Question 5 33 | 34 | The log structured approach performs much better for avoiding unnecessary erases which is very expensive. 35 | 36 | ## Question 6 37 | 38 | There garbage in the system. Storage will seem to be full even though it is not, because blocks with a few live pages can't be erased. It's actually more like fragmentation. 39 | 40 | ## Question 7 41 | 42 | I think think 7 3 is a good combination. 43 | 44 | 45 | ## Question 8 46 | 47 | The gc causes extra logical writes in the log structured approach. But it causes less physical writes and of course erases. 48 | 49 | ## Question 9 50 | 51 | Skewed workload gives better performance in both approaches. But the improvement is more significant in the log structured approach. 52 | 53 | This might be because skewed workload puts the active pages in same blocks. 54 | -------------------------------------------------------------------------------- /os/OSTEP/33-event-based-concurrency/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 33 solution 2 | 3 | ## Question 1 4 | [tcp.c](./tcp.c) 5 | 6 | Serves one connection at a time. Other connections wait while one connection is not fully done. Usages: 7 | 8 | `./tcp.c` 9 | 10 | In another shell, while running: 11 | 12 | ``` 13 | telnet localhost 8080 14 | 15 | Trying 127.0.0.1... 16 | Connected to localhost. 17 | Escape character is '^]'. 18 | 19 | Henlo! 20 | Server time: 14 Apr 2020 11:07 21 | 22 | hi # <- input 23 | hi you # <- response 24 | 25 | bye 26 | Connection closed by foreign host. 27 | ``` 28 | 29 | ## Question 2 30 | 31 | [multi-tcp.c](./multi-tcp.c) 32 | 33 | Can serve other connections while waiting for input in one. One interesting mistake that I made was not using `FD_CLR` after closing a connection. That causes the loop keep running even when there is not active connection. 34 | 35 | ## Question 4 36 | 37 | [aio-file-tcp.c](./aio-file-tcp.c) 38 | 39 | Apart from the cumbersome API C provides for doing stuff, incorporating async I/O was not that hard for this simple use case. 40 | 41 | ## Question 6 42 | 43 | Event based async approaches are worth it when the concurrency is too high, like thousands of connections. Using thousands of threads would be very expensive. And if the computation needed to serve a connection isn't too high, async approach is definitely the way to go. And if there is heavy computation to be done for any connection, that can be done in a separate thread. 44 | -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva843/uva843.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | n = int(input()) 4 | all_words = [] 5 | 6 | for i in range(n): 7 | all_words.append(input()) 8 | 9 | 10 | def match(idx): 11 | if idx == len(words): 12 | return True 13 | word = words[idx] # encrypted word 14 | 15 | for w in all_words: 16 | if len(word) != len(w): 17 | continue 18 | 19 | success = True 20 | added = set() 21 | for i, c in enumerate(word): 22 | if (c in mapping and mapping[c] != w[i]) or (c not in mapping and w[i] in mapped): 23 | for c in added: 24 | mapped.remove(mapping[c]) 25 | del mapping[c] 26 | success = False 27 | break 28 | if c not in mapping: 29 | mapping[c] = w[i] 30 | mapped.add(w[i]) 31 | added.add(c) 32 | if not success: 33 | continue 34 | 35 | if match(idx+1): 36 | return True 37 | else: 38 | for c in added: 39 | mapped.remove(mapping[c]) 40 | del mapping[c] 41 | return False 42 | 43 | 44 | for line in sys.stdin: 45 | words = line.split() 46 | mapping = {} 47 | mapped = set() 48 | found_match = match(0) 49 | 50 | for i, word in enumerate(words): 51 | for c in word: 52 | print(mapping[c] if found_match else '*', end='') 53 | if i != len(words)-1: 54 | print(' ', end='') 55 | print('') 56 | -------------------------------------------------------------------------------- /os/OSTEP/39-files-and-directories/homeworks/tree.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define INDENT 6 11 | 12 | char indent[1024]; 13 | 14 | 15 | void join_path(char* path1, char* path2, char* final) { 16 | sprintf(final, "%s%s%s", path1, path1[strlen(path1)-1] == '/' ? "" : "/", path2); 17 | } 18 | 19 | void print_contents(char* path, int level) { 20 | struct dirent* pDirent; 21 | DIR *pDir; 22 | struct stat statbuf; 23 | char new_path[1024]; 24 | 25 | if ((pDir = opendir(path)) == NULL) { 26 | return; 27 | } 28 | while ((pDirent = readdir(pDir)) != NULL ) { 29 | if (!strcmp(pDirent->d_name, ".") || !strcmp(pDirent->d_name, "..")) { 30 | continue; 31 | } 32 | 33 | printf("%s", indent); 34 | 35 | printf("%s\n", pDirent->d_name); 36 | join_path(path, pDirent->d_name, new_path); 37 | if (stat(new_path, &statbuf) < 0) { 38 | continue; 39 | } 40 | if (S_ISDIR(statbuf.st_mode)) { 41 | sprintf(indent+(level*INDENT), "\u2502 \u251c\u2500"); 42 | print_contents(new_path, level+1); 43 | sprintf(indent+(level*INDENT), "\u251c\u2500"); 44 | } 45 | } 46 | } 47 | 48 | 49 | int main(int argc, char** argv) { 50 | char* dir = argc >= 2 ? argv[1] : "."; 51 | sprintf(indent, "\u251c\u2500"); 52 | print_contents(dir, 0); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /os/OSTEP/48-distributed-systems/homeworks/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define BUFFER_SIZE 1024 8 | 9 | int UDP_Open(int port) { 10 | int sd; 11 | if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return -1; 12 | struct sockaddr_in myaddr; 13 | bzero(&myaddr, sizeof(myaddr)); 14 | myaddr.sin_family = AF_INET; 15 | myaddr.sin_port = htons(port); 16 | myaddr.sin_addr.s_addr = INADDR_ANY; 17 | if (bind(sd, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) { 18 | close(sd); 19 | return -1; 20 | } 21 | return sd; 22 | } 23 | 24 | int UDP_FillSockAddr(struct sockaddr_in *addr, char *hostname, int port) { 25 | bzero(addr, sizeof(struct sockaddr_in)); 26 | addr->sin_family = AF_INET; // host byte order 27 | addr->sin_port = htons(port); // network byte order 28 | struct in_addr *in_addr; 29 | struct hostent *host_entry; 30 | if ((host_entry = gethostbyname(hostname)) == NULL) return -1; 31 | in_addr = (struct in_addr *)host_entry->h_addr; 32 | addr->sin_addr = *in_addr; 33 | return 0; 34 | } 35 | 36 | int UDP_Write(int sd, struct sockaddr_in *addr, char *buffer, int n) { 37 | int addr_len = sizeof(struct sockaddr_in); 38 | return sendto(sd, buffer, n, 0, (struct sockaddr *)addr, addr_len); 39 | } 40 | 41 | int UDP_Read(int sd, struct sockaddr_in *addr, char *buffer, int n) { 42 | int len = sizeof(struct sockaddr_in); 43 | return recvfrom(sd, buffer, n, 0, (struct sockaddr *)addr, 44 | (socklen_t *)&len); 45 | } 46 | -------------------------------------------------------------------------------- /os/OSTEP/27-thread-api/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 27 solution 2 | 3 | ## Question 1 4 | 5 | It does points to the right line of code. Additionally it provides where the threads were created. 6 | 7 | ## Question 2 8 | 9 | Removing one of them make the reports go away as expected. 10 | 11 | Adding locks around the two operations makes the report go away when the thread is declared at global scope, i.e. the lock is the same lock for both cases. Initializing the lock after the second thread was created should be problematic, `helgrind` failed to report that. 12 | 13 | ## Question 3 14 | 15 | If both of the new threads start running at the same time, that would be a problem. Both of them will acquire one and wait for the other. Which they will never get. 16 | 17 | ## Question 4 18 | 19 | `helgrind` reports that lock order is violated. 20 | 21 | ## Question 5 22 | 23 | The problem should go away now. With the third lock, only one thread will be able to enter the code specific for only that thread. Then that thread will easily acquire both locks and then release them. Then the other thread can do the same. 24 | 25 | But `helgrind` still reports violation. 26 | 27 | ## Question 6 28 | 29 | It is inefficient because the parent keeps checking a condition repeatedly while the child id running. 30 | 31 | ## Question 7 32 | 33 | `helgrind` reports data race because of the `done = 1` write. 34 | 35 | ## Question 8 36 | 37 | Performance is is clearing a reason. Because the waiting thread will to sleep and thus will not keep using the CPU. But to me, it doesn't seem to be more correct. 38 | 39 | ## Question 9 40 | 41 | Doesn't report any problem. 42 | 43 | -------------------------------------------------------------------------------- /os/OSTEP/37-hard-disk-drive/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 37 solution 2 | 3 | ## Question 2 4 | 5 | One issue here is that the rotation keeps going on while seeking is being done. That causes unnecessary rotations sometimes. Higher seek rate helps only when it prevents such unnecessary rotation. Lower seek rate causes more of these unnecessary rotations, and thus decreases overall performance. If the rotation stopped during seeking, seek rate would have had direct impact on performance. 6 | 7 | ## Question 3 8 | 9 | Rotation rate always has direct relation to performance. But sometimes fast rotations can cause extra rotation and decrease performance. For example `./disk.py -a 7,30,8 -c -S 1 -R 4` is slower than `./disk.py -a 7,30,8 -c -S 1 -R 3` 10 | 11 | 12 | ## Question 4 13 | 14 | `-p SSSTF` performs better that `FIFO`. 15 | 16 | ## Question 5 17 | 18 | `./disk.py -a 7,19,35 -c -p SATF` is faster than `./disk.py -a 7,19,35 -c -p SSTF` 19 | 20 | When there is a request to sector that is close to seek, but requires more rotation, `SSTF` is slow. 21 | 22 | ## Question 6 23 | 24 | minium required skew = `(track_width / S) * (sector_per_track*R/360)` 25 | 26 | ## Question 7 27 | 28 | `./disk.py -z 10,20,30 -A 5,-1,0 -a -1 -G` 29 | 30 | Outer track bandwidth: `30/360 = .083` 31 | Middle track bandwidth: `20/360 = .083` 32 | Inner track bandwidth: `10/360 = .027` 33 | 34 | ## Question 8 35 | 36 | The window needs to be of size of number of requests to maximize performance. Window size of 1 makes all policy equal. 37 | 38 | ## Question 9 39 | 40 | `./disk.py -a 0,30,1,0,5,4,3,6` 41 | 42 | Using small window size solves starvation. 43 | 44 | 45 | ## Question 10 46 | 47 | `./disk.py -a 9,20 -p SATF` 48 | -------------------------------------------------------------------------------- /os/OSTEP/39-files-and-directories/homeworks/ls.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | void join_path(char* path1, char* path2, char* final) { 12 | sprintf(final, "%s%s%s", path1, path1[strlen(path1)-1] == '/' ? "" : "/", path2); 13 | } 14 | 15 | void print_stats(char* path) { 16 | struct stat statbuf; 17 | if (stat(path, &statbuf) < 0) { 18 | printf("Failed to get stats\n"); 19 | exit(-1); 20 | } 21 | printf("%5u %5u %5lu %12ld ", statbuf.st_uid, statbuf.st_uid, statbuf.st_nlink, statbuf.st_size); 22 | if (S_ISDIR(statbuf.st_mode)) printf("📂 "); 23 | else if (S_ISREG(statbuf.st_mode)) printf("📄 "); 24 | else if (S_ISLNK(statbuf.st_mode)) printf("🔗 "); 25 | else printf("👽 "); 26 | } 27 | 28 | 29 | int main(int argc, char** argv) { 30 | int show_details = 0, opt; 31 | while ((opt = getopt(argc, argv, "l")) != -1) { 32 | if (opt == 'l') show_details = 1; 33 | } 34 | char* dir = optind < argc ? argv[optind] : "."; 35 | 36 | char path[1024]; 37 | struct dirent* pDirent; 38 | DIR *pDir; 39 | 40 | if ((pDir = opendir(dir)) == NULL) { 41 | fprintf(stderr, "Failed to open directory\n"); 42 | exit(-1); 43 | } 44 | if (show_details) { 45 | printf(" UID GID NLink Size Type Name\n"); 46 | } 47 | while ((pDirent = readdir(pDir)) != NULL ) { 48 | if (show_details) { 49 | join_path(dir, pDirent->d_name, path); 50 | print_stats(path); 51 | } 52 | printf("%s\n", pDirent->d_name); 53 | } 54 | return 0; 55 | } -------------------------------------------------------------------------------- /os/OSTEP/31-semaphores/homeworks/mutex-nostarve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "common_threads.h" 6 | 7 | // 8 | // Here, you have to write (almost) ALL the code. Oh no! 9 | // How can you show that a thread does not starve 10 | // when attempting to acquire this mutex you build? 11 | // 12 | 13 | typedef struct __ns_mutex_t { 14 | int turn; 15 | int count; 16 | sem_t lock; 17 | sem_t turnlock; 18 | } ns_mutex_t; 19 | 20 | ns_mutex_t m; 21 | 22 | void ns_mutex_init(ns_mutex_t *m) { 23 | Sem_init(&m->lock, 1); 24 | Sem_init(&m->turnlock, 1); 25 | m->turn = 1; 26 | m->count = 0; 27 | } 28 | 29 | void ns_mutex_acquire(ns_mutex_t *m) { 30 | Sem_wait(&m->turnlock); 31 | int turn = ++m->count; 32 | while (turn != m->turn) { 33 | Sem_post(&m->turnlock); 34 | Sem_wait(&m->lock); 35 | Sem_wait(&m->turnlock); 36 | } 37 | Sem_post(&m->turnlock); 38 | } 39 | 40 | void ns_mutex_release(ns_mutex_t *m) { 41 | Sem_wait(&m->turnlock); 42 | m->turn++; 43 | Sem_post(&m->lock); 44 | Sem_post(&m->turnlock); 45 | } 46 | 47 | 48 | void *worker(void *arg) { 49 | printf("Started: %lu\n", pthread_self()); 50 | ns_mutex_acquire(&m); 51 | printf("Got lock: %lu\n", pthread_self()); 52 | ns_mutex_release(&m); 53 | return NULL; 54 | } 55 | 56 | int main(int argc, char *argv[]) { 57 | printf("parent: begin\n"); 58 | ns_mutex_init(&m); 59 | pthread_t threads[10]; 60 | for(int i = 0; i < 10; i++) { 61 | Pthread_create(&threads[i], NULL, worker, NULL); 62 | } 63 | for(int i = 0; i < 10; i++) { 64 | Pthread_join(threads[i], NULL); 65 | } 66 | printf("parent: end\n"); 67 | return 0; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /os/OSTEP/32-concurrency-bugs/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 32 solution 2 | 3 | ## Question 1 4 | 5 | The order in which the threads run changes from run to run. 6 | 7 | ## Question 2 8 | 9 | Deadlock never happens. Tried with higher value for `-l`, in a single core machine and multicore machine. 10 | 11 | ## Question 3 12 | 13 | Deadlock happens more often with `-n` more than three. 14 | 15 | ## Question 4 16 | 17 | The code avoids deadlock by using global order in acquiring the locks so that no circular wait happens. When the two vectors are same, waiting for the same lock for twice will cause deadlock. Hence the special case. 18 | 19 | ## Question 5 20 | 21 | `./vector-global-order -t -n 10 -l 100000 -d` takes about .05s. Increasing loops increase time somewhat linearly. Increasing number of threads increase time linearly as well. 22 | 23 | ## Question 6 24 | 25 | Performance increases as expected since the treads doesn't have to wait go acquire locks. 26 | 27 | ## Question 7 28 | 29 | The first call to `pthread_mutex_trylock` was not really necessary. It probably decrease performance even, since a normal `pthread_mutex_lock` would have slept while waiting. But this one will keep jumping. 30 | 31 | Performance is worse than global order approach and number of retries increase exponentially. 32 | 33 | ## Question 8 34 | 35 | In this case, the problem arise only when `-p` flag is used. Performance decrease as all the threads has to wait for the global lock even though they are working on different vectors. 36 | 37 | ## Question 9 38 | 39 | Not using locks at all makes the program much simpler with the same interface. 40 | 41 | # Question 10 42 | 43 | But surprisingly it is not a whole lot faster than other solutions. Slower that global order approach. 44 | -------------------------------------------------------------------------------- /os/OSTEP/04-processes/common_threads.h: -------------------------------------------------------------------------------- 1 | #ifndef __common_threads_h__ 2 | #define __common_threads_h__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef __linux__ 9 | #include 10 | #endif 11 | 12 | #define Pthread_create(thread, attr, start_routine, arg) assert(pthread_create(thread, attr, start_routine, arg) == 0); 13 | #define Pthread_join(thread, value_ptr) assert(pthread_join(thread, value_ptr) == 0); 14 | 15 | #define Pthread_mutex_lock(m) assert(pthread_mutex_lock(m) == 0); 16 | #define Pthread_mutex_unlock(m) assert(pthread_mutex_unlock(m) == 0); 17 | #define Pthread_cond_signal(cond) assert(pthread_cond_signal(cond) == 0); 18 | #define Pthread_cond_wait(cond, mutex) assert(pthread_cond_wait(cond, mutex) == 0); 19 | 20 | #define Mutex_init(m) assert(pthread_mutex_init(m, NULL) == 0); 21 | #define Mutex_lock(m) assert(pthread_mutex_lock(m) == 0); 22 | #define Mutex_unlock(m) assert(pthread_mutex_unlock(m) == 0); 23 | #define Cond_init(cond) assert(pthread_cond_init(cond, NULL) == 0); 24 | #define Cond_signal(cond) assert(pthread_cond_signal(cond) == 0); 25 | #define Cond_wait(cond, mutex) assert(pthread_cond_wait(cond, mutex) == 0); 26 | 27 | #ifdef __linux__ 28 | #define Sem_init(sem, value) assert(sem_init(sem, 0, value) == 0); 29 | #define Sem_wait(sem) assert(sem_wait(sem) == 0); 30 | #define Sem_post(sem) assert(sem_post(sem) == 0); 31 | #endif // __linux__ 32 | 33 | #endif // __common_threads_h__ 34 | -------------------------------------------------------------------------------- /os/OSTEP/31-semaphores/homeworks/common_threads.h: -------------------------------------------------------------------------------- 1 | #ifndef __common_threads_h__ 2 | #define __common_threads_h__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef __linux__ 9 | #include 10 | #endif 11 | 12 | #define Pthread_create(thread, attr, start_routine, arg) assert(pthread_create(thread, attr, start_routine, arg) == 0); 13 | #define Pthread_join(thread, value_ptr) assert(pthread_join(thread, value_ptr) == 0); 14 | 15 | #define Pthread_mutex_lock(m) assert(pthread_mutex_lock(m) == 0); 16 | #define Pthread_mutex_unlock(m) assert(pthread_mutex_unlock(m) == 0); 17 | #define Pthread_cond_signal(cond) assert(pthread_cond_signal(cond) == 0); 18 | #define Pthread_cond_wait(cond, mutex) assert(pthread_cond_wait(cond, mutex) == 0); 19 | 20 | #define Mutex_init(m) assert(pthread_mutex_init(m, NULL) == 0); 21 | #define Mutex_lock(m) assert(pthread_mutex_lock(m) == 0); 22 | #define Mutex_unlock(m) assert(pthread_mutex_unlock(m) == 0); 23 | #define Cond_init(cond) assert(pthread_cond_init(cond, NULL) == 0); 24 | #define Cond_signal(cond) assert(pthread_cond_signal(cond) == 0); 25 | #define Cond_wait(cond, mutex) assert(pthread_cond_wait(cond, mutex) == 0); 26 | 27 | #ifdef __linux__ 28 | #define Sem_init(sem, value) assert(sem_init(sem, 0, value) == 0); 29 | #define Sem_wait(sem) assert(sem_wait(sem) == 0); 30 | #define Sem_post(sem) assert(sem_post(sem) == 0); 31 | #endif // __linux__ 32 | 33 | #endif // __common_threads_h__ -------------------------------------------------------------------------------- /algorithms/the-algorithm-design-manual/programming-challenges/uva10142/uva10142.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from collections import deque 3 | 4 | 5 | def line(): 6 | return sys.stdin.readline() 7 | 8 | 9 | class Candidate: 10 | def __init__(self, name, idx): 11 | self.name = name 12 | self.votes = 0 13 | self.idx = idx 14 | 15 | 16 | nn = int(line()) 17 | line() 18 | 19 | for ii in range(nn): 20 | n = int(line()) 21 | candidates = {} 22 | for i in range(n): 23 | candidates[i+1] = Candidate(line().strip(), i+1) 24 | 25 | all_votes = [] 26 | while True: 27 | votes = deque(map(int, line().split())) 28 | if not votes: 29 | break 30 | all_votes.append(votes) 31 | 32 | for votes in all_votes: 33 | if votes and votes[0] in candidates: 34 | candidates[votes[0]].votes += 1 35 | 36 | while True: 37 | sorted_candidates = sorted(candidates.values(), key=lambda c: c.votes, reverse=True) 38 | eliminated = [sorted_candidates.pop()] 39 | while sorted_candidates and sorted_candidates[-1].votes == eliminated[0].votes: 40 | eliminated.append(sorted_candidates.pop()) 41 | 42 | for c in eliminated: 43 | for votes in all_votes: 44 | if votes[0] == c.idx: 45 | votes.popleft() 46 | while votes and votes[0] not in candidates: 47 | votes.popleft() 48 | if votes: 49 | candidates[votes[0]].votes += 1 50 | del candidates[c.idx] 51 | if not candidates: 52 | for c in eliminated: 53 | print(c.name) 54 | break 55 | if sorted_candidates[0].votes * 2 > len(all_votes): 56 | print(sorted_candidates[0].name) 57 | break 58 | if ii != nn-1: 59 | print() 60 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 18 solution 2 | 3 | ## Question 1 4 | 5 | Since `gettimeofday` is a system call, it does take some time and there is a few micro second inaccuracy. My strategy here is to use only twice, so that the inaccuracy is negligible. 6 | 7 | ## Question 3 8 | 9 | About 100000 iterations give pretty stable result. Some distortions remain which doesn't go away with 10x more iterations. 10 | 11 | ## Question 4 12 | 13 | ![Chart](./chart.png) 14 | 100000 iterations. Intel Core i7-9750H CPU @ 2.60GHz, 2592 Mhz, 6 Core(s), 12 Logical Processor(s) and 8GB RAM. 15 | 16 | ![Chart AWS](./chart-aws.png) 17 | 100000 iterations. AWS t2.micro instance with 1 vCPU and 1GB RAM. 18 | 19 | Maybe because evolution in the savannah trained humans more to work with visual information than numbers. 20 | 21 | ## Question 5 22 | 23 | Compiler doesn't seem to be removing any loops here. If it did, could be solved easily by adding some other simple instructions like incrementing a counter and printing that counter later. 24 | 25 | ## Question 6 26 | 27 | When the programs runs for shorter length of time, the thread affinity doesn't cause much of a difference. But when it runs for long, the scheduler probably does bounce it around a few threads. 28 | ![with affinity](./chart-thread-affinity.png) 29 | With thread affinity. 30 | 31 | ![without affinity](./chart.png) 32 | Without thread affinity. Never gets above 2000 33 | 34 | ## Question 7 35 | 36 | Initialization doesn't effect this implementation. 37 | 38 | # Notes 39 | 40 | - The first level TLB can hold 8 entries. The second level TLB can hold about 4096 entries. 41 | - The first level TLB is about 3.5x faster than the second level TLB. And the second level TLB is about 2.5x faster that third level TLB (or plain page table). 42 | - In the graph, right before switching to third level TLB, there is a jump in performance, weird. 43 | -------------------------------------------------------------------------------- /os/OSTEP/06-limited-direct-execution/homeworks/system_call.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "common.h" 9 | 10 | int main(int argc, char *argv[]) { 11 | int ITERATION_COUNT; 12 | printf("Iteration count: "); 13 | scanf("%d", &ITERATION_COUNT); 14 | struct timeval t; 15 | gettimeofday(&t, NULL); 16 | long tu = t.tv_usec; 17 | long ts = t.tv_sec; 18 | long dt; 19 | for (int i = 0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BLOCKSIZE 5 9 | #define MAX_SIZE 1<<20 10 | 11 | #define MAX(x, y) (((x) > (y)) ? (x) : (y)) 12 | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 13 | 14 | void reverse(char* s, int len) { 15 | char tmp; 16 | for(int i = 0; i < len / 2; i++) { 17 | tmp = s[i]; 18 | s[i] = s[len-i-1]; 19 | s[len-i-1] = tmp; 20 | } 21 | } 22 | 23 | int main(int argc, char** argv) { 24 | int lines = 1, opt; 25 | char* path; 26 | while ((opt = getopt(argc, argv, "n:")) != -1) { 27 | if (opt == 'n') lines = atoi(optarg); 28 | } 29 | if (optind >= argc) { 30 | fprintf(stderr, "File path is required\n"); 31 | exit(-1); 32 | } else { 33 | path = argv[optind]; 34 | } 35 | 36 | int fd; 37 | struct stat statbuf; 38 | if ((fd = open(path, O_RDONLY)) < 0) { 39 | fprintf(stderr, "Can't read file %s\n", path); 40 | } 41 | fstat(fd, &statbuf); 42 | 43 | int done = 0, seek_pos = BLOCKSIZE, pos = 0, len, res_pos = 0, read_size; 44 | char buff[BLOCKSIZE+1], res[MAX_SIZE]; 45 | while (done < lines) { 46 | lseek(fd, MAX(-statbuf.st_size, -seek_pos), SEEK_END); 47 | read_size = MIN(BLOCKSIZE, statbuf.st_size - pos); 48 | read(fd, buff, read_size); 49 | len = strlen(buff); 50 | len = MIN(len, read_size); 51 | pos+= read_size; 52 | for(int i = len-1; i >= 0; i--) { 53 | if (buff[i] == '\n' && res_pos != 0) done++; 54 | if (done >= lines) break; 55 | res[res_pos++] = buff[i]; 56 | } 57 | if (len < BLOCKSIZE) break; 58 | seek_pos += BLOCKSIZE; 59 | } 60 | res[res_pos] = '\0'; 61 | reverse(res, res_pos); 62 | printf("%s\n", res); 63 | return 0; 64 | } -------------------------------------------------------------------------------- /os/OSTEP/06-limited-direct-execution/homeworks/context_switch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common.h" 7 | 8 | int main(int argc, char **argv) { 9 | int ITERATION; 10 | printf("Iteration count: "); 11 | scanf("%d", &ITERATION); 12 | int fd1[2]; 13 | int fd2[2]; 14 | char buff[128]; 15 | 16 | struct timeval t; 17 | 18 | if(pipe(fd1) < 0) { 19 | fprintf(stderr, "first pipe failed\n"); 20 | } 21 | if(pipe(fd2) < 0) { 22 | fprintf(stderr, "second pipe failed\n"); 23 | } 24 | 25 | int rc = fork(); 26 | if (rc < 0) { 27 | fprintf(stderr, "fork failed\n"); 28 | } else if (rc == 0) { 29 | close(fd1[0]); 30 | close(fd2[1]); 31 | 32 | gettimeofday(&t, NULL); 33 | int tu = t.tv_usec; 34 | int ts = t.tv_sec; 35 | for (int i = 0; i< ITERATION; i++) { 36 | read(fd2[0], buff, sizeof buff); 37 | // printf("Read from parent: %s\n\n", buff); 38 | 39 | sprintf(buff, "mommy-%d", i); 40 | write(fd1[1], buff, strlen(buff)); 41 | } 42 | gettimeofday(&t, NULL); 43 | long dt = get_dt(t.tv_sec, t.tv_usec, ts, tu); 44 | printf("In child: %.4f\n", dt/(double)ITERATION); 45 | 46 | } else { 47 | close(fd1[1]); 48 | close(fd2[0]); 49 | gettimeofday(&t, NULL); 50 | int tu = t.tv_usec; 51 | int ts = t.tv_sec; 52 | for (int i = 0; i< ITERATION; i++) { 53 | sprintf(buff, "baby-%d", i); 54 | write(fd2[1], buff, strlen(buff)); 55 | 56 | read(fd1[0], buff, sizeof buff); 57 | // printf("Read from child: %s\n", buff); 58 | } 59 | gettimeofday(&t, NULL); 60 | long dt = get_dt(t.tv_sec, t.tv_usec, ts, tu); 61 | printf("In parent: %.4f\n", dt/(double)ITERATION); 62 | } 63 | return 0; 64 | } -------------------------------------------------------------------------------- /os/OSTEP/28-locks/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 28 solution 2 | 3 | ## Question 1 4 | 5 | Yes, it is quite simple. 6 | 7 | ## Question 2 8 | 9 | `flag` will end up with 0 10 | 11 | ## Question 3 12 | 13 | The loops run twice, but flag still ends up with 0. 14 | 15 | ## Question 4 16 | 17 | The interrupt must not happen while the flag is being acquired. For higher values of `bx`, the program never works correctly, unless the interrupt frequency is lower that the whole time a thread needs to finish. 18 | 19 | ## Question 5 20 | 21 | Test and set the lock variable, if the lock variable was 0 before setting, critical section starts. Otherwise wait in loop. Releasing lock is simply setting 0 to the lock variable. 22 | 23 | ## Question 6 24 | 25 | It does work correctly all the time. But the CPU waste is high if the interrupt frequency is low. 26 | 27 | ## Question 7 28 | 29 | It prevents acquisition of a acquired lock, but fairness is not guaranteed here. 30 | 31 | ## Question 8 32 | 33 | It makes sense. The turn variable is there to make sure, two thread doesn't get stuck infinitely in attempt to acquire a lock. It's like one thread saying to the other: 'I am about to attempt acquiring the lock. But if I can't (because you already set your flag to 1) then you can go ahead even though my flag is set to 1. 34 | 35 | ## Question 9 36 | 37 | It works. Can't see any different behavior. 38 | 39 | ## Question 10 40 | 41 | We can use interrupt frequency from 1 to high number to show that no matter where one thread gets interrupted, it still produces correct result. 42 | 43 | ## Question 11 44 | 45 | It is like described in the chapter. It does spend time on spin-waiting just like any spinning lock. 46 | 47 | ## Question 12 48 | 49 | It still works with more threads. 50 | 51 | ## Question 13 52 | 53 | With any low interrupt frequency, `yeild` can save about 40-50 percent CPU time. 54 | 55 | ## Question 14 56 | 57 | It does some savings only if writing or the `xchg` is considered expensive 58 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/LoxFunction.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | import java.util.List; 4 | 5 | public class LoxFunction implements LoxCallable { 6 | private final List params; 7 | private final List body; 8 | private final Token name; 9 | private final Environment closure; 10 | private final boolean isInitializer; 11 | 12 | public LoxFunction(Stmt.Function declaration, Environment closure, boolean isInitializer) { 13 | this.params = declaration.params; 14 | this.body = declaration.body; 15 | this.name = declaration.name; 16 | this.closure = closure; 17 | this.isInitializer = isInitializer; 18 | } 19 | 20 | public LoxFunction(Expr.Function declaration, Environment closure) { 21 | this.params = declaration.params; 22 | this.body = declaration.body; 23 | this.name = null; 24 | this.closure = closure; 25 | this.isInitializer = false; 26 | } 27 | 28 | LoxFunction bind(LoxInstance instance) { 29 | Environment environment = new Environment(closure); 30 | environment.define(instance); 31 | return new LoxFunction(new Stmt.Function(name, params, body), environment, isInitializer); 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return ""; 37 | } 38 | 39 | @Override 40 | public int arity() { 41 | return params.size(); 42 | } 43 | 44 | @Override 45 | public Object call(Interpreter interpreter, List arguments) { 46 | Environment environment = new Environment(closure); 47 | for (int i = 0; i < params.size(); i++) { 48 | environment.define(arguments.get(i)); 49 | } 50 | try { 51 | interpreter.executeBlock(body, environment); 52 | } catch (Return returnValue) { 53 | if (isInitializer) return closure.getAt(0, 0); 54 | return returnValue.value; 55 | } 56 | 57 | if (isInitializer) return closure.getAt(0, 0); 58 | 59 | return null; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/sample.lox: -------------------------------------------------------------------------------- 1 | // this is single line comment 2 | 3 | /* this is a multiline comment 4 | /* nested */ 5 | */ 6 | 7 | // (2 + 2 * 3 / 4 , 11 != 12 + 1) 8 | 9 | // (1, 1), 2 10 | 11 | // 1 + 2 12 | 13 | // 1 == 2 ? 3 == 4 ? "false" : "true" : 0 14 | 15 | // 1 + 2 == 4 ? "true" : 0 / 0 16 | 17 | // 10/0 18 | 19 | // if (10 > 20 and 10 / 0) { 20 | // print "greater"; 21 | // } else { 22 | // print "smaller"; 23 | // } 24 | 25 | 26 | // var i = 1; 27 | 28 | // print i; 29 | 30 | // while (i <= 100) { 31 | // print "hello world"; 32 | 33 | // print i; 34 | 35 | // i = i + 1; 36 | // } 37 | 38 | // var a = 0; 39 | // var temp; 40 | 41 | // for (var b = 1; a < 10000; b = temp + b) { 42 | // print a; 43 | // temp = a; 44 | // a = b; 45 | // } 46 | 47 | //var i = 0; 48 | 49 | // while (i < 100) { 50 | // print i; 51 | // if ( i == 50) { 52 | // { 53 | // print "hello"; 54 | // } 55 | // break; 56 | // } 57 | // { 58 | // print "xxxx"; 59 | // } 60 | // i = i + 1; 61 | // } 62 | 63 | // for (var i = 0; i < 10; i = i+1) { 64 | 65 | // if (i == 5) { 66 | // {continue;} 67 | // } 68 | // print i; 69 | 70 | // } 71 | 72 | // var t = clock(); 73 | 74 | // print t - clock(); 75 | 76 | // (fun() {print "hello func";})(); 77 | 78 | // var x = 10; 79 | 80 | var x = 20; 81 | 82 | print x; 83 | 84 | print clock(); 85 | 86 | fun counter() { 87 | var x= 0; 88 | return fun() { 89 | x = x + 1; 90 | return x; 91 | }; 92 | } 93 | 94 | var c = counter(); 95 | 96 | print c(); 97 | print c(); 98 | 99 | fun abs(x) { 100 | if (x < 0) return -x; 101 | return x; 102 | } 103 | 104 | fun sqrt(x) { 105 | var res = x; 106 | while (abs(res*res - x) > 0.00000000001) { 107 | res = res + (x - res*res)/(2*res); 108 | } 109 | return res; 110 | } 111 | 112 | class Vector { 113 | init(x, y) { 114 | this.x = x; 115 | this.y = y; 116 | } 117 | 118 | mod() { 119 | return sqrt(this.x*this.x + this.y*this.y); 120 | } 121 | } 122 | 123 | var v = Vector(10, 20); 124 | 125 | 126 | print v.mod(); -------------------------------------------------------------------------------- /os/OSTEP/33-event-based-concurrency/homeworks/tcp.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define PORT 8080 11 | #define BUFF_SIZE 1024 12 | 13 | void trimnewline(char* s) { 14 | int i = 0; 15 | while(i < BUFF_SIZE) { 16 | if(s[i] == '\r' || s[i] == '\n') { 17 | s[i] = '\0'; 18 | return; 19 | } 20 | i++; 21 | } 22 | } 23 | 24 | void get_greeting(char* buff) { 25 | time_t now; 26 | time(&now); 27 | struct tm* time_info = localtime(&now); 28 | strftime(buff, BUFF_SIZE, 29 | "\nHenlo!\nServer time: %d %b %Y %H:%M\n\n", 30 | time_info); 31 | } 32 | 33 | int main(int argc, char** argv) { 34 | char buffer[BUFF_SIZE] = {0}; 35 | char replay[BUFF_SIZE + 16]; 36 | 37 | // address for the socket 38 | struct sockaddr_in address; 39 | socklen_t addrlen = sizeof(address); 40 | address.sin_family = AF_INET; 41 | address.sin_addr.s_addr = INADDR_ANY; 42 | address.sin_port = htons(PORT); 43 | 44 | // set up the socket 45 | int socket_fd, opt = 1; 46 | socket_fd = socket(AF_INET, SOCK_STREAM, 0); 47 | setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 48 | bind(socket_fd, (struct sockaddr*) &address, addrlen); 49 | 50 | // prepare socket to take connections 51 | listen(socket_fd, 3); 52 | 53 | while(1) { 54 | // accept a connection 55 | int connection_fd = accept(socket_fd, (struct sockaddr*) &address, &addrlen); 56 | get_greeting(buffer); 57 | send(connection_fd, buffer, strlen(buffer), 0); 58 | // keep replaying until "bye" is received 59 | while (1) { 60 | read(connection_fd, buffer, sizeof(buffer)); 61 | trimnewline(buffer); 62 | 63 | if (strcmp(buffer, "bye") == 0) { 64 | break; 65 | } 66 | 67 | sprintf(replay, "%s you\n", buffer); 68 | send(connection_fd, replay, strlen(replay), 0); 69 | } 70 | // close the connection 71 | shutdown(connection_fd, SHUT_RDWR); 72 | } 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /os/OSTEP/27-thread-api/pi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define ul unsigned long long 8 | 9 | typedef struct { 10 | int num; 11 | ul i; 12 | ul j; 13 | double long* sum; 14 | } range_t; 15 | 16 | 17 | float get_dt(struct timeval *t1, struct timeval *t2) { 18 | return (t2->tv_sec - t1->tv_sec) + (t2->tv_usec - t1->tv_usec) / (float)1e6; 19 | } 20 | 21 | long double term(ul i) { 22 | long double t = ((long double)1.0 / i) * ((long double)1.0 / i); 23 | return t; 24 | } 25 | 26 | void *range(void *arg) { 27 | range_t *r = (range_t*) arg; 28 | struct timeval t1; 29 | gettimeofday(&t1, NULL); 30 | long double* sum = r->sum; 31 | for (ul k = r->i; k <= r->j; k++) { 32 | *sum += term(k); 33 | } 34 | struct timeval t2; 35 | gettimeofday(&t2, NULL); 36 | printf("Thread #%d finished in: %fs\n", r->num, get_dt(&t1, &t2)); 37 | return NULL; 38 | } 39 | 40 | int main(int argc, char **argv) { 41 | struct timeval t1; 42 | gettimeofday(&t1, NULL); 43 | 44 | ul iterations = atoll(argv[1]); 45 | int number_of_threads = argc >= 3 ? atoi(argv[2]) : 2; 46 | ul per_thread_iteration = iterations / number_of_threads; 47 | 48 | pthread_t threads[number_of_threads]; 49 | range_t ranges[number_of_threads]; 50 | double long sums[number_of_threads]; 51 | for(int i = 0; i < number_of_threads; i++) { 52 | ranges[i].i = i*per_thread_iteration + 1; 53 | ranges[i].j = i == number_of_threads-1 ? iterations : (i+1)*per_thread_iteration; 54 | ranges[i].num = i; 55 | sums[i] = 0; 56 | ranges[i].sum = &sums[i]; 57 | pthread_create(threads + i, NULL, range, ranges + i); 58 | } 59 | double long sum = 0; 60 | for(int i = 0; i< number_of_threads; i++) { 61 | pthread_join(threads[i], NULL); 62 | sum += sums[i]; 63 | } 64 | 65 | int precision = log10(iterations) - 1; 66 | printf("Value of PI %d digits afeter decimal point: %.*Lf\n", precision, precision, sqrtl(sum * (long double)6.0)); 67 | 68 | struct timeval t2; 69 | gettimeofday(&t2, NULL); 70 | printf("Time: %fs\n", get_dt(&t1, &t2)); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /os/OSTEP/17-freespace/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 17 solution 2 | 3 | ## Question 1 4 | 5 | `./malloc.py -n 10 -H 0 -p BEST -s 0 -c` 6 | 7 | Eventually we end up with size 1 free spaces as there is no coalesce. 8 | 9 | ## Question 2 10 | 11 | When `-p WORST` is used, the space doesn't get congested at first like before. But the final outcome will be same. 12 | 13 | ## Question 3 14 | 15 | Allocation gets fast with `-p FIRST` as one doesn't need to search of the best or worst match. 16 | 17 | ## Question 4 18 | 19 | First fit is not effected by how the list is sorted. Best and worst fit is benefitted from `SIZESORT+` and `SIZESORT-` respectively. However if we did have coalescing, `ADDRSORT` would have helped coalescing. 20 | 21 | ## Question 5 22 | 23 | Without coalescing and with higher `-n` we, end up with 1 sized free spaces. Which is not useful at all. 24 | 25 | When coalescing is on, `ADDRSORT` obviously gives the best result with all of the fitting policies. 26 | 27 | The other two sorting with coalescing: 28 | 29 | 1. Worst fit performs bad with either sorting. This is because the smaller free spaces doesn't get used until the larger free spaces get all chopped up. Over time, with sorting, these free spaces get separated from their contagious spaces. Which doesn't let them get coalesced. A different coalescing algorithm could solve this problem, but would coalescing much more time costly. 30 | 31 | 2. Best fit performs similarly with either sorting. Because smaller spaces get used more frequently and thus contagious spaces gets to stay together more compared to worst fit approach. 32 | 33 | 3. First fit with size sorting is just either worst fit or best fit. So, gives same result as them result. 34 | 35 | ## Question 6 36 | 37 | If `P` is higher than 50 the system gets full eventually. When it is below 50, the simulator still produces 50% allocation requests. Because one cant not free memory that is not allocated. 38 | 39 | ## Question 7 40 | 41 | Not possible with address sorting and coalescing on. 42 | 43 | * `./malloc.py -c -A +10,+15,+20,+25,+30,-0,-1,-2,-3,-4` 44 | * `./malloc.py -c -A +10,+15,+20,+25,+30,-0,-1,-2,-3,-4 -l SIZESORT+ -C` 45 | * `./malloc.py -c -A +10,+15,+20,+25,+30,-0,-1,-2,-3,-4 -l SIZESORT- -C` 46 | -------------------------------------------------------------------------------- /os/OSTEP/31-semaphores/homeworks/barrier.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "common_threads.h" 7 | 8 | // If done correctly, each child should print their "before" message 9 | // before either prints their "after" message. Test by adding sleep(1) 10 | // calls in various locations. 11 | 12 | // You likely need two semaphores to do this correctly, and some 13 | // other integers to track things. 14 | 15 | typedef struct __barrier_t { 16 | sem_t s; 17 | sem_t lock; 18 | int waiting; 19 | int theaads; 20 | } barrier_t; 21 | 22 | 23 | // the single barrier we are using for this program 24 | barrier_t b; 25 | 26 | void barrier_init(barrier_t *b, int num_threads) { 27 | Sem_init(&b->s, 0); 28 | Sem_init(&b->lock, 1); 29 | b->waiting = 0; 30 | b->theaads = num_threads; 31 | } 32 | 33 | void barrier(barrier_t *b) { 34 | Sem_wait(&b->lock); 35 | if (b->waiting < b->theaads -1) { 36 | b->waiting++; 37 | Sem_post(&b->lock); 38 | Sem_wait(&b->s); 39 | } 40 | Sem_post(&b->lock); // this is not necessary 41 | Sem_post(&b->s); 42 | 43 | } 44 | 45 | // 46 | // XXX: don't change below here (just run it!) 47 | // 48 | typedef struct __tinfo_t { 49 | int thread_id; 50 | } tinfo_t; 51 | 52 | void *child(void *arg) { 53 | tinfo_t *t = (tinfo_t *) arg; 54 | if(t->thread_id == 0) sleep(1); 55 | printf("child %d: before\n", t->thread_id); 56 | barrier(&b); 57 | printf("child %d: after\n", t->thread_id); 58 | return NULL; 59 | } 60 | 61 | 62 | // run with a single argument indicating the number of 63 | // threads you wish to create (1 or more) 64 | int main(int argc, char *argv[]) { 65 | assert(argc == 2); 66 | int num_threads = atoi(argv[1]); 67 | assert(num_threads > 0); 68 | 69 | pthread_t p[num_threads]; 70 | tinfo_t t[num_threads]; 71 | 72 | printf("parent: begin\n"); 73 | barrier_init(&b, num_threads); 74 | 75 | int i; 76 | for (i = 0; i < num_threads; i++) { 77 | t[i].thread_id = i; 78 | Pthread_create(&p[i], NULL, child, &t[i]); 79 | } 80 | 81 | for (i = 0; i < num_threads; i++) 82 | Pthread_join(p[i], NULL); 83 | 84 | printf("parent: end\n"); 85 | return 0; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /os/OSTEP/29-locked-data-structures/homeworks/counter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common.h" 8 | 9 | 10 | typedef struct { 11 | long counter; 12 | pthread_mutex_t lock; 13 | } counter_t; 14 | 15 | typedef struct { 16 | counter_t * counter; 17 | int iterations; 18 | int i; 19 | } arg_t; 20 | 21 | void init_counter(counter_t* counter) { 22 | counter->counter = 0; 23 | pthread_mutex_init(&counter->lock, NULL); 24 | } 25 | 26 | void inc_counter(counter_t* counter) { 27 | pthread_mutex_lock(&counter->lock); 28 | counter->counter+=1; 29 | pthread_mutex_unlock(&counter->lock); 30 | } 31 | 32 | int get_count(counter_t* counter) { 33 | int ret = -1; 34 | pthread_mutex_lock(&counter->lock); 35 | ret = counter->counter; 36 | pthread_mutex_unlock(&counter->lock); 37 | return ret; 38 | } 39 | 40 | void* inc(void* args) { 41 | arg_t* arg = (arg_t*) args; 42 | struct timeval t1; 43 | gettimeofday(&t1, NULL); 44 | for(int i = 0;iiterations; i++) { 45 | inc_counter(arg->counter); 46 | } 47 | struct timeval t2; 48 | gettimeofday(&t2, NULL); 49 | printf("Thread #%d: %f\n", arg->i, get_dt(&t1, &t2)); 50 | return NULL; 51 | } 52 | 53 | int main(int argc, char** argv) { 54 | setlocale(LC_NUMERIC, "en_US.UTF-8"); 55 | 56 | int number_of_threads = atoi(argv[1]); 57 | int iterations = atoi(argv[2]); 58 | 59 | counter_t counter; 60 | init_counter(&counter); 61 | 62 | pthread_t threads[number_of_threads]; 63 | arg_t args[number_of_threads]; 64 | 65 | for(int i = 0; i< number_of_threads; i++) { 66 | args[i].counter = &counter; 67 | args[i].iterations = iterations / number_of_threads; 68 | args[i].i = i; 69 | pthread_create(&threads[i], NULL, inc, &args[i]); 70 | } 71 | 72 | struct timeval t1; 73 | gettimeofday(&t1, NULL); 74 | for(int i = 0; i { 4 | String print(Expr expr) { 5 | return expr.accept(this); 6 | } 7 | 8 | @Override 9 | public String visitTernaryExpr(Expr.Ternary expr) { 10 | return parenthesize("ternary", expr.condition, expr.left, expr.right); 11 | } 12 | 13 | @Override 14 | public String visitBinaryExpr(Expr.Binary expr) { 15 | return parenthesize(expr.operator.lexeme, expr.left, expr.right); 16 | } 17 | 18 | @Override 19 | public String visitCallExpr(Expr.Call expr) { 20 | return "fun " + expr.callee.toString(); 21 | } 22 | 23 | @Override 24 | public String visitGetExpr(Expr.Get expr) { 25 | return expr.object.toString() + '.' + expr.name; 26 | } 27 | 28 | @Override 29 | public String visitSetExpr(Expr.Set expr) { 30 | return "Set " + expr.object.toString() + '.' + expr.name + ": " + expr.value; 31 | } 32 | 33 | @Override 34 | public String visitThisExpr(Expr.This expr) { 35 | return "this"; 36 | } 37 | 38 | @Override 39 | public String visitGroupingExpr(Expr.Grouping expr) { 40 | return parenthesize("group", expr.expression); 41 | } 42 | 43 | @Override 44 | public String visitLiteralExpr(Expr.Literal expr) { 45 | if (expr.value == null) return "nil"; 46 | return expr.value.toString(); 47 | } 48 | 49 | @Override 50 | public String visitLogicalExpr(Expr.Logical expr) { 51 | return parenthesize(expr.operator.lexeme, expr.left, expr.right); 52 | } 53 | 54 | @Override 55 | public String visitUnaryExpr(Expr.Unary expr) { 56 | return parenthesize(expr.operator.lexeme, expr.right); 57 | } 58 | 59 | @Override 60 | public String visitVariableExpr(Expr.Variable expr) { 61 | return expr.name.lexeme; 62 | } 63 | 64 | @Override 65 | public String visitFunctionExpr(Expr.Function expr) { 66 | return expr.toString(); 67 | } 68 | 69 | @Override 70 | public String visitAssignExpr(Expr.Assign expr) { 71 | return expr.name + " <- " + expr.value.toString(); 72 | } 73 | 74 | private String parenthesize(String name, Expr... exprs) { 75 | StringBuilder builder = new StringBuilder(); 76 | 77 | builder.append("(").append(name); 78 | for (Expr expr : exprs) { 79 | builder.append(" "); 80 | builder.append(expr.accept(this)); 81 | } 82 | builder.append(")"); 83 | 84 | return builder.toString(); 85 | } 86 | } -------------------------------------------------------------------------------- /os/OSTEP/31-semaphores/homeworks/reader-writer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "common_threads.h" 5 | 6 | // 7 | // Your code goes in the structure and functions below 8 | // 9 | 10 | typedef struct __rwlock_t { 11 | // sem_t readlock; 12 | sem_t countlock; 13 | sem_t writelock; 14 | 15 | int readers; 16 | } rwlock_t; 17 | 18 | 19 | void rwlock_init(rwlock_t *rw) { 20 | // Sem_init(&rw->readlock, 1); 21 | Sem_init(&rw->writelock, 1); 22 | Sem_init(&rw->countlock, 1); 23 | rw->readers = 0; 24 | } 25 | 26 | void rwlock_acquire_readlock(rwlock_t *rw) { 27 | Sem_wait(&rw->countlock); 28 | if(rw->readers == 0) { 29 | Sem_wait(&rw->writelock); 30 | } 31 | rw->readers++; 32 | Sem_post(&rw->countlock); 33 | } 34 | 35 | void rwlock_release_readlock(rwlock_t *rw) { 36 | Sem_wait(&rw->countlock); 37 | if(rw->readers == 1) { 38 | Sem_post(&rw->writelock); 39 | } 40 | rw->readers--; 41 | Sem_post(&rw->countlock); 42 | } 43 | 44 | void rwlock_acquire_writelock(rwlock_t *rw) { 45 | Sem_wait(&rw->writelock); 46 | } 47 | 48 | void rwlock_release_writelock(rwlock_t *rw) { 49 | Sem_post(&rw->writelock); 50 | } 51 | 52 | // 53 | // Don't change the code below (just use it!) 54 | // 55 | 56 | int loops; 57 | int value = 0; 58 | 59 | rwlock_t lock; 60 | 61 | void *reader(void *arg) { 62 | int i; 63 | for (i = 0; i < loops; i++) { 64 | rwlock_acquire_readlock(&lock); 65 | printf("read %d\n", value); 66 | rwlock_release_readlock(&lock); 67 | } 68 | return NULL; 69 | } 70 | 71 | void *writer(void *arg) { 72 | int i; 73 | for (i = 0; i < loops; i++) { 74 | rwlock_acquire_writelock(&lock); 75 | value++; 76 | printf("write %d\n", value); 77 | rwlock_release_writelock(&lock); 78 | } 79 | return NULL; 80 | } 81 | 82 | int main(int argc, char *argv[]) { 83 | assert(argc == 4); 84 | int num_readers = atoi(argv[1]); 85 | int num_writers = atoi(argv[2]); 86 | loops = atoi(argv[3]); 87 | 88 | pthread_t pr[num_readers], pw[num_writers]; 89 | 90 | rwlock_init(&lock); 91 | 92 | printf("begin\n"); 93 | 94 | int i; 95 | for (i = 0; i < num_readers; i++) 96 | Pthread_create(&pr[i], NULL, reader, NULL); 97 | for (i = 0; i < num_writers; i++) 98 | Pthread_create(&pw[i], NULL, writer, NULL); 99 | 100 | for (i = 0; i < num_readers; i++) 101 | Pthread_join(pr[i], NULL); 102 | for (i = 0; i < num_writers; i++) 103 | Pthread_join(pw[i], NULL); 104 | 105 | printf("end: value %d\n", value); 106 | 107 | return 0; 108 | } 109 | 110 | -------------------------------------------------------------------------------- /os/OSTEP/26-concurrency-and-threads/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 26 solution 2 | 3 | ## Question 1 4 | 5 | Assuming the initial value of `%dx` is 0, `%dx` will be -1 after executing the first line. 6 | 7 | ## Question 2 8 | 9 | `./x86.py -p loop.s -t 2 -i 100 -R dx -a dx=3,dx=3` 10 | No loading from memory is involved here. So as expected, in both threads, `%dx` will be 3,2,1,0 and then -1 and then the thread will exit. 11 | 12 | ## Question 3 13 | 14 | `./x86.py -p loop.s -t 2 -i 3 -r -R dx -a dx=3,dx=3` 15 | Still nothing, because register states are preserved on thread switches. 16 | 17 | ## Question 4 18 | 19 | `./x86.py -p looping-race-nolock.s -t 1 -M 2000` 20 | 21 | Value at 2000 changes to 1 when `%ax` is moved back to 2000 at line 8. 22 | 23 | ## Question 5 24 | 25 | `./x86.py -p looping-race-nolock.s -t 2 -M 2000 -a bx=3` 26 | 27 | Each thread keeps it own register state. So both of them loops three times. 28 | The final value would be simply 6 because the interruption frequency is too high for the threads to be interrupted after register is updated but before moved back to memory. 29 | 30 | ## Question 6 31 | 32 | `./x86.py -p looping-race-nolock.s -t 2 -M 2000 -i 4 -r -s 0` 33 | 34 | The final value would be 2. In this case the timing is safe. Both registers moves the value back before any interruptions happen. 35 | 36 | Not so in this case: 37 | `./x86.py -p looping-race-nolock.s -t 2 -M 2000 -i 4 -r -s 0` 38 | 39 | The critical section is this: 40 | 41 | ``` 42 | mov 2000, %ax # get 'value' at address 2000 43 | add $1, %ax # increment it 44 | mov %ax, 2000 # store it back 45 | ``` 46 | 47 | ## Question 7 48 | 49 | `./x86.py -p looping-race-nolock.s -t 2 -a bx=1 -M 2000 -i 1` 50 | 51 | If interruption frequency is at least 3 the program will give correct result provided the program runs in a single CPU. Because length if the critical section is 3 which is at the beginning of the program. 52 | 53 | ## Question 8 54 | 55 | `./x86.py -p looping-race-nolock.s -t 2 -a bx=100 -M 2000 -i 1` 56 | 57 | Even with higher loops, interrupt frequency 3 gives correct result. Because length of the non-critical section is 3 too. 58 | 59 | ## Question 9 60 | 61 | `./x86.py -p wait-for-me.s -a ax=1,ax=0 -R ax -M 2000` 62 | 63 | The final value has to be 1. Because the first thead just waits for the value to be 1 and no matter when it is started, the second thread sets it to 1. 64 | 65 | ## Question 10 66 | 67 | `./x86.py -p wait-for-me.s -a ax=0,ax=1 -R ax -M 2000` 68 | 69 | Thread 0 is just waiting for thread 1 to set the value to 1. If thread 0 runs before thead 1, it waits until interruption happens. Thats is a waste of CPU. Sorter interruption frequency will improve performance. 70 | -------------------------------------------------------------------------------- /os/OSTEP/19-tlb/homeworks/data-v1.csv: -------------------------------------------------------------------------------- 1 | 1, 202 2 | 2, 227 3 | 3, 368 4 | 4, 204 5 | 5, 214 6 | 6, 315 7 | 7, 218 8 | 8, 216 9 | 9, 249 10 | 10, 337 11 | 11, 408 12 | 12, 388 13 | 13, 429 14 | 14, 429 15 | 15, 480 16 | 16, 531 17 | 17, 670 18 | 18, 973 19 | 19, 963 20 | 20, 943 21 | 21, 857 22 | 22, 818 23 | 23, 808 24 | 24, 805 25 | 25, 808 26 | 26, 802 27 | 27, 810 28 | 28, 811 29 | 29, 811 30 | 30, 805 31 | 31, 805 32 | 32, 806 33 | 33, 815 34 | 34, 804 35 | 35, 807 36 | 36, 811 37 | 37, 806 38 | 38, 810 39 | 39, 805 40 | 40, 808 41 | 41, 804 42 | 42, 806 43 | 43, 806 44 | 44, 803 45 | 45, 804 46 | 46, 804 47 | 47, 809 48 | 48, 806 49 | 49, 806 50 | 50, 805 51 | 51, 805 52 | 52, 801 53 | 53, 832 54 | 54, 809 55 | 55, 804 56 | 56, 805 57 | 57, 791 58 | 58, 808 59 | 59, 807 60 | 60, 805 61 | 61, 809 62 | 62, 807 63 | 63, 805 64 | 64, 801 65 | 65, 795 66 | 66, 814 67 | 67, 811 68 | 68, 806 69 | 69, 808 70 | 70, 823 71 | 71, 822 72 | 72, 849 73 | 73, 827 74 | 74, 815 75 | 75, 804 76 | 76, 808 77 | 77, 913 78 | 78, 872 79 | 79, 839 80 | 80, 815 81 | 81, 810 82 | 82, 804 83 | 83, 808 84 | 84, 804 85 | 85, 809 86 | 86, 831 87 | 87, 817 88 | 88, 816 89 | 89, 809 90 | 90, 807 91 | 91, 807 92 | 92, 816 93 | 93, 830 94 | 94, 807 95 | 95, 811 96 | 96, 812 97 | 97, 823 98 | 98, 843 99 | 99, 830 100 | 100, 835 101 | 100, 823 102 | 110, 812 103 | 120, 810 104 | 130, 812 105 | 140, 808 106 | 150, 804 107 | 160, 808 108 | 170, 816 109 | 180, 801 110 | 190, 809 111 | 200, 855 112 | 210, 802 113 | 220, 802 114 | 230, 819 115 | 240, 802 116 | 250, 803 117 | 260, 815 118 | 270, 793 119 | 280, 811 120 | 290, 797 121 | 300, 816 122 | 310, 785 123 | 320, 801 124 | 330, 791 125 | 340, 821 126 | 350, 793 127 | 360, 801 128 | 370, 809 129 | 380, 809 130 | 390, 808 131 | 400, 805 132 | 410, 798 133 | 420, 787 134 | 430, 794 135 | 440, 795 136 | 450, 788 137 | 460, 814 138 | 470, 792 139 | 480, 800 140 | 490, 819 141 | 500, 794 142 | 510, 796 143 | 520, 797 144 | 530, 790 145 | 540, 787 146 | 550, 791 147 | 560, 807 148 | 570, 800 149 | 580, 805 150 | 590, 795 151 | 600, 791 152 | 610, 787 153 | 620, 791 154 | 630, 793 155 | 640, 790 156 | 650, 789 157 | 660, 794 158 | 670, 791 159 | 680, 805 160 | 690, 791 161 | 700, 787 162 | 710, 789 163 | 720, 783 164 | 730, 790 165 | 740, 789 166 | 750, 789 167 | 760, 793 168 | 770, 785 169 | 780, 788 170 | 790, 785 171 | 800, 784 172 | 810, 792 173 | 820, 792 174 | 830, 788 175 | 840, 788 176 | 850, 789 177 | 860, 787 178 | 870, 791 179 | 880, 790 180 | 890, 784 181 | 900, 788 182 | 910, 787 183 | 920, 809 184 | 930, 787 185 | 940, 790 186 | 950, 786 187 | 960, 792 188 | 970, 785 189 | 980, 846 190 | 990, 786 191 | 1000, 799 192 | 1000, 805 193 | 2000, 533 194 | 3000, 835 195 | 4000, 1228 196 | 5000, 1448 197 | 6000, 1567 198 | 7000, 1643 199 | 8000, 1709 200 | 9000, 1759 201 | 10000, 1791 202 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/Lox.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.math.RoundingMode; 7 | import java.nio.charset.Charset; 8 | import java.nio.file.Files; 9 | import java.nio.file.Paths; 10 | import java.util.List; 11 | 12 | 13 | public class Lox { 14 | private static final Interpreter interpreter = new Interpreter(); 15 | static boolean hadError = false; 16 | static boolean hadRuntimeError = false; 17 | 18 | public static void main(String[] args) throws IOException { 19 | if (args.length > 1) { 20 | System.out.println("Usage: jlox [script]"); 21 | System.exit(64); 22 | } else if (args.length == 1) { 23 | runFile(args[0]); 24 | } else { 25 | runPrompt(); 26 | } 27 | } 28 | 29 | private static void runFile(String path) throws IOException { 30 | byte[] bytes = Files.readAllBytes(Paths.get(path)); 31 | run(new String(bytes, Charset.defaultCharset())); 32 | 33 | if (hadError) System.exit(65); 34 | if (hadRuntimeError) System.exit(70); 35 | } 36 | 37 | private static void runPrompt() throws IOException { 38 | InputStreamReader input = new InputStreamReader(System.in); 39 | BufferedReader reader = new BufferedReader(input); 40 | 41 | for (; ; ) { 42 | System.out.print("> "); 43 | String line = reader.readLine(); 44 | if (line == null) break; 45 | if (line.length() > 0 && !line.endsWith(";")) { 46 | line = "print " + line + ";"; 47 | } 48 | run(line); 49 | hadError = false; 50 | } 51 | } 52 | 53 | private static void run(String source) { 54 | Scanner scanner = new Scanner(source); 55 | List tokens = scanner.scanTokens(); 56 | Parser parser = new Parser(tokens); 57 | List statements = parser.parse(); 58 | 59 | if (hadError) return; 60 | 61 | Resolver resolver = new Resolver(interpreter); 62 | resolver.resolve(statements); 63 | 64 | interpreter.interpret(statements); 65 | } 66 | 67 | static void error(int line, String message) { 68 | report(line, "", message); 69 | } 70 | 71 | static void runtimeError(RuntimeError error) { 72 | System.err.println(error.getMessage() + "\n[line " + error.token.line + "]"); 73 | hadRuntimeError = true; 74 | } 75 | 76 | private static void report(int line, String where, String message) { 77 | System.err.println("[line " + line + "] Error" + where + ": " + message); 78 | hadError = true; 79 | } 80 | 81 | static void error(Token token, String message) { 82 | if (token.type == TokenType.EOF) { 83 | report(token.line, " at end", message); 84 | 85 | } else { 86 | report(token.line, " at '" + token.lexeme + "'", message); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /os/OSTEP/16-segmentation/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 16 solution 2 | 3 | ## Question 1 4 | 5 | `segmentation.py -a 128 -p 512 -b 0 -l 20 -B 512 -L 20 -s 0` 6 | 7 | ``` 8 | ARG seed 0 9 | ARG address space size 128 10 | ARG phys mem size 512 11 | 12 | Segment register information: 13 | 14 | Segment 0 base (grows positive) : 0x00000000 (decimal 0) 15 | Segment 0 limit : 20 16 | 17 | Segment 1 base (grows negative) : 0x00000200 (decimal 512) 18 | Segment 1 limit : 59 19 | 20 | Virtual Address Trace 21 | VA 0: 0x00000061 (decimal: 97) --> PA or segmentation violation? 22 | VA 1: 0x00000035 (decimal: 53) --> PA or segmentation violation? 23 | VA 2: 0x00000021 (decimal: 33) --> PA or segmentation violation? 24 | VA 3: 0x00000041 (decimal: 65) --> PA or segmentation violation? 25 | VA 4: 0x00000033 (decimal: 51) --> PA or segmentation violation? 26 | 27 | For each virtual address, either write down the physical address it translates to 28 | OR write down that it is an out-of-bounds address (a segmentation violation). For 29 | this problem, you should assume a simple address space with two segments: the top 30 | bit of the virtual address can thus be used to check whether the virtual address 31 | is in segment 0 (topbit=0) or segment 1 (topbit=1). Note that the base/limit pairs 32 | given to you grow in different directions, depending on the segment, i.e., segment 0 33 | grows in the positive direction, whereas segment 1 in the negative. 34 | ``` 35 | 36 | ### The first address is 108 37 | 38 | - In 7 bit binary: `1100001`. The first bit suggest it is of `seg1`. 39 | - Without the first bit the address is 44 in decimal. 40 | - Since `seg1` growth is negative, we need to calculate how many units we need to come from end to reach 44. That would be `44 - 64 = -20`. (Address space size is 128, so seg1 max size is `128/2 = 64`) 41 | - `|-20| <= 20`. So the access is valid. 42 | - The physical translation would be `512 - 31 = 481` 43 | 44 | ### The second address is 53 45 | 46 | - In 7 bit binary: `1100001`. So in `seg0` 47 | - Without first bit: 33 48 | `33 - 64 = -31` 49 | - `|-31| > 20`. So invalid. 50 | 51 | ## Question 2 52 | 53 | Highest in legal `seg0` is 19. Lowest legal in `seg1` is 108. Lowest illegal in whole space is 20, highest illegal 107. 54 | Generate all the possible comma separated virtual address with this python script: 55 | 56 | ```py 57 | ','.join([str(i) for i in range(128)]) 58 | ``` 59 | 60 | Then use them with the `-A` flag. Of course one doesn't need all of them. Only `19,20,107,108` is enough. But why not? 61 | 62 | ## Question 3 63 | 64 | `./segmentation.py -a 16 -p 128 -A 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 --b0 0 --l0 2 --b1 16 --l1 2` 65 | 66 | ## Question 4 67 | 68 | Generated address are all within the address space. So one needs to give `seg0` and `seg1` length of 90% of the address space in total. 69 | 70 | `./segmentation.py -a 100 -p 512 -n 1000 --b0 0 --l0 45 --b1 100 --l1 45 -c` 71 | 72 | ## Question 5 73 | 74 | `./segmentation.py -a 100 -p 512 -n 10 --b0 0 --l0 0 --b1 100 --l1 0 -c` 75 | -------------------------------------------------------------------------------- /os/OSTEP/29-locked-data-structures/homeworks/sloppycounter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common.h" 8 | 9 | #define NUMCPUS 12 10 | 11 | int THREADS[NUMCPUS]; 12 | 13 | typedef struct { 14 | long count; 15 | long locals[NUMCPUS]; 16 | pthread_mutex_t glock; 17 | pthread_mutex_t llocks[NUMCPUS]; 18 | int threshold; 19 | } counter_t; 20 | 21 | typedef struct { 22 | counter_t * counter; 23 | int iterations; 24 | int i; 25 | } arg_t; 26 | 27 | void init_counter(counter_t* counter, int threshold) { 28 | counter->count = 0; 29 | counter->threshold = threshold; 30 | pthread_mutex_init(&counter->glock, NULL); 31 | for(int i = 0; illocks[i], NULL); 33 | counter->locals[i] = 0; 34 | } 35 | } 36 | 37 | void inc_counter(counter_t* counter, int thread_id) { 38 | int lock_id = thread_id % NUMCPUS; 39 | pthread_mutex_lock(&counter->llocks[lock_id]); 40 | counter->locals[lock_id]+=1; 41 | if(counter->locals[lock_id] > counter->threshold) { 42 | pthread_mutex_lock(&counter->glock); 43 | counter->count += counter->locals[lock_id]; 44 | counter->locals[lock_id] = 0; 45 | pthread_mutex_unlock(&counter->glock); 46 | } 47 | pthread_mutex_unlock(&counter->llocks[lock_id]); 48 | } 49 | 50 | int get_count(counter_t* counter) { 51 | int ret = -1; 52 | pthread_mutex_lock(&counter->glock); 53 | ret = counter->count; 54 | pthread_mutex_unlock(&counter->glock); 55 | return ret; 56 | } 57 | 58 | void* inc(void* args) { 59 | arg_t* arg = (arg_t*) args; 60 | struct timeval t1; 61 | gettimeofday(&t1, NULL); 62 | for(int i = 0;iiterations; i++) { 63 | inc_counter(arg->counter, arg->i); 64 | } 65 | struct timeval t2; 66 | gettimeofday(&t2, NULL); 67 | // printf("Thread #%d: %f\n", arg->i, get_dt(&t1, &t2)); 68 | return NULL; 69 | } 70 | 71 | int main(int argc, char** argv) { 72 | setlocale(LC_NUMERIC, "en_US.UTF-8"); 73 | 74 | int number_of_threads = argc >= 1 ? atoi(argv[1]) : 4; 75 | int iterations = argc >= 2 ? atoi(argv[2]) : 1e6; 76 | int threshold = argc >= 4 ? atoi(argv[3]) : 16; 77 | 78 | counter_t counter; 79 | init_counter(&counter, threshold); 80 | 81 | pthread_t threads[number_of_threads]; 82 | arg_t args[number_of_threads]; 83 | 84 | for(int i = 0; i< number_of_threads; i++) { 85 | args[i].counter = &counter; 86 | args[i].iterations = iterations / number_of_threads; 87 | args[i].i = i; 88 | pthread_create(&threads[i], NULL, inc, &args[i]); 89 | } 90 | 91 | struct timeval t1; 92 | gettimeofday(&t1, NULL); 93 | for(int i = 0; i 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define PORT 8080 12 | #define BUFF_SIZE 1024 13 | 14 | char buffer[BUFF_SIZE] = {0}; 15 | char replay[BUFF_SIZE + 16]; 16 | 17 | void trimnewline(char* s) { 18 | int i = 0; 19 | while(i < BUFF_SIZE) { 20 | if(s[i] == '\r' || s[i] == '\n') { 21 | s[i] = '\0'; 22 | return; 23 | } 24 | i++; 25 | } 26 | } 27 | 28 | void get_greeting(char* buff) { 29 | time_t now; 30 | time(&now); 31 | struct tm* time_info = localtime(&now); 32 | strftime(buff, BUFF_SIZE, 33 | "\nHenlo!\nServer time: %d %b %Y %H:%M:%S\n\n", 34 | time_info); 35 | } 36 | 37 | void send_greetings(int fd) { 38 | get_greeting(buffer); 39 | send(fd, buffer, strlen(buffer), 0); 40 | } 41 | 42 | int read_and_serve(int fd) { 43 | read(fd, buffer, sizeof(buffer)); 44 | trimnewline(buffer); 45 | 46 | if (strcmp(buffer, "bye") == 0) { 47 | return 1; 48 | } 49 | 50 | sprintf(replay, "%s you\n", buffer); 51 | send(fd, replay, strlen(replay), 0); 52 | return 0; 53 | } 54 | 55 | int main(int argc, char** argv) { 56 | // address for the socket 57 | struct sockaddr_in address; 58 | socklen_t addrlen = sizeof(address); 59 | address.sin_family = AF_INET; 60 | address.sin_addr.s_addr = INADDR_ANY; 61 | address.sin_port = htons(PORT); 62 | 63 | // set up the socket 64 | int socket_fd, opt = 1; 65 | socket_fd = socket(AF_INET, SOCK_STREAM, 0); 66 | setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 67 | bind(socket_fd, (struct sockaddr*) &address, addrlen); 68 | listen(socket_fd, 3); 69 | 70 | fd_set activeFDs; // the fds we are going to look for inputs 71 | FD_ZERO(&activeFDs); 72 | 73 | // this main socket fd is one of them 74 | FD_SET(socket_fd, &activeFDs); 75 | 76 | while(1) { 77 | fd_set readFDs = activeFDs; // copy 78 | select(FD_SETSIZE, &readFDs, NULL, NULL, NULL); 79 | for(int fd = 0; fd < FD_SETSIZE; fd++) { 80 | if (!FD_ISSET(fd, &readFDs)) continue; 81 | 82 | if (fd == socket_fd) { 83 | // input in the main socket fd, means new connect 84 | // accept it 85 | int new_connection = accept(fd, (struct sockaddr*) &address, &addrlen); 86 | // send greetings 87 | send_greetings(new_connection); 88 | // add this new connection fd to the active fds 89 | FD_SET(new_connection, &activeFDs); 90 | } else { 91 | // input in a already connected connection fd 92 | // read and serve, close if necessary 93 | int close = read_and_serve(fd); 94 | if (close) { 95 | FD_CLR(fd, &activeFDs); // don't monitor this fd anymore 96 | shutdown(fd, SHUT_RDWR); 97 | } 98 | } 99 | } 100 | } 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /os/OSTEP/42-fsck-and-journaling/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 42 solution 2 | 3 | ## Question 1 4 | ``` 5 | ./fsck.py -D 6 | 7 | ARG seed 0 8 | ARG seedCorrupt 0 9 | ARG numInodes 16 10 | ARG numData 16 11 | ARG numRequests 15 12 | ARG printFinal False 13 | ARG whichCorrupt -1 14 | ARG dontCorrupt True 15 | 16 | Final state of file system: 17 | 18 | inode bitmap 1100100010000110 19 | inodes [d a:0 r:4] [f a:-1 r:1] [] [] [d a:8 r:2] [] [] [] [d a:6 r:2] [] [] [] [] [f a:15 r:1] [f a:12 r:1] [] 20 | data bitmap 1000001010001001 21 | data [(.,0) (..,0) (g,8) (t,14) (w,4) (m,13)] [] [] [] [] [] [(.,8) (..,0)] [] [(.,4) (..,0) (p,1)] [] [] [] [z] [] [] [g] 22 | ``` 23 | 24 | ``` 25 | - / 26 | |---- g (d) 27 | |---- t (f) 28 | |---- w (d) 29 | | |---- p (f) 30 | |---- m (f) 31 | ``` 32 | 33 | 34 | ## Question 2 35 | 36 | ``` 37 | ARG seed 0 38 | ARG seedCorrupt 1 39 | ARG numInodes 16 40 | ARG numData 16 41 | ARG numRequests 15 42 | ARG printFinal False 43 | ARG whichCorrupt -1 44 | ARG dontCorrupt False 45 | 46 | Final state of file system: 47 | 48 | inode bitmap 1100100010000010 49 | inodes [d a:0 r:4] [f a:-1 r:1] [] [] [d a:8 r:2] [] [] [] [d a:6 r:2] [] [] [] [] [f a:15 r:1] [f a:12 r:1] [] 50 | data bitmap 1000001010001001 51 | data [(.,0) (..,0) (g,8) (t,14) (w,4) (m,13)] [] [] [] [] [] [(.,8) (..,0)] [] [(.,4) (..,0) (p,1)] [] [] [] [z] [] [] [g] 52 | 53 | Can you figure out how the file system was corrupted? 54 | ``` 55 | 56 | Inode block 13 is wrongly marked as unused. Marking it used fixes the problem. 57 | 58 | ## Question 3 59 | 60 | One corruption increase a reference count, while the other decreases one. Bot can be fixed by checking the contents of all the directories. 61 | 62 | ## Question 4 63 | 64 | `./fsck.py -S 5`. Fixing this one will not be simple. The system has to check if all directories has reference to their parents and themselves. Then have to check all the entries, and update name if parent inode is referred. This sort of corruption is unlikely to arise naturally though. 65 | 66 | `./fsck.py -S 38`, a file is simply renamed. Might be possible to detect from the name length in a real system. Not fixable. 67 | 68 | `./fsck.py -S 642`, Another rename. Easily detectable, because there's another entry with the same name. Not fixable. 69 | 70 | 71 | ## Question 5 72 | 73 | ``` 74 | ./fsck.py -S 6 75 | ./fsck.py -S 13 76 | ``` 77 | 78 | In both cases we have an inode that has data bus is not referred in any directory and is marked unused. In one case it is a file inode while in the other case it is a directory inode. They have to be cleared. 79 | 80 | ## Question 6 81 | 82 | ``` 83 | ./fsck.py -S 9 84 | ``` 85 | 86 | The system can check data block 15 to check it really is directory. If not then then can change the type. 87 | 88 | ## Question 7 89 | 90 | ``` 91 | ./fsck.py -S 15 92 | ``` 93 | 94 | Easily detectable and fixable. Inode 0 can not be file. No data is lost. 95 | 96 | ## Question 8 97 | 98 | `./fsck.py -S 10` 99 | 100 | The inode bitmap can help perhaps, but not if more than one such corruption happens. 101 | 102 | ## Question 9 103 | 104 | `./fsck.py -S 16` The data bitmap can be used to fix this, only if one such corruption happens. 105 | 106 | -------------------------------------------------------------------------------- /os/OSTEP/31-semaphores/homeworks/reader-writer-nostarve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "common_threads.h" 5 | 6 | // 7 | // Your code goes in the structure and functions below 8 | // 9 | 10 | typedef struct __rwlock_t { 11 | sem_t countlock; 12 | sem_t waitinglock; 13 | sem_t writelock; 14 | sem_t read_sem; 15 | 16 | int readers; 17 | int writer_waiting; 18 | } rwlock_t; 19 | 20 | 21 | void rwlock_init(rwlock_t *rw) { 22 | Sem_init(&rw->writelock, 1); 23 | Sem_init(&rw->countlock, 1); 24 | Sem_init(&rw->waitinglock, 1); 25 | Sem_init(&rw->read_sem, 0); 26 | rw->readers = 0; 27 | rw->writer_waiting = 0; 28 | } 29 | 30 | void rwlock_acquire_readlock(rwlock_t *rw) { 31 | Sem_wait(&rw->countlock); 32 | 33 | 34 | Sem_wait(&rw->waitinglock); 35 | if(rw->writer_waiting >= 1) { 36 | Sem_post(&rw->writelock); 37 | Sem_post(&rw->waitinglock); 38 | 39 | Sem_wait(&rw->read_sem); 40 | Sem_wait(&rw->writelock); 41 | } else { 42 | Sem_post(&rw->waitinglock); 43 | } 44 | 45 | if(rw->readers == 0) { 46 | Sem_wait(&rw->writelock); 47 | } 48 | rw->readers++; 49 | Sem_post(&rw->countlock); 50 | } 51 | 52 | void rwlock_release_readlock(rwlock_t *rw) { 53 | Sem_wait(&rw->countlock); 54 | if(rw->readers == 1) { 55 | Sem_post(&rw->writelock); 56 | } 57 | rw->readers--; 58 | Sem_post(&rw->countlock); 59 | } 60 | 61 | void rwlock_acquire_writelock(rwlock_t *rw) { 62 | Sem_wait(&rw->waitinglock); 63 | rw->writer_waiting++; 64 | Sem_post(&rw->waitinglock); 65 | 66 | Sem_wait(&rw->writelock); 67 | 68 | Sem_wait(&rw->waitinglock); 69 | rw->writer_waiting--; 70 | Sem_post(&rw->waitinglock); 71 | } 72 | 73 | void rwlock_release_writelock(rwlock_t *rw) { 74 | Sem_post(&rw->read_sem); 75 | Sem_post(&rw->writelock); 76 | } 77 | 78 | // 79 | // Don't change the code below (just use it!) 80 | // 81 | 82 | int loops; 83 | int value = 0; 84 | 85 | rwlock_t lock; 86 | 87 | void *reader(void *arg) { 88 | int i; 89 | for (i = 0; i < loops; i++) { 90 | rwlock_acquire_readlock(&lock); 91 | printf("read %d\n", value); 92 | rwlock_release_readlock(&lock); 93 | } 94 | return NULL; 95 | } 96 | 97 | void *writer(void *arg) { 98 | int i; 99 | for (i = 0; i < loops; i++) { 100 | rwlock_acquire_writelock(&lock); 101 | value++; 102 | printf("write %d\n", value); 103 | rwlock_release_writelock(&lock); 104 | } 105 | return NULL; 106 | } 107 | 108 | int main(int argc, char *argv[]) { 109 | assert(argc == 4); 110 | int num_readers = atoi(argv[1]); 111 | int num_writers = atoi(argv[2]); 112 | loops = atoi(argv[3]); 113 | 114 | pthread_t pr[num_readers], pw[num_writers]; 115 | 116 | rwlock_init(&lock); 117 | 118 | printf("begin\n"); 119 | 120 | int i; 121 | for (i = 0; i < num_readers; i++) 122 | Pthread_create(&pr[i], NULL, reader, NULL); 123 | for (i = 0; i < num_writers; i++) 124 | Pthread_create(&pw[i], NULL, writer, NULL); 125 | 126 | for (i = 0; i < num_readers; i++) 127 | Pthread_join(pr[i], NULL); 128 | for (i = 0; i < num_writers; i++) 129 | Pthread_join(pw[i], NULL); 130 | 131 | printf("end: value %d\n", value); 132 | 133 | return 0; 134 | } 135 | 136 | -------------------------------------------------------------------------------- /os/OSTEP/33-event-based-concurrency/homeworks/file-tcp.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | #define PORT 8080 14 | #define BUFF_SIZE 1024 15 | #define FILE_BUFFER_SIZE 1 << 20 // 1 MB 16 | 17 | char buffer[BUFF_SIZE] = {0}; 18 | char file_buff[FILE_BUFFER_SIZE]; 19 | char replay[BUFF_SIZE + 16]; 20 | 21 | void trimnewline(char* s) { 22 | int i = 0; 23 | while(i < BUFF_SIZE) { 24 | if(s[i] == '\r' || s[i] == '\n') { 25 | s[i] = '\0'; 26 | return; 27 | } 28 | i++; 29 | } 30 | } 31 | 32 | void get_greeting(char* buff) { 33 | time_t now; 34 | time(&now); 35 | struct tm* time_info = localtime(&now); 36 | strftime(buff, BUFF_SIZE, 37 | "\nHenlo!\nServer time: %d %b %Y %H:%M:%S\n\n", 38 | time_info); 39 | } 40 | 41 | void send_greetings(int fd) { 42 | get_greeting(buffer); 43 | send(fd, buffer, strlen(buffer), 0); 44 | } 45 | 46 | int read_and_serve(int fd) { 47 | read(fd, buffer, sizeof(buffer)); 48 | trimnewline(buffer); 49 | 50 | int f_fd = open(buffer, O_RDONLY); 51 | if (f_fd < 0) { 52 | sprintf(replay, "Failed to open file `%s`\n", buffer); 53 | send(fd, replay, strlen(replay), 0); 54 | return 0; 55 | } 56 | int nbytes = read(f_fd, file_buff, sizeof(file_buff)); 57 | file_buff[nbytes] = '\0'; 58 | 59 | send(fd, file_buff, strlen(file_buff), 0); 60 | return 1; 61 | } 62 | 63 | int main(int argc, char** argv) { 64 | // address for the socket 65 | struct sockaddr_in address; 66 | socklen_t addrlen = sizeof(address); 67 | address.sin_family = AF_INET; 68 | address.sin_addr.s_addr = INADDR_ANY; 69 | address.sin_port = htons(PORT); 70 | 71 | // set up the socket 72 | int socket_fd, opt = 1; 73 | socket_fd = socket(AF_INET, SOCK_STREAM, 0); 74 | setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 75 | bind(socket_fd, (struct sockaddr*) &address, addrlen); 76 | listen(socket_fd, 3); 77 | 78 | fd_set activeFDs; // the fds we are going to look for inputs 79 | FD_ZERO(&activeFDs); 80 | 81 | // this main socket fd is one of them 82 | FD_SET(socket_fd, &activeFDs); 83 | 84 | while(1) { 85 | fd_set readFDs = activeFDs; // copy 86 | select(FD_SETSIZE, &readFDs, NULL, NULL, NULL); 87 | for(int fd = 0; fd < FD_SETSIZE; fd++) { 88 | if (!FD_ISSET(fd, &readFDs)) continue; 89 | 90 | if (fd == socket_fd) { 91 | // input in the main socket fd, means new connect 92 | // accept it 93 | int new_connection = accept(fd, (struct sockaddr*) &address, &addrlen); 94 | // send greetings 95 | send_greetings(new_connection); 96 | // add this new connection fd to the active fds 97 | FD_SET(new_connection, &activeFDs); 98 | } else { 99 | // input in a already connected connection fd 100 | // read and serve, close if necessary 101 | int close = read_and_serve(fd); 102 | if (close) { 103 | FD_CLR(fd, &activeFDs); // don't monitor this fd anymore 104 | shutdown(fd, SHUT_RDWR); 105 | } 106 | } 107 | } 108 | } 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /os/OSTEP/30-condition-variables/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 30 solution 2 | 3 | ## Question 1 4 | 5 | ## Question 2 6 | 7 | Behavior doesn't change with larger buffer. NF is always 0 or 1. When `-C 0,0,0,0,0,0,1` is used, consumer sleeps for 1 second after every consumption. The producer fills whole the buffer in that time. 8 | 9 | ## Question 3 10 | 11 | ## Question 4 12 | 13 | `./main-two-cvs-while -p 1 -c 3 -m 1 -C 0,0,0,1,0,0,0:0,0,0,1,0,0,0:0,0,0,1,0,0,0 -l 10 -v -t` 14 | 15 | The first consumer gets a value without waiting and thus without sleeping. Then the second consumer gets to waiting, but when the producer release the lock after producing, the first consumer again acquires the lock. So when the second consumer wakes up, it doesn't get a value and sleeps for a second holding the lock. In this way, the second and third consumer sleeps for 9 second in total. And at end of stream, all three consumers sleeps for 1 second each. So, the program takes total 12 seconds and some for for the actual executing. 16 | 17 | ## Question 5 18 | 19 | Now it takes 11 seconds. Since there is only producers, there isn't much change. But since there is enough buffer slot now, one of the threads (the one that didn't come to c2 before main produced those EOS) doesn't have to wait for the EOS. 20 | 21 | ## Question 6 22 | 23 | `./main-two-cvs-while -p 1 -c 3 -m 1 -C 0,0,0,0,0,0,1:0,0,0,0,0,0,1:0,0,0,0,0,0,1 -l 10 -v -t` 24 | 25 | 5 seconds. 9 consumption happen in three batches with every consumer sleeping 1 second after a batch, since the consumers don't hold the lock while sleeping. After that 1 consumer has to consume the last value and sleep for one second while the other two consumes EOS and sleeps for 1 second after that. Then the consumer consuming the last value wakes up, consumes EOS and sleeps for 1 second. 26 | 27 | ## Question 7 28 | 29 | `./main-two-cvs-while -p 1 -c 3 -m 3 -C 0,0,0,0,0,0,1:0,0,0,0,0,0,1:0,0,0,0,0,0,1 -l 10 -v -t` 30 | 31 | Same as last time. 32 | 33 | ## Question 8 34 | 35 | It's not possible. Because there's only a single producers and a single consumer here. So one condition variable is enough. 36 | 37 | ## Question 9 38 | 39 | Maybe because of scheduling priority or execution speed of different CPUs I couldn't put the consumers and producers to sleep at the same time but did manage to put the main thread and one consumer to sleep at the same time. 40 | 41 | `./main-one-cv-while -l 3 -m 1 -p 1 -c 2 -v -t -P 0,0,0,0,0,0,1` 42 | 43 | ## Question 10 44 | 45 | Not possible with one consumer. With many consumers, problem happen without any sleeping. 46 | 47 | ## Question 11 48 | 49 | Problem should occur when two producers try to `do_fill` at the same time or two consumers try to `do_get` at the same time. Or one consumer checks that one value is available but when the lock is released before `do_get`, gets interrupted and another consumer consumes it by the time it resumes. 50 | 51 | But I failed to produce such a case with the provided tools. However modifying the code a little, it is easy. 52 | 53 | The code: 54 | 55 | ```diff 56 | void *consumer(void *arg) { 57 | int id = (int) arg; 58 | int tmp = 0; 59 | int consumed_count = 0; 60 | while (tmp != END_OF_STREAM) { c0; 61 | Mutex_lock(&m); c1; 62 | while (num_full == 0) { c2; 63 | Cond_wait(&fill, &m); c3; 64 | } 65 | 66 | - Mutex_unlock(&m); 67 | - tmp = do_get(); c4; 68 | + Mutex_unlock(&m); c4; 69 | + tmp = do_get(); 70 | Mutex_lock(&m); 71 | Cond_signal(&empty); c5; 72 | Mutex_unlock(&m); c6; 73 | consumed_count++; 74 | } 75 | 76 | // return consumer_count-1 because END_OF_STREAM does not count 77 | return (void *) (long long) (consumed_count - 1); 78 | } 79 | ``` 80 | 81 | Case: 82 | `./main-two-cvs-while-extra-unlock -p 1 -c 2 -m 2 -l 100 -v -C 0,0,0,0,1,0,0:0,0,0,0,1,0,0` 83 | -------------------------------------------------------------------------------- /os/OSTEP/43-lfs/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 43 solution 2 | 3 | ## Question 1 4 | 5 | ``` 6 | ./lfs.py -n 3 7 | 8 | INITIAL file system contents: 9 | [ 0 ] live checkpoint: 3 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 10 | [ 1 ] live [.,0] [..,0] -- -- -- -- -- -- 11 | [ 2 ] live type:dir size:1 refs:2 ptrs: 1 -- -- -- -- -- -- -- 12 | [ 3 ] live chunk(imap): 2 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 13 | 14 | command? 15 | command? 16 | command? 17 | 18 | FINAL file system contents: 19 | [ 0 ] ? checkpoint: 14 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20 | [ 1 ] ? [.,0] [..,0] -- -- -- -- -- -- 21 | [ 2 ] ? type:dir size:1 refs:2 ptrs: 1 -- -- -- -- -- -- -- 22 | [ 3 ] ? chunk(imap): 2 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 23 | [ 4 ] ? [.,0] [..,0] [ku3,1] -- -- -- -- -- 24 | [ 5 ] ? type:dir size:1 refs:2 ptrs: 4 -- -- -- -- -- -- -- 25 | [ 6 ] ? type:reg size:0 refs:1 ptrs: -- -- -- -- -- -- -- -- 26 | [ 7 ] ? chunk(imap): 5 6 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 27 | [ 8 ] ? z0z0z0z0z0z0z0z0z0z0z0z0z0z0z0z0 28 | [ 9 ] ? type:reg size:8 refs:1 ptrs: -- -- -- -- -- -- -- 8 29 | [ 10 ] ? chunk(imap): 5 9 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30 | [ 11 ] ? [.,0] [..,0] [ku3,1] [qg9,2] -- -- -- -- 31 | [ 12 ] ? type:dir size:1 refs:2 ptrs: 11 -- -- -- -- -- -- -- 32 | [ 13 ] ? type:reg size:0 refs:1 ptrs: -- -- -- -- -- -- -- -- 33 | [ 14 ] ? chunk(imap): 12 9 13 -- -- -- -- -- -- -- -- -- -- -- -- -- 34 | ``` 35 | 36 | Commands: 37 | 38 | ``` 39 | creat('/ku3') 40 | open('/ku3'); write(); close('/ku3'); 41 | creat('/qg9'); 42 | ``` 43 | 44 | Block 0,8,9,11,12,13,14 are active. 45 | 46 | ## Question 2 47 | 48 | The `-i` flag definitely makes it easier to understand the commands. 49 | 50 | ## Question 3 51 | 52 | ``` 53 | INITIAL file system contents: 54 | [ 0 ] live checkpoint: 3 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 55 | [ 1 ] live [.,0] [..,0] -- -- -- -- -- -- 56 | [ 2 ] live type:dir size:1 refs:2 ptrs: 1 -- -- -- -- -- -- -- 57 | [ 3 ] live chunk(imap): 2 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 58 | 59 | create file /us7 60 | write file /us7 offset=4 size=0 61 | write file /us7 offset=7 size=7 62 | ``` 63 | 64 | ``` 65 | [ 0 ] live checkpoint: 3 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 66 | --- 67 | [ 4 ] live [.,0] [..,0] [us7, 1] 68 | [ 5 ] live type:dir size:1 refs:2 ptrs: 4 -- -- -- -- -- -- -- 69 | [ 6 ] type: reg, size: 0, refs: 0, ptrs: -- -- -- -- -- -- -- -- 70 | [ 7 ] chunk(imap) 5 6 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 71 | [ 8 ] type:reg size:4 refs:1 ptrs: -- -- -- -- -- -- -- -- 72 | [ 9 ] chunk(imap): 5 8 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 73 | [ 10 ] live i0i0i0i0i0i0i0i0i0i0i0i0i0i0i0i0 74 | [ 11 ] live type:reg size:8 refs:1 ptrs: -- -- -- -- -- -- -- 10 75 | [ 12 ] live chunk(imap): 5 11 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 76 | ``` 77 | 78 | 79 | ## Question 4 80 | 81 | One needs to look into the last imap to find out the active files and directories. 82 | 83 | ## Question 5 84 | 85 | ` ./lfs.py -o -L c,/foo:w,/foo,0,1:w,/foo,1,1:w,/foo,2,1:w,/foo,3,1` 86 | 87 | Block 0,4,5,8,11,14,17,18,19 are live. Again the last imap helps. 88 | 89 | ## Question 6 90 | 91 | Apart from producing more write operations, small writes produce produce more garbage. 92 | 93 | ## Question 7 94 | 95 | `./lfs.py -L c,/foo:w,/foo,0,1` 96 | `./lfs.py -L c,/foo:w,/foo,7,1` 97 | 98 | The later writes with an offset, which makes the size in inode offset+write size. 99 | 100 | ## Question 8 101 | 102 | With directory creation, data block has to be written immediately. With file, data block is allocated and written when the file is written to. 103 | 104 | ## Question 9 105 | 106 | `./lfs.py -L c,/foo:l,/foo,/bar:l,/foo,/goo -o -i` 107 | 108 | In both cases, a new entry is added to the parent directory. But with a link, no new inodes are required. The old inode has to be updated and thus copied though with the new ref count. 109 | 110 | ## Question 10 111 | 112 | A random policy creates more fragmentation. 113 | -------------------------------------------------------------------------------- /os/OSTEP/22-swapping-policy/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 22 solution 2 | 3 | ## Question 1 4 | 5 | ``` 6 | ./paging-policy.py -s 0 -n 10 7 | ARG addresses -1 8 | ARG addressfile 9 | ARG numaddrs 10 10 | ARG policy FIFO 11 | ARG clockbits 2 12 | ARG cachesize 3 13 | ARG maxpage 10 14 | ARG seed 0 15 | ARG notrace False 16 | 17 | Assuming a replacement policy of FIFO, and a cache of size 3 pages, 18 | figure out whether each of the following page references hit or miss 19 | in the page cache. 20 | 21 | Access: 8 Hit/Miss? State of Memory? 22 | Access: 7 Hit/Miss? State of Memory? 23 | Access: 4 Hit/Miss? State of Memory? 24 | Access: 2 Hit/Miss? State of Memory? 25 | Access: 5 Hit/Miss? State of Memory? 26 | Access: 4 Hit/Miss? State of Memory? 27 | Access: 7 Hit/Miss? State of Memory? 28 | Access: 3 Hit/Miss? State of Memory? 29 | Access: 4 Hit/Miss? State of Memory? 30 | Access: 5 Hit/Miss? State of Memory? 31 | ``` 32 | 1. With FIFO 33 | | Access | Cache | Outcome | 34 | | ------ | ----------- | ------- | 35 | | 8 | [] | miss | 36 | | 7 | \[8] | miss | 37 | | 4 | \[8, 7] | miss | 38 | | 2 | \[8, 7, 4] | miss | 39 | | 5 | \[7, 4, 2] | miss | 40 | | 4 | \[4, 2, 5] | hit | 41 | | 7 | \[4, 2, 5] | miss | 42 | | 3 | \[2, 5, 7 ] | miss | 43 | | 4 | \[5, 7, 3 ] | miss | 44 | | 5 | \[7, 3, 4 ] | miss | 45 | 46 | 2. With LRU 47 | | Access | Cache | Outcome | 48 | | ------ | ----------- | ------- | 49 | | 8 | [] | miss | 50 | | 7 | \[8] | miss | 51 | | 4 | \[8, 7] | miss | 52 | | 2 | \[8, 7, 4] | miss | 53 | | 5 | \[7, 4, 2] | miss | 54 | | 4 | \[4, 2, 5] | hit | 55 | | 7 | \[4, 2, 5] | miss | 56 | | 3 | \[4, 5, 7 ] | miss | 57 | | 4 | \[4, 7, 3 ] | hit | 58 | | 5 | \[4, 7, 3 ] | miss | 59 | 60 | 3. With OPT 61 | | Access | Cache | Outcome | 62 | | ------ | ----------- | ------- | 63 | | 8 | [] | miss | 64 | | 7 | \[8] | miss | 65 | | 4 | \[8, 7] | miss | 66 | | 2 | \[8, 7, 4] | miss | 67 | | 5 | \[7, 4, 2] | miss | 68 | | 4 | \[7, 4, 5] | hit | 69 | | 7 | \[7, 4, 5] | hit | 70 | | 3 | \[7, 4, 5] | miss | 71 | | 4 | \[4, 5, 3] | hit | 72 | | 5 | \[4, 7, 3 ] | hit | 73 | 74 | 75 | ## Question 2 76 | * FIFO: `./paging-policy.py -s 0 --policy=FIFO -C 5 -a 0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5 -c` 77 | * LRU: The same input is worst case for LRU as well. Increasing cache size by 1 gives result identical to OPT in both cases. 78 | * MRU: `./paging-policy.py -s 0 --policy=MRU -C 5 -a 0,1,2,3,4,5,4,5,4,5,4,5,4,5,4,5,4,5 -c` 79 | 80 | ## Question 3 81 | `./paging-policy.py -s 0 --policy=LRU -C 4 -a 7,5,1,5,1,7,5,3,3,0,4,1,3,5,2,5,6,0,1,2,3,0,8,1,0,1,3,1,6,1,5,1 -c` 82 | 83 | LRU, MRU, FIFO has equal chance of performing good or bad in random sequences. In this particular sequence, FIFO does best with 50% hit rate. LRU does slightly worse with 43%. MRU does worst with 25% 84 | 85 | ## Question 4 86 | 87 | This script gives us a normal distribution sequence with every access being likely to be close to the last access. 88 | ```py 89 | import random 90 | 91 | arr = [10] 92 | 93 | for i in range(32): 94 | arr.append(abs(int(random.normalvariate(arr[-1], 2)))) 95 | print(','.join(str(x) for x in arr)) 96 | 97 | ``` 98 | `10,9,9,11,7,6,6,7,6,3,4,6,6,5,5,6,6,2,2,1,2,3,3,1,1,2,0,3,4,3,6,5,8` 99 | 100 | FIFO and LRU performs similarly in this, close to OPT. But MRU performs much worse as expected. 101 | 102 | This script gives a rough 20-80 workload 103 | ```py 104 | import random 105 | random.seed(0) 106 | 107 | total = 10 108 | 109 | hot = int(total*.2) 110 | 111 | arr = [] 112 | 113 | for i in range(80): 114 | arr.append(random.randint(0, hot)) 115 | 116 | for i in range(20): 117 | arr.append(random.randint(hot, total)) 118 | 119 | random.shuffle(arr) 120 | 121 | print(','.join(str(x) for x in arr)) 122 | ``` 123 | 124 | LRU gives 60, where RAND gives 53. CLOCK with one bit performs just like RAND. But clock with 2 bits can perform better than LRU, 62. CLOCK with more bits can get as high as 65. 125 | 126 | ## Question 5 127 | 128 | ![Chart](FIFO, RAND, LRU and CLOCK.png) 129 | 130 | Thanks to paging, even with a cache size of 1 gives 50% hits. How do I find a working set? 131 | -------------------------------------------------------------------------------- /os/OSTEP/33-event-based-concurrency/homeworks/aio-file-tcp.c: -------------------------------------------------------------------------------- 1 | 2 | #define _XOPEN_SOURCE 700 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define PORT 8080 17 | #define BUFF_SIZE 1024 18 | #define FILE_BUFFER_SIZE 1 << 20 // 1 MB 19 | 20 | #define IO_SIGNAL SIGUSR1 21 | 22 | char buffer[BUFF_SIZE] = {0}; 23 | char file_buff[FILE_BUFFER_SIZE]; 24 | char replay[BUFF_SIZE + 32]; 25 | 26 | fd_set activeFDs; // the fds we are going to look for inputs 27 | 28 | 29 | struct io_request { 30 | int connection_fd; 31 | struct aiocb* cb; 32 | }; 33 | 34 | void trimnewline(char* s) { 35 | int i = 0; 36 | while(i < BUFF_SIZE) { 37 | if(s[i] == '\r' || s[i] == '\n') { 38 | s[i] = '\0'; 39 | return; 40 | } 41 | i++; 42 | } 43 | } 44 | 45 | void get_greeting(char* buff) { 46 | time_t now; 47 | time(&now); 48 | struct tm* time_info = localtime(&now); 49 | strftime(buff, BUFF_SIZE, 50 | "\nHenlo!\nServer time: %d %b %Y %H:%M:%S\n\n", 51 | time_info); 52 | } 53 | 54 | void send_greetings(int fd) { 55 | get_greeting(buffer); 56 | send(fd, buffer, strlen(buffer), 0); 57 | } 58 | 59 | int read_and_serve(int fd) { 60 | read(fd, buffer, sizeof(buffer)); 61 | trimnewline(buffer); 62 | 63 | int f_fd = open(buffer, O_RDONLY); 64 | if (f_fd < 0) { 65 | sprintf(replay, "Failed to open file `%s`\n", buffer); 66 | send(fd, replay, strlen(replay), 0); 67 | return 0; 68 | } 69 | struct io_request* req = malloc(sizeof(struct io_request)); 70 | req->connection_fd = fd; 71 | req->cb = malloc(sizeof(struct aiocb)); 72 | req->cb->aio_fildes = f_fd; 73 | req->cb->aio_offset = 0; 74 | req->cb->aio_buf = malloc(FILE_BUFFER_SIZE); 75 | req->cb->aio_nbytes = FILE_BUFFER_SIZE; 76 | req->cb->aio_reqprio = 0; 77 | req->cb->aio_sigevent.sigev_notify = SIGEV_SIGNAL; 78 | req->cb->aio_sigevent.sigev_signo = IO_SIGNAL; 79 | req->cb->aio_sigevent.sigev_value.sival_ptr = req; 80 | 81 | aio_read(req->cb); 82 | return 0; 83 | } 84 | 85 | static void aio_handler(int signo, siginfo_t* si, void* ucontext) { 86 | if (si->si_code != SI_ASYNCIO) return; 87 | struct io_request* req = si->si_value.sival_ptr; 88 | 89 | send(req->connection_fd, (const void*) req->cb->aio_buf, req->cb->aio_nbytes, 0); 90 | 91 | // close connection 92 | FD_CLR(req->connection_fd, &activeFDs); 93 | shutdown(req->connection_fd, SHUT_RDWR); 94 | 95 | // free up allocated memory 96 | free(req->cb->aio_buf); 97 | free(req->cb); 98 | free(req); 99 | } 100 | 101 | int main(int argc, char** argv) { 102 | // set up signaling 103 | struct sigaction sa; 104 | sa.sa_flags = SA_RESTART | SA_SIGINFO; 105 | sigemptyset(&sa.sa_mask); 106 | sa.sa_sigaction = aio_handler; 107 | sigaction(IO_SIGNAL, &sa, NULL); 108 | // signal(IO_SIGNAL, aio_handler); 109 | 110 | // address for the socket 111 | struct sockaddr_in address; 112 | socklen_t addrlen = sizeof(address); 113 | address.sin_family = AF_INET; 114 | address.sin_addr.s_addr = INADDR_ANY; 115 | address.sin_port = htons(PORT); 116 | 117 | // set up the socket 118 | int socket_fd, opt = 1; 119 | socket_fd = socket(AF_INET, SOCK_STREAM, 0); 120 | setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 121 | bind(socket_fd, (struct sockaddr*) &address, addrlen); 122 | listen(socket_fd, 3); 123 | 124 | FD_ZERO(&activeFDs); 125 | 126 | // this main socket fd is one of them 127 | FD_SET(socket_fd, &activeFDs); 128 | 129 | while(1) { 130 | fd_set readFDs = activeFDs; // copy 131 | select(FD_SETSIZE, &readFDs, NULL, NULL, NULL); 132 | for(int fd = 0; fd < FD_SETSIZE; fd++) { 133 | if (!FD_ISSET(fd, &readFDs)) continue; 134 | 135 | if (fd == socket_fd) { 136 | // input in the main socket fd, means new connect 137 | // accept it 138 | int new_connection = accept(fd, (struct sockaddr*) &address, &addrlen); 139 | // send greetings 140 | send_greetings(new_connection); 141 | // add this new connection fd to the active fds 142 | FD_SET(new_connection, &activeFDs); 143 | } else { 144 | // input in a already connected connection fd 145 | // read and serve, close if necessary 146 | int close = read_and_serve(fd); 147 | if (close) { 148 | FD_CLR(fd, &activeFDs); // don't monitor this fd anymore 149 | shutdown(fd, SHUT_RDWR); 150 | } 151 | } 152 | } 153 | } 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/Stmt.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | import java.util.List; 4 | 5 | abstract class Stmt { 6 | interface Visitor { 7 | R visitBlockStmt(Block stmt); 8 | R visitClassStmt(Class stmt); 9 | R visitExpressionStmt(Expression stmt); 10 | R visitFunctionStmt(Function stmt); 11 | R visitIfStmt(If stmt); 12 | R visitPrintStmt(Print stmt); 13 | R visitReturnStmt(Return stmt); 14 | R visitWhileStmt(While stmt); 15 | R visitBreakStmt(Break stmt); 16 | R visitContinueStmt(Continue stmt); 17 | R visitVarStmt(Var stmt); 18 | } 19 | static class Block extends Stmt { 20 | Block(List statements) { 21 | this.statements = statements; 22 | } 23 | 24 | @Override 25 | R accept(Visitor visitor) { 26 | return visitor.visitBlockStmt(this); 27 | } 28 | 29 | final List statements; 30 | } 31 | 32 | static class Class extends Stmt { 33 | Class(Token name, List methods) { 34 | this.name = name; 35 | this.methods = methods; 36 | } 37 | 38 | @Override 39 | R accept(Visitor visitor) { 40 | return visitor.visitClassStmt(this); 41 | } 42 | 43 | final Token name; 44 | final List methods; 45 | } 46 | 47 | static class Expression extends Stmt { 48 | Expression(Expr expression) { 49 | this.expression = expression; 50 | } 51 | 52 | @Override 53 | R accept(Visitor visitor) { 54 | return visitor.visitExpressionStmt(this); 55 | } 56 | 57 | final Expr expression; 58 | } 59 | 60 | static class Function extends Stmt { 61 | Function(Token name, List params, List body) { 62 | this.name = name; 63 | this.params = params; 64 | this.body = body; 65 | } 66 | 67 | @Override 68 | R accept(Visitor visitor) { 69 | return visitor.visitFunctionStmt(this); 70 | } 71 | 72 | final Token name; 73 | final List params; 74 | final List body; 75 | } 76 | 77 | static class If extends Stmt { 78 | If(Expr condition, Stmt thenBranch, Stmt elseBranch) { 79 | this.condition = condition; 80 | this.thenBranch = thenBranch; 81 | this.elseBranch = elseBranch; 82 | } 83 | 84 | @Override 85 | R accept(Visitor visitor) { 86 | return visitor.visitIfStmt(this); 87 | } 88 | 89 | final Expr condition; 90 | final Stmt thenBranch; 91 | final Stmt elseBranch; 92 | } 93 | 94 | static class Print extends Stmt { 95 | Print(Expr expression) { 96 | this.expression = expression; 97 | } 98 | 99 | @Override 100 | R accept(Visitor visitor) { 101 | return visitor.visitPrintStmt(this); 102 | } 103 | 104 | final Expr expression; 105 | } 106 | 107 | static class Return extends Stmt { 108 | Return(Token keyword, Expr value) { 109 | this.keyword = keyword; 110 | this.value = value; 111 | } 112 | 113 | @Override 114 | R accept(Visitor visitor) { 115 | return visitor.visitReturnStmt(this); 116 | } 117 | 118 | final Token keyword; 119 | final Expr value; 120 | } 121 | 122 | static class While extends Stmt { 123 | While(Expr condition, Stmt body, boolean isFor) { 124 | this.condition = condition; 125 | this.body = body; 126 | this.isFor = isFor; 127 | } 128 | 129 | @Override 130 | R accept(Visitor visitor) { 131 | return visitor.visitWhileStmt(this); 132 | } 133 | 134 | final Expr condition; 135 | final Stmt body; 136 | final boolean isFor; 137 | } 138 | 139 | static class Break extends Stmt { 140 | Break() { 141 | } 142 | 143 | @Override 144 | R accept(Visitor visitor) { 145 | return visitor.visitBreakStmt(this); 146 | } 147 | 148 | } 149 | 150 | static class Continue extends Stmt { 151 | Continue() { 152 | } 153 | 154 | @Override 155 | R accept(Visitor visitor) { 156 | return visitor.visitContinueStmt(this); 157 | } 158 | 159 | } 160 | 161 | static class Var extends Stmt { 162 | Var(Token name, Expr initializer) { 163 | this.name = name; 164 | this.initializer = initializer; 165 | } 166 | 167 | @Override 168 | R accept(Visitor visitor) { 169 | return visitor.visitVarStmt(this); 170 | } 171 | 172 | final Token name; 173 | final Expr initializer; 174 | } 175 | 176 | 177 | abstract R accept(Visitor visitor); 178 | } 179 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/tool/src/GenerateAst.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | import java.io.PrintWriter; 3 | import java.nio.charset.StandardCharsets; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class GenerateAst { 8 | public static void main(String[] args) throws IOException { 9 | if (args.length != 1) { 10 | System.err.println("Usage: generate_ast "); 11 | System.exit(64); 12 | } 13 | 14 | System.out.println(args[0]); 15 | 16 | String outputDir = args[0]; 17 | defineAst(outputDir, "Expr", Arrays.asList( 18 | "Function : List params, List body", 19 | "Assign : Token name, Expr value", 20 | "Ternary : Expr condition, Expr left, Expr right", 21 | "Binary : Expr left, Token operator, Expr right", 22 | "Call : Expr callee, Token paren, List arguments", 23 | "Get : Expr object, Token name", 24 | "Set : Expr object, Token name, Expr value", 25 | "This : Token keyword", 26 | "Grouping : Expr expression", 27 | "Literal : Object value", 28 | "Logical : Expr left, Token operator, Expr right", 29 | "Unary : Token operator, Expr right", 30 | "Variable : Token name" 31 | )); 32 | 33 | defineAst(outputDir, "Stmt", Arrays.asList( 34 | "Block : List statements", 35 | "Class : Token name, List methods", 36 | "Expression : Expr expression", 37 | "Function : Token name, List params," + 38 | " List body", 39 | "If : Expr condition, Stmt thenBranch, Stmt elseBranch", 40 | "Print : Expr expression", 41 | "Return : Token keyword, Expr value", 42 | "While : Expr condition, Stmt body, boolean isFor", 43 | "Break", 44 | "Continue", 45 | "Var : Token name, Expr initializer" 46 | )); 47 | } 48 | 49 | private static void defineAst(String outputDir, String baseName, List types) throws IOException { 50 | String path = outputDir + "/" + baseName + ".java"; 51 | PrintWriter writer = new PrintWriter(path, StandardCharsets.UTF_8); 52 | 53 | writer.println("package dev.sakib.lox;"); 54 | writer.println(); 55 | writer.println("import java.util.List;"); 56 | writer.println(); 57 | writer.println("abstract class " + baseName + " {"); 58 | 59 | defineVisitor(writer, baseName, types); 60 | 61 | for (String type : types) { 62 | String[] typeParts = type.split(":"); 63 | String className = typeParts[0].trim(); 64 | String fields = typeParts.length > 1 ? typeParts[1].trim() : null; 65 | defineType(writer, baseName, className, fields); 66 | } 67 | 68 | writer.println(); 69 | writer.println(" abstract R accept(Visitor visitor);"); 70 | 71 | writer.println("}"); 72 | writer.close(); 73 | 74 | } 75 | 76 | private static void defineVisitor(PrintWriter writer, String baseName, List types) { 77 | writer.println(" interface Visitor {"); 78 | 79 | for (String type : types) { 80 | String typeName = type.split(":")[0].trim(); 81 | writer.println(" R visit" + typeName + baseName + "(" + typeName + " " + baseName.toLowerCase() + ");"); 82 | } 83 | writer.println(" }"); 84 | } 85 | 86 | private static void defineType(PrintWriter writer, String baseName, String className, String fieldList) { 87 | writer.println(" static class " + className + " extends " + baseName + " {"); 88 | 89 | // constructor 90 | writer.println(" " + className + "(" + (fieldList != null ? fieldList : "") + ") {"); 91 | 92 | // store parameters in fields 93 | String[] fields = fieldList != null ? fieldList.split(", ") : new String[0]; 94 | for (String field : fields) { 95 | System.out.println(field); 96 | String name = field.split(" ")[1]; 97 | writer.println(" this." + name + " = " + name + ";"); 98 | } 99 | 100 | writer.println(" }"); 101 | 102 | // visitor pattern 103 | writer.println(); 104 | writer.println(" @Override"); 105 | writer.println(" R accept(Visitor visitor) {"); 106 | writer.println(" return visitor.visit" + className + baseName + "(this);"); 107 | writer.println(" }"); 108 | 109 | // Fields 110 | writer.println(); 111 | for (String field : fields) { 112 | writer.println(" final " + field + ";"); 113 | } 114 | 115 | writer.println(" }"); 116 | writer.println(""); 117 | } 118 | } -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/Expr.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | import java.util.List; 4 | 5 | abstract class Expr { 6 | interface Visitor { 7 | R visitFunctionExpr(Function expr); 8 | R visitAssignExpr(Assign expr); 9 | R visitTernaryExpr(Ternary expr); 10 | R visitBinaryExpr(Binary expr); 11 | R visitCallExpr(Call expr); 12 | R visitGetExpr(Get expr); 13 | R visitSetExpr(Set expr); 14 | R visitThisExpr(This expr); 15 | R visitGroupingExpr(Grouping expr); 16 | R visitLiteralExpr(Literal expr); 17 | R visitLogicalExpr(Logical expr); 18 | R visitUnaryExpr(Unary expr); 19 | R visitVariableExpr(Variable expr); 20 | } 21 | static class Function extends Expr { 22 | Function(List params, List body) { 23 | this.params = params; 24 | this.body = body; 25 | } 26 | 27 | @Override 28 | R accept(Visitor visitor) { 29 | return visitor.visitFunctionExpr(this); 30 | } 31 | 32 | final List params; 33 | final List body; 34 | } 35 | 36 | static class Assign extends Expr { 37 | Assign(Token name, Expr value) { 38 | this.name = name; 39 | this.value = value; 40 | } 41 | 42 | @Override 43 | R accept(Visitor visitor) { 44 | return visitor.visitAssignExpr(this); 45 | } 46 | 47 | final Token name; 48 | final Expr value; 49 | } 50 | 51 | static class Ternary extends Expr { 52 | Ternary(Expr condition, Expr left, Expr right) { 53 | this.condition = condition; 54 | this.left = left; 55 | this.right = right; 56 | } 57 | 58 | @Override 59 | R accept(Visitor visitor) { 60 | return visitor.visitTernaryExpr(this); 61 | } 62 | 63 | final Expr condition; 64 | final Expr left; 65 | final Expr right; 66 | } 67 | 68 | static class Binary extends Expr { 69 | Binary(Expr left, Token operator, Expr right) { 70 | this.left = left; 71 | this.operator = operator; 72 | this.right = right; 73 | } 74 | 75 | @Override 76 | R accept(Visitor visitor) { 77 | return visitor.visitBinaryExpr(this); 78 | } 79 | 80 | final Expr left; 81 | final Token operator; 82 | final Expr right; 83 | } 84 | 85 | static class Call extends Expr { 86 | Call(Expr callee, Token paren, List arguments) { 87 | this.callee = callee; 88 | this.paren = paren; 89 | this.arguments = arguments; 90 | } 91 | 92 | @Override 93 | R accept(Visitor visitor) { 94 | return visitor.visitCallExpr(this); 95 | } 96 | 97 | final Expr callee; 98 | final Token paren; 99 | final List arguments; 100 | } 101 | 102 | static class Get extends Expr { 103 | Get(Expr object, Token name) { 104 | this.object = object; 105 | this.name = name; 106 | } 107 | 108 | @Override 109 | R accept(Visitor visitor) { 110 | return visitor.visitGetExpr(this); 111 | } 112 | 113 | final Expr object; 114 | final Token name; 115 | } 116 | 117 | static class Set extends Expr { 118 | Set(Expr object, Token name, Expr value) { 119 | this.object = object; 120 | this.name = name; 121 | this.value = value; 122 | } 123 | 124 | @Override 125 | R accept(Visitor visitor) { 126 | return visitor.visitSetExpr(this); 127 | } 128 | 129 | final Expr object; 130 | final Token name; 131 | final Expr value; 132 | } 133 | 134 | static class This extends Expr { 135 | This(Token keyword) { 136 | this.keyword = keyword; 137 | } 138 | 139 | @Override 140 | R accept(Visitor visitor) { 141 | return visitor.visitThisExpr(this); 142 | } 143 | 144 | final Token keyword; 145 | } 146 | 147 | static class Grouping extends Expr { 148 | Grouping(Expr expression) { 149 | this.expression = expression; 150 | } 151 | 152 | @Override 153 | R accept(Visitor visitor) { 154 | return visitor.visitGroupingExpr(this); 155 | } 156 | 157 | final Expr expression; 158 | } 159 | 160 | static class Literal extends Expr { 161 | Literal(Object value) { 162 | this.value = value; 163 | } 164 | 165 | @Override 166 | R accept(Visitor visitor) { 167 | return visitor.visitLiteralExpr(this); 168 | } 169 | 170 | final Object value; 171 | } 172 | 173 | static class Logical extends Expr { 174 | Logical(Expr left, Token operator, Expr right) { 175 | this.left = left; 176 | this.operator = operator; 177 | this.right = right; 178 | } 179 | 180 | @Override 181 | R accept(Visitor visitor) { 182 | return visitor.visitLogicalExpr(this); 183 | } 184 | 185 | final Expr left; 186 | final Token operator; 187 | final Expr right; 188 | } 189 | 190 | static class Unary extends Expr { 191 | Unary(Token operator, Expr right) { 192 | this.operator = operator; 193 | this.right = right; 194 | } 195 | 196 | @Override 197 | R accept(Visitor visitor) { 198 | return visitor.visitUnaryExpr(this); 199 | } 200 | 201 | final Token operator; 202 | final Expr right; 203 | } 204 | 205 | static class Variable extends Expr { 206 | Variable(Token name) { 207 | this.name = name; 208 | } 209 | 210 | @Override 211 | R accept(Visitor visitor) { 212 | return visitor.visitVariableExpr(this); 213 | } 214 | 215 | final Token name; 216 | } 217 | 218 | 219 | abstract R accept(Visitor visitor); 220 | } 221 | -------------------------------------------------------------------------------- /languages/craftinginterpreters/jlox/src/dev/sakib/lox/Scanner.java: -------------------------------------------------------------------------------- 1 | package dev.sakib.lox; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import static dev.sakib.lox.TokenType.*; 9 | 10 | class Scanner { 11 | private final String source; 12 | private int start = 0; 13 | private int current = 0; 14 | private int line = 1; 15 | 16 | 17 | private static final Map keywords; 18 | 19 | static { 20 | keywords = new HashMap<>(); 21 | keywords.put("and", AND); 22 | keywords.put("class", CLASS); 23 | keywords.put("else", ELSE); 24 | keywords.put("false", FALSE); 25 | keywords.put("for", FOR); 26 | keywords.put("fun", FUN); 27 | keywords.put("if", IF); 28 | keywords.put("nil", NIL); 29 | keywords.put("or", OR); 30 | keywords.put("print", PRINT); 31 | keywords.put("return", RETURN); 32 | keywords.put("super", SUPER); 33 | keywords.put("this", THIS); 34 | keywords.put("true", TRUE); 35 | keywords.put("var", VAR); 36 | keywords.put("while", WHILE); 37 | keywords.put("continue", CONTINUE); 38 | keywords.put("break", BREAK); 39 | } 40 | 41 | private final List tokens = new ArrayList<>(); 42 | 43 | Scanner(String source) { 44 | this.source = source; 45 | } 46 | 47 | List scanTokens() { 48 | while (!isAtEnd()) { 49 | start = current; 50 | scanToken(); 51 | } 52 | tokens.add(new Token(EOF, "", null, line)); 53 | 54 | return tokens; 55 | } 56 | 57 | private void scanToken() { 58 | char c = advance(); 59 | switch (c) { 60 | case '(': 61 | addToken(LEFT_PAREN); 62 | break; 63 | case ')': 64 | addToken(RIGHT_PAREN); 65 | break; 66 | case '{': 67 | addToken(LEFT_BRACE); 68 | break; 69 | case '}': 70 | addToken(RIGHT_BRACE); 71 | break; 72 | case ',': 73 | addToken(COMMA); 74 | break; 75 | case '.': 76 | addToken(DOT); 77 | break; 78 | case '-': 79 | addToken(MINUS); 80 | break; 81 | case '+': 82 | addToken(PLUS); 83 | break; 84 | case ';': 85 | addToken(SEMICOLON); 86 | break; 87 | case '*': 88 | addToken(STAR); 89 | break; 90 | case '?': 91 | addToken(QUESTION); 92 | break; 93 | case ':': 94 | addToken(COLON); 95 | break; 96 | case '!': 97 | addToken(match('=') ? BANG_EQUAL : BANG); 98 | break; 99 | case '=': 100 | addToken(match('=') ? EQUAL_EQUAL : EQUAL); 101 | break; 102 | case '<': 103 | addToken(match('=') ? LESS_EQUAL : LESS); 104 | break; 105 | case '>': 106 | addToken(match('=') ? GREATER_EQUAL : GREATER); 107 | break; 108 | case '/': 109 | comment(); 110 | break; 111 | case ' ': 112 | case '\r': 113 | case '\t': 114 | break; 115 | case '\n': 116 | line++; 117 | break; 118 | case '"': 119 | string(); 120 | break; 121 | default: 122 | if (isDigit(c)) { 123 | number(); 124 | } else if (isAlpha(c)) { 125 | identifier(); 126 | } else { 127 | Lox.error(line, "Unexpected character." + c); 128 | } 129 | break; 130 | } 131 | } 132 | 133 | private void identifier() { 134 | while (isAlphaNumeric(peek())) advance(); 135 | 136 | String text = source.substring(start, current); 137 | 138 | TokenType type = keywords.get(text); 139 | if (type == null) type = IDENTIFIER; 140 | addToken(type); 141 | } 142 | 143 | private void number() { 144 | while (isDigit(peek())) advance(); 145 | 146 | if (peek() == '.' && isDigit(peekNext())) { 147 | advance(); 148 | 149 | while (isDigit(peek())) advance(); 150 | } 151 | 152 | addToken(NUMBER, Double.parseDouble(source.substring(start, current))); 153 | } 154 | 155 | private void string() { 156 | while (peek() != '"' && !isAtEnd()) { 157 | if (peek() == '\n') line++; 158 | advance(); 159 | } 160 | 161 | if (isAtEnd()) { 162 | Lox.error(line, "Unterminated string."); 163 | return; 164 | } 165 | advance(); 166 | 167 | String value = source.substring(start + 1, current - 1); 168 | addToken(STRING, value); 169 | } 170 | 171 | private void comment() { 172 | if (peek() == '/') { 173 | // single line comment 174 | while (peek() != '\n' && !isAtEnd()) advance(); 175 | } else if (match('*')) { 176 | while (!(peek() == '*' && peekNext() == '/')) { 177 | if (peek() == '/' && peekNext() == '*') { 178 | advance(); 179 | comment(); 180 | } else { 181 | if (peek() == '\n') line++; 182 | advance(); 183 | } 184 | if (isAtEnd()) { 185 | Lox.error(line, "Unterminated multiline comment"); 186 | return; 187 | } 188 | } 189 | current += 2; 190 | } else { 191 | addToken(SLASH); 192 | } 193 | } 194 | 195 | private char peek() { 196 | if (isAtEnd()) return '\0'; 197 | return source.charAt(current); 198 | } 199 | 200 | private char peekNext() { 201 | if (current + 1 >= source.length()) return '\0'; 202 | return source.charAt(current + 1); 203 | } 204 | 205 | private boolean isDigit(char c) { 206 | return c >= '0' && c <= '9'; 207 | } 208 | 209 | private boolean isAlpha(char c) { 210 | return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; 211 | } 212 | 213 | private boolean isAlphaNumeric(char c) { 214 | return isDigit(c) || isAlpha(c); 215 | } 216 | 217 | private boolean match(char expected) { 218 | if (isAtEnd()) return false; 219 | if (source.charAt(current) != expected) return false; 220 | current++; 221 | return true; 222 | } 223 | 224 | private boolean isAtEnd() { 225 | return current >= source.length(); 226 | } 227 | 228 | private char advance() { 229 | return source.charAt(current++); 230 | } 231 | 232 | private void addToken(TokenType type) { 233 | addToken(type, null); 234 | } 235 | 236 | private void addToken(TokenType type, Object literal) { 237 | String text = source.substring(start, current); 238 | tokens.add(new Token(type, text, literal, line)); 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /os/OSTEP/40-fs-implementation/homeworks/README.md: -------------------------------------------------------------------------------- 1 | # Operating systems Three Easy Pieces: Chapter 40 solution 2 | 3 | ## Question 1 4 | ``` 5 | ./vsfs.py -s 17 6 | ARG seed 17 7 | ARG numInodes 8 8 | ARG numData 8 9 | ARG numRequests 10 10 | ARG reverse False 11 | ARG printFinal False 12 | 13 | Initial state 14 | 15 | inode bitmap 10000000 16 | inodes [d a:0 r:2] [] [] [] [] [] [] [] 17 | data bitmap 10000000 18 | data [(.,0) (..,0)] [] [] [] [] [] [] [] 19 | 20 | Which operation took place? 21 | 22 | inode bitmap 11000000 23 | inodes [d a:0 r:3] [d a:1 r:2] [] [] [] [] [] [] 24 | data bitmap 11000000 25 | data [(.,0) (..,0) (u,1)] [(.,1) (..,0)] [] [] [] [] [] [] 26 | 27 | Which operation took place? 28 | 29 | inode bitmap 11100000 30 | inodes [d a:0 r:3] [d a:1 r:2] [f a:-1 r:1] [] [] [] [] [] 31 | data bitmap 11000000 32 | data [(.,0) (..,0) (u,1) (a,2)] [(.,1) (..,0)] [] [] [] [] [] [] 33 | 34 | Which operation took place? 35 | 36 | inode bitmap 11000000 37 | inodes [d a:0 r:3] [d a:1 r:2] [] [] [] [] [] [] 38 | data bitmap 11000000 39 | data [(.,0) (..,0) (u,1)] [(.,1) (..,0)] [] [] [] [] [] [] 40 | 41 | Which operation took place? 42 | 43 | inode bitmap 11100000 44 | inodes [d a:0 r:4] [d a:1 r:2] [d a:2 r:2] [] [] [] [] [] 45 | data bitmap 11100000 46 | data [(.,0) (..,0) (u,1) (z,2)] [(.,1) (..,0)] [(.,2) (..,0)] [] [] [] [] [] 47 | 48 | Which operation took place? 49 | 50 | inode bitmap 11110000 51 | inodes [d a:0 r:5] [d a:1 r:2] [d a:2 r:2] [d a:3 r:2] [] [] [] [] 52 | data bitmap 11110000 53 | data [(.,0) (..,0) (u,1) (z,2) (s,3)] [(.,1) (..,0)] [(.,2) (..,0)] [(.,3) (..,0)] [] [] [] [] 54 | 55 | Which operation took place? 56 | 57 | inode bitmap 11111000 58 | inodes [d a:0 r:5] [d a:1 r:2] [d a:2 r:2] [d a:3 r:2] [f a:-1 r:1] [] [] [] 59 | data bitmap 11110000 60 | data [(.,0) (..,0) (u,1) (z,2) (s,3)] [(.,1) (..,0)] [(.,2) (..,0) (x,4)] [(.,3) (..,0)] [] [] [] [] 61 | 62 | Which operation took place? 63 | 64 | inode bitmap 11111000 65 | inodes [d a:0 r:5] [d a:1 r:2] [d a:2 r:2] [d a:3 r:2] [f a:-1 r:2] [] [] [] 66 | data bitmap 11110000 67 | data [(.,0) (..,0) (u,1) (z,2) (s,3)] [(.,1) (..,0) (b,4)] [(.,2) (..,0) (x,4)] [(.,3) (..,0)] [] [] [] [] 68 | 69 | Which operation took place? 70 | 71 | inode bitmap 11111000 72 | inodes [d a:0 r:5] [d a:1 r:2] [d a:2 r:2] [d a:3 r:2] [f a:-1 r:1] [] [] [] 73 | data bitmap 11110000 74 | data [(.,0) (..,0) (u,1) (z,2) (s,3)] [(.,1) (..,0)] [(.,2) (..,0) (x,4)] [(.,3) (..,0)] [] [] [] [] 75 | 76 | Which operation took place? 77 | 78 | inode bitmap 11111000 79 | inodes [d a:0 r:5] [d a:1 r:2] [d a:2 r:2] [d a:3 r:2] [f a:4 r:1] [] [] [] 80 | data bitmap 11111000 81 | data [(.,0) (..,0) (u,1) (z,2) (s,3)] [(.,1) (..,0)] [(.,2) (..,0) (x,4)] [(.,3) (..,0)] [v] [] [] [] 82 | 83 | Which operation took place? 84 | 85 | inode bitmap 11111100 86 | inodes [d a:0 r:5] [d a:1 r:2] [d a:2 r:2] [d a:3 r:2] [f a:4 r:1] [f a:-1 r:1] [] [] 87 | data bitmap 11111000 88 | data [(.,0) (..,0) (u,1) (z,2) (s,3)] [(.,1) (..,0) (b,5)] [(.,2) (..,0) (x,4)] [(.,3) (..,0)] [v] [] [] [] 89 | ``` 90 | 91 | 1. `mkdir('/u')` 92 | 2. `creat('/a')` 93 | 3. `unlink('/a')` 94 | 4. `mkdir('/z')` 95 | 5. `mkdir('/s')` 96 | 6. `creat('/z/x')` 97 | 7. `link('/z/x', '/u/b')` 98 | 8. `unlink('/u/b')` 99 | 9. `fd=open("/z/x", O_WRONLY|O_APPEND); write(fd, buf, BLOCKSIZE); close(fd);` 100 | 10. `creat('/u/b')` 101 | 102 | 103 | ## Question 2 104 | 105 | ``` 106 | ./vsfs.py -s 21 -r 107 | ARG seed 21 108 | ARG numInodes 8 109 | ARG numData 8 110 | ARG numRequests 10 111 | ARG reverse True 112 | ARG printFinal False 113 | 114 | Initial state 115 | 116 | inode bitmap 10000000 117 | inodes [d a:0 r:2] [] [] [] [] [] [] [] 118 | data bitmap 10000000 119 | data [(.,0) (..,0)] [] [] [] [] [] [] [] 120 | 121 | mkdir("/o"); 122 | 123 | State of file system (inode bitmap, inodes, data bitmap, data)? 124 | 125 | creat("/b"); 126 | 127 | State of file system (inode bitmap, inodes, data bitmap, data)? 128 | 129 | creat("/o/q"); 130 | 131 | State of file system (inode bitmap, inodes, data bitmap, data)? 132 | 133 | fd=open("/b", O_WRONLY|O_APPEND); write(fd, buf, BLOCKSIZE); close(fd); 134 | 135 | State of file system (inode bitmap, inodes, data bitmap, data)? 136 | 137 | fd=open("/o/q", O_WRONLY|O_APPEND); write(fd, buf, BLOCKSIZE); close(fd); 138 | 139 | State of file system (inode bitmap, inodes, data bitmap, data)? 140 | 141 | creat("/o/j"); 142 | 143 | State of file system (inode bitmap, inodes, data bitmap, data)? 144 | 145 | unlink("/b"); 146 | 147 | State of file system (inode bitmap, inodes, data bitmap, data)? 148 | 149 | fd=open("/o/j", O_WRONLY|O_APPEND); write(fd, buf, BLOCKSIZE); close(fd); 150 | 151 | State of file system (inode bitmap, inodes, data bitmap, data)? 152 | 153 | creat("/o/x"); 154 | 155 | State of file system (inode bitmap, inodes, data bitmap, data)? 156 | 157 | mkdir("/o/t"); 158 | 159 | State of file system (inode bitmap, inodes, data bitmap, data)? 160 | ``` 161 | 162 | ``` 163 | inode bitmap 10000000 164 | inodes [d a:0 r:2] [] [] [] [] [] [] [] 165 | data bitmap 10000000 166 | data [(.,0) (..,0)] [] [] [] [] [] [] [] 167 | ``` 168 | 169 | ``` 170 | inode bitmap 11000000 171 | inodes [d a:0 r:3] [d a:1 r:2] [] [] [] [] [] [] 172 | data bitmap 11000000 173 | data [(.,0) (..,0) (o,1)] [(.,1) (..,0)] [] [] [] [] [] [] 174 | ``` 175 | 176 | ``` 177 | inode bitmap 11100000 178 | inodes [d a:0 r:3] [d a:1 r:2] [f a:-1 r:1] [] [] [] [] [] 179 | data bitmap 11000000 180 | data [(.,0) (..,0) (o,1) (b,2)] [(.,1) (..,0)] [] [] [] [] [] [] 181 | ``` 182 | 183 | ``` 184 | inode bitmap 11110000 185 | inodes [d a:0 r:3] [d a:1 r:2] [f a:-1 r:1] [f a:-1 r:1] [] [] [] [] 186 | data bitmap 11000000 187 | data [(.,0) (..,0) (o,1) (b,2)] [(.,1) (..,0) (q,3)] [] [] [] [] [] [] 188 | ``` 189 | 190 | ``` 191 | inode bitmap 11110000 192 | inodes [d a:0 r:3] [d a:1 r:2] [f a:2 r:1] [f a:-1 r:1] [] [] [] [] 193 | data bitmap 11100000 194 | data [(.,0) (..,0) (o,1) (b,2)] [(.,1) (..,0) (q,3)] [m] [] [] [] [] [] 195 | ``` 196 | 197 | ``` 198 | inode bitmap 11110000 199 | inodes [d a:0 r:3] [d a:1 r:2] [f a:2 r:1] [f a:3 r:1] [] [] [] [] 200 | data bitmap 11110000 201 | data [(.,0) (..,0) (o,1) (b,2)] [(.,1) (..,0) (q,3)] [m] [j] [] [] [] [] 202 | ``` 203 | 204 | ``` 205 | inode bitmap 11111000 206 | inodes [d a:0 r:3] [d a:1 r:2] [f a:2 r:1] [f a:3 r:1] [f a:-1 r:1] [] [] [] 207 | data bitmap 11110000 208 | data [(.,0) (..,0) (o,1) (b,2)] [(.,1) (..,0) (q,3) (j,4)] [m] [j] [] [] [] [] 209 | ``` 210 | 211 | ``` 212 | inode bitmap 11011000 213 | inodes [d a:0 r:3] [d a:1 r:2] [] [f a:3 r:1] [f a:-1 r:1] [] [] [] 214 | data bitmap 11010000 215 | data [(.,0) (..,0) (o,1)] [(.,1) (..,0) (q,3) (j,4)] [] [j] [] [] [] [] 216 | ``` 217 | 218 | ``` 219 | inode bitmap 11011000 220 | inodes [d a:0 r:3] [d a:1 r:2] [] [f a:3 r:1] [f a:2 r:1] [] [] [] 221 | data bitmap 11110000 222 | data [(.,0) (..,0) (o,1)] [(.,1) (..,0) (q,3) (j,4)] [g] [j] [] [] [] [] 223 | ``` 224 | 225 | The algorithm prefers to allocate the first available block for data. 226 | 227 | ## Question 3 228 | 229 | The system will end up with mostly directories and empty files. Naturally, `creat`, `mkdir`, `write` operations will fail afterwards. 230 | 231 | ## Question 4 232 | 233 | With fewer inodes, `mkdir`, `creat` operations will start failing. 234 | 235 | 236 | One aspect of the simulated file system is that it allows only one data block file and as soon as one operation fails, it stops. So availability of either inode or data block alone does not make much of a difference. --------------------------------------------------------------------------------