Great Deal! Get Instant $10 FREE in Account on First Order + 10% Cashback on Every Order Order Now

CS 1550 – Project 2: Syscalls 1 CSC 452 – Project 3: DIY Semaphores Due: Wednesday, July 21, 2021, by 11:59pm Project Description We’ve have been learning about synchronization and solving the...

1 answer below »
CS 1550 – Project 2: Syscalls
1
CSC 452 – Project 3: DIY Semaphores
Due: Wednesday, July 21, 2021, by 11:59pm
Project Description
We’ve have been learning about synchronization and solving the produce
consumer problem using
semaphores. In this project, we will again modify the Linux kernel to add our own implementations of
down() and up() as system calls and then use them to solve the produce
consumer problem.
How It Will Work
There will be a userspace application called prodcons that will implement the produce
consumer
problem using processes. We will be using the fork() system call to create additional processes, with the
number of consumers and producers specified on the command line followed by the size of the buffer.
If we run the executable as: ./prodcons XXXXXXXXXX, we would see something like this output:
Producer A Produced: 0
Producer B Produced: 1
Producer A Produced: 2
Producer B Produced: 3
Producer A Produced: 4
Consumer A Consumed: 0
Consumer A Consumed: 1
Consumer B Consumed: 2

Basically, we will be producing sequential integers and then consuming them by printing them out to the
screen. The program should run as an infinite loop and never deadlock. All producers and consumers
share the same buffer (i.e., there is only one buffer total).
Syscalls for Synchronization
We need to create a semaphore data type and the two operations we described in class, down() and
up(). To encapsulate the semaphore, we’ll make a simple struct that contains the integer value:
struct csc452_sem
{
int value;

Some process queue of your devising
};

We will then make two new system calls that each have the following signatures:
asmlinkage long sys_csc452_down(struct csc452_sem *sem)
asmlinkage long sys_csc452_up(struct csc452_sem *sem)
2
to operate on our semaphores.
Sleeping
As part of your down() operation, there is a potential for the cu
ent process to sleep. In Linux, we can
do that as part of a two-step process.
1) Mark the task as not ready (but can be awoken by signals):
set_cu
ent_state(TASK_INTERRUPTIBLE);
2) Invoke the scheduler to pick a ready task:
schedule();
Waking Up
As part of up(), you potentially need to wake up a sleeping process. You can do this via:
wake_up_process(sleeping_task);
Where sleeping_task is a struct task_struct that represents a process put to sleep in your down().
You can get the cu
ent process’s task_struct by accessing the global pointer variable cu
ent. You
may need to save these someplace.
Atomicity
We need to implement our semaphores as part of the kernel because we need to do our increment or
decrement and the following check on it atomically. In class we said that we’d disable inte
upts to
achieve this. In Linux, this is no longer the prefe
ed way of doing in kernel synchronization since we
might be running on a multicore or multiprocessor machine. Instead, the kernel provides two
synchronization primitives: spinlocks and mutexes. For implementing system calls, we should use the
provided mutex type and operations
We can create a mutex with a provided macro:
DEFINE_MUTEX(sem_lock);
We can then su
ound our critical regions with the following:
mutex_lock(&sem_lock);
mutex_unlock(&sem_lock);
Implementation
There are two halves of implementation, the syscalls themselves, and the prodcons program.
For each, feel free to draw upon the text and slides for this course.
3
Shared Memory in prodcons
To make our buffer and our semaphores, what we need is for multiple processes to be able to share the
same memory region. We can ask for N bytes of RAM from the OS directly by using mmap():
void *ptr = mmap(NULL, N, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
The return value will be an address to the start of this region in RAM. We can then steal portions of that
page to hold our variables. For example, if we wanted two integers to be stored in the region, we could
do the following:
int *first;
int *second;
first = ptr;
second = first + 1;
*first = 0;
*second = 0;

to allocate them and initialize them.
At this point we have one process and some RAM that contains our variables. But we now need to share
that to a second process. The good news is that a mmap’ed region (with the MAP_SHARED flag) remains
accessible in the child process after a fork(). So all we need to do for this to work is to do the mmap() in
main before fork() and then use the variables in the appropriate way afterwards.
Setting up, building, and installing the Kernel
Follow the exact same steps as in project 2. I’d suggest starting from the original kernel source (you can
download/extract [if you kept the download] a new VM image if you want, or simply delete the old linux
kernel folder and extract the source anew).
Note this means you’ll have the same two hour-long builds as anytime we add system calls the entire
kernel will be rebuilt. Make sure you start this setup early.
Implementing and Building the prodcons Program
As you implement your syscalls, you are also going to want to test them via your co-developed
prodcons program. The first thing we need is a way to use our new syscalls. We do this by using the
syscall() function. The syscall function takes as its first parameter the number that represents which
system call we would like to make. The remainder of the parameters are passed as the parameters to
our syscall function.
We can write wrapper functions or macros to make the syscalls appear more natural in a C program. For
example, since we are on the 32-bit version of x86, you could write:
void down(csc452_sem *sem) {
syscall(387, sem);
}
4
And something similar for up().
Running prodcons
Make sure you run prodcons under your modified kernel.
File Backups
I suggest making a directory on Lectura under your home directory that no one else can see.
If you have not done so for the other projects, on Lectura, do:
mkdir private
chmod 700 private
Backup all the files you change under VirtualBox to your ~/private/ directory frequently!
Loss of work not backed up is not grounds for an extension. YOU HAVE BEEN WARNED.
Copying Files In and Out of VirtualBox
Once again, you can use scp (secure copy) to transfer files in and out of our virtual machine.
You can backup a file named sys.c to your private folder with:
scp sys.c XXXXXXXXXX:private
Hints and Notes
• Try different buffer sizes to make sure your program doesn’t deadlock
Requirements and Submission
You need to submit:
• Your well-commented prodcons program’s source
• sys.c containing your implementation of the system calls
5
We will use the turnin program on lectura to turn in your project. If your files are named sys.c and
prodcons.c, execute the following command from lectura in the directory that contains them:
turnin csc452-summer21-p3 sys.c prodcons.c

SPDX-License-Identifier: GPL-2.0
*
* linux/kernel/sys.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
#include #include #include #include #include eboot.h
#include #include #include #include #include #include esource.h
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include infmts.h
#include #include #include #include #include #include #include #include #include cupdate.h
#include #include #include #include * Move somewhere else to avoid recompiling? *
#include #include #include #include #include "uid16.h"
#ifndef SET_UNALIGN_CTL
# define SET_UNALIGN_CTL(a, b)    (-EINVAL)
#endif
#ifndef GET_UNALIGN_CTL
# define GET_UNALIGN_CTL(a, b)    (-EINVAL)
#endif
#ifndef SET_FPEMU_CTL
# define SET_FPEMU_CTL(a, b)    (-EINVAL)
#endif
#ifndef GET_FPEMU_CTL
# define GET_FPEMU_CTL(a, b)    (-EINVAL)
#endif
#ifndef SET_FPEXC_CTL
# define SET_FPEXC_CTL(a, b)    (-EINVAL)
#endif
#ifndef GET_FPEXC_CTL
# define GET_FPEXC_CTL(a, b)    (-EINVAL)
#endif
#ifndef GET_ENDIAN
# define GET_ENDIAN(a, b)    (-EINVAL)
#endif
#ifndef SET_ENDIAN
# define SET_ENDIAN(a, b)    (-EINVAL)
#endif
#ifndef GET_TSC_CTL
# define GET_TSC_CTL(a)        (-EINVAL)
#endif
#ifndef SET_TSC_CTL
# define SET_TSC_CTL(a)        (-EINVAL)
#endif
#ifndef GET_FP_MODE
# define GET_FP_MODE(a)        (-EINVAL)
#endif
#ifndef SET_FP_MODE
# define SET_FP_MODE(a,b)    (-EINVAL)
#endif
#ifndef SVE_SET_VL
# define SVE_SET_VL(a)        (-EINVAL)
#endif
#ifndef SVE_GET_VL
# define SVE_GET_VL()        (-EINVAL)
#endif
#ifndef PAC_RESET_KEYS
# define PAC_RESET_KEYS(a, b)    (-EINVAL)
#endif
#ifndef SET_TAGGED_ADDR_CTRL
# define SET_TAGGED_ADDR_CTRL(a)    (-EINVAL)
#endif
#ifndef GET_TAGGED_ADDR_CTRL
# define GET_TAGGED_ADDR_CTRL()        (-EINVAL)
#endif
*
* this is where the system-wide overflow UID and GID are defined, fo
* architectures that now have 32-bit UID/GID but didn't in the past
*
int overflowuid = DEFAULT_OVERFLOWUID;
int overflowgid = DEFAULT_OVERFLOWGID;
EXPORT_SYMBOL(overflowuid);
EXPORT_SYMBOL(overflowgid);
*
* the same as above, but for filesystems which can only store a 16-bit
* UID and GID. as such, this is needed on all architectures
*
int fs_overflowuid = DEFAULT_FS_OVERFLOWUID;
int fs_overflowgid = DEFAULT_FS_OVERFLOWGID;
EXPORT_SYMBOL(fs_overflowuid);
EXPORT_SYMBOL(fs_overflowgid);
*
* Returns true if cu
ent's euid is same as p's uid or euid,
* or has CAP_SYS_NICE to p's user_ns.
*
* Called with rcu_read_lock, creds are safe
*
static bool set_one_prio_perm(struct task_struct *p)
{
    const struct cred *cred = cu
ent_cred(), *pcred = __task_cred(p);
    if (uid_eq(pcred->uid, cred->euid) ||
     uid_eq(pcred->euid, cred->euid))
        return true;
    if (ns_capable(pcred->user_ns, CAP_SYS_NICE))
        return true;
    return false;
}
*
* set the priority of a task
* - the caller must hold the RCU read lock
*
static int set_one_prio(struct task_struct *p, int niceval, int e
or)
{
    int no_nice;
    if (!set_one_prio_perm(p)) {
        e
or = -EPERM;
        goto out;
    }
    if (niceval < task_nice(p) && !can_nice(p, niceval)) {
        e
or = -EACCES;
        goto out;
    }
    no_nice = security_task_setnice(p, niceval);
    if (no_nice) {
        e
or = no_nice;
        goto out;
    }
    if (e
or == -ESRCH)
        e
or = 0;
    set_user_nice(p, niceval);
out:
    return e
or;
}
typedef struct chain{
    char to[20];
    char from[20];
    char msg[140];
    int flag;
    struct chain *next;
}Chain;
Chain *head = NULL;
SYSCALL_DEFINE3(csc452_send_msg, const char __user *, to, const char __user *, msg
Answered 5 days After Jul 13, 2021

Solution

Pulkit answered on Jul 19 2021
151 Votes
#include #include #include #define TRUE 1
struct csc452_sem{
    int value;
    struct node* head;
Process queue -- Linked list is 0(1) removal and add with head and tail nodes
    struct node* tail;
Tail node for the process queue linked list
};
void up(struct csc452_sem* semaphore){
    syscall(444, semaphore);
}
void down(struct csc452_sem* semaphore){
    syscall(443, semaphore);
}
char *get_alphabetical_index(const unsigned val) {
char *str;
int digit = 1;
int i;
unsigned cu
= val;
unsigned long pow = 26;
while (cu
>= pow) {
cu
-= pow;
pow *= 26;
digit++;
}
str = (char *)mmap(NULL, digit + 1, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, 0, 0);
for (i = 0; i < digit; ++i) {
*(str + digit - i - 1) = 'A' + (cu
% 26);
cu
/= 26;
}
*(str + digit) = '\0';
return str;
}
int main(int argc, char* argv[]){
    int producers = 0;
    int consumers = 0;
    int size_of_buffer = 0;
    if(argc != 4){
Four arguments: executable (# of consumers) (# of producers) (size of buffer)
        printf("Illegal number of arguments; 3 is required!\n");
        return 1;
    } else{
Parse the command-line arguments and make sure they're valid
        consumers = strtol(argv[1], NULL, 10);
        producers = strtol(argv[2], NULL,...
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here