|
DDD Student Documentation |
·
Installation
Instructions of DDD for Windows User (Especially Remote Students)
·
Following Debug Path for a test case using DDD
DDD is a graphical front-end for GDB and other command-line debuggers
(called inferior debugger, because it lies at the layer beneath DDD). The purpose of a debugger such as DDD is to allow you to see what is going on
"inside" another program while it executes.
Edit your .cshrc file in your home directory and add following line at the end of your file
set path=(/auto/usc/ddd/3.2.1/bin $path)
Type source .cshrc to make that change effective for your current login session. From this point on, you can just type 'ddd' from any directory in your account and it will execute.
Installation Instructions
for Windows User (Especially Remote Students)
1) Make sure you can run the DDD program in your account on Solaris system configured with X-window, e.g. the sun workstation in SAL 125.
2) Download the X-Win32 program from the following link:
http://software.usc.edu/win9x/
3) Install X-Win32 to you own system
4) Run X-Win32 in the Program menu
5) Add aludra as a new session to the X-Win32 session list
6) Get the ip address of the windows system with command
ipconfig (for windows 2000)
7) Log into your Solaris account
8) type the following command:
ddd -display 128.125.3.172:0&
Note: 128.125.3.172 is my current ip. Replace it.
Please make sure:
- The correctness of your IP address
- ‘:0’ is added after the IP address in your command line
9) Now an new X-Windows session connection is forwarded to you X-Win32, select
“accept”
10) Now the DDD main window will come into your vision on you PC.
A possible problem is if X-windows is running through
a 56k modem, it can be fairly slow. Some of previous students overcame this
problem by simply printing out the variable value for debugging.
The main thing you have to do
is to follow the simple test case provided to you. It shows how the threads are
executed without synchronization.
After you are done with installing and compiling the nachos and ddd, the main
thing you have to do is to follow the path for the simple test case provided to
you. It shows how the threads are executed.
1) Go to the directory nachos-csci402/code/threads.
cd
nachos-csci402/code/threads
2) Type there
ddd&
this will run ddd .
3) From the ddd File menu press open program, highlight nachos and press
open.main.cc will be opened at your front with the separate small menu.
Yes every program in nachos starts from here "main.cc". (poject1
-- project4)
--You will feel uncomfortable by seeing new functions and variables.
--Don't worry about that.
-- You can edit this file , infact, any file you see in the ddd screen.
*go to the ddd menu at top .From source menu press edit source.
-- Before going further let me explain you few things in general and for
main.cc in particular.
Global
Variables
All global variables and global object pointers are defined in threads
directory system.h and system.cc
These are
Thread *currentThread; // the thread we are running now
Thread *threadToBeDestroyed; // the thread that just finished
Scheduler *scheduler; // the ready list
Interrupt *interrupt; // interrupt status
Statistics *stats; // performance metrics
Timer *timer; // the hardware timer device,
Initialize
Function
Initialize function is also
implemented in system.cc
What it does is take the argument variables from the command prompt and invokes
particular functions and
initialize variables. Take a look at it as which objects or variables are
initialized.
Macro
Guards
You will encounter various macro guards #ifdef --- #endif at various places in
nachos.
These are used for defining the particular functions and variables associated
with THREADS (project1) for threads
, USER_PROGRAM(project2) for user programs, USE_TLB (project3) use of TLB,
FILESYS(project4) for filesystem. and various other
self explanatory purposes.
Extern functions
Prototypes of functions implemented else where are defined as External
functions in main.cc
Like
extern void threadtest() is implemented in threadtest.cc in threads
directory.
4) Now, set the breakpoint at the threadtest() function.
You can do it by pressing left click on the line where threadtest(); is written
and then press Breakat()
from the bottom menu of the ddd screen.
Stop sign will appear at that line.
5) In options menu at the top of ddd screen press
"run in execution window"
Now your out put will be shown in the separate window.
6) In program menu at the top of ddd screen press run.
type run command as follows
nachos -P -d
-P will run the testcase for
threads
-d will display the debug messages for displaying what's happening.
Press okay .
The cursor (-> sign)will stop at the place where you put the breakpoint.
>From the separate small ddd menu , you can press "step" to go
inside the functions.
Stepping through will take you to the each detail of the function being called
during the program execution.
"Next" command on that menu will only execute next line but will not
take you inside the functions.
7) Now , in a threadtest() function in threadtest.cc You will see that ,
a)
It prints a debug message
b) Initializes a new thread pointer by giving it name.In our case it is
"forked thread".
check the thread constructor in thread.h/thread.cc
c) Calls the fork member function of thread class .
Fork function takes as an argument as the pointer of a function as its first
argumenet and the argument of that funtion as the second
argument.
So, it takes "SimpleThread" as its first argument and "1"
as the second argument which is actually the argument of function
SimpleThread.
Basically, It passes the function SimpleThread(1) in fork function like this
t->Fork(SimpleThread,1);
What a fork does is allocates the stack for this thread by calling stack
allocate function.
Stack allocate function calls Alloctate bounded array , this allocate bounded
array function allocates array of pages
for the thread in memory by calling mprotect function.(This function resides in
machine directory in sysdep.cc).
After that , since host cpu is MIPS for nachos so stacktop is adjusted
accordingly in the stack allocate function.
Basically , the functoin pointer is stored in the stack.
Fork function disable interrupt stores old value of interrupt in oldlevel and
then put the thread into the readylist of the cpu.
scheduler->ReadyToRun(this);
This function is implemented in schedule.h/.cc in threads directory and ready
list is implemented in list.h/.cc in same threads directory.
After that it enables the interrupt by setting it with the oldlevel.
Interrupt functions are implemented in machine directory in interrupt.h/.cc
d) Then it calls the simplethread function with 0 argument .
f) Function is called, printf statement is displayed like "thread 0 looped
0 times"
g) Then currentThread->Yield() is called . what it does is put the
currentThread running which is "main" thread currently runnung ,
to the end of the ready list and pulls out the thread which is at the
front of the readylist.
Guess what we have at the front of the readylist. At the front of the ready
list we have our function SimpleThread with argument 1 .
This function is being associated with the thread named "forked
thread". Since we put that thread over there when we called the fork
function.
This is what we call is the "Context Switching".
Lets go little bit into the details of this yield function.
--It disables interrupt
--Checks if the thread calling this function is the currentThread.
--Prints the debug message
--Pulls out the thread from the front of the readylist by calling
FindNextToRun() function and storing it in the nextThread pointer .
--Inserts the current thread into the ready list.
--Calls the run function
In the run() function
we see that schedular's run function
----disables interrupt
----assigns the currentThread as the nextThread.
----sets its status to running .
----displays which threads it is switching to by debug message.
----Then a switch function which is defined in switch.s is called , You don't
have to go in its details.
----It simply switches the threads and now the running function will be the
simpleThread(1) a "forked thread"
h) so message printed will be "thread 1 looped 0 times.
i) Again currenthread->Yield() will be called, so, main thread will again
come to play and message printed will be
"thread 0 looped 1 times"
j) so, thread 0 is looped five times and thread 1 is looped five times.
k) In the end
currentthread->Finish() is called.
It assigns currentThtread to be the threadToBeDestroyed and eventually calls
sleep().
An error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers in the source code, dereferencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.