├── README.md ├── elixir └── p1-20241-SO.pdf ├── intro ├── README ├── io.c ├── cpu.c ├── mem.c └── newproc.c ├── process ├── prod_cons │ └── src │ │ └── prod_cons │ │ ├── SharedBoundedStack.java │ │ ├── MainSemaphore.java │ │ ├── MainSemaphoreBugged.java │ │ ├── MainMonitorIncomplete.java │ │ ├── MainMonitor.java │ │ ├── Consumer.java │ │ ├── Producer.java │ │ ├── SharedBoundedStackMonitorIncomplete.java │ │ ├── SharedBoundedStackMonitor.java │ │ ├── OtherConsumer.java │ │ ├── OtherProducer.java │ │ ├── SharedBoundedStackSemaphore.java │ │ └── SharedBoundedStackSemaphoreBugged.java ├── dup_ex.c ├── README.md ├── word_count │ ├── make_dataset │ ├── README.md │ ├── Makefile │ ├── wc_single_proc.c │ ├── wc_mult_proc.c │ ├── wc_thread.c │ ├── flag_wc_thread.c │ ├── longer_sem_wc_thread.c │ ├── wc_thread_shmstyle.c │ ├── sem_wc_thread.c │ ├── turn_wc_thread.c │ ├── longer_tsl_wc_thread.c │ ├── tsl_wc_thread.c │ └── wc_mult_proc_shm.c ├── shared_fd.c ├── mycat.c ├── cat_redirect.c ├── newproc.c ├── hello_world.asm └── threads2.c ├── fork ├── exemplo_fork_1.c └── exemplo_fork_2.c ├── memory ├── big-footprint.c └── allocation.c ├── LICENSE └── exercises └── README.md /README.md: -------------------------------------------------------------------------------- 1 | # SO 2 | 3 | Code snippets for operating system classes 4 | -------------------------------------------------------------------------------- /elixir/p1-20241-SO.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thiagomanel/SO/HEAD/elixir/p1-20241-SO.pdf -------------------------------------------------------------------------------- /intro/README: -------------------------------------------------------------------------------- 1 | This code was borrowed from the pages.cs.wisc.edu/~remzi/OSTEP/ book 2 | 3 | To compile the mem.c code type 4 | cc -o mem mem.c -Wl,-no_pie 5 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/SharedBoundedStack.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | public interface SharedBoundedStack { 4 | public int get(); 5 | public void put(int item); 6 | } 7 | -------------------------------------------------------------------------------- /process/dup_ex.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | int main() { 8 | int fd; 9 | fd = dup(1); 10 | write(1, "hello ", 6); 11 | write(fd, "world\n", 6); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /intro/io.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | int fd = open("/tmp/file", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); 10 | int rc = write(fd, "hello world\n", 13); 11 | close(fd); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /intro/cpu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) { 8 | if (argc != 2) { 9 | fprintf(stderr, "usage: cpu \n"); 10 | exit(1); 11 | } 12 | char *str = argv[1]; 13 | while (1) { 14 | sleep(1); 15 | printf("%s\n", str); 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /process/README.md: -------------------------------------------------------------------------------- 1 | # Process 2 | 3 | Code here is based on OSTEP book and xv6 manuals 4 | 5 | The assembly code works for macOS (from https://lord.io/blog/2014/assembly-on-osx/) 6 | 7 | To assemble your code, run: 8 | # Generate object file from assembly: 9 | nasm -f macho64 -o hello_world.o hello_world.asm 10 | 11 | # Link object file: 12 | ld hello_world.o -o hello_world 13 | 14 | # Run executable: 15 | ./hello_world 16 | -------------------------------------------------------------------------------- /process/word_count/make_dataset: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # it creates a tree dataset 4 | # it creates four directories below the root dir "dataset" 5 | # in each directory, it creates 1000 files. Each file has 154KB 6 | 7 | for d_i in `seq 0 3`; 8 | do 9 | subdir="dataset/dataset${d_i}" 10 | mkdir -p $subdir 11 | for f_i in `seq 0 999`; 12 | do 13 | cp file2count.data $subdir/file2count.data.$f_i 14 | done 15 | done 16 | -------------------------------------------------------------------------------- /process/shared_fd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | int main() { 8 | //how to write "hellow world" using two processes? 9 | pid_t pid, donep; 10 | pid = 0; 11 | pid = fork(); 12 | if (pid == 0) { 13 | write(1, "hello ", 6); 14 | exit(0); 15 | } else { 16 | donep = wait(0); 17 | write(1, "world\n", 6); 18 | return 0; 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /intro/mem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //cc -o mem mem.c -Wl,-no_pie 7 | int main(int argc, char *argv[]) { 8 | int *p = malloc(sizeof(int)); // a1 9 | printf("(%d) address pointed to by p: %p\n", 10 | getpid(), p); // a2 11 | *p = atoi(argv[1]); // a3 12 | while (1) { 13 | sleep(1); 14 | *p = *p + 1; 15 | printf("(%d) p: %d\n", getpid(), *p); // a4 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /process/mycat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) { 8 | 9 | char buf[512]; 10 | int n; 11 | for(;;) { 12 | n = read(0, buf, sizeof buf); 13 | if (n == 0) 14 | break; 15 | if (n < 0) { 16 | fprintf(2, "read error\n"); 17 | exit(0); 18 | } 19 | if (write(1, buf, n) != n) { 20 | fprintf(2, "write error\n"); 21 | exit(0); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /fork/exemplo_fork_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char** argv) { 8 | char estado = 'p'; 9 | int child_pid; 10 | 11 | system("ps -f"); 12 | printf("processo %d: criando processo filho\n", getpid()); 13 | child_pid = fork(); 14 | system("ps -f"); 15 | printf("processo %d: fork retornou %d\n", getpid(), child_pid); 16 | if (child_pid == 0) estado = 'f'; 17 | printf("processo %d: o valor da variável estado deste processo é: %c\n", getpid(), estado); 18 | } 19 | -------------------------------------------------------------------------------- /intro/newproc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | int main() { 8 | char *argv[3]; 9 | pid_t pid, donep; 10 | pid = 0; 11 | pid = fork(); 12 | if (pid == 0) { 13 | printf("Upon successful completion, fork() returns a value of 0 to the child process\n"); 14 | printf("child dying\n"); 15 | exit(0); 16 | } else { 17 | printf("Upon successful completion, fork() returns returns the process ID of the child process to the parent process\n"); 18 | donep = wait(0); 19 | printf("child %d has gone\n", donep); 20 | return 0; 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /memory/big-footprint.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | char *my_memory[1024]; 6 | size_t dezeseis_mega = 1024*1024*16; 7 | 8 | if (argc != 2) { 9 | fprintf(stderr, "sintaxe: %s size\n", argv[0]); 10 | exit(0); 11 | } 12 | 13 | fprintf(stderr, "Alocando memória: "); 14 | for (int i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | //it is equivalent to "cat < foo.txt" 10 | char *argv[2]; 11 | argv[0] = "cat"; 12 | argv[1] = NULL; 13 | pid_t pid, donep; 14 | pid = 0; 15 | pid = fork(); 16 | if (pid == 0) { 17 | printf("Upon successful completion, fork() returns a value of 0 to the child process\n"); 18 | close(0); 19 | open("newproc.c", O_RDONLY); 20 | execv("/bin/cat", argv); 21 | exit(0); 22 | } else { 23 | donep = wait(0); 24 | printf("child %d has gone\n", donep); 25 | return 0; 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/MainSemaphore.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | public class MainSemaphore { 4 | private static int bufferSize = 5; 5 | private static int producerServiceTime = 100; 6 | private static int consumerServiceTime = 100; 7 | 8 | public static void main(String[] args) { 9 | // write your code here 10 | // creating buffer queue 11 | SharedBoundedStack buffer = new SharedBoundedStackSemaphore(MainSemaphore.bufferSize); 12 | 13 | // starting consumer thread 14 | new Consumer(buffer, MainSemaphore.consumerServiceTime); 15 | 16 | // starting producer thread 17 | new Producer(buffer, MainSemaphore.producerServiceTime); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /process/newproc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) { 7 | pid_t pid, donep; 8 | pid = 0; 9 | pid = fork(); 10 | if (pid == 0) { 11 | printf("Upon successful completion, fork() returns a value of 0 to the " 12 | "child process %d\n", 13 | getpid()); 14 | // execv(argv[1], &argv[1]); 15 | exit(0); 16 | } else { 17 | printf("Upon successful completion, fork() returns returns the process ID " 18 | "of the child process to the parent process %d\n", 19 | getpid()); 20 | donep = wait(0); 21 | printf("child %d has gone\n", donep); 22 | return 0; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/MainSemaphoreBugged.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | public class MainSemaphoreBugged { 4 | private static int bufferSize = 5; 5 | private static int producerServiceTime = 100; 6 | private static int consumerServiceTime = 100; 7 | 8 | public static void main(String[] args) { 9 | // write your code here 10 | // creating buffer queue 11 | SharedBoundedStack buffer = new SharedBoundedStackSemaphoreBugged(MainSemaphoreBugged.bufferSize); 12 | 13 | // starting consumer thread 14 | new Consumer(buffer, MainSemaphoreBugged.consumerServiceTime); 15 | 16 | // starting producer thread 17 | new Producer(buffer, MainSemaphoreBugged.producerServiceTime); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /memory/allocation.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int n_turns = 5; // variável global iniciada (static) 5 | int i_global; // variável global não iniciada (bss) 6 | 7 | void add_all(int *i_dynamic) 8 | { 9 | int i_local = 0; // variável local (stack) 10 | 11 | printf ("i_global: %d, i_local: %d, i_dynamic: %d\n", i_global, i_local, *i_dynamic); 12 | i_global++; 13 | i_local++; 14 | (*i_dynamic)++; 15 | } 16 | 17 | int main() { 18 | int *i_dynamic; // variável local (stack) 19 | i_dynamic = malloc(sizeof(int)); // memória alocada dinamicamente (heap) 20 | *i_dynamic = 0; 21 | 22 | for(int j=0; j 2 | #include 3 | #include 4 | 5 | long count = 0; 6 | int thread_ids[3] = {0,1,2}; 7 | 8 | void *inc_count(void *t) { 9 | int i; 10 | long my_id = (long)t; 11 | printf("I am a counter %ld\n", my_id); 12 | for (i = 0; i < 1e7; i++) { 13 | count = count + 1; 14 | } 15 | sleep(1); 16 | pthread_exit(NULL); 17 | } 18 | 19 | int main (int argc, char *argv[]) { 20 | int i; 21 | long t1=1, t2=2, t3=3; 22 | 23 | pthread_t threads[3]; 24 | pthread_attr_t attr; 25 | 26 | pthread_attr_init(&attr); 27 | 28 | pthread_create(&threads[0], &attr, inc_count, (void *)t1); 29 | pthread_create(&threads[1], &attr, inc_count, (void *)t2); 30 | pthread_create(&threads[2], &attr, inc_count, (void *)t3); 31 | 32 | for (i=0; i<3; i++) { 33 | pthread_join(threads[i], NULL); 34 | } 35 | 36 | printf("count %ld\n", count); 37 | pthread_exit(NULL); 38 | } 39 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/Consumer.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | public class Consumer implements Runnable { 4 | private SharedBoundedStack buffer; 5 | private int serviceTime; 6 | 7 | Consumer(SharedBoundedStack b, int serviceTime) 8 | { 9 | this.buffer = b; 10 | this.serviceTime = serviceTime; 11 | new Thread((Runnable) this, "Consumer").start(); 12 | } 13 | 14 | public void run() 15 | { 16 | int item; 17 | while(true) { 18 | // consumer get items 19 | item = buffer.get(); 20 | // the sleep simulates the time to consume an item 21 | try { 22 | Thread.sleep(this.serviceTime); 23 | } catch (InterruptedException e) { 24 | e.printStackTrace(); 25 | } 26 | System.out.println(String.format("Consumer has consumed %d", item)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/Producer.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | public class Producer implements Runnable { 4 | private SharedBoundedStack buffer; 5 | private int serviceTime; 6 | 7 | Producer(SharedBoundedStack b, int serviceTime) 8 | { 9 | this.buffer = b; 10 | this.serviceTime = serviceTime; 11 | new Thread((Runnable) this, "Producer").start(); 12 | } 13 | 14 | public void run() 15 | { 16 | int i = 1; 17 | while (true) { 18 | // producer producing an item; the sleep just simulates the time to produce 19 | try { 20 | Thread.sleep(this.serviceTime); 21 | } catch (InterruptedException e) { 22 | e.printStackTrace(); 23 | } 24 | // producer put items 25 | System.out.println(String.format("Producer has produced %d", i)); 26 | this.buffer.put(i++); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /fork/exemplo_fork_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char** argv) { 8 | char estado = 'p'; 9 | int my_pid = getpid(); 10 | int child_pid; 11 | 12 | printf("%d: processos antes da criação do processo filho\n", my_pid); 13 | system("ps -f"); 14 | printf("%d: criando processo filho\n", my_pid); 15 | if ((child_pid = fork()) == 0) { 16 | printf("%d: minha cópia de pid ainda tem o id de meu pai: %d\n", getpid(), my_pid); 17 | my_pid = getpid(); 18 | printf("%d: o valor da variável estado no processo filho é: %c\n", my_pid, estado); 19 | printf("%d: filho está aguardando uma entrada do teclado\n", my_pid); 20 | estado = getchar(); 21 | } else { 22 | printf("%d: processos depois da criação do processo filho\n", my_pid); 23 | system("ps -f"); 24 | printf("%d: pai está esperando pelo filho: %d\n", my_pid, child_pid); 25 | wait(&child_pid); 26 | } 27 | printf("%d: terminando com o valor da variável estado igual a: %c\n", my_pid, estado); 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Thiago Emmanuel Pereira 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/SharedBoundedStackMonitorIncomplete.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | public class SharedBoundedStackMonitorIncomplete implements SharedBoundedStack { 4 | // size of the shared buffer 5 | private int stackSize; 6 | // shared buffer 7 | private int[] stack; 8 | // points to the top of the stack; 0 means that the stack is empty 9 | private int stackPointer; 10 | 11 | public SharedBoundedStackMonitorIncomplete(int stackSize) { 12 | this.stackSize = stackSize; 13 | this.stack = new int[this.stackSize]; 14 | this.stackPointer = 0; 15 | } 16 | 17 | // to get an item from buffer 18 | synchronized public int get() 19 | { 20 | int ret; 21 | 22 | ret = this.stack[--this.stackPointer]; 23 | System.out.println(String.format("Consumer has removed %d from slot %d", ret, this.stackPointer)); 24 | 25 | return ret; 26 | } 27 | 28 | // to put an item in buffer 29 | synchronized public void put(int item) 30 | { 31 | System.out.println(String.format("Producer has inserted %d in slot %d", item, this.stackPointer)); 32 | this.stack[this.stackPointer++] = item; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /exercises/README.md: -------------------------------------------------------------------------------- 1 | # API threads 2 | ``` 3 | // cria uma nova thread, que será apontada por t. A thread criada executará 4 | // a função apontada por function_ptr. Ao fim da execução, a thread que foi 5 | // criada já está pronta para ser executada pelo escalonador. 6 | void create (thread* t, function_ptr*) 7 | 8 | // esta função permite que a thread que a chamou indique o fim de sua 9 | // execução 10 | void exit () 11 | 12 | // esta função permite bloquear a thread que a chama até que uma outra 13 | // target_thread termine sua execução. Caso a target_thread já tenha 14 | // terminado sua execução antes da chamada para join, a chamada para join 15 | // não irá bloquear. 16 | void join (thread target_thread) 17 | 18 | // para implementar as funções acima, você pode considerar o uso das 19 | // seguintes funções auxiliares 20 | 21 | // esta função retorna a thread que executa atualmente 22 | thread current_thread() 23 | 24 | // Toda thread tem um identificador inteiro único. Esta função retorna o 25 | // valor deste identificador para a thread t 26 | int get_tid(thread t) 27 | ``` 28 | 29 | # API Barreira 30 | 31 | ``` 32 | // Constrói um objeto Barreira de tamanho size 33 | Barreira (int size) 34 | 35 | // Espera até que um número suficiente de fluxos tenham chamado wait() 36 | void wait () 37 | ``` 38 | -------------------------------------------------------------------------------- /process/word_count/README.md: -------------------------------------------------------------------------------- 1 | These snippets support learning execution flows (processes vs threads) 2 | 3 | All the programs have the same objective: to count words in text files under a root directory. 4 | Under this root dir we have a collection of subdirectories. Under each one of these subdirs, we have text files. 5 | 6 | * wc_single_proc.c - This program process the whole dataset, using a single process. 7 | * wc_mult_proc.c - This program uses multiple processes to process the dataset. The parent process creates a new process to each one of the subdirectories. This program is buggy (on purpose). It highlights child processes have a copy of parents memory. Then, we need explicitly communicate with parent to send the partial word count 8 | * wc_mult_proc_shm.c - This program solves the bug of the previous one by communicating through shared memory 9 | * wc_thread_shmstyle.c - This program uses multiple threads to process the dataset. It emulates the program style found on the above programs 10 | * wc_thread.c - This program takes advantage threads share the same address space to simplify the code shown in the wc_thread_shmstyle.c program. (beware, it has a bug; again, on purpose) 11 | 12 | 13 | To build above programs, type *make* 14 | 15 | To generate the dataset, type *bash ./make_dataset* 16 | 17 | To execute above programs, type *./program_name dataset* 18 | 19 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/SharedBoundedStackMonitor.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | public class SharedBoundedStackMonitor implements SharedBoundedStack { 4 | // size of the shared buffer 5 | private int stackSize; 6 | // shared buffer 7 | private int[] stack; 8 | // points to the top of the stack; 0 means that the stack is empty 9 | private int stackPointer; 10 | 11 | public SharedBoundedStackMonitor(int stackSize) { 12 | this.stackSize = stackSize; 13 | this.stack = new int[this.stackSize]; 14 | this.stackPointer = 0; 15 | } 16 | 17 | synchronized public int getStackPointer() { 18 | return this.stackPointer; 19 | } 20 | 21 | synchronized public int getStackSize() { 22 | return this.stackSize; 23 | } 24 | 25 | // to get an item from buffer 26 | synchronized public int get() 27 | { 28 | int ret; 29 | 30 | ret = this.stack[--this.stackPointer]; 31 | System.out.println(String.format("Consumer has removed %d from slot %d", ret, this.stackPointer)); 32 | 33 | return ret; 34 | } 35 | 36 | // to put an item in buffer 37 | synchronized public void put(int item) 38 | { 39 | System.out.println(String.format("Producer has inserted %d in slot %d", item, this.stackPointer)); 40 | this.stack[this.stackPointer++] = item; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/OtherConsumer.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | public class OtherConsumer implements Runnable { 4 | private SharedBoundedStackMonitor buffer; 5 | private int serviceTime; 6 | private Integer full; 7 | private Integer empty; 8 | 9 | OtherConsumer(SharedBoundedStack b, int serviceTime, Integer full, Integer empty) 10 | { 11 | this.buffer = (SharedBoundedStackMonitor) b; 12 | this.serviceTime = serviceTime; 13 | this.full = full; 14 | this.empty = empty; 15 | new Thread((Runnable) this, "Consumer").start(); 16 | } 17 | 18 | public void run() 19 | { 20 | int item; 21 | while(true) { 22 | synchronized (this.empty) { 23 | while (this.buffer.getStackPointer() == 0) { 24 | try { 25 | this.empty.wait(); 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | } 31 | 32 | // consumer get items 33 | item = buffer.get(); 34 | // the sleep simulates the time to consume an item 35 | try { 36 | Thread.sleep(this.serviceTime); 37 | } catch (InterruptedException e) { 38 | e.printStackTrace(); 39 | } 40 | System.out.println(String.format("Consumer has consumed %d", item)); 41 | 42 | synchronized (this.full) { 43 | this.full.notify(); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /process/word_count/Makefile: -------------------------------------------------------------------------------- 1 | # build all versions 2 | 3 | all: wc_single_proc wc_mult_proc wc_mult_procv_shm wc_thread_shmstyle wc_thread flag_wc_thread turn_wc_thread tsl_wc_thread longer_tsl_wc_thread sem_wc_thread longer_sem_wc_thread 4 | 5 | FLAGS=-Wall \ 6 | -pthread \ 7 | -pedantic 8 | 9 | wc_single_proc: wc_single_proc.c 10 | gcc $(FLAGS) -Wall -pedantic -o wc_single_proc wc_single_proc.c 11 | 12 | wc_mult_proc: wc_mult_proc.c 13 | gcc $(FLAGS) -o wc_mult_proc wc_mult_proc.c 14 | 15 | wc_mult_procv_shm: wc_mult_proc_shm.c 16 | gcc $(FLAGS) -o wc_mult_proc_shm wc_mult_proc_shm.c 17 | 18 | wc_thread_shmstyle: wc_thread_shmstyle.c 19 | gcc $(FLAGS) -o wc_thread_shmstyle wc_thread_shmstyle.c 20 | 21 | wc_thread: wc_thread.c 22 | gcc $(FLAGS) -o wc_thread wc_thread.c 23 | 24 | flag_wc_thread: flag_wc_thread.c 25 | gcc $(FLAGS) -o flag_wc_thread flag_wc_thread.c 26 | 27 | turn_wc_thread: turn_wc_thread.c 28 | gcc $(FLAGS) -o turn_wc_thread turn_wc_thread.c 29 | 30 | tsl_wc_thread: tsl_wc_thread.c 31 | gcc $(FLAGS) -no-pie -o tsl_wc_thread tsl_wc_thread.c 32 | 33 | longer_tsl_wc_thread: longer_tsl_wc_thread.c 34 | gcc $(FLAGS) -no-pie -o longer_tsl_wc_thread longer_tsl_wc_thread.c 35 | 36 | sem_wc_thread: sem_wc_thread.c 37 | gcc $(FLAGS) -o sem_wc_thread sem_wc_thread.c 38 | 39 | longer_sem_wc_thread: longer_sem_wc_thread.c 40 | gcc $(FLAGS) -o longer_sem_wc_thread longer_sem_wc_thread.c 41 | 42 | clean: 43 | rm -rf wc_single_proc wc_mult_proc wc_mult_proc_shm wc_thread_shmstyle wc_thread flag_wc_thread turn_wc_thread tsl_wc_thread longer_tsl_wc_thread sem_wc_thread longer_sem_wc_thread 44 | 45 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/OtherProducer.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | public class OtherProducer implements Runnable { 4 | private SharedBoundedStackMonitor buffer; 5 | private int serviceTime; 6 | private Integer full; 7 | private Integer empty; 8 | 9 | OtherProducer(SharedBoundedStack b, int serviceTime, Integer full, Integer empty) 10 | { 11 | this.buffer = (SharedBoundedStackMonitor) b; 12 | this.serviceTime = serviceTime; 13 | this.full = full; 14 | this.empty = empty; 15 | new Thread((Runnable) this, "Producer").start(); 16 | } 17 | 18 | public void run() 19 | { 20 | int i = 1; 21 | while (true) { 22 | synchronized (this.full) { 23 | while (this.buffer.getStackPointer() == this.buffer.getStackSize()) { 24 | try { 25 | this.full.wait(); 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | } 31 | 32 | // producer producing an item; the sleep just simulates the time to produce 33 | try { 34 | Thread.sleep(this.serviceTime); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | 39 | // producer put items 40 | System.out.println(String.format("Producer has produced %d", i)); 41 | this.buffer.put(i++); 42 | 43 | synchronized (this.empty) { 44 | this.empty.notify(); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /process/word_count/wc_single_proc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | size_t wc(const char *content) { 11 | size_t count = 0; 12 | 13 | for (bool inword = false; *content; ++content) { 14 | if (isspace(*content)) { 15 | if (inword) { 16 | inword = false; 17 | } 18 | } else { 19 | if (!inword) { 20 | inword = true; 21 | ++count; 22 | } 23 | } 24 | } 25 | return count; 26 | } 27 | 28 | size_t wc_file(const char *filename) { 29 | char *file_content = 0; 30 | long length; 31 | 32 | FILE *f = fopen(filename, "rb"); 33 | 34 | if (f) { 35 | fseek(f, 0, SEEK_END); 36 | length = ftell(f); 37 | fseek(f, 0, SEEK_SET); 38 | // put the whole file into the memory (beware) 39 | file_content = malloc(length); 40 | if (file_content) { 41 | fread(file_content, 1, length, f); 42 | } 43 | fclose(f); 44 | 45 | // count word from this buffer 46 | return wc(file_content); 47 | } 48 | 49 | return -1; 50 | } 51 | 52 | // count words in file within dir_path 53 | // we do not walk in subdirs 54 | size_t wc_dir(const char *dir_path) { 55 | 56 | DIR *dir; 57 | struct dirent *ent; 58 | char filepath[1024]; // unsafe 59 | 60 | size_t count = 0; 61 | 62 | dir = opendir(dir_path); 63 | if (dir) { 64 | while ((ent = readdir(dir)) != NULL) { 65 | if (ent->d_type == DT_REG) { // if it is regular file 66 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 67 | count += wc_file(filepath); 68 | } 69 | } 70 | } 71 | closedir(dir); 72 | return count; 73 | } 74 | 75 | // it calculates the number of words in files 76 | // stored under directory argv[1] 77 | // 78 | // we assume a depth 3 hierarchy. 79 | // At level 1, we have the root 80 | // at level 2, we have subdirs 81 | // at level 3, we have files 82 | // 83 | // root-- 84 | // |-- subdir-1 85 | // |-- subdir-2 86 | // |-- ... 87 | // |-- subdir-3 88 | // 89 | int main(int argc, char *argv[argc + 1]) { 90 | 91 | DIR *root_dir; 92 | struct dirent *ent; 93 | char filepath[1024]; // unsafe 94 | char *root_path = argv[1]; 95 | 96 | size_t count = 0; 97 | 98 | root_dir = opendir(root_path); 99 | 100 | if (root_dir) { 101 | while ((ent = readdir(root_dir)) != NULL) { 102 | if (ent->d_type == DT_DIR) { 103 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 104 | sprintf(filepath, "%s/%s", root_path, ent->d_name); 105 | // sums the subdir total 106 | count += wc_dir(filepath); 107 | } 108 | } 109 | } 110 | closedir(root_dir); 111 | } 112 | 113 | printf("%zu\n", count); 114 | return EXIT_SUCCESS; 115 | } 116 | -------------------------------------------------------------------------------- /process/word_count/wc_mult_proc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | size_t wc(const char *content) { 12 | size_t count = 0; 13 | 14 | for (bool inword = false; *content; ++content) { 15 | if (isspace(*content)) { 16 | if (inword) { 17 | inword = false; 18 | } 19 | } else { 20 | if (!inword) { 21 | inword = true; 22 | ++count; 23 | } 24 | } 25 | } 26 | return count; 27 | } 28 | 29 | size_t wc_file(const char *filename) { 30 | char *file_content = 0; 31 | long length; 32 | 33 | FILE *f = fopen(filename, "rb"); 34 | 35 | if (f) { 36 | fseek(f, 0, SEEK_END); 37 | length = ftell(f); 38 | fseek(f, 0, SEEK_SET); 39 | file_content = malloc(length); 40 | if (file_content) { 41 | fread(file_content, 1, length, f); 42 | } 43 | fclose(f); 44 | 45 | return wc(file_content); 46 | } 47 | 48 | return -1; 49 | } 50 | 51 | // count words in file within dir_path 52 | // we do not walk in subdirs 53 | size_t wc_dir(const char *dir_path) { 54 | 55 | DIR *dir; 56 | struct dirent *ent; 57 | char filepath[1024]; // unsafe 58 | 59 | size_t count = 0; 60 | 61 | dir = opendir(dir_path); 62 | if (dir) { 63 | while ((ent = readdir(dir)) != NULL) { 64 | if (ent->d_type == DT_REG) { // if is regular file 65 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 66 | count += wc_file(filepath); 67 | } 68 | } 69 | } 70 | closedir(dir); 71 | return count; 72 | } 73 | 74 | // it calculates the number of words in files 75 | // stored under directory argv[1] 76 | // 77 | // we assume a depth 3 hierarchy. 78 | // At level 1, we have the root 79 | // at level 2, we have subdirs 80 | // at level 3, we have files 81 | // 82 | // root-- 83 | // |-- subdir-1 84 | // |-- subdir-2 85 | // |-- ... 86 | // |-- subdir-3 87 | int main(int argc, char *argv[argc + 1]) { 88 | 89 | DIR *root_dir; 90 | struct dirent *ent; 91 | char filepath[1024]; // unsafe 92 | char *root_path = argv[1]; 93 | 94 | size_t count = 0; 95 | 96 | pid_t wpid; 97 | int status; 98 | 99 | root_dir = opendir(root_path); 100 | 101 | if (root_dir) { 102 | while ((ent = readdir(root_dir)) != NULL) { 103 | if (ent->d_type == DT_DIR) { 104 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 105 | sprintf(filepath, "%s/%s", root_path, ent->d_name); 106 | if (fork() == 0) { 107 | count += wc_dir(filepath); 108 | exit(0); 109 | } 110 | } 111 | } 112 | } 113 | closedir(root_dir); 114 | 115 | status = 0; 116 | while ((wpid = wait(&status)) > 0) 117 | ; 118 | } 119 | 120 | printf("%zu\n", count); 121 | 122 | return EXIT_SUCCESS; 123 | } 124 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/SharedBoundedStackSemaphore.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | import java.util.concurrent.Semaphore; 4 | 5 | public class SharedBoundedStackSemaphore implements SharedBoundedStack { 6 | // size of the shared buffer 7 | private int stackSize; 8 | // shared buffer 9 | private int[] stack; 10 | // points to the top of the stack; 0 means that the stack is empty 11 | private int stackPointer; 12 | // "mutex" ensures that access to the shared stack does not lead to a race condition 13 | private Semaphore mutex; 14 | // "empty" blocks the Consumer when the stack is empty; the shared stack is initially empty. 15 | private Semaphore empty; 16 | // "full" blocks the producer when there is no space left in the shared stack. 17 | private Semaphore full; 18 | 19 | public SharedBoundedStackSemaphore(int stackSize) { 20 | this.stackSize = stackSize; 21 | this.stack = new int[this.stackSize]; 22 | this.stackPointer = 0; 23 | this.mutex = new Semaphore(1); 24 | this.empty = new Semaphore(0); 25 | this.full = new Semaphore(this.stackSize); 26 | } 27 | 28 | // to get an item from buffer 29 | public int get() 30 | { 31 | int ret; 32 | 33 | try { 34 | // Before a consumer can consume an item, it must make sure there is an item to be consumed 35 | this.empty.acquire(); 36 | } 37 | catch (InterruptedException e) { 38 | System.out.println("InterruptedException caught"); 39 | } 40 | 41 | try { 42 | // Before a consumer can consume an item, it must acquire a permit from mutex to enter the critical region 43 | this.mutex.acquire(); 44 | } 45 | catch (InterruptedException e) { 46 | System.out.println("InterruptedException caught"); 47 | } 48 | 49 | ret = this.stack[--this.stackPointer]; 50 | System.out.println(String.format("Consumer has removed %d from slot %d", ret, this.stackPointer)); 51 | 52 | // After a consumer consumes an item, it releases mutex to allow others to enter the critical region 53 | this.mutex.release(); 54 | // After a consumer consumes an item, it releases full to notify the provider that there is a new free slot 55 | this.full.release(); 56 | 57 | return ret; 58 | } 59 | 60 | // to put an item in buffer 61 | public void put(int item) 62 | { 63 | try { 64 | // Before a producer can produce an item, it must make sure there is a free slot to add the new item 65 | this.full.acquire(); 66 | } 67 | catch (InterruptedException e) { 68 | System.out.println("InterruptedException caught"); 69 | } 70 | try { 71 | // Before a producer can produce an item, it must acquire a permit from mutex to enter the critical region 72 | this.mutex.acquire(); 73 | } 74 | catch (InterruptedException e) { 75 | System.out.println("InterruptedException caught"); 76 | } 77 | 78 | System.out.println(String.format("Producer has inserted %d in slot %d", item, this.stackPointer)); 79 | this.stack[this.stackPointer++] = item; 80 | 81 | // After a producer produces an item, it releases mutex to allow others to enter the critical region 82 | this.mutex.release(); 83 | // After a producer produces an item, it releases empty to notify the consumer that there is a new item to consume 84 | this.empty.release(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /process/prod_cons/src/prod_cons/SharedBoundedStackSemaphoreBugged.java: -------------------------------------------------------------------------------- 1 | package prod_cons; 2 | 3 | import java.util.concurrent.Semaphore; 4 | 5 | public class SharedBoundedStackSemaphoreBugged implements SharedBoundedStack { 6 | // size of the shared buffer 7 | private int stackSize; 8 | // shared buffer 9 | private int[] stack; 10 | // points to the top of the stack; 0 means that the stack is empty 11 | private int stackPointer; 12 | // "mutex" ensures that access to the shared stack does not lead to a race condition 13 | private Semaphore mutex; 14 | // "empty" blocks the Consumer when the stack is empty; the shared stack is initially empty. 15 | private Semaphore empty; 16 | // "full" blocks the producer when there is no space left in the shared stack. 17 | private Semaphore full; 18 | 19 | public SharedBoundedStackSemaphoreBugged(int stackSize) { 20 | this.stackSize = stackSize; 21 | this.stack = new int[this.stackSize]; 22 | this.stackPointer = 0; 23 | this.mutex = new Semaphore(1); 24 | this.empty = new Semaphore(0); 25 | this.full = new Semaphore(this.stackSize); 26 | } 27 | 28 | // to get an item from buffer 29 | public int get() 30 | { 31 | int ret; 32 | 33 | try { 34 | // Before a consumer can consume an item, it must acquire a permit from mutex to enter the critical region 35 | this.mutex.acquire(); 36 | } 37 | catch (InterruptedException e) { 38 | System.out.println("InterruptedException caught"); 39 | } 40 | 41 | try { 42 | // Before a consumer can consume an item, it must make sure there is an item to be consumed 43 | this.empty.acquire(); 44 | } 45 | catch (InterruptedException e) { 46 | System.out.println("InterruptedException caught"); 47 | } 48 | 49 | ret = this.stack[--this.stackPointer]; 50 | System.out.println(String.format("Consumer has removed %d from slot %d", ret, this.stackPointer)); 51 | 52 | // After a consumer consumes an item, it releases mutex to allow others to enter the critical region 53 | this.mutex.release(); 54 | // After a consumer consumes an item, it releases full to notify the provider that there is a new free slot 55 | this.full.release(); 56 | 57 | return ret; 58 | } 59 | 60 | // to put an item in buffer 61 | public void put(int item) 62 | { 63 | try { 64 | // Before a producer can produce an item, it must make sure there is a free slot to add the new item 65 | this.full.acquire(); 66 | } 67 | catch (InterruptedException e) { 68 | System.out.println("InterruptedException caught"); 69 | } 70 | try { 71 | // Before a producer can produce an item, it must acquire a permit from mutex to enter the critical region 72 | this.mutex.acquire(); 73 | } 74 | catch (InterruptedException e) { 75 | System.out.println("InterruptedException caught"); 76 | } 77 | 78 | System.out.println(String.format("Producer has inserted %d in slot %d", item, this.stackPointer)); 79 | this.stack[this.stackPointer++] = item; 80 | 81 | // After a producer produces an item, it releases mutex to allow others to enter the critical region 82 | this.mutex.release(); 83 | // After a producer produces an item, it releases empty to notify the consumer that there is a new item to consume 84 | this.empty.release(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /process/word_count/wc_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_ANSWERS 1024 12 | 13 | struct thread_param { 14 | char *dir_path; 15 | }; 16 | 17 | size_t WC_COUNT; 18 | 19 | size_t wc(const char *content) { 20 | size_t count = 0; 21 | 22 | for (bool inword = false; *content; ++content) { 23 | if (isspace(*content)) { 24 | if (inword) { 25 | inword = false; 26 | } 27 | } else { 28 | if (!inword) { 29 | inword = true; 30 | ++count; 31 | } 32 | } 33 | } 34 | return count; 35 | } 36 | 37 | size_t wc_file(const char *filename) { 38 | char *file_content = NULL; 39 | long length; 40 | 41 | FILE *f = fopen(filename, "rb"); 42 | 43 | if (f) { 44 | fseek(f, 0, SEEK_END); 45 | length = ftell(f); 46 | fseek(f, 0, SEEK_SET); 47 | file_content = malloc(length); 48 | if (file_content) { 49 | fread(file_content, 1, length, f); 50 | } 51 | fclose(f); 52 | 53 | return wc(file_content); 54 | } 55 | 56 | return -1; 57 | } 58 | 59 | // count words in file within dir_path 60 | // we do not walk in subdirs 61 | void *wc_dir(void *t) { 62 | struct thread_param *param = (struct thread_param*) t; 63 | char *dir_path = param->dir_path; 64 | 65 | DIR *dir; 66 | struct dirent *ent; 67 | char *filepath; 68 | size_t count = 0; 69 | 70 | dir = opendir(dir_path); 71 | if (dir) { 72 | while ((ent = readdir(dir)) != NULL) { 73 | if (ent->d_type == DT_REG) { // if is regular file 74 | filepath = malloc(strlen(dir_path) + strlen(ent->d_name) + 2); 75 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 76 | count = wc_file(filepath); 77 | free(filepath); 78 | WC_COUNT += count; 79 | } 80 | } 81 | } 82 | closedir(dir); 83 | 84 | pthread_exit(NULL); 85 | } 86 | 87 | // it calculates the number of words in files 88 | // stored under directory argv[1] 89 | // 90 | // we assume a depth 3 hierarchy. 91 | // At level 1, we have the root 92 | // at level 2, we have subdirs 93 | // at level 3, we have files 94 | // 95 | // root-- 96 | // |-- subdir-1 97 | // |-- subdir-2 98 | // |-- ... 99 | // |-- subdir-3 100 | int main(int argc, char *argv[argc + 1]) { 101 | DIR *root_dir; 102 | struct dirent *ent; 103 | char *filepath[MAX_ANSWERS]; 104 | char *root_path = argv[1]; 105 | 106 | WC_COUNT = 0; 107 | 108 | size_t n_threads = 0; 109 | pthread_t threads[MAX_ANSWERS]; 110 | struct thread_param params[MAX_ANSWERS]; 111 | 112 | root_dir = opendir(root_path); 113 | 114 | if (root_dir) { 115 | while ((ent = readdir(root_dir)) != NULL) { 116 | if (ent->d_type == DT_DIR) { 117 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 118 | filepath[n_threads] = malloc(strlen(root_path) + strlen(ent->d_name) + 2); 119 | sprintf(filepath[n_threads], "%s/%s", root_path, ent->d_name); 120 | params[n_threads].dir_path = filepath[n_threads]; 121 | pthread_create(&threads[n_threads], NULL, wc_dir, (void *)¶ms[n_threads]); 122 | n_threads++; 123 | } 124 | } 125 | } 126 | closedir(root_dir); 127 | } 128 | 129 | for (size_t i = 0; i < n_threads; i++) { 130 | pthread_join(threads[i], NULL); 131 | } 132 | 133 | printf("%zu\n", WC_COUNT); 134 | pthread_exit(NULL); 135 | } 136 | -------------------------------------------------------------------------------- /process/word_count/flag_wc_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_ANSWERS 1024 12 | 13 | struct thread_param { 14 | char *dir_path; 15 | }; 16 | 17 | size_t WC_COUNT; 18 | bool flag; 19 | 20 | size_t wc(const char *content) { 21 | size_t count = 0; 22 | 23 | for (bool inword = false; *content; ++content) { 24 | if (isspace(*content)) { 25 | if (inword) { 26 | inword = false; 27 | } 28 | } else { 29 | if (!inword) { 30 | inword = true; 31 | ++count; 32 | } 33 | } 34 | } 35 | return count; 36 | } 37 | 38 | size_t wc_file(const char *filename) { 39 | char *file_content = NULL; 40 | long length; 41 | 42 | FILE *f = fopen(filename, "rb"); 43 | 44 | if (f) { 45 | fseek(f, 0, SEEK_END); 46 | length = ftell(f); 47 | fseek(f, 0, SEEK_SET); 48 | file_content = malloc(length); 49 | if (file_content) { 50 | fread(file_content, 1, length, f); 51 | } 52 | fclose(f); 53 | 54 | return wc(file_content); 55 | } 56 | 57 | return -1; 58 | } 59 | 60 | // count words in file within dir_path 61 | // we do not walk in subdirs 62 | void *wc_dir(void *t) { 63 | struct thread_param *param = (struct thread_param*) t; 64 | char *dir_path = param->dir_path; 65 | 66 | DIR *dir; 67 | struct dirent *ent; 68 | char *filepath; 69 | size_t count = 0; 70 | 71 | dir = opendir(dir_path); 72 | if (dir) { 73 | while ((ent = readdir(dir)) != NULL) { 74 | if (ent->d_type == DT_REG) { // if is regular file 75 | filepath = malloc(strlen(dir_path) + strlen(ent->d_name) + 2); 76 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 77 | count = wc_file(filepath); 78 | free(filepath); 79 | while (flag) 80 | ; 81 | flag = true; 82 | WC_COUNT += count; 83 | flag = false; 84 | } 85 | } 86 | } 87 | closedir(dir); 88 | 89 | pthread_exit(NULL); 90 | } 91 | 92 | // it calculates the number of words in files 93 | // stored under directory argv[1] 94 | // 95 | // we assume a depth 3 hierarchy. 96 | // At level 1, we have the root 97 | // at level 2, we have subdirs 98 | // at level 3, we have files 99 | // 100 | // root-- 101 | // |-- subdir-1 102 | // |-- subdir-2 103 | // |-- ... 104 | // |-- subdir-3 105 | int main(int argc, char *argv[argc + 1]) { 106 | DIR *root_dir; 107 | struct dirent *ent; 108 | char *filepath[MAX_ANSWERS]; 109 | char *root_path = argv[1]; 110 | 111 | WC_COUNT = 0; 112 | flag = false; 113 | 114 | size_t n_threads = 0; 115 | pthread_t threads[MAX_ANSWERS]; 116 | struct thread_param params[MAX_ANSWERS]; 117 | 118 | root_dir = opendir(root_path); 119 | 120 | if (root_dir) { 121 | while ((ent = readdir(root_dir)) != NULL) { 122 | if (ent->d_type == DT_DIR) { 123 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 124 | filepath[n_threads] = malloc(strlen(root_path) + strlen(ent->d_name) + 2); 125 | sprintf(filepath[n_threads], "%s/%s", root_path, ent->d_name); 126 | params[n_threads].dir_path = filepath[n_threads]; 127 | pthread_create(&threads[n_threads], NULL, wc_dir, (void *)¶ms[n_threads]); 128 | n_threads++; 129 | } 130 | } 131 | } 132 | closedir(root_dir); 133 | } 134 | 135 | for (size_t i = 0; i < n_threads; i++) { 136 | pthread_join(threads[i], NULL); 137 | } 138 | 139 | printf("%zu\n", WC_COUNT); 140 | pthread_exit(NULL); 141 | } 142 | -------------------------------------------------------------------------------- /process/word_count/longer_sem_wc_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define MAX_ANSWERS 1024 15 | 16 | struct thread_param { 17 | char *dir_path; 18 | }; 19 | 20 | sem_t *mutex; 21 | size_t WC_COUNT; 22 | 23 | size_t wc(const char *content) { 24 | size_t count = 0; 25 | 26 | for (bool inword = false; *content; ++content) { 27 | if (isspace(*content)) { 28 | if (inword) { 29 | inword = false; 30 | } 31 | } else { 32 | if (!inword) { 33 | inword = true; 34 | ++count; 35 | } 36 | } 37 | } 38 | return count; 39 | } 40 | 41 | size_t wc_file(const char *filename) { 42 | char *file_content = NULL; 43 | long length; 44 | 45 | FILE *f = fopen(filename, "rb"); 46 | 47 | if (f) { 48 | fseek(f, 0, SEEK_END); 49 | length = ftell(f); 50 | fseek(f, 0, SEEK_SET); 51 | file_content = malloc(length); 52 | if (file_content) { 53 | fread(file_content, 1, length, f); 54 | } 55 | fclose(f); 56 | 57 | return wc(file_content); 58 | } 59 | 60 | return -1; 61 | } 62 | 63 | // count words in file within dir_path 64 | // we do not walk in subdirs 65 | void *wc_dir(void *t) { 66 | struct thread_param *param = (struct thread_param*) t; 67 | char *dir_path = param->dir_path; 68 | 69 | DIR *dir; 70 | struct dirent *ent; 71 | char *filepath; 72 | 73 | dir = opendir(dir_path); 74 | if (dir) { 75 | while ((ent = readdir(dir)) != NULL) { 76 | if (ent->d_type == DT_REG) { // if is regular file 77 | filepath = malloc(strlen(dir_path) + strlen(ent->d_name) + 2); 78 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 79 | sem_wait(mutex); 80 | WC_COUNT += wc_file(filepath); 81 | sem_post(mutex); 82 | free(filepath); 83 | } 84 | } 85 | } 86 | closedir(dir); 87 | 88 | pthread_exit(NULL); 89 | } 90 | 91 | // it calculates the number of words in files 92 | // stored under directory argv[1] 93 | // 94 | // we assume a depth 3 hierarchy. 95 | // At level 1, we have the root 96 | // at level 2, we have subdirs 97 | // at level 3, we have files 98 | // 99 | // root-- 100 | // |-- subdir-1 101 | // |-- subdir-2 102 | // |-- ... 103 | // |-- subdir-3 104 | int main(int argc, char *argv[argc + 1]) { 105 | DIR *root_dir; 106 | struct dirent *ent; 107 | char *filepath[MAX_ANSWERS]; 108 | char *root_path = argv[1]; 109 | 110 | mutex = sem_open("/mutex", O_CREAT, 0644, 1); 111 | WC_COUNT = 0; 112 | 113 | size_t n_threads = 0; 114 | pthread_t threads[MAX_ANSWERS]; 115 | struct thread_param params[MAX_ANSWERS]; 116 | 117 | root_dir = opendir(root_path); 118 | 119 | if (root_dir) { 120 | while ((ent = readdir(root_dir)) != NULL) { 121 | if (ent->d_type == DT_DIR) { 122 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 123 | filepath[n_threads] = malloc(strlen(root_path) + strlen(ent->d_name) + 2); 124 | sprintf(filepath[n_threads], "%s/%s", root_path, ent->d_name); 125 | params[n_threads].dir_path = filepath[n_threads]; 126 | pthread_create(&threads[n_threads], NULL, wc_dir, (void *)¶ms[n_threads]); 127 | n_threads++; 128 | } 129 | } 130 | } 131 | closedir(root_dir); 132 | } 133 | 134 | for (size_t i = 0; i < n_threads; i++) { 135 | pthread_join(threads[i], NULL); 136 | } 137 | 138 | sem_close(mutex); 139 | sem_unlink("/mutex"); 140 | printf("%zu\n", WC_COUNT); 141 | pthread_exit(NULL); 142 | } 143 | -------------------------------------------------------------------------------- /process/word_count/wc_thread_shmstyle.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_ANSWERS 1024 12 | 13 | // the processes will share this Response on the shared memory 14 | typedef struct Response { 15 | size_t answers[MAX_ANSWERS]; 16 | } Response; 17 | 18 | size_t wc(const char *content) { 19 | size_t count = 0; 20 | 21 | for (bool inword = false; *content; ++content) { 22 | if (isspace(*content)) { 23 | if (inword) { 24 | inword = false; 25 | } 26 | } else { 27 | if (!inword) { 28 | inword = true; 29 | ++count; 30 | } 31 | } 32 | } 33 | return count; 34 | } 35 | 36 | size_t wc_file(const char *filename) { 37 | char *file_content = 0; 38 | long length; 39 | 40 | FILE *f = fopen(filename, "rb"); 41 | 42 | if (f) { 43 | fseek(f, 0, SEEK_END); 44 | length = ftell(f); 45 | fseek(f, 0, SEEK_SET); 46 | file_content = malloc(length); 47 | if (file_content) { 48 | fread(file_content, 1, length, f); 49 | } 50 | fclose(f); 51 | 52 | return wc(file_content); 53 | } 54 | 55 | return -1; 56 | } 57 | 58 | // count words in file within dir_path 59 | // we do not walk in subdirs 60 | size_t wc_dir(const char *dir_path) { 61 | 62 | DIR *dir; 63 | struct dirent *ent; 64 | char filepath[1024]; // unsafe 65 | 66 | size_t count = 0; 67 | 68 | dir = opendir(dir_path); 69 | if (dir) { 70 | // printf("pid %d dir %s\n", getpid(), root_path); 71 | while ((ent = readdir(dir)) != NULL) { 72 | if (ent->d_type == DT_REG) { // if is regular file 73 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 74 | count += wc_file(filepath); 75 | } 76 | } 77 | } 78 | closedir(dir); 79 | return count; 80 | } 81 | 82 | void *wc_dir_wrap(void *t) { 83 | size_t count; 84 | char *dir_path = (char *)t; 85 | count = wc_dir(dir_path); 86 | pthread_exit((void *)count); 87 | } 88 | 89 | // it calculates the number of words in files 90 | // stored under directory argv[1] 91 | // 92 | // we assume a depth 3 hierarchy. 93 | // At level 1, we have the root 94 | // at level 2, we have subdirs 95 | // at level 3, we have files 96 | // 97 | // root-- 98 | // |-- subdir-1 99 | // |-- subdir-2 100 | // |-- ... 101 | // |-- subdir-3 102 | int main(int argc, char *argv[argc + 1]) { 103 | 104 | DIR *root_dir; 105 | struct dirent *ent; 106 | char filepath[1024]; // unsafe 107 | char *root_path = argv[1]; 108 | 109 | size_t count = 0; 110 | size_t n_threads = 0; 111 | pthread_t threads[MAX_ANSWERS]; 112 | 113 | // we will collect answer on this Response object 114 | Response response; 115 | for (size_t i = 0; i < MAX_ANSWERS; i++) { 116 | response.answers[i] = 0; 117 | } 118 | 119 | root_dir = opendir(root_path); 120 | 121 | if (root_dir) { 122 | while ((ent = readdir(root_dir)) != NULL) { 123 | if (ent->d_type == DT_DIR) { 124 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 125 | sprintf(filepath, "%s/%s", root_path, ent->d_name); 126 | pthread_create(&threads[n_threads++], NULL, wc_dir_wrap, 127 | (void *)filepath); 128 | } 129 | } 130 | } 131 | closedir(root_dir); 132 | } 133 | 134 | long child_count; 135 | for (size_t i = 0; i < n_threads; i++) { 136 | pthread_join(threads[i], (void *)&child_count); 137 | response.answers[i] = child_count; 138 | } 139 | 140 | for (size_t i = 0; i < n_threads; i++) { 141 | count += response.answers[i]; 142 | } 143 | 144 | printf("%zu\n", count); 145 | pthread_exit(NULL); 146 | } 147 | -------------------------------------------------------------------------------- /process/word_count/sem_wc_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define MAX_ANSWERS 1024 15 | 16 | struct thread_param { 17 | char *dir_path; 18 | }; 19 | 20 | sem_t *mutex; 21 | size_t WC_COUNT; 22 | 23 | size_t wc(const char *content) { 24 | size_t count = 0; 25 | 26 | for (bool inword = false; *content; ++content) { 27 | if (isspace(*content)) { 28 | if (inword) { 29 | inword = false; 30 | } 31 | } else { 32 | if (!inword) { 33 | inword = true; 34 | ++count; 35 | } 36 | } 37 | } 38 | return count; 39 | } 40 | 41 | size_t wc_file(const char *filename) { 42 | char *file_content = NULL; 43 | long length; 44 | 45 | FILE *f = fopen(filename, "rb"); 46 | 47 | if (f) { 48 | fseek(f, 0, SEEK_END); 49 | length = ftell(f); 50 | fseek(f, 0, SEEK_SET); 51 | file_content = malloc(length); 52 | if (file_content) { 53 | fread(file_content, 1, length, f); 54 | } 55 | fclose(f); 56 | 57 | return wc(file_content); 58 | } 59 | 60 | return -1; 61 | } 62 | 63 | // count words in file within dir_path 64 | // we do not walk in subdirs 65 | void *wc_dir(void *t) { 66 | struct thread_param *param = (struct thread_param*) t; 67 | char *dir_path = param->dir_path; 68 | 69 | DIR *dir; 70 | struct dirent *ent; 71 | char *filepath; 72 | size_t count; 73 | 74 | dir = opendir(dir_path); 75 | if (dir) { 76 | while ((ent = readdir(dir)) != NULL) { 77 | if (ent->d_type == DT_REG) { // if is regular file 78 | filepath = malloc(strlen(dir_path) + strlen(ent->d_name) + 2); 79 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 80 | count = wc_file(filepath); 81 | sem_wait(mutex); 82 | WC_COUNT += count; 83 | sem_post(mutex); 84 | free(filepath); 85 | } 86 | } 87 | } 88 | closedir(dir); 89 | 90 | pthread_exit(NULL); 91 | } 92 | 93 | // it calculates the number of words in files 94 | // stored under directory argv[1] 95 | // 96 | // we assume a depth 3 hierarchy. 97 | // At level 1, we have the root 98 | // at level 2, we have subdirs 99 | // at level 3, we have files 100 | // 101 | // root-- 102 | // |-- subdir-1 103 | // |-- subdir-2 104 | // |-- ... 105 | // |-- subdir-3 106 | int main(int argc, char *argv[argc + 1]) { 107 | DIR *root_dir; 108 | struct dirent *ent; 109 | char *filepath[MAX_ANSWERS]; 110 | char *root_path = argv[1]; 111 | 112 | mutex = sem_open("/mutex", O_CREAT, 0644, 1); 113 | WC_COUNT = 0; 114 | 115 | size_t n_threads = 0; 116 | pthread_t threads[MAX_ANSWERS]; 117 | struct thread_param params[MAX_ANSWERS]; 118 | 119 | root_dir = opendir(root_path); 120 | 121 | if (root_dir) { 122 | while ((ent = readdir(root_dir)) != NULL) { 123 | if (ent->d_type == DT_DIR) { 124 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 125 | filepath[n_threads] = malloc(strlen(root_path) + strlen(ent->d_name) + 2); 126 | sprintf(filepath[n_threads], "%s/%s", root_path, ent->d_name); 127 | params[n_threads].dir_path = filepath[n_threads]; 128 | pthread_create(&threads[n_threads], NULL, wc_dir, (void *)¶ms[n_threads]); 129 | n_threads++; 130 | } 131 | } 132 | } 133 | closedir(root_dir); 134 | } 135 | 136 | for (size_t i = 0; i < n_threads; i++) { 137 | pthread_join(threads[i], NULL); 138 | } 139 | 140 | sem_close(mutex); 141 | sem_unlink("/mutex"); 142 | printf("%zu\n", WC_COUNT); 143 | pthread_exit(NULL); 144 | } 145 | -------------------------------------------------------------------------------- /process/word_count/turn_wc_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_ANSWERS 1024 12 | 13 | struct thread_param { 14 | size_t thread_id; 15 | char *dir_path; 16 | }; 17 | 18 | size_t WC_COUNT; 19 | size_t TURN; 20 | size_t n_threads; 21 | 22 | size_t wc(const char *content) { 23 | size_t count = 0; 24 | 25 | for (bool inword = false; *content; ++content) { 26 | if (isspace(*content)) { 27 | if (inword) { 28 | inword = false; 29 | } 30 | } else { 31 | if (!inword) { 32 | inword = true; 33 | ++count; 34 | } 35 | } 36 | } 37 | return count; 38 | } 39 | 40 | size_t wc_file(const char *filename) { 41 | char *file_content = NULL; 42 | long length; 43 | 44 | FILE *f = fopen(filename, "rb"); 45 | 46 | if (f) { 47 | fseek(f, 0, SEEK_END); 48 | length = ftell(f); 49 | fseek(f, 0, SEEK_SET); 50 | file_content = malloc(length); 51 | if (file_content) { 52 | fread(file_content, 1, length, f); 53 | } 54 | fclose(f); 55 | 56 | return wc(file_content); 57 | } 58 | 59 | return -1; 60 | } 61 | 62 | // count words in file within dir_path 63 | // we do not walk in subdirs 64 | void *wc_dir(void *t) { 65 | struct thread_param *param = (struct thread_param*) t; 66 | char *dir_path = param->dir_path; 67 | size_t thread_id = param->thread_id; 68 | 69 | DIR *dir; 70 | struct dirent *ent; 71 | char *filepath; 72 | size_t count = 0; 73 | 74 | dir = opendir(dir_path); 75 | if (dir) { 76 | while ((ent = readdir(dir)) != NULL) { 77 | if (ent->d_type == DT_REG) { // if is regular file 78 | filepath = malloc(strlen(dir_path) + strlen(ent->d_name) + 2); 79 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 80 | count = wc_file(filepath); 81 | free(filepath); 82 | while (TURN != thread_id) 83 | ; 84 | WC_COUNT += count; 85 | if (++TURN == n_threads) TURN = 0; 86 | } 87 | } 88 | } 89 | closedir(dir); 90 | 91 | pthread_exit(NULL); 92 | } 93 | 94 | // it calculates the number of words in files 95 | // stored under directory argv[1] 96 | // 97 | // we assume a depth 3 hierarchy. 98 | // At level 1, we have the root 99 | // at level 2, we have subdirs 100 | // at level 3, we have files 101 | // 102 | // root-- 103 | // |-- subdir-1 104 | // |-- subdir-2 105 | // |-- ... 106 | // |-- subdir-3 107 | int main(int argc, char *argv[argc + 1]) { 108 | DIR *root_dir; 109 | struct dirent *ent; 110 | char *filepath[MAX_ANSWERS]; 111 | char *root_path = argv[1]; 112 | 113 | WC_COUNT = 0; 114 | TURN = 0; 115 | n_threads = 0; 116 | 117 | pthread_t threads[MAX_ANSWERS]; 118 | struct thread_param params[MAX_ANSWERS]; 119 | 120 | root_dir = opendir(root_path); 121 | 122 | if (root_dir) { 123 | while ((ent = readdir(root_dir)) != NULL) { 124 | if (ent->d_type == DT_DIR) { 125 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 126 | filepath[n_threads] = malloc(strlen(root_path) + strlen(ent->d_name) + 2); 127 | sprintf(filepath[n_threads], "%s/%s", root_path, ent->d_name); 128 | params[n_threads].dir_path = filepath[n_threads]; 129 | params[n_threads].thread_id = n_threads; 130 | pthread_create(&threads[n_threads], NULL, wc_dir, (void *)¶ms[n_threads]); 131 | n_threads++; 132 | } 133 | } 134 | } 135 | closedir(root_dir); 136 | } 137 | 138 | for (size_t i = 0; i < n_threads; i++) { 139 | pthread_join(threads[i], NULL); 140 | } 141 | 142 | printf("%zu\n", WC_COUNT); 143 | pthread_exit(NULL); 144 | } 145 | -------------------------------------------------------------------------------- /process/word_count/longer_tsl_wc_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_ANSWERS 1024 12 | 13 | struct thread_param { 14 | char *dir_path; 15 | }; 16 | 17 | size_t WC_COUNT; 18 | 19 | void enter_region() { 20 | asm( 21 | ".data\n\t" 22 | "lock:\n\t" 23 | ".byte 0\n\t" 24 | ".text\n\t" 25 | 26 | "_enter_region:\n\t" 27 | "movb $1, %al\n\t" /* move 1 to AL */ 28 | "xchgb (lock),%al\n\t" 29 | "cmp $0, %al\n\t" 30 | "jne _enter_region\n\t" 31 | 32 | ); 33 | } 34 | 35 | void leave_region() { 36 | asm("movb $0, (lock)"); 37 | } 38 | 39 | size_t wc(const char *content) { 40 | size_t count = 0; 41 | 42 | for (bool inword = false; *content; ++content) { 43 | if (isspace(*content)) { 44 | if (inword) { 45 | inword = false; 46 | } 47 | } else { 48 | if (!inword) { 49 | inword = true; 50 | ++count; 51 | } 52 | } 53 | } 54 | return count; 55 | } 56 | 57 | size_t wc_file(const char *filename) { 58 | char *file_content = NULL; 59 | long length; 60 | 61 | FILE *f = fopen(filename, "rb"); 62 | 63 | if (f) { 64 | fseek(f, 0, SEEK_END); 65 | length = ftell(f); 66 | fseek(f, 0, SEEK_SET); 67 | file_content = malloc(length); 68 | if (file_content) { 69 | fread(file_content, 1, length, f); 70 | } 71 | fclose(f); 72 | 73 | return wc(file_content); 74 | } 75 | 76 | return -1; 77 | } 78 | 79 | // count words in file within dir_path 80 | // we do not walk in subdirs 81 | void *wc_dir(void *t) { 82 | struct thread_param *param = (struct thread_param*) t; 83 | char *dir_path = param->dir_path; 84 | 85 | DIR *dir; 86 | struct dirent *ent; 87 | char *filepath; 88 | 89 | dir = opendir(dir_path); 90 | if (dir) { 91 | while ((ent = readdir(dir)) != NULL) { 92 | if (ent->d_type == DT_REG) { // if is regular file 93 | filepath = malloc(strlen(dir_path) + strlen(ent->d_name) + 2); 94 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 95 | enter_region(); 96 | WC_COUNT += wc_file(filepath); 97 | leave_region(); 98 | free(filepath); 99 | } 100 | } 101 | } 102 | closedir(dir); 103 | 104 | pthread_exit(NULL); 105 | } 106 | 107 | // it calculates the number of words in files 108 | // stored under directory argv[1] 109 | // 110 | // we assume a depth 3 hierarchy. 111 | // At level 1, we have the root 112 | // at level 2, we have subdirs 113 | // at level 3, we have files 114 | // 115 | // root-- 116 | // |-- subdir-1 117 | // |-- subdir-2 118 | // |-- ... 119 | // |-- subdir-3 120 | int main(int argc, char *argv[argc + 1]) { 121 | DIR *root_dir; 122 | struct dirent *ent; 123 | char *filepath[MAX_ANSWERS]; 124 | char *root_path = argv[1]; 125 | 126 | WC_COUNT = 0; 127 | 128 | size_t n_threads = 0; 129 | pthread_t threads[MAX_ANSWERS]; 130 | struct thread_param params[MAX_ANSWERS]; 131 | 132 | root_dir = opendir(root_path); 133 | 134 | if (root_dir) { 135 | while ((ent = readdir(root_dir)) != NULL) { 136 | if (ent->d_type == DT_DIR) { 137 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 138 | filepath[n_threads] = malloc(strlen(root_path) + strlen(ent->d_name) + 2); 139 | sprintf(filepath[n_threads], "%s/%s", root_path, ent->d_name); 140 | params[n_threads].dir_path = filepath[n_threads]; 141 | pthread_create(&threads[n_threads], NULL, wc_dir, (void *)¶ms[n_threads]); 142 | n_threads++; 143 | } 144 | } 145 | } 146 | closedir(root_dir); 147 | } 148 | 149 | for (size_t i = 0; i < n_threads; i++) { 150 | pthread_join(threads[i], NULL); 151 | } 152 | 153 | printf("%zu\n", WC_COUNT); 154 | pthread_exit(NULL); 155 | } 156 | -------------------------------------------------------------------------------- /process/word_count/tsl_wc_thread.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAX_ANSWERS 1024 12 | 13 | struct thread_param { 14 | char *dir_path; 15 | }; 16 | 17 | size_t WC_COUNT; 18 | 19 | void enter_region() { 20 | asm( 21 | ".data\n\t" 22 | "lock:\n\t" 23 | ".byte 0\n\t" 24 | ".text\n\t" 25 | 26 | "_enter_region:\n\t" 27 | "movb $1, %al\n\t" /* move 1 to AL */ 28 | "xchgb (lock),%al\n\t" 29 | "cmp $0, %al\n\t" 30 | "jne _enter_region\n\t" 31 | 32 | ); 33 | } 34 | 35 | void leave_region() { 36 | asm("movb $0, (lock)"); 37 | } 38 | 39 | size_t wc(const char *content) { 40 | size_t count = 0; 41 | 42 | for (bool inword = false; *content; ++content) { 43 | if (isspace(*content)) { 44 | if (inword) { 45 | inword = false; 46 | } 47 | } else { 48 | if (!inword) { 49 | inword = true; 50 | ++count; 51 | } 52 | } 53 | } 54 | return count; 55 | } 56 | 57 | size_t wc_file(const char *filename) { 58 | char *file_content = NULL; 59 | long length; 60 | 61 | FILE *f = fopen(filename, "rb"); 62 | 63 | if (f) { 64 | fseek(f, 0, SEEK_END); 65 | length = ftell(f); 66 | fseek(f, 0, SEEK_SET); 67 | file_content = malloc(length); 68 | if (file_content) { 69 | fread(file_content, 1, length, f); 70 | } 71 | fclose(f); 72 | 73 | return wc(file_content); 74 | } 75 | 76 | return -1; 77 | } 78 | 79 | // count words in file within dir_path 80 | // we do not walk in subdirs 81 | void *wc_dir(void *t) { 82 | struct thread_param *param = (struct thread_param*) t; 83 | char *dir_path = param->dir_path; 84 | 85 | DIR *dir; 86 | struct dirent *ent; 87 | char *filepath; 88 | size_t count = 0; 89 | 90 | dir = opendir(dir_path); 91 | if (dir) { 92 | while ((ent = readdir(dir)) != NULL) { 93 | if (ent->d_type == DT_REG) { // if is regular file 94 | filepath = malloc(strlen(dir_path) + strlen(ent->d_name) + 2); 95 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 96 | count = wc_file(filepath); 97 | free(filepath); 98 | enter_region(); 99 | WC_COUNT += count; 100 | leave_region(); 101 | } 102 | } 103 | } 104 | closedir(dir); 105 | 106 | pthread_exit(NULL); 107 | } 108 | 109 | // it calculates the number of words in files 110 | // stored under directory argv[1] 111 | // 112 | // we assume a depth 3 hierarchy. 113 | // At level 1, we have the root 114 | // at level 2, we have subdirs 115 | // at level 3, we have files 116 | // 117 | // root-- 118 | // |-- subdir-1 119 | // |-- subdir-2 120 | // |-- ... 121 | // |-- subdir-3 122 | int main(int argc, char *argv[argc + 1]) { 123 | DIR *root_dir; 124 | struct dirent *ent; 125 | char *filepath[MAX_ANSWERS]; 126 | char *root_path = argv[1]; 127 | 128 | WC_COUNT = 0; 129 | 130 | size_t n_threads = 0; 131 | pthread_t threads[MAX_ANSWERS]; 132 | struct thread_param params[MAX_ANSWERS]; 133 | 134 | root_dir = opendir(root_path); 135 | 136 | if (root_dir) { 137 | while ((ent = readdir(root_dir)) != NULL) { 138 | if (ent->d_type == DT_DIR) { 139 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 140 | filepath[n_threads] = malloc(strlen(root_path) + strlen(ent->d_name) + 2); 141 | sprintf(filepath[n_threads], "%s/%s", root_path, ent->d_name); 142 | params[n_threads].dir_path = filepath[n_threads]; 143 | pthread_create(&threads[n_threads], NULL, wc_dir, (void *)¶ms[n_threads]); 144 | n_threads++; 145 | } 146 | } 147 | } 148 | closedir(root_dir); 149 | } 150 | 151 | for (size_t i = 0; i < n_threads; i++) { 152 | pthread_join(threads[i], NULL); 153 | } 154 | 155 | printf("%zu\n", WC_COUNT); 156 | pthread_exit(NULL); 157 | } 158 | -------------------------------------------------------------------------------- /process/word_count/wc_mult_proc_shm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define SHM_FILE "/tmp/shm_wc" 14 | #define MAX_ANSWERS 1024 15 | 16 | // the processes will share this Response on the shared memory 17 | typedef struct Response { 18 | size_t answers[MAX_ANSWERS]; 19 | } Response; 20 | 21 | size_t wc(const char *content) { 22 | size_t count = 0; 23 | 24 | for (bool inword = false; *content; ++content) { 25 | if (isspace(*content)) { 26 | if (inword) { 27 | inword = false; 28 | } 29 | } else { 30 | if (!inword) { 31 | inword = true; 32 | ++count; 33 | } 34 | } 35 | } 36 | return count; 37 | } 38 | 39 | size_t wc_file(const char *filename) { 40 | char *file_content = 0; // how to init? 0 or null? 41 | long length; // what is the modern typ? 42 | 43 | FILE *f = fopen(filename, "rb"); 44 | 45 | if (f) { 46 | fseek(f, 0, SEEK_END); 47 | length = ftell(f); 48 | fseek(f, 0, SEEK_SET); 49 | file_content = malloc(length); 50 | if (file_content) { 51 | fread(file_content, 1, length, f); 52 | } 53 | fclose(f); 54 | 55 | return wc(file_content); 56 | } 57 | 58 | return -1; 59 | } 60 | 61 | // count words in file within dir_path 62 | // we do not walk in subdirs 63 | size_t wc_dir(const char *dir_path) { 64 | 65 | DIR *dir; 66 | struct dirent *ent; 67 | char filepath[1024]; // unsafe 68 | 69 | size_t count = 0; 70 | 71 | dir = opendir(dir_path); 72 | if (dir) { 73 | while ((ent = readdir(dir)) != NULL) { 74 | if (ent->d_type == DT_REG) { // if is regular file 75 | sprintf(filepath, "%s/%s", dir_path, ent->d_name); 76 | count += wc_file(filepath); 77 | } 78 | } 79 | } 80 | closedir(dir); 81 | return count; 82 | } 83 | 84 | int init_shm() { 85 | // the shared memory is backed by a file, we need to create it 86 | FILE *f; 87 | f = fopen(SHM_FILE, "w"); 88 | fclose(f); 89 | return 0; 90 | } 91 | 92 | key_t generate_key() { 93 | key_t key = ftok(SHM_FILE, 666); 94 | if (key == -1) { 95 | perror("ftok error"); 96 | return -1; 97 | } 98 | return key; 99 | } 100 | 101 | int generate_mem_segment_id(key_t key) { 102 | int shmid; 103 | shmid = shmget(key, sizeof(Response), 0777 | IPC_CREAT); 104 | if (shmid == -1) { 105 | perror("shmge error"); 106 | return -1; 107 | } 108 | return shmid; 109 | } 110 | 111 | int destroy_shm() { 112 | key_t key = generate_key(); 113 | int shm_id = generate_mem_segment_id(key); 114 | shmctl(shm_id, IPC_RMID, NULL); 115 | return 0; 116 | } 117 | 118 | // attach to the shared memory identified by shmid 119 | int attach_mem_segment_id(int shmid, Response **response) { 120 | void *shm = shmat(shmid, (void *)0, 0); 121 | if (shm == (void *)(-1)) { 122 | perror("error on shmat"); 123 | return -1; 124 | } 125 | *response = shm; 126 | return 0; 127 | } 128 | 129 | int attach(Response **response) { 130 | // we need a key to access the shm region 131 | key_t key = generate_key(); 132 | if (key == -1) { 133 | return key; 134 | } 135 | 136 | // the shm memory region has an id 137 | int shmid = generate_mem_segment_id(key); 138 | if (shmid == -1) { 139 | return shmid; 140 | } 141 | 142 | return attach_mem_segment_id(shmid, response); 143 | } 144 | 145 | int detach(Response *response) { 146 | if (shmdt(response) == -1) { 147 | perror("error on detaching shared mem"); 148 | } 149 | 150 | return 0; 151 | } 152 | 153 | // it calculates the number of words in files 154 | // stored under directory argv[1] 155 | // 156 | // we assume a depth 3 hierarchy. 157 | // At level 1, we have the root 158 | // at level 2, we have subdirs 159 | // at level 3, we have files 160 | // 161 | // root-- 162 | // |-- subdir-1 163 | // |-- subdir-2 164 | // |-- ... 165 | // |-- subdir-3 166 | int main(int argc, char *argv[argc + 1]) { 167 | 168 | DIR *root_dir; 169 | struct dirent *ent; 170 | char filepath[1024]; // unsafe 171 | char *root_path = argv[1]; 172 | 173 | size_t count = 0; 174 | size_t child_count = 0; 175 | 176 | pid_t wpid; 177 | int status; 178 | 179 | init_shm(); 180 | // we will collect answer on this Response object, living on the shared memory 181 | Response *shm_response; 182 | if (attach(&shm_response) == -1) { 183 | return EXIT_FAILURE; 184 | } 185 | 186 | for (size_t i = 0; i < MAX_ANSWERS; i++) { 187 | shm_response->answers[i] = 0; 188 | } 189 | 190 | root_dir = opendir(root_path); 191 | 192 | if (root_dir) { 193 | // printf("pid %d dir %s\n", getpid(), root_path); 194 | while ((ent = readdir(root_dir)) != NULL) { 195 | if (ent->d_type == DT_DIR) { 196 | if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { 197 | sprintf(filepath, "%s/%s", root_path, ent->d_name); 198 | 199 | if (fork() == 0) { 200 | Response *child_response; 201 | if (attach(&child_response) == -1) { 202 | perror("error attaching child\n"); 203 | } 204 | child_response->answers[child_count] = wc_dir(filepath); 205 | detach(child_response); 206 | exit(0); 207 | } 208 | 209 | // we need a counter to the children know where to write in the vector 210 | ++child_count; 211 | } 212 | } 213 | } 214 | closedir(root_dir); 215 | 216 | status = 0; 217 | while ((wpid = wait(&status)) > 0) 218 | ; 219 | } 220 | 221 | for (size_t i = 0; i < child_count; i++) { 222 | count += shm_response->answers[i]; 223 | } 224 | 225 | printf("%zu\n", count); 226 | destroy_shm(); 227 | 228 | return EXIT_SUCCESS; 229 | } 230 | --------------------------------------------------------------------------------