Threads and Scheduling

feat: Finished commenting program.

+68 -18
+45 -14
README.md
··· 1 1 # tsched 2 2 3 - This project is the second assignment for CCOM4017. 3 + This project is the second assignment for CCOM-4017. 4 4 5 - I am using a sockets library I developed myself on: 5 + I am using a sockets library I developed mysel. For more information on how the 6 + sockets library was developed, feel free to visit the repo: 6 7 - https://git.gay/sona/enchufe 7 8 9 + For threads, I am using a builtin library called `threads.h`. This library is 10 + documented on [cppreference.com](https://cppreference.com) as: 11 + - https://en.cppreference.com/w/c/header/threads.html 12 + 13 + From this library I used the functionality provided to create the threads and 14 + the mutex that they define. 15 + 8 16 # Running 9 17 10 - You can simply execute: 18 + ## Cluster 11 19 12 20 ```sh 13 - make run 21 + make cluster.py 14 22 ``` 15 23 16 - This will run the cluster on address `127.0.0.1` on port `42069` and connect the 17 - embedded device to it. 18 - 19 - If you prefer to run each separately then you can run the program like in the 20 - following two sections. 21 - 22 - ## Cluster 24 + This will simply run the cluster on the server's loopback `127.0.0.1` and on 25 + port `42069`. If youu want to supply your own server and port, use: 23 26 24 27 ```sh 25 28 make cluster.py ADDRESS=<server address> PORT=<server port> 26 29 ``` 27 30 28 31 where `<server address>` is the IP address of the cluster, and `<server port>` 29 - is the port number of the cluster. 32 + is the port number of the cluster. Remember that you must put the words 33 + "`ADDRESS`" and "`PORT`" before the `<server address>` and `<server port>`. If 34 + you don't `make` will not detect that you passed those arguments to the 35 + executable. 30 36 31 37 ## Embedded device 32 38 33 - Example of how to run the embedded device: 39 + This is the same as the cluster. The default server and port are the loopback 40 + and `42069` respectively, and supplying the parameters for `ADDRESS` and `PORT` 41 + will let make know on which server and port you want to run it. 34 42 35 43 ```sh 36 44 make edevice.py ADDRESS=<server address> PORT=<server port> ··· 39 47 where `<server address>` is the IP address of the cluster, and `<server port>` 40 48 is the port number of the cluster. 41 49 42 - Example of how to run the cluster: 50 + # Building 51 + 52 + If you just want to build the files, run: 53 + 54 + ```sh 55 + make .build/edevice 56 + ``` 57 + 58 + To build the embedded device and run: 59 + 60 + ```sh 61 + make .build/cluster 62 + ``` 43 63 64 + To build the cluster. From these two executables, you can then run the programs 65 + like, 66 + ```sh 67 + ./.build/cluster <server address> <server port> 68 + ./.build/edevice <server address> <server port> 69 + ``` 70 + 71 + # Contributions 72 + 73 + I would like to thank Gabriel Romero and Anasofia Colon while developing this 74 + project. Without them, this project would have been impossible.
+3
src/cluster.c
··· 19 19 bool client_closed = false; 20 20 21 21 22 + // The consumer. 22 23 int consume(void*args) { 23 24 // Turns the strange looking thing thrd_current() into a smaller number. 24 25 size_t tid = ((thrd_current() & 0xFFFF) >> 12) % 12; 25 26 26 27 log(INFO, "Consumer %zu started.\n", tid); 27 28 29 + // Get client from argument. 28 30 exists(args); 29 31 Enchufe cliente = *(Enchufe*)args; 30 32 ··· 61 63 return thrd_success; 62 64 } 63 65 66 + // The producer. 64 67 int produce(void* args) { 65 68 exists(args); 66 69 Enchufe cliente = *(Enchufe*)args;
+20 -4
src/edevice.c
··· 11 11 int main(int argc, char** argv) { 12 12 assert(argc == 3 && "You must provide three arguments."); 13 13 14 + // Create the socket 14 15 IPv4 ip = parse_address(argv[1]); 15 16 Port port = (Port)atoi(argv[2]); 16 17 log(INFO, "Connecting to: %d.%d.%d.%d on port: %d", ip.bytes[0], ip.bytes[1], ip.bytes[2], ip.bytes[3], port); ··· 18 19 Enchufe enchufe = enchufa(ip, port); 19 20 conecta(enchufe); 20 21 22 + /* run the command 23 + * here I used `ps auxww -Aeo args` in order to use the entire string used 24 + * by `ps`. 25 + */ 21 26 FILE* fp = popen("ps auxww -Aeo args", "r"); 22 27 exists(fp); 23 28 29 + // Initialize random seed generator. 24 30 srand((uint32_t)time(NULL)); 31 + 25 32 char program[BUF_LEN]; 26 - size_t counter = 0; 27 - while (fgets(program, BUF_LEN, fp)) { 33 + for (size_t counter = 0; fgets(program, BUF_LEN, fp); ++counter) { 34 + /* the first two lines of that `ps` command are the headers for the 35 + * output, not actual programs. 36 + */ 28 37 if (counter <3 ) { 29 38 ++counter; 30 39 continue; ··· 34 43 size_t len = safe_strlen(program, BUF_LEN) - 1; 35 44 program[len] = '\0'; 36 45 46 + // Create the process that will be sent 37 47 Proc proc = { 38 48 .time = (Time)rand() % 5, 39 49 .program = { ··· 42 52 }, 43 53 }; 44 54 55 + // Send the process. 45 56 log(INFO, "Sent program: %s with time %d.\n", proc.program.buf, proc.time); 46 - 47 57 Buffer in_buf = serialize(proc); 48 58 zumba(enchufe, in_buf); 49 59 60 + /* Clear the buffer for the program and free the memory associated to 61 + * what was just sent. 62 + */ 50 63 memset(program, 0, BUF_LEN); 51 64 free(in_buf.buf); 52 - ++counter; 53 65 66 + // Create new buffer to receive output from cluster. 54 67 Byte buf[BUF_LEN] = {0}; 55 68 Buffer out_buf = { 56 69 .buf = buf, 57 70 .len = BUF_LEN, 58 71 }; 72 + // Receive message from cluster. 59 73 size_t msg_len = recibe(enchufe, out_buf); 60 74 assert(safe_strlen((char*)out_buf.buf, BUF_LEN) == msg_len); 61 75 log(INFO, "Received: %s.\n", (char*)out_buf.buf); 62 76 } 63 77 78 + // Let the user know that the program is done. 64 79 log(INFO, "Done.\n"); 65 80 81 + // Close socket. 66 82 desenchufa(enchufe); 67 83 68 84 return 0;