{"id":20345784,"url":"https://github.com/izzypt/philosophers","last_synced_at":"2025-07-08T10:42:01.843Z","repository":{"id":167691347,"uuid":"643313164","full_name":"izzypt/Philosophers","owner":"izzypt","description":"In this project we work with the basics of threading a process. We will create threads, work with them and discover mutexes.","archived":false,"fork":false,"pushed_at":"2023-06-09T11:34:20.000Z","size":200,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-04T15:48:01.925Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/izzypt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-20T19:04:02.000Z","updated_at":"2023-06-05T18:48:54.000Z","dependencies_parsed_at":"2025-01-14T21:34:33.070Z","dependency_job_id":"2ee0ed3b-f1de-4338-952e-663b053a8f95","html_url":"https://github.com/izzypt/Philosophers","commit_stats":null,"previous_names":["izzypt/philosophers"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/izzypt/Philosophers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/izzypt%2FPhilosophers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/izzypt%2FPhilosophers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/izzypt%2FPhilosophers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/izzypt%2FPhilosophers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/izzypt","download_url":"https://codeload.github.com/izzypt/Philosophers/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/izzypt%2FPhilosophers/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264252909,"owners_count":23579958,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T22:09:47.257Z","updated_at":"2025-07-08T10:42:01.795Z","avatar_url":"https://github.com/izzypt.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Philosophers\n\n# The problem\n\n- One or more philosophers sit at a round table.\n- There is a large bowl of spaghetti in the middle of the table.\n- The philosophers alternatively eat, think, or sleep.\n- There are also forks on the table. There are as many forks as philosophers.\n- Because serving and eating spaghetti with only one fork is very inconvenient, a\nphilosopher takes their right and their left forks to eat, one in each hand.\n- When a philosopher has finished eating, they put their forks back on the table and\nstart sleeping. Once awake, they start thinking again. The simulation stops when\na philosopher dies of starvation.\n- Every philosopher needs to eat and should never starve.\n- Philosophers don’t speak with each other.\n- Philosophers don’t know if another philosopher is about to die.\n- No need to say that philosophers should avoid dying!\n\n![image](https://github.com/izzypt/Philosophers/assets/73948790/a8bf1018-e804-41a8-8407-7f9fb58d904e)\n\n![image](https://github.com/izzypt/Philosophers/assets/73948790/12729974-4dab-4fb8-9064-e0335f2ea448)\n\n# Project rules\n\n![image](https://github.com/izzypt/Philosophers/assets/73948790/c0f85277-6e26-437c-8af4-3b5794540df1)\n\n\n- Each philosopher should be a thread.\n- There is one fork between each pair of philosophers. \n- If there are several philosophers, each philosopher has a fork on their left side and a fork on their right\nside. \n- If there is only one philosopher, there should be only one fork on the table.\n- To prevent philosophers from duplicating forks, you should protect the forks state\nwith a mutex for each of them.\n- Your(s) program(s) should take the following arguments:\n  - number_of_philosophers \n  - time_to_die \n  - time_to_eat \n  - time_to_sleep\n  - number_of_times_each_philosopher_must_eat\n- Philosopher number 1 sits next to philosopher ```number_of_philosophers```.\n- Any other philosopher number ```N``` sits between philosopher number ```N - 1``` and philosopher number ```N + 1```.\n\n# Core concepts\n\n- \u003cins\u003e***What is a Thread?***\u003c/ins\u003e\n\nTo talk about thread, we must also be familiar with processes (In case, you're not, check out [this link](https://www.codequoi.com/en/creating-and-killing-child-processes-in-c/) by another 42 student)\n  - A thread is a basic unit of execution of any process. \n  - A program comprises many processes and all the processes comprise much simpler units known as threads. \n  - So, the thread can be referred to as the basic unit of a process or it is the simpler unit that tother makes the CPU utilization\n  - Threads allow for parallel execution of multiple tasks within a single process.\n\n![image](https://github.com/izzypt/Philosophers/assets/73948790/d63d984b-e2f8-48c1-9e42-56d376f31ba9)\n\n\n- \u003cins\u003e***Thread elements***\u003c/ins\u003e\n  - A thread ID: \n    - It is a unique ID of the thread that is created during the creation of the thread and it remains for the whole life of that particular thread.\n  - Program Counter: \n    - Also known as the instruction pointer, is a special register that keeps track of the address of the next instruction to be executed by a thread. \n    - It points to the current position in the program's execution flow.\n  - A registered set: \n    -  Refers to the collection of registers that store the thread's current execution context. \n    -  These registers typically include the program counter, general-purpose registers, and other architecture-specific registers. \n    -  The register set allows the thread to save and restore its execution state during context switches.\n  - A stack: \n    - It is the memory of that particular thread.\n    - A region of memory used by a thread to store local variables, function calls, and other related data.\n    - Each thread typically has its own stack\n    - The stack grows and shrinks dynamically as the thread executes\n\n\n![image](https://github.com/izzypt/Philosophers/assets/73948790/324ea47d-77a1-4d44-9ebf-8c895241c43f)\n\n- \u003cins\u003e***What are the differences between processes and thread?***\u003c/ins\u003e \n  - Threads are not independent from each other unlike processes. \n  - As a result, threads shares with other threads their code section, data section and OS resources like open files and signals. \n  - But, like processes, a thread has its own program counter (PC), a register set, and a stack space.\n\n \u003cins\u003e***Why Multithreading?***\u003c/ins\u003e \n \n- Threads are popular way to improve application through parallelism. \n- For example, in a browser, multiple tabs can be different threads. MS word uses multiple threads, one thread to format the text, other thread to process inputs, etc. \n- Threads operate faster than processes due to following reasons: \n  - Thread creation is much faster. \n  - Context switching between threads is much faster. \n  - Threads can be terminated easily \n  - Communication between threads is faster.\n\n- \u003cins\u003e***Mutex***\u003c/ins\u003e\n  - In computer programming, a mutual exclusion (mutex) is a program object that \u003cins\u003e***prevents multiple threads from accessing the same shared resource simultaneously***\u003c/ins\u003e . \n- \u003cins\u003e***Shared Resource***\u003c/ins\u003e\n  - A shared resource in this context is a code element with a critical section, the part of the code that should not be executed by more than one thread at a time. \n  - For example, a critical section might update \u003cins\u003e***a global variable***\u003c/ins\u003e, modify \u003cins\u003e***a table in a database***\u003c/ins\u003e or write a file to a network server. \n  - In such cases, access to the shared resource must be controlled to prevent problems to the data or the program itself.\n- \u003cins\u003e***Mutex object***\u003c/ins\u003e\n  - A mutex is a mechanism used to ensure that multiple concurrent threads do not try to execute a critical section of code simultaneously.\n- \u003cins\u003e***Race condition***\u003c/ins\u003e\n  - A race condition refers to a situation where the behavior or outcome of a program becomes unpredictable or incorrect due to the simultaneous and uncoordinated access to shared resources by multiple threads or processes.\n  - Race conditions typically occur when two or more threads access and manipulate a shared resource concurrently, without proper synchronization mechanisms in place. \n  - This can lead to unexpected results because the order and timing of the operations become unpredictable. \n  - If a mutex is not applied, the program might be subject to a race condition, a situation in which multiple threads try to access a shared resource at the same time. When this happens, unintended results can occur, such as data being read or written incorrectly or the program misbehaving or crashing.\n  - Example :\n    - For example, let's consider a scenario where two threads are incrementing a shared variable simultaneously. If the threads perform the following steps:\n\n     - Read the current value of the shared variable.\n    - Increment the value.\n    - Write the updated value back to the shared variable.\n    - A race condition can occur if both threads read the value simultaneously, then increment it separately, and finally write back their results. \n    - In this case, the final value of the shared variable may not be the sum of the increments from both threads, as expected. The outcome will depend on the interleaving of instructions from different threads, leading to data corruption or incorrect results.\n\n- To mitigate race conditions, synchronization mechanisms like locks, semaphores, or mutexes can be used to enforce mutual exclusion and coordinate access to shared resources. \n- These mechanisms ensure that only one thread/process can access the shared resource at a time, preventing conflicts and maintaining the desired consistency in the program's execution.\n\n# Getting started with threads\n\n1 - To use threads in C , you need to include the \u003cpthread.h\u003e header file in your program.\n  - When compiling , dont forget to include the flag ```-pthread```.\n```\n #include \u003cpthread.h\u003e\n```\n\n2 - The first thing it happens when you create a thread is : it executes a function.\n  - Define the function that will be executed by the thread. This function should have a ```void*``` return type and take a ```void*``` argument. For example\n```\nvoid* thread_function(void* arg) {\n    // Code to be executed by the thread\n    // You can typecast arg to the appropriate data type if needed\n    return NULL;  // Return value of the thread\n}\n```\n3 - We will need to create a variable which will hold some information about the thread. \n  - It will be a  ```pthread_t``` type variable (a type we imported from the ```\u003cpthread.h\u003e```).\n  - Start the thread using the ```pthread_create``` function:\n```\nint main() {\n    pthread_t thread;\n    int status;\n\n    status = pthread_create(\u0026thread, NULL, thread_function, NULL);\n    if (status != 0) {\n        // Handle error\n    }\n\n    // Continue with the main program\n\n    pthread_exit(NULL);  // Wait for the thread to finish before exiting\n}\n```\n\n4 - It is also important to wait for the thread to finish executing (Imagine your program finishes before the thread)\n  - We can use ```pthread_join()``` to do that.\n \n# Getting start with Mutex\n\nThis is a chatGPT example :\n\nHere's a short example that demonstrates the usage of mutex with the `pthread.h` library in C:\n\n```c\n#include \u003cstdio.h\u003e\n#include \u003cpthread.h\u003e\n\n// Global variables\nint counter = 0;\npthread_mutex_t mutex;\n\n// Thread function\nvoid *threadFunction(void *arg) {\n    // Lock the mutex before accessing the shared variable\n    pthread_mutex_lock(\u0026mutex);\n\n    // Critical section: increment the counter\n    counter++;\n\n    // Print the updated counter value\n    printf(\"Thread ID: %lu, Counter: %d\\n\", pthread_self(), counter);\n\n    // Unlock the mutex after finishing the critical section\n    pthread_mutex_unlock(\u0026mutex);\n\n    // Terminate the thread\n    pthread_exit(NULL);\n}\n\nint main() {\n    pthread_t threads[5];\n\n    // Initialize the mutex\n    pthread_mutex_init(\u0026mutex, NULL);\n\n    // Create five threads\n    for (int i = 0; i \u003c 5; i++) {\n        pthread_create(\u0026threads[i], NULL, threadFunction, NULL);\n    }\n\n    // Wait for all threads to finish\n    for (int i = 0; i \u003c 5; i++) {\n        pthread_join(threads[i], NULL);\n    }\n\n    // Destroy the mutex\n    pthread_mutex_destroy(\u0026mutex);\n\n    return 0;\n}\n```\n\n- In this example, we have a global variable `counter` that is accessed by multiple threads. \n- The `pthread_mutex_t` variable `mutex` is used to protect the critical section where the `counter` is incremented.\n- Each thread locks the mutex before accessing the critical section and unlocks it after finishing the critical section.\n\n- The `threadFunction` is the entry point for each thread. \n- It increments the `counter` and prints the updated value. \n- The `main` function creates five threads, waits for them to finish using `pthread_join`, and then destroys the mutex.\n\nNote that the `pthread_mutex_init` function initializes the mutex, `pthread_mutex_lock` locks the mutex, `pthread_mutex_unlock` unlocks the mutex, and `pthread_mutex_destroy` destroys the mutex.\n\nBy using the mutex, we ensure that only one thread can access the critical section at a time, preventing race conditions and ensuring the integrity of the shared variable.\n\n# A summary on the allowed functions for the project\n\n## `pthread_create()`: \n  - This function is used to create a new thread of execution within a program. \n  - On success, it returns 0, and on failure, it returns an error code. \n  - The `pthread_create()` function creates a new thread and starts its execution by calling a specified function. This function runs concurrently with the calling thread, allowing multiple tasks to be performed simultaneously.\n\n    The `pthread_create()` function takes four arguments:\n\n    1. `thread`: A pointer to a `pthread_t` variable that will hold the identifier (tid) of the newly created thread. This identifier can be used later to refer to the thread in other pthread functions.\n\n    2. `attr`: An optional pointer to a `pthread_attr_t` structure that specifies attributes for the new thread, such as its stack size or scheduling policy. If `NULL` is passed, default attributes are used.\n\n    3. `start_routine`: A pointer to the function that will be executed by the new thread. This function should have a specific signature: `void *function_name(void *arg)`. It takes a single argument of type `void *`, which can be used to pass data to the thread function, and returns a `void *` pointer.\n\n    4. `arg`: An optional argument that can be passed to the thread function `start_routine`. It is of type `void *` and can be used to provide additional data or context to the thread function.\n\n    Here's an example usage of `pthread_create()`:\n\n    ```c\n    #include \u003cpthread.h\u003e\n    #include \u003cstdio.h\u003e\n\n    void *thread_func(void *arg) {\n        // Thread operations\n        printf(\"Hello from the new thread!\\n\");\n        return NULL;\n    }\n\n    int main() {\n        pthread_t tid;\n        pthread_create(\u0026tid, NULL, thread_func, NULL);\n\n        // Continue with main thread operations\n        printf(\"Hello from the main thread!\\n\");\n\n        pthread_join(tid, NULL);  // Wait for the new thread to finish\n\n        return 0;\n    }\n    ```\n\n    In this example, `pthread_create()` is used to create a new thread that will execute the `thread_func()` function. The `tid` variable holds the identifier of the newly created thread. The `thread_func()` function simply prints a message. After creating the thread, the main thread continues its operations, printing its own message. Finally, `pthread_join()` is used to wait for the newly created thread to finish executing before the program terminates.\n\n    Note that `pthread_create()` returns 0 on success, and a non-zero error code if an error occurs during thread creation. It's a good practice to check the return value for errors when working with threads.\n \n## `pthread_join()`: \n  - It is used to wait for a thread to terminate and retrieve its exit status. \n  - When a thread is joined, the calling thread blocks until the specified thread finishes execution. \n  - It allows for synchronization between threads and enables the retrieval of any return value or exit status from the joined thread.\n  - When a pthread_join() returns successfully, the target thread has been terminated. \n  - The results of multiple simultaneous calls to pthread_join() specifying the same target thread are undefined.\n  - Return values : On success, it returns 0, and on failure, it returns an error code.\n\n## `pthread_detach()`: \n  - This function is used to detach a thread, allowing it to run independently and release its resources when it terminates.\n  - Once a thread is detached, its resources are automatically reclaimed by the system upon termination, and it cannot be joined using pthread_join().\n\n  - When a thread is detached, it means that its resources (memory, file descriptors, etc.) are automatically released and cleaned up by the system once the thread exits. The calling thread does not need to wait or join the detached thread to obtain its exit status.\n\n  - The `pthread_detach()` function takes a single argument, `tid`, which is the identifier of the thread to be detached. The `tid` is usually obtained when creating a thread using the `pthread_create()` function.\n\n  - Here's an example usage of `pthread_detach()`:\n\n      ```c\n      #include \u003cpthread.h\u003e\n      #include \u003cstdio.h\u003e\n\n      void *thread_func(void *arg) {\n          // Thread operations\n          return NULL;\n      }\n\n      int main() {\n          pthread_t tid;\n          pthread_create(\u0026tid, NULL, thread_func, NULL);\n\n          // Detach the thread\n          pthread_detach(tid);\n\n          // Continue with main thread operations\n          // ...\n\n          pthread_exit(NULL);\n      }\n      ```\n\n    In this example, a new thread is created using `pthread_create()` and the `tid` is obtained. \n    Then, `pthread_detach()` is called to detach the thread. After detaching, the main thread can continue with its operations without explicitly waiting for the detached thread to finish.\n\n    It's important to note that if a detached thread is not explicitly joined or detached using `pthread_detach()`, it remains in a \"zombie\" state even after it has finished executing, consuming system resources until the process terminates. \n    Therefore, it's good practice to detach or join threads that are no longer needed to ensure proper cleanup.\n\n## `pthread_mutex_init()`: \n  - The `pthread_mutex_init()` function initializes a mutex object with default attributes. A mutex ensures that only one thread can access a shared resource at a time, preventing data races and ensuring thread-safe access.\n\n    The `pthread_mutex_init()` function takes two arguments:\n\n    1. `mutex`: A pointer to a `pthread_mutex_t` variable that represents the mutex object. The function initializes this variable to represent a valid mutex.\n\n    2. `attr`: An optional pointer to a `pthread_mutexattr_t` structure that specifies attributes for the mutex. If `NULL` is passed, default attributes are used.\n\n    Here's an example usage of `pthread_mutex_init()`:\n\n    ```c\n    #include \u003cpthread.h\u003e\n    #include \u003cstdio.h\u003e\n\n    pthread_mutex_t mutex;  // Declare a mutex object\n\n    int shared_variable = 0;\n\n    void *thread_func(void *arg) {\n        pthread_mutex_lock(\u0026mutex);  // Acquire the lock\n\n        // Thread-safe access to shared resource\n        shared_variable++;\n        printf(\"Thread: %d\\n\", shared_variable);\n\n        pthread_mutex_unlock(\u0026mutex);  // Release the lock\n\n        return NULL;\n    }\n\n    int main() {\n        pthread_mutex_init(\u0026mutex, NULL);  // Initialize the mutex\n\n        pthread_t tid1, tid2;\n        pthread_create(\u0026tid1, NULL, thread_func, NULL);\n        pthread_create(\u0026tid2, NULL, thread_func, NULL);\n\n        // Wait for both threads to finish\n        pthread_join(tid1, NULL);\n        pthread_join(tid2, NULL);\n\n        pthread_mutex_destroy(\u0026mutex);  // Destroy the mutex\n\n        return 0;\n    }\n    ```\n\n    In this example, the `pthread_mutex_init()` function is used to initialize the `mutex` object. The `thread_func()` function is executed by multiple threads. Before accessing the shared variable `shared_variable`, each thread acquires the lock using `pthread_mutex_lock()`, ensuring exclusive access. After modifying the variable, the thread releases the lock using `pthread_mutex_unlock()`. The main thread waits for both threads to finish using `pthread_join()`. Finally, the `pthread_mutex_destroy()` function is called to destroy the mutex object and release its associated resources.\n\n    It's important to note that mutexes should be initialized before they are used, and they should be destroyed when they are no longer needed to avoid resource leaks.\n\n## `pthread_mutex_destroy()`: \n\n  - Here's the function signature of `pthread_mutex_destroy`:\n\n    ```c\n    #include \u003cpthread.h\u003e\n\n    int pthread_mutex_destroy(pthread_mutex_t *mutex);\n    ```\n\n  - The `pthread_mutex_destroy` function takes a pointer to a mutex object (`pthread_mutex_t`) as its parameter and returns an integer value indicating success or failure. It destroys the mutex object, releasing any system resources associated with it.\n\n  - Before calling `pthread_mutex_destroy`, it is essential to ensure that the mutex is no longer in use by any thread. Attempting to destroy a mutex while it is locked by a thread can lead to undefined behavior.\n\n  - Here's an example usage of `pthread_mutex_destroy`:\n\n        ```c\n        #include \u003cpthread.h\u003e\n        #include \u003cstdio.h\u003e\n\n        pthread_mutex_t mutex;\n\n        void* thread_func(void* arg) {\n            pthread_mutex_lock(\u0026mutex);\n            // Critical section\n            pthread_mutex_unlock(\u0026mutex);\n            return NULL;\n        }\n\n        int main() {\n            pthread_t thread;\n            pthread_mutex_init(\u0026mutex, NULL);\n\n            // Create and join a thread to simulate mutex usage\n            pthread_create(\u0026thread, NULL, thread_func, NULL);\n            pthread_join(thread, NULL);\n\n            // Destroy the mutex\n            pthread_mutex_destroy(\u0026mutex);\n\n            return 0;\n        }\n    ```\n   - In the example above, the `pthread_mutex_init` function initializes the mutex object, and `pthread_mutex_destroy` is called after the thread completes execution and the mutex is no longer needed.\n\n   - Remember to always check the return value of `pthread_mutex_destroy`. It returns 0 on success and an error code otherwise. If an error occurs, you can use `pthread_mutex_destroy` in a cleanup routine to ensure proper resource deallocation.\n\n\n- `pthread_mutex_lock()`: \n  - It acquires a lock on a mutex, making the calling thread the owner of the mutex. \n  - If the mutex is already locked by another thread, the calling thread will block until it can acquire the lock. This function is used to enforce mutual exclusion and ensure that only one thread can access a critical section of code at a time.\n  - `pthread_mutex_lock()` is a function in the POSIX thread library (pthread) that is used to acquire a mutex (short for mutual exclusion). A mutex is a synchronization primitive that ensures only one thread can access a shared resource or a critical section of code at a time, preventing simultaneous access and potential data corruption.\n\n    Here is a step-by-step explanation of how `pthread_mutex_lock()` works:\n\n    1. Mutex Initialization: Before using a mutex, it needs to be initialized using the `pthread_mutex_init()` function. This function sets the initial state of the mutex to an unlocked state.\n\n    2. Locking the Mutex: When a thread wants to access a shared resource or a critical section of code, it calls `pthread_mutex_lock()` to acquire the mutex. If the mutex is currently unlocked, the calling thread successfully acquires it and continues execution. The mutex becomes locked, and any subsequent threads trying to acquire it will be blocked until the mutex is unlocked.\n\n    3. Blocking Behavior: If the mutex is already locked by another thread when `pthread_mutex_lock()` is called, the calling thread will be blocked and put into a waiting state. It will remain blocked until the mutex is unlocked by the thread currently holding it.\n\n    4. Unlocking the Mutex: When a thread completes its work on the shared resource or critical section of code, it must release the mutex to allow other threads to access it. This is done using the `pthread_mutex_unlock()` function. Once the mutex is unlocked, one of the waiting threads will be unblocked and acquire the mutex, while the rest will continue waiting.\n\n    It's important to note that the order in which blocked threads acquire the mutex after it's unlocked is not guaranteed. The system determines which waiting thread gets the mutex based on its own scheduling algorithm.\n\n    Using `pthread_mutex_lock()` and `pthread_mutex_unlock()` correctly ensures that only one thread accesses a shared resource at a time, preventing race conditions and maintaining data integrity.\n\n- `pthread_mutex_unlock()`: \n  - This function releases the lock on a mutex, allowing other threads to acquire the mutex and access the protected resource.\n  - It should be called after a critical section of code has been executed to release the lock and enable other threads to proceed.\n\n- `usleep()`\n  - The usleep() function in C is used to suspend the execution of the program for a specified number of microseconds \n\n- `gettimeofday()` : \n  - Is a commonly used function in the C programming language that retrieves the current time and stores it in a timeval structure. \n  - This function is often used for measuring elapsed time, calculating time differences, or benchmarking code.\n\n  - Here's the function signature for `gettimeofday()`:\n\n```c\nint gettimeofday(struct timeval *tv, struct timezone *tz);\n```\n\n  - The function takes two arguments:\n\n  - 1. `struct timeval *tv`: A pointer to a timeval structure where the current time will be stored.\n  - 2. `struct timezone *tz`: A pointer to a timezone structure (deprecated and usually set to NULL).\n\nHere's an example of how to use `gettimeofday()`:\n\n```c\n#include \u003cstdio.h\u003e\n#include \u003csys/time.h\u003e\n\nint main() {\n    struct timeval tv;\n    \n    // Get the current time\n    int result = gettimeofday(\u0026tv, NULL);\n    if (result != 0) {\n        perror(\"gettimeofday\");\n        return 1;\n    }\n    \n    // Access the time values\n    printf(\"Seconds: %ld\\n\", tv.tv_sec);\n    printf(\"Microseconds: %ld\\n\", tv.tv_usec);\n    \n    return 0;\n}\n```\n\n- We declare a `struct timeval` variable `tv` to hold the time values. \n- We then call `gettimeofday()` with a pointer to `tv` and NULL as the second argument.\n\n- If `gettimeofday()` returns 0, it means the function call was successful. \n- We can then access the time values using the `tv_sec` and `tv_usec` members of the `tv` structure. `tv_sec` represents the number of seconds, and `tv_usec` represents the number of microseconds since the Epoch (January 1, 1970).\n\n- In the example, we print the values of `tv_sec` and `tv_usec` using `printf()`.\n\n- Remember to compile your C program with the `-lrt` flag to link against the real-time library, as `gettimeofday()` is part of that library.\n\nAnother resource:\n\nhttps://www.youtube.com/watch?v=d9s_d28yJq0\u0026list=PLfqABt5AS4FmuQf70psXrsMLEDQXNkLq2\n\nhttps://www.scaler.com/topics/multithreading-in-c/\n\nhttps://www.youtube.com/watch?v=LOfGJcVnvAk\u0026ab_channel=NesoAcademy\n\nhttps://medium.com/swlh/the-dining-philosophers-problem-bbdb92e6b788\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fizzypt%2Fphilosophers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fizzypt%2Fphilosophers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fizzypt%2Fphilosophers/lists"}