diff --git a/README.md b/README.md index c70e486..42795f6 100644 --- a/README.md +++ b/README.md @@ -1 +1,91 @@ -[![Open in Visual Studio Code](https://classroom.github.com/assets/open-in-vscode-718a45dd9cf7e7f842a935f5ebbe5719a5e09af4491e668f4dbf3b35d5cca122.svg)](https://classroom.github.com/online_ide?assignment_repo_id=11143217&assignment_repo_type=AssignmentRepo) + + PROJECT REPORT + + + System call using spinlock + + +By: +K213330 Muneeb Ahmed +K213371 Agha Fardeen + + + + + + + +OBJECTIVES: +The objective of using a system call with a spinlock is to provide mutual exclusion or synchronization in a multi-threaded or multi-process environment. A spinlock is a synchronization primitive that allows only one thread or process to access a shared resource at a time. When a thread or process wants to access the shared resource, it acquires the spinlock and proceeds with its operations. If the spinlock is already held by another thread or process, the thread or process "spins" in a loop, repeatedly checking the state of the spinlock until it becomes available. +When a system call involves a spinlock, the objective is to protect critical sections of code or shared data structures from concurrent ac-cess, ensuring data integrity and preventing race conditions. The spinlock is typically used to guard access to resources that must be accessed atomically, meaning they should not be accessed by multi-ple threads or processes simultaneously. + + + +INTRODUCTION: + + +Spinlock: + +Spinlocks are simple synchronization primitives that allow only one thread or process to access a shared resource at a time. They are typically implemented as a special type of lock that a thread or process must acquire before accessing the critical section of code or shared data structure. If the spinlock is already held by another thread or process, the requesting thread or process "spins" in a loop, continuously checking the state of the spinlock until it becomes available. + +System call: + +System calls are a fundamental mechanism in operating systems that allow user-level programs to request services or resources from the kernel. They provide an interface for applications to interact with the underlying operating system and perform privileged operations. In a multi-threaded or multi-process environment, where concurrent access to shared resources is possible, spinlocks are often used to provide mutual exclusion and synchronization. + +When it comes to system calls, using spinlocks is a common tech-nique to protect critical sections of code or shared data structures within the kernel. The objective is to ensure data integrity, prevent race conditions, and provide exclusive access to shared resources. +By incorporating spinlocks into system calls, the following benefits can be achieved: +1. Mutual Exclusion: Spinlocks provide mutual exclusion by al-lowing only one thread or process to execute the critical section at a time. This ensures that concurrent accesses to shared re-sources do not result in inconsistent or corrupted data. + +2. Simple Implementation: Spinlocks have a relatively simple im-plementation compared to other synchronization mechanisms, such as semaphores or mutexes. They are often used in situa-tions where the critical sections are short, and the expected waiting time for acquiring the lock is brief. + + +3. Low Overhead: Spinlocks have lower overhead compared to other synchronization primitives since they avoid context switching and the associated costs of blocking and unblocking threads or processes. However, spinlocks are efficient only when the waiting time is expected to be short, as continuously spinning consumes CPU cycles. + +4. Real-Time Constraints: Spinlocks are particularly useful in real-time systems or situations where strict timing constraints need to be met. They have deterministic behavior, and a thread or process can spin until the lock is available, eliminating the un-predictability associated with blocking mechanisms. + +Platform: + +Linux: The Linux operating system provides a rich set of system calls and synchronization primitives, including spinlocks. In Linux, system calls can be implemented using the C programming language. The Linux kernel provides spinlock implementations, such as the spinlock_t structure, which can be used in system call imple-mentations. + +Languages: +We have used C language because of its low-level capabilities and direct interaction with the operating system, other languages can also be utilized. + +Methodology: + +1. Identify the Critical Section: Determine the critical section of code or the shared data structure that needs to be protected from concurrent access. This critical section typically contains opera-tions that should be executed atomically. + +2. Declare and Initialize the Spinlock: Define a spinlock variable to guard the critical section. The spinlock can be a simple integer or a more complex structure provided by the operating system or synchronization library. Initialize the spinlock to an unlocked state. + + +3. Acquire the Spinlock: Before entering the critical section, the system call code should attempt to acquire the spinlock. This is typically done using an atomic compare-and-swap operation or an atomic test-and-set operation provided by the platform or lan-guage. If the spinlock is already acquired by another thread or process, the code enters a spin loop. + +4. Spin Loop: In the spin loop, the code repeatedly checks the state of the spinlock until it becomes available. This is usually done by continuously polling the spinlock, checking if it is still locked. The exact implementation of the spin loop may vary depending on the platform and language used. + + +5. Execute the Critical Section: Once the spinlock is acquired, the system call code can safely execute the critical section of code or operate on the shared data structure. This section should be kept as short and efficient as possible to minimize the waiting time for other threads or processes. + +6. Release the Spinlock: After completing the operations in the criti-cal section, the system call code should release the spinlock, al-lowing other threads or processes to acquire it. This is typically done by setting the spinlock to an unlocked state. + + +7. Return from the System Call: The system call code should return the appropriate result or value to the caller, indicating the success or failure of the requested operation. + +Results: + +The results of a system call using a spinlock depend on the specific functionality and purpose of the system call itself. The use of a spinlock in a system call is primarily aimed at providing mutual ex-clusion and synchronization, ensuring that critical sections of code or shared resources are accessed by only one thread or process at a time. Here are some potential results and outcomes of a system call using a spinlock: +1. Exclusive Access: The use of a spinlock ensures that only one thread or process can acquire the lock and access the critical sec-tion at any given time. This guarantees exclusive access to shared resources, preventing race conditions and maintaining da-ta integrity. + +2. Synchronization: By employing a spinlock, the system call can synchronize concurrent accesses to shared resources. Threads or processes that attempt to access the critical section while the spinlock is already held will spin in a loop until the lock be-comes available. This synchronization mechanism helps in pre-venting data corruption and ensuring correct execution of the critical section. + + +3. Reduced Race Conditions: The presence of a spinlock in a sys-tem call reduces the likelihood of race conditions. Race condi-tions occur when multiple threads or processes access shared re-sources simultaneously and produce unpredictable or erroneous results. With a spinlock in place, concurrent accesses are serial-ized, eliminating race conditions and providing predictable be-havior. + +Conclusion: +In conclusion, incorporating a spinlock in a system call provides a mechanism for mutual exclusion and synchronization in a multi-threaded or multi-process environment. By using a spinlock, the sys-tem call ensures that critical sections of code or shared resources are accessed by only one thread or process at a time, thereby preventing race conditions, maintaining data integrity, and providing exclusive access to shared resources. +The use of a spinlock in a system call offers several benefits, includ-ing simplicity of implementation, low overhead compared to other synchronization primitives, and deterministic behavior suitable for real-time systems. However, it's important to carefully consider the expected waiting times and system characteristics to avoid excessive spinning and CPU consumption. +The specific results of a system call using a spinlock include exclu-sive access to shared resources, synchronization of concurrent ac-cesses, reduced race conditions, waiting and spinning for lock acqui-sition, and the risk of deadlocks if proper locking and unlocking pro-tocols are not followed. +Overall, incorporating a spinlock in a system call provides a reliable and efficient approach to ensure correct and synchronized execution of critical sections of code, promoting data integrity and preventing race conditions in a concurrent programming environment. + + + + + diff --git a/spinlock.c b/spinlock.c new file mode 100644 index 0000000..0d3ca3d --- /dev/null +++ b/spinlock.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include + +#define SPINLOCK_INIT 0 +#define SPINLOCK_LOCKED 1 +void *thread_func(void *arg); +static unsigned int spinlock = SPINLOCK_INIT; + +int main() +{ + pthread_t thread_id[10]; + int i; + + for (i = 0; i < 2; i++) { + pthread_create(&thread_id[i], NULL, thread_func, NULL); + } + + for (i = 0; i < 2; i++) { + pthread_join(thread_id[i], NULL); + } + + return 0; +} + +void *thread_func(void *arg) +{ + while (syscall(335, &spinlock)) { + + } + + printf("Thread %ld acquired the spinlock\n", syscall(SYS_gettid)); + + syscall(336, &spinlock); + + printf("Thread %ld released the spinlock\n", syscall(SYS_gettid)); + + pthread_exit(NULL); +} diff --git a/systemcall.c b/systemcall.c new file mode 100644 index 0000000..cad840a --- /dev/null +++ b/systemcall.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include +#include + +static int initialized = 0; + +asmlinkage long sys_spinlock(unsigned int *lock) +{ + if (!initialized) { + struct mutex *mutex = (struct mutex *) lock; + mutex_init(mutex); + initialized = 1; + } + + struct mutex *mutex = (struct mutex *) lock; + mutex_lock(mutex); + + + mutex_unlock(mutex); + + return 0; +}