Skip navigation

Monthly Archives: January 2006

Apart from Windows XP and Ubuntu Linux, my laptop has one more feather in its cap. It is FreeBSD 6.0 My passion on this OS stands for long time since I read about its background through Linus’s autobiography.

I have installed FreeBSD 6.0 on my laptop. Here is the configuration:
1. Intel Centrino 1.7GHz.
2. 512MB RAM
3. 2.5 GB Partition for FreeBSD
4. Intel ICH6 sound (AC97)
5. Broadcom BCM5705M ethernet
6. Intel Wireless 2200
7. Broadcom Bluetooth

Out of 2 CDs of FreeBSD 6.0, I have first CD only. Anyhow I started with it. This CD contains all basic base system, X.org and development tools. The installation is pretty easy for any linux man. The only new thing is slice concept in disk partitioning. The installation wizard screens are cursor based text. The installation time for base system is very minimal in the range of 10-15 minutes only. It detected my ethernet card. After restart, I got 8 consoles (F1 to F8). When I do startx, I got that wdm window manager screen. I went back to console and run sysinstall tool. The beauty of FreeBSD is this tool. This is highly centralized tool which comes handy for any installation related tasks. Using this tool I selected ftp.freebsd.org as installation source (since I don’t have 2nd CD). I selected kde-lite from the listed ports (Here packages are called ports). I marked all dependent ports as D. The installation was perfect. Samba network detected automatically and working fine. Apart from sysinstall tool, the /etc/defaults/rc.conf is a nice all in one system tweak file (Caution: /etc/rc.conf file overrides this file. So any tweak you do should be on /etc/rc.conf only). Another configuration file for kernel and module control is /boot/defaults/loader.conf. This file is simple in format to control the modules to be loaded and kernel settings.

Here are some tweaks I did for my laptop:

Tweak1: To start GUI at boot time: Since I have installed kde-lite, I preferred having kdm as display manager. So I edited /etc/ttys, replaced the line starting with ttyv8 which started xdm with the following line:
ttyv8 “/usr/local/bin/kdm -nodaemon” xterm on secure
Tweak2: For fast boot without menu options: modified the following settings as given below in /boot/defaults/loader.conf.
autoboot_delay=”-1″
beastie_disable=”YES”
Tweak3: To enable built in sound card: In /boot/defaults/loader.conf:
snd_ich_load=”YES” # Intel ICH
Tweak4: To enable ACPI: In /boot/defaults/loader.conf:
acpi_load=”YES”
Tweak5: To enable other other filesystems such as FAT16/32 and NTFS:
msdosfs_load=”YES”
ntfs_load=”YES”
Tweak6: If you don’t want sysinstall to install further packages, you can go to /usr/ports. You have well classified directories with all important packages index. Only thing what we have do do is to enter the corresponding application directory and run “make install”. That is it. No worry of dependencies. Happy installation only!
Tweak7: Here are the harddisk naming conventions mapped with linux for reference:
/dev/hda -> /dev/ad0
/dev/hda1 -> /dev/ad0s1
(e.g:) To mount /dev/hda6 of vfat:
mount -t msdos /dev/ad0s6 /mnt/winhome

Checklists:
Ethernet Networking – OK
Audio card – OK
Wireless – not detected – Not tested
Bluetooth – detected – Not tested
Firewire – detected – Not tested
IrDA – detected – Not tested

Conclusion: Linux is not the only option to come out of Windows loop, there are many upcomings. FreeBSD is one such promising both in Desktop and Server. Hats off to FreeBSD team!

Critical Section:
The threads share several variables or a data structure. Often, these multiple variables or the fields of the structure must be consistent among themselves. The operating system could interrupt a thread in the middle of updating these variables. The thread that uses these variables would then be dealing with inconsistent data. The result is a collision, and it’s not difficult to imagine how an error like this could crash the program. What we need are the programming equivalents of traffic lights to help coordinate and synchronize the thread traffic. That’s the critical section. Basically, a critical section is a block of code that should not be interrupted.

Declaring: CRITICAL_SECTION cs ;
Initializing: InitializeCriticalSection (&cs) ;
Entering: EnterCriticalSection (&cs) ;
Leaving: LeaveCriticalSection (&cs) ;
Deleting: DeleteCriticalSection (&cs) ;

Event Signalling:
The most common use of multiple threads of execution is for programs that find they must carry out some lengthy processing. We can call this a “big job,” which is anything a program has to do that might violate the 1/10-second rule. Obvious big jobs include a spelling check in a word processing program, a file sort or indexing in a database program, a spreadsheet recalculation, printing, and even complex drawing. Of course, as we know by now, the best solution to following the 1/10-second rule is to farm out big jobs to secondary threads of execution. These secondary threads do not create windows, and hence they are not bound by the 1/10-second rule.

Create: hEvent = CreateEvent (&sa, fManual, fInitial, pszName) ;
Set the Event state as signalled: SetEvent (hEvent) ;
Set the Event state as unsignalled: ResetEvent (hEvent) ;
Waiting for the signalled state: WaitForSingleObject (hEvent, dwTimeOut) ;
Waiting for the multiple signalled state: WaitForMultipleObject (…) ;

Each process is started with a single thread, often called the primary thread, but can create additional threads from any of its threads.

A thread is the entity within a process that can be scheduled for execution. All threads of a process share its virtual address space and system resources. In addition, each thread maintains exception handlers, a scheduling priority, thread local storage, a unique thread identifier, and a set of structures the system will use to save the thread context until it is scheduled. The thread context includes the thread’s set of machine registers, the kernel stack, a thread environment block, and a user stack in the address space of the thread’s process. Threads can also have their own security context, which can be used for impersonating clients.

Windows supports preemptive multitasking, which creates the effect of simultaneous execution of multiple threads from multiple processes. On a multiprocessor computer, the system can simultaneously execute as many threads as there are processors on the computer.
CreateProcess() : Create a Process with the attributes set. GetPriorityClass() and SetPriorityClass() can be used to process Priority of the created Process. The Priority class can be one of the following:

IDLE_PRIORITY_CLASS
BELOW_NORMAL_PRIORITY_CLASS
NORMAL_PRIORITY_CLASS (default)
ABOVE_NORMAL_PRIORITY_CLASS
HIGH_PRIORITY_CLASS
REALTIME_PRIORITY_CLASS
The following are priority levels within each priority class. GetThreadPriority() and SetThreadPriority() are related APIs. The levels are THREAD_PRIORITY_IDLE / LOWEST / BELOW_NORMAL / NORMAL (default) / ABOVE_NORMAL, HIGHEST and TIME_CRITICAL.

By default child process By default, a child process inherits a copy of the environment block of the parent process.

CreateThread() : Create a Thread with the attributes set. Priority levels can be set as discussed above. By default threads are created in executable state. If we use CREATE_SUSPENDED flag while creating a thread, the thread will not be executed immediately. We need to issue ResumeThread() to bring it back to executable state. ExitThread() will terminate a thread in order. GetExitCodeThread() returns the termination status of a thread.

The SwitchToThread() function causes the calling thread to yield execution to another thread that is ready to run on the current processor. The operating system selects the thread to yield to. This can be implemented with Sleep() also. Sleep(0) causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution.

TerminateThread() can result in the following problems (ExitThread() is preferred):
If the target thread owns a critical section, the critical section will not be released.
If the target thread is allocating memory from the heap, the heap lock will not be released.
If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread’s process could be inconsistent.
If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.

Thread Local Storage (TLS): Thread local storage (TLS) enables multiple threads of the same process to use an index allocated by the TlsAlloc function to store and retrieve a value that is local to the thread. In this example, an index is allocated when the process starts. When each thread starts, it allocates a block of dynamic memory and stores a pointer to this memory in the TLS slot using the TlsSetValue function. The CommonFunc function uses the TlsGetValue function to access the data associated with the index that is local to the calling thread. Before each thread terminates, it releases its dynamic memory. Before the process terminates, it calls TlsFree to release the index. This is quite interesting concept worth to describe more here. Here’s how the APIs work:

First define a structure that contains all the data that needs to be unique among the threads. For example,

typedef struct
{
int a ;
int b ;
}
DATA, * PDATA ;

The primary thread calls TlsAlloc to obtain an index value:

dwTlsIndex = TlsAlloc () ;

This index value can be stored in a global variable or passed to the Thread function in the argument structure.

The Thread function begins by allocating memory for the data structure and calling TlsSetValue using the index obtained above:

TlsSetValue (dwTlsIndex, GlobalAlloc (GPTR, sizeof (DATA)) ;

This associates a pointer with a particular thread and a particular thread index. Now any function that needs to use this pointer, including the original Thread function itself, can include code like so:

PDATA pdata ;

pdata = (PDATA) TlsGetValue (dwTlsIndex) ;

Now it can set or use pdata->a and pdata->b. Before the Thread function terminates, it frees the allocated memory:

GlobalFree (TlsGetValue (dwTlsIndex)) ;

When all the threads using this data have terminated, the primary thread frees the index:

TlsFree (dwTlsIndex) ;

There are two types of dialog boxes:
1. Modal dialog
2. Modeless dialog

When a program displays a modal dialog box, the user cannot switch between the dialog box and another window in your program. The user must explicitly end the dialog box. The user can, however, switch to another program while the dialog box is still displayed. Some dialog boxes (called “system modal”) do not allow even this. System modal dialog boxes must be ended before the user can do anything else in Windows.

Modeless dialog boxes allow the user to switch between the dialog box and the window that created it as well as between the dialog box and other programs.

Some of the common dialog boxes available in the Windows for uniform user interface across applications. They are listed below:
GetOpenFileName() – Displays a Open File dialog box
GetSaveFileName() – Displays a Save File dialog box
ChooseFont() – Displays a Font selection dialog box
FindText() and ReplaceText() – Displays a string finding and replacing modeless dialog box

SetTimer(): Sets the time out interval between 1 msec to 50 days (approx.). For every time out, window proc receives a WM_TIMER message.
KillTimer(): Stops the timer message. It purges any pending WM_TIMER message in queue.
The Timer messages are not asynchronous. The WM_TIMER messages are queued in normal message queue. The window proc may miss a WM_TIMER message when it is busy. The time set though SetTimer() is not accurate since the resolution of time depends on hardware resolution.

There are two major methods to implement a timer.
1. SetTimer() to set the timer interval and processing the WM_TIMER in window proc.
2. SetTimer() to set the timer interval and attach a callback function to this timer. Now the WM_TIMER messages will be redirected to this callback function instead of window proc.