A Developer's Diary

Mar 20, 2011

POSIX Threads - A simple Example

In our earlier post, we have written multithreaded program using win32 apis. This post deals with writing the multithreaded programs using POSIX thread apis. The important POSIX thread apis are namely pthread_create, pthread_exit and pthread_join

Create a thread

int pthread_create
(
    pthread_t *thread,
    const pthread_attr_t *attr,
    void *( *start_routine)(void *), 
    void *arg
);

Terminate a thread
void pthread_exit (void *retval);

Wait on a thread
int pthread_join (pthread_t thread, void **status);

The Complete Example
#include <pthread.h>
#include <iostream>

//File: SimpleThreadExample.cpp

#define MAX_THREADS 3
using namespace std;

void* func(void *args)
{
    int tp = *(int *)args * 10;
    while(tp--)
    {
        cout << *(int *) args;
        fflush(stdout);
        sleep(1);
    }

    cout << endl;
    pthread_exit((void *)10);
    return (void *)10;
}

int main(void)
{
    pthread_t tid[MAX_THREADS] = {0};
    int param[MAX_THREADS] = { 1, 2, 3 };

    int rc;
    for(int i = 0; i < MAX_THREADS; ++i)
    {
        rc = pthread_create(&tid[i], NULL, func, ¶m[i]);
        if(0 != rc)
        {
            cout << "ERROR: Thread Creation failed" << endl;
        }
        cout << "Thread[" << tid[i] << "] Created" << endl;
    }

    void *status[3];
    for(int i = 0; i < MAX_THREADS; ++i)
    {
        rc = pthread_join(tid[i], &status[i]);
    }

    for(int i = 0; i < MAX_THREADS; ++i)
    {
        cout << "Thread[" << tid[i] << "] returned with exit code=" << (long) status[i] << endl;
    }

    cout << "Main thread terminating" << endl;
    return 0;
}
The makefile for the project
#-----------------------------------------------------------------------
#                   A simple thread example
#-----------------------------------------------------------------------
PROJECT := SimpleThreadExample

SRCEXT := .h .cpp
OBJEXT := .o
EXEEXT := .exe

#compilers
CC := gcc
CXX := g++

#flags
CFLAGS := -o
CXXFLAGS := -o
LDFLAGS := -lpthread -o

#disable implicit suffix rules
.SUFFIXES:
.SUFFIXES: $(SRCEXT) $(OBJEXT) $(EXEEXT)

SRC := \
    SimpleThreadExample.cpp

OBJ := \
    $(SRC:.cpp=.o)

EXE := \
    $(PROJECT)$(EXEEXT)

#define dummy targets
.PHONY: all clean compile link

all : compile link

clean :
    @echo

    @echo "Cleaning Temporary Files..."
    $(RM) $(OBJ) $(EXE)

compile : $(OBJ)

link : $(EXE)

$(OBJ) :
    @echo
    @echo "Compiling Source Files..."
    $(CXX) $(CXXFLAGS) $(OBJ) $(SRC)

$(EXE) :
    @echo
    @echo "Linking..."
    $(LD) $(OBJ) $(LDFLAGS) $(EXE)

run :
    @echo
    @$(EXE)
Building the project. (The output is from Cygwin Environment. You may need to modify the makefile to compile it on a linux environment)
$ gmake clean all

Cleaning Temporary Files...
rm -f SimpleThreadExample.o SimpleThreadExample.exe

Compiling Source Files...
g++ -o SimpleThreadExample.o SimpleThreadExample.cpp

Linking...
ld SimpleThreadExample.o -lpthread -o SimpleThreadExample.exe
Output:

Read more ...

Command prompt and setting environment variable properties

Working on multiple projects which require different compiler versions can be a daunting task especially if you are using windows command prompt cmd.exe to build the projects. You need to export the compiler specific environment variables and set the PATH variable appropriately each time you launch the command window to build each project. Here is a small tip that can help save some time

Tip
Write a batch file which will set the necessary environment variables and the path variable before launching the command window
A simple batch script which sets JAVA_HOME to jdk1.6.0_21 and launches the command prompt window
set JAVA_HOME=
set JAVA_HOME=c:\Program Files\Java\jdk1.6.0_21

set PATH=%JAVA_HOME%\bin;%PATH%
start cmd /k

On executing the batch file, command prompt window is launched with the JAVA_HOME environment variable set to the desired version (jdk1.6.0_21)

Read more ...

Mar 15, 2011

Customize Cygwin/Linux command prompt

From the bash manual, the following environment variables control the display of prompt in a Cygwin or Linux terminal namely PS1, PS2, PS3, PS4.
Note: For referring the bash manual type info bash

Key Points
1. PS1 : The value of this parameter is expanded and used as the primary prompt string. It's default value is '\s-\v\$ '
2. PS2 : The value of this parameter is expanded as with PS1 and used as the secondary prompt string. The default value is >
3. PS3 : The value of this variable is used as the prompt for select command. If this variable is not set, select command prompts with #?
4. PS4 : The prompt is used when you have tracing enabled for debugging the bash scripts. The PS4 value is printed each time the command is echoed on the screen. The default value is +

a) PS1 demo
1. Identify the current prompt setting in your Cygwin/Linux terminal by typing echo $PS1
2. Make the modifications to PS1 and export the new PS1 variable. Your prompt should change immediately


b) PS2 demo
When executing interactively, bash displays the primary prompt PS1 when it is ready to read a command, and the secondary prompt PS2 when
it needs more input to complete a command.


c) PS3 demo
This prompts user to provide an input.
#!/bin/bash

LINUX=linux
WIN32=win32
HPUX=hpux
SUNOS=sunos
AIX=aix
QUIT=quit

OPTIONS="\
    $LINUX \
    $WIN32 \
    $HPUX \
    $SUNOS \
    $AIX \
    $QUIT"

select option in $OPTIONS;
do
  echo "${option}"  
  if [ "${option}" = "quit" ]; then
    exit
  fi
done
Output:


d) PS4 demo
Enable tracing by typing the following command set -x


Bash allows these prompt strings to be customized by inserting a number of backslash-escaped special characters that are decoded as follows:

\a     an ASCII bell character (07)
\d     the date in "Weekday Month Date" format (e.g., "Tue May 26")
\D{format}
    the format is passed to strftime(3) and the result is inserted into the prompt  string;  an  empty  format  results  in  a locale-specific time representation.  The braces are required
\e     an ASCII escape character (033)
\h     the hostname up to the first `.'
\H     the hostname
\j     the number of jobs currently managed by the shell
\l     the basename of the shell's terminal device name
\n     newline
\r     carriage return
\s     the name of the shell, the basename of $0 (the portion following the final slash)
\t     the current time in 24-hour HH:MM:SS format
\T     the current time in 12-hour HH:MM:SS format
\@     the current time in 12-hour am/pm format
\A     the current time in 24-hour HH:MM format
\u     the username of the current user
\v     the version of bash (e.g., 2.00)
\V     the release of bash, version + patch level (e.g., 2.00.0)
\w     the current working directory, with $HOME abbreviated with a tilde
\W     the basename of the current working directory, with $HOME abbreviated with a tilde
\!     the history number of this command
\#     the command number of this command
\$     if the effective UID is 0, a #, otherwise a $
\nnn   the character corresponding to the octal number nnn
\\     a backslash
\[     begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
\]     end a sequence of non-printing characters

References:
1. bash manual

Read more ...

Mar 14, 2011

Anatomy of a process stack

A process is a program in execution. A process may have one or more threads executing different sections of the program. Every thread in the process maintains it's own separate stack, registers and program counter.

Key Points
A stack is a collection of stack frames where each stack frame refers to a function call

Stack Frame
When a function call is made, a block of memory is set aside which stores information about the following:
1. Arguments passed to the function
2. Return address of the caller function
3. Local variables used by the function and
4. Other temporary variables needed by the compiler
This block of memory is called a stack frame. When the function returns, the stack frame is turned invalid and reclaimed.

Registers used in a Stack Frame
1. ESP (Extended Stack Pointer) : 32 bit register that points to the top of the stack. All the addresses lower than the stack pointer are considered unused or garbage and all the higher addresses are considered valid
2. EBP (Extended Base Pointer) : Also known as Frame Pointer, this 32 bit register is used to reference all the function parameters and the local variables in the current stack frame

ebp + 4 + 4 * n points to the address at which the nth argument of the function is stored
ebp + 4 points to the address at which return address of the caller function is stored
ebp is the frame pointer of the callee function
ebp - 4n refers to the address where the nth local variable is stored

3. EIP (Extended Instruction Pointer) : This register holds the address of the next instruction to be executed. It is saved on to the stack as part of the CALL instruction. Also known as Program Counter
4. EAX, EBX, ECX, EDX : General purpose registers for storing intermediate results

Following figure shows how stack frames are laid out in memory during execution


Read more ...

Mar 6, 2011

A simple Makefile example

Continuing our series on makefile tutorial, below is a simple makefile which compiles the Hello World program Main.cpp into an object file Main.o and generates the binary executable Main.exe

#-----------------------------------------------------------------------
#                   A Simple Makefile example
#-----------------------------------------------------------------------
PROJECT := Main

SRCEXT := .h .cpp
OBJEXT := .o
EXEEXT := .exe

#compilers
CC := gcc
CXX := g++


#flags
CFLAGS := -o
CXXFLAGS := -o
LDFLAGS := -o


#disable implicit suffix rules
.SUFFIXES:
.SUFFIXES: $(SRCEXT) $(OBJEXT) $(EXEEXT)

SRC := \
    Main.cpp

OBJ := \
    $(SRC:.cpp=.o)

EXE := \
    $(PROJECT)$(EXEEXT)

#define dummy targets
.PHONY: all clean compile link

all : compile link
    
clean :
    @echo
    @echo "Cleaning Temporary Files..."
    $(RM) $(OBJ) $(EXE)

compile : $(OBJ)

link : $(EXE)

$(OBJ) :
    @echo
    @echo "Compiling Source Files..."
    $(CXX) $(CXXFLAGS) $(OBJ) $(SRC)

$(EXE) :
    @echo
    @echo "Linking..."
    $(LD) $(OBJ) $(LDFLAGS) $(EXE)

run :
    @echo
    @$(EXE)

The Hello World program
#include <iostream>

int main()
{
    printf("Hello World");
    return 0;
}

Output

Read more ...