DT 8025 2016 Practical 2

From CERES
Revision as of 20:10, 3 October 2016 by Ceres (Talk | contribs)

Jump to: navigation, search

Objectives

There are three objectives for this practical:

  • Learn about and implement the basic ingredients for concurrency,
  • Implement the mutual exclusion primitives,
  • Use them in implementing a simple access control protocol

Instructions

Submit a single .zip file on blackboard with separate folders, each containing the solutions to the below-specified parts.

For each function in the code, you need to write evidence of test-driven development, both in terms of comments (description, pre- and post-condition and properties) and unit testing test suites (e.g., in CUnit, see below). To show the successful execution of your test suite, also include the XML file resulting from its execution. Include a report document (preferably with PDF format) which explains the details about the implementation of each part of the assignment (including details of the implemented functions and what they do).

Part 1: Yield and Taskswitch

Download the Libtask library and run the sample program primes on the Raspberry Pi. This is a simple example with only one thread to execute. There is no way of switching context because there is no invocation to taskyield() which is a function in the library used for changing control between threads. Hence, to be able to switch the control between threads using this library you need to implement two functions. The first function is:

taskyield() 

This is the main function used for cooperative control switch. Implement the function such that it

  • enqueues the current thread in the ready queue,
  • set the state of the task as "yield",
  • pick the first element in the queue, dequeue it and dispatch it by switching the context of two tasks

In order to switch the context of two tasks you need to implement another function in the library, namely:


taskswitch()


This function is used to switch the context between two tasks by calling the contextswitch() function in libtask.

Complete the body of these two functions in the library and test your implementation using unit tests.

Part 2: Concurrency and Dining Philosophers

This part of the assignment consists of implementing a sample of dining philosophers. In this protocol a group of philosophers are siting around a table and there is a fork placed between each two philosophers. The configuration of the protocol with two philosophers and forks can be displayed on the display (or PiFace) by an integer comprising 4 digits:

  • the first and the third digits represent the state of the first and the second forks, respectively; value 0 (for each fork) means free and 1 means taken,
  • the second and fourth digits represent the state of philosopher 1 and philosopher 2, respectively; value 0 means thinking, 1 means hungry (waiting to get one fork), 2 means having one fork, 3 means trying to get the other fork, and 4 means eating (possessing 2 forks).

For example, 1 4 1 1 denotes the situation where the first philosopher is eating with two forks and the second philosopher is hungry and trying to get hold of one fork.

Implement the protocol with two philosophers and forks by implementing following functions.

void phil1() 
void phil2() 

to represent the behavior of philosophers (first thinking, then becoming hungry and trying to grab one fork, grabbing a fork when available, then trying to grab the other fork, then grabbing the other fork and eating and finally, going back to the thinking state). Note that the access to the forks (global variables) should be surrounded by a locks. Each philosopher process is responsible for updating the digit of the corresponding philosopher on the display as well as both forks whenever it makes any change to them.


Implement the protocol in a way that it is deadlock free (using yieldtask() properly) and test your program by providing unit tests.