Assignment 1 of comp5461

                       Assignment 1 of comp5461

1. Same results with different codes or different results of same code?
Without looking into details of any code, you must have a clear concept about running 
under java 1.2 and java 1.5. If with java 1.2, everything is pre-fixed which means the 
result is predictable and you can simply imagine that they are like sequential execution. 
In java 1.5, everything is unpredictable which means the outcome can be anything, highly 
depending on the running load of current OS. i.e. If you run your machine or server with 
some big application programs at the same time, i.e. many word program etc. and try to 
observe the running result.

So, it is not strange that you may get same result from two DIFFERENT codes in java 1.5. 
But it should be impossible for you to run with different results under java 1.2 with 
SAME code.
	

                        Assignment 2 of comp5461

question 5a-i: Will the modulus of value be equal to the number of waiting processes?
If the semaphore "synch" is a counting semaphore, then what I said in tutorial is correct. However, here we are using "binary semaphore"
which can only have two possible value, namely either 0 or 1. So, no matter how many time you call its "signal(synch)" the internal value
of "synch" is always "1" which means "binary-semaphore" cannot "remember" how many times you call its "signal" method. Then we will have 
problem when the signal(synch) is called many times before context switch happens. Think about it.
In order to help you understand without giving your too much clue, I try to modify the code like below and this will satisfy the requiremnet
such that the modulus of semaphore value is equal to number of waiting processes.
Wait () 
{                                
	wait(mutex) 
	sem.value-- 
	if (sem.value < 0) 
	{ 
		signal(mutex); 		
		wait(synch); //... (hint: the problem might be here)
		sem.value++; //why do I do like this way?
	}
	else
	{
		signal(mutex);
	}
}


 Signal()
 {
	wait(mutex);
	//sem.value++; //why do I do like this way?
	if (sem.value <= 0)
	{
		signal(synch);
	}
	else
	{
		signal(mutex);
	}
}
Please note that we still have the problem of "lost signal" in binary semaphore. However, now this modified version at least satisfies the 
semantics of "i" in 5a. You are supposed to give explanation of the problem in your solution.
*************************************************************************************
question 4: Can we do it without using any semaphore?
The answer is yes or no. When I say yes what I mean is that we can use a simple global variable to "function" as semaphore like below. 
The answer is no because the requirement of assignment is to ask you to use semaphore. 
Please note: 
1. Here only shows you some way of without using semaphore which is expansive. And global variable is itself a kind of semaphore.
2. Here I ignore the code of process 0 which is supposed to be control of system. If you really want to do that, try to move those modification 
of global variable inside code of process 0 and you may need some extra global variable.
3. The assignment requires you to use semaphore. The code below won't be acceptable.
//global variable shared by all processes
int phase1_starting_process_counter=0;
int phase2_executing_process_index=N;

//code for process i where i=1...N
//Pi:

//Phase I begins
	//doing job of Phase I
	phase1_starting_process_counter++;//I am entering phase I
	while (phase1_starting_process_counter<N)
	{
		;//busy waiting
	}
	
//Phase I ends
//Phase II begins
	//doing job of Phase II
	while (phase2_executing_process_index!=i)
	{
		;//busy waiting
	}
//Phase II ends
	phase2_executing_process_index=i-1; //we will pass control to processes with descending ID number
 
************************************************************************
Question: How to solve questions about memory paging?
Some student asks me about this question and at that time I was in a state of lost memory because I learned this long time ago.( As long as two 
years ago which is very long time for me. :) ) Then when I got home my memory recovers. It is a simple counting question if you know the 
following principles:
a) The size of page is usually fixed, say 4k (or 2^12bytes).
b) The size of each address is fixed, say 4 bytes (in 32bit OS).
Then what you need to do is simply counting.
a) A virtual memory system has 4g memory or 2^32 then we need to put this 4g different addresses into a series of pages (or tables).
b) The number of addresses that each page can only hold is 4k/4=1k.
c) Then how many page table we need: 4g/1k=4m
d) Suppose we need to do 2-level paging which will put each address of page into pages. Then the number of page of page (like pointer to 
pointer) is 4m/1k=4k. And in plain English it says that we need 4k tables and each address in these tables pointing to a page table. 
These kind of questions only require you to do counting and you will find similar question in Linux file-index-problem where file-index-table
itself need to be indexed. 
 
Question about mode bit. Suppose you really believe every word written in textbook of OS and lecture slides given by professor, maybe you
would have such doubt like me: If privileged instruction is indeed checked at hardware level, then who can flip the mode bit?
(The following is what I found in my notes when I took an advanced course comp444 which talks more about detail than concept
of OS)

                     Who can flip mode bit?

    I forget part of detail in your slides in class. So, I just checked with our O.S. textbook, and the following is my understanding about the question "who flips the mode bit"? Can you justify my understanding as below?

    It seems to me that "wrap function" of C-library cannot flip the mode bit of user process. On page 43 of Silberschatz's "Operating System Concepts" 6th edition, it says,

    "When a system call is executed, it is treated by the hardware as a software interrupt. Control passes through the interrupt vector to a service routine in the operating system, and the mode bit is set to monitor mode. The system-call service routine is a part of the operating system...."

    And ANSI-C library is not part of OS and it cannot set the mode bit because it is itself just a software supplied by some party. The "trap" interrupt service routine is the one who checks the process identity and decide if the intended memory address is allowed for access. (i.e. check if address is between "limit" and "base" register. )

    A second thought is that "flipping mode bit" is a kind of privileged instruction and can never be done at user mode. This is stated very clear in the textbook. So, I think when we make system call, we are unable to flip the mode bit even from VC++ library's wrapping function of Microsoft who happens to be the supplier of both VC++ and windows.

    Thank you for your attention.

    Professor gives a very detailed explanation and thanks for that:

As we discussed in class, System Calls are initiated by a wrapper function that is part of the C libraries. This code is linked into our application and thus resides in user space (it is not part of the kernel). The wrapper function invokes the system call by executing the "int 0x80" assembly language instruction. This is one of four special machine instructions (on the Intel CPU) that allows a user process to initiate a transition to kernel space. You do not need to be in kernel space to execute int 0x80.

When the CPU executes this instruction, it knows that a system call is taking place. It then consults the Interrupt Descriptor Table (IDT) to find out what routine in the kernel should be run when int 0x80 is executed. Note that 0x80 is a hexidecimal number that translates to 128 in base 10. Basically, this means that the CPU should jump to the address specified in location 128 of the IDT. Where does this address come from? The IDT is a memory-resident table that is initialized by the OS at boot time with the addresses of the various interrupt handlers that are part of the kernel.

So the CPU then hands control to the kernel by invoking the code at the address specified in the IDT. This code is actually the main system call handler whose job it is to (i) determine which system call is being invoked and (ii) to jump to the function that will actually handle the call for the user.

So that's the idea. If you read the explanation closely, you'll see that it's consistent with the description in your textbook. Keep in mind that the Intel processor does not actually have a global "mode bit" (other processors do). User space and kernel space "identification" is actually assigned on a segment by segment basis (where a segment is a block of code/data). Logically, the result is the same, however. In any case, the user process cannot change mode directly - it does not have the authority to do this. Instead it uses the special int 0x80 assembly language instruction to tell the CPU that it needs assistance from the kernel. The CPU uses the previously assigned address in the IDT to pass control to the kernel so that it can decide what to do about the user's request.

Hope this helps.