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.