{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a4d3c9e5-e2ac-45e1-9c06-e65d2092b1d8",
   "metadata": {},
   "source": [
    "<h1>Lab 4: Experiments with OS Simulator and Synchronisation</h1>\n",
    "<hr>\n",
    "<center>INSTRUCTIONS</center>\n",
    "<ul>\n",
    "    <li>Open a terminal on your system.</li></li>\n",
    "    <li>Change to the <b>AOS2026</b> directory on your Desktop.</li>\n",
    "    <li>Copy the <b>OS Simulator</b> that you implemented as your assignment into\n",
    "        the <b>lab04</b> directory.</li>\n",
    "    <li>You may have to compile your simulator C source files again to create a\n",
    "        working executable.</li>\n",
    "    <li>Activate the <bf>AOS2026</b> or the <b>aos2026</b> virtual environment by\n",
    "        typing \n",
    "        <center>source AOS2026 (or aos2026)/bin/activate</center>\n",
    "        If successful, you will see the virtual environment name prefixed to your\n",
    "        terminal prompt.</li>\n",
    "    <li>Run your simulator as indicated below in the different notebook cells.</li>\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a4398dd9-1713-4f71-9ca8-73e7d69c7360",
   "metadata": {},
   "source": [
    "<hr />\n",
    "<h3>Task 1: Study of Round Robin Scheduling Algorithm</h3>\n",
    "<p>\n",
    "    In this task, we will explore the functioning of the Round Robin algorithm. Run your simulator with about 8 - 12 processes of different sizes and types. Specify Round Robin scheduler. Make a note of the following:\n",
    "    <ul>\n",
    "        <li>The sequence in which the processes complete.</li>\n",
    "        <li>The Response, Waiting and Running times.</li>\n",
    "    </ul>\n",
    "    Answer the following\n",
    "    <ol>\n",
    "        <li>Is there any relationship between the sequence of processes and their\n",
    "            sizes and types? Explain in two-three sentences.</li>\n",
    "        <li>How much variation is there in the Response times? Are they nearly the\n",
    "            same for all the processes or do they vary?</li>\n",
    "        <li>Is there a link between the Running times and the sizes; and between\n",
    "            Waiting times and process types?</li>\n",
    "    </ol>\n",
    "</p>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "79f565f7-30cf-430c-a703-cf1ab74e729c",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "# Run your simulator executable with the necessary arguments"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77f92b29-dcef-42cf-8ff6-823058060594",
   "metadata": {},
   "source": [
    "<h5>Answers and Explanations</h5>\n",
    "(Double-click here to open the cell for writing your answers)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cbedecc-ff27-4b01-993f-0037738cf3e8",
   "metadata": {},
   "source": [
    "<hr />\n",
    "<h3>Task 2: Comparison of Scheduling Algorithms</h3>\n",
    "<p>\n",
    "    Repeat the above experiment but after changing the scheduling algorithm to any other: FCFS, Priority, SJF, ...\n",
    "</p>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f9c948d8-d539-49c8-8f6b-b99639850471",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "(Run your simulator here so that the results are seen below)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "26be1956-00be-4f79-b0cf-a89a62276066",
   "metadata": {},
   "source": [
    "<h5>Answers and Explanations</h5>\n",
    "(Double-click here to open a cell in which you can write down your observations)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20323be9-4daf-4c58-a2c1-ceb6df7f5438",
   "metadata": {},
   "source": [
    "<hr>\n",
    "<h3>Task 3: Bounded Buffer Reader-Writer Problem with Semaphores</h3>\n",
    "This is yet another variant of the Reader-Writer problem where the buffer is \n",
    "<b>circular</b>, i.e. the number of items to write is more than the size of the buffer and get written from the start again once the end of the buffer is reached. Of course, no writer can write into a location that has not yet been seen by a reader.\n",
    "<p>\n",
    "    Here are the parameters for the problem for this lab.\n",
    "    <ol>\n",
    "        <li>The size of the buffer is 5000.</li>\n",
    "        <li>The number of writers cannot be more than 50.</li>\n",
    "        <li>In this task, there is <b>only one reader.</b></li>\n",
    "        <li>The <em>writer</em> and <em>reader</em> threads start concurrently.</li>\n",
    "        <li>The number of items written is given as a <b>command-line</b> argument\n",
    "            and <b>must be more than 8000.</b></li>\n",
    "        <li>Each writer writes the value <em>i</em> into the buffer location\n",
    "            <em>i</em>. Remember that the writers may write into the same location\n",
    "            again <b>but only after the reader verified the value in that\n",
    "                location.</b></li>\n",
    "    </ol>\n",
    "    The outputs are similar to the other versions done in the class and in the lab. Each writer thread outputs the number of items written by it while the reader checks if there is anywhere a mismatch between the buffer index and the value written.\n",
    "</p>\n",
    "<p>Fill in the code in the cell below and run it in our usual way in the cells further below.</p>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d9bb9f91-9c1a-4c24-8d53-2b2883fdf28d",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%file semaphores_02.c\n",
    "#include <stdio.h>\n",
    "#include <stdlib.h>\n",
    "#include <semaphore.h>\n",
    "#include <pthread.h>\n",
    "\n",
    "#define MAXNITEMS  \t5000\n",
    "#define MINITEMS    8000\n",
    "#define MAXNTHREADS\t  50\n",
    "#define MIN(A, B) ((A) > (B) ? (B) : (A))\n",
    "#define MAX(A, B) ((A) > (B) ? (A) : (B))\n",
    "\n",
    "int nitems;\n",
    "struct {\n",
    "     sem_t           /* Insert all the semaphores as needed */\n",
    "     int             buff[MAXNITEMS];\n",
    "     int             nput;\n",
    "     int             nputval;\n",
    "} shared;\n",
    "\n",
    "void *reader(void *), *writer(void *);\n",
    "\n",
    "int main(int argc, char **argv)\n",
    "{\n",
    "     int i, sum=0, nthreads, count[MAXNTHREADS];\n",
    "     pthread_t tid_writer[MAXNTHREADS], tid_reader;\n",
    "\n",
    "     nitems = MAX(atoi(argv[1]), MINITEMS);           /* First argument: # items */\n",
    "     nthreads = MIN(atoi(argv[2]), MAXNTHREADS);      /* Second argument: # writers */ \n",
    "\n",
    "     /* Create necessary writers and the single reader threads */ \n",
    "     for (i=0; i<nthreads; i++) {\n",
    "          count[i] = 0;\n",
    "     }\n",
    "\n",
    "     /* Wait for all the threads to complete; print items counts as well\n",
    "        as total number of items written                                  */\n",
    "     for (i=0; i<nthreads; i++) {\n",
    "          pthread_join(tid_writer[i], NULL);\n",
    "          printf(\"count[%d] = %d\\n\", i, count[i]);\n",
    "          sum += count[i];\n",
    "     }\n",
    "     pthread_join(tid_reader, NULL);\n",
    "     printf(\"Total:\\t%d\\n\", sum);\n",
    "     \n",
    "     exit(0);\n",
    "}\n",
    "\n",
    "/*** The writer function; insert required synchronisation primitives ***/\n",
    "void *writer(void *arg)\n",
    "{\n",
    "     for ( ; ; ) {\n",
    "          if (shared.nput >= nitems) {\n",
    "               return(NULL);\n",
    "          }\n",
    "\n",
    "          shared.buff[shared.nput % MAXNITEMS] = shared.nputval;\n",
    "          shared.nput++;\n",
    "          shared.nputval++;\n",
    "\n",
    "          *((int *) arg) += 1;\n",
    "     }\n",
    "}\n",
    "\n",
    "/*** The reader function; insert synchronisation primitives as needed ***/\n",
    "void *reader(void *arg)\n",
    "{\n",
    "     int i;\n",
    "     for (i=0; i<nitems; i++) {\n",
    "          if (shared.buff[i % MAXNITEMS] != i)\n",
    "               printf(\"buff[%d] = %d\\n\", i, shared.buff[i]);\n",
    "     }\n",
    "     \n",
    "     return(NULL);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19a976f5-84ee-4f9d-8af7-debae1503fe4",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%bash\n",
    "gcc -o sem02 semaphores_02.c -lpthread"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb74ca35-24b4-491d-ac07-4de2e7942c5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "./sem02 32453 6"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ceebbad6-3cfe-46ac-a99e-dda588128333",
   "metadata": {},
   "source": [
    "<hr />\n",
    "<h3>Task 4: Bounded Buffer Problem with Multiple Writers and Multiple Readers</h3>\n",
    "This is a small variation of the problem in the previous task. Now, instead of a single reader, we have multiple readers too. The number of readers is <b>4; or 5 less than the number of writers<b> whichever is larger. </b>Everything else remains the same. Copy and modify the above source code in the cell below to solve this version of the problem."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b12c412f-ba62-4662-9de6-308f24ef71fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%file semaphores_03.c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "923d83d4-594f-4043-a68e-a048b235ed49",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "gcc -o sem03 semaphores_03.c -lpthread"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f0bf3467-47a5-4553-9270-c93fda39ac05",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "./sem03 13879 6"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79a82e34-fb3f-4542-9ab6-e48bd62a572a",
   "metadata": {},
   "source": [
    "<hr />\n",
    "<center>THE END</center>\n",
    "<hr />"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
