Showing posts with label bits. Show all posts
Showing posts with label bits. Show all posts

Tuesday, September 17, 2013

World of Bits and Bytes



Recently, I have realized that no matter how much C, C++ or other high level languages you know it all comes down to bit and bytes view of program. 
I started realizing that after all it’s not that easy to actually think and write in bit/byte manipulation. This is my attempt to learn and be more comfortable about thinking in bit/bytes.


Table of Contents



Basics

Inroduction link


 0 1 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1 0 0 0
||              |               |               |              ||
|+- bit 31      |               |               |       bit 0 -+|
|               |               |               |               |
+-- BYTE 3 -----+--- BYTE 2 ----+--- BYTE 1 ----+-- BYTE 0 -----+
|                               |                               |
+----------- WORD 1 ------------+----------- WORD 0 ------------+
|                                                               |
+--------------------------- DWORD -----------------------------+

Hexadecimal Numbers
0 1 2 3 4 5 6 7 8 9 A B C D E F


Bitwise Operators
The & operator (AND)
1   &   1   ==   1
1   &   0   ==   0
0   &   1   ==   0
0   &   0   ==   0

The | operator (OR)
1  |   1   ==   1
1  |   0   ==   1
0  |   1   ==   1
0  |   0   ==   0

The ^ operator (XOR)
1  ^   1   ==   0
1  ^   0   ==   1
0  ^   1   ==   1
0  ^   0   ==   0

The ~ operator
The ~ (Ones Complement or inversion) operator acts only on one value and it inverts it.

The >> (Right Shift)
00001100  - b 
00110000  - b << 2

The << (Left Shift)
00001100  - b
00000011  - b >> 2

Another example is
1<<4; 0001 0000



Bit Fields 



struct date_struct {
    BYTE day   : 5,   // 1 to 31
         month : 4,   // 1 to 12
         year  : 14;  // 0 to 9999
    } date

|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|
  |                           |       |         |
  +------ year ---------------+ month +-- day --+

date.day = 12;
dateptr = &date;
dateptr->year = 1852;


Basics of Binary numbers and operations (link) 


Problems 

How set a single bit in a byte?

 For e.g In byte 0000 1000 set bit no 6 will produce 0100 1000
 (Remember bit number starts with 0-7)
         
//For problems where certain bit values needs to be changed, first we
//need to create a bit mask.
//Bit mask is a temporary variable with some value. Using this value
//we will access and change specific bits in a byte of data.

//For e.g.
//To set 6th bit in a byte 0000 1000
//We have             MASK 0100 0000  (OR)
//                    ——————————————
//                         0100 1000

//To turn on certain bit in a byte (OR) is used.

int set_bit(int val, int num, bool bitval)
{
    return (val | (bitval << num));
}
//Here, val    = 0000 1000 = 8
//      num    = 6 (set 6th bit)
//      bitval = 1 (set to 1)

//      0000 1000
//(OR)  0100 0000  (1 << 6)
//      ————————-
//      0100 0000

How to unset single bit in a byte?

For e.g In byte 0100 1000 unset bit no 6 will produce 0000 1000
(Remember bit number starts with 0-7)        

//To unset specific bit we will use (AND) operation.
//Mask value need to be ‘0’ for the bit to unset but rest of the bits
//need to ‘1’. The reason for rest of the bits to set as ‘1’ is as
//we are doing (AND), we don’t want to unset other bits which are
//already set.
//
//For e.g.
//To unset 6th bit 0100 1000
//            MASK 1011 1111 (AND)
//                ——————————-
//                 0000 1000   (Result)
int unset_bit(int val, int num, bool bitval)
{
    return (val & ~(bitval << num));
}

//Here, val    = 0100 1000
//      num    = 6
//      bitval = 0
//      (bitval << num) = 0100 0000
//     ~(bitval << num) = 1011 1111
//
//      0100 1000
//      1011 1111 (AND)
//      —————————-
//      0000 1000    (Result)


One function to set and unset

int change_bit(int val, int num, bool bitval)
{
    return (((val & ~(bitval << num)) | (bitval << num));
}


Unset range of bits



Set range of bits





Links



Sunday, September 15, 2013

Process synchronization in OS

This post is all about very simplistic approach towards process and process synchronization.


Table of Contents


What is a Process?

OS objective is to keep as many as of the computer resources as busy as possible. It is used to keep track of all the things an OS must remember about the state of user program.

Process = Code + Allocated Resources + Book keeping information

Process is like a box, a complete entity in itself which does a step by step task written in progam. More formally it is called program in execution.

Lets consider a very basic operating system with very least complexity. This operating system can run only one process at a time. Since, only one process is working at a time, it may happen that all the resources occupied by process will not be used at the same time.


To maximize the resource utilization, we need to have entities running at the same time. When its said multiple entities it is logical that either we need to have multiple process running at the same time or light weight multiple entities running inside process.


Lets explore the second option, now consider process is like a box and it has resources inside the box. We create multiple child of process which is called thread.


Thread is a child of process and hence it will use resource Process have. Theoretically, there is no limit on number of child threads a process can have but it seems logical that process should have enough resource for administrative purpose for these threads. 


Once there are multiple threads they are going to ask for same resource at the same time. For example, if two children are in one room then they will always fight for same toy. Same applies to threads. 


3 Issues with Sharing



  1. How to Share data?
  2. How to ensure threads in a process, executes on at a time?
  3. How to ensure proper sequencing of events?

To understand it better, lets take a real world example


Carl’s Jr. Restaurant


Process


  1. Customer arrives
  2. Employee takes order
  3. Employee cooks food
  4. Employee bag food
  5. Employee takes money
  6. Customer gets food and leaves
If a single employee is doing steps from 1-6 then all other customers have to wait in line and its going to be long wait.
Instead, lets have multiple employees for taking order, cook food, bag food, take money. Each of these 'employees' are multiple threads on Process 'Restaurant'. Each thread is responsible for doing specialized task.

Lets associate 3 issues in current situation
  1. What is shared data? - In step 2-3, Quantity of food. In step 3-4, how much food to bag
  2. Does sequence matters? -  Cook can't cook food until order arrives. Employee can't bag food until it is cooked. So, sequencing matters.
Shared data can be distributed either using message passing or storing that data in global memory of process and each thread read from that memory location.

The next logical question is, How to ensure threads in a process, executes on at a time?
More formally there are three types of solution categories
  1. Algorithmic approach
  2. Software Primitives
  3. Concurrent programming construct

Algorithmic approach

The algorithmic approach to process synchronization does not use any assistance from the computer architecture or the OS kernel. Instead it uses an arrangement of logical conditions to satisfy the desired synchronization requirements. [Dhamdhere]

Software Primitives

A set of software primitives for mutual exclusion e.g Semaphore, Locks etc. were developed to overcome the logical complexity of algorithmic implementations. This is implemented using some special architectural features of computer systems. But, ease of use and correctness still remained the major obstacle in a development of large concurrent systems.

Semaphores

It is a shared integer variable with non-negative values that have Initialization, wait and signal as a indivisible operation.

Semaphore Constructor
Semaphore Destructor
Semaphore Wait
Semaphore Signal

Locks

The basic idea is to close a lock at the start of critical section or an indivisible operation and open it at the end of the critical section or the indivisible operation.

Locks solves, How to ensure threads in a process, executes on at a time? but not the sequencing problem.


Lock Constructor

Lock Destructor

Lock Acquire

Lock Release

Lock Owner




Concurrent Programming Construct


Locks can only solve mutual exclusion problem, they can not solve sequencing problem. We need another mechanism "Monitors"

Monitors is a programming language construct that supports both data access synchronization and control synchronization.


Monitors have 3 parts



  1. Lock for mutual exclusion
  2. 1 or more condition variables for sequencing
  3. Monitor variables for make sequencing decisions -> Shared data 

Condition Variables

Each condition variable is only associated with one lock.

CV Constructor

CV Destructor
CV Wait
CV Signal

Producer-Consumer Problem

Lets consider we have infinite buffer

monitor variable  => int itemCount = 0;

monitor lock        => monitorLock;
monitor condition => needItem;
Producer
Consumer



Recommended reading