\documentclass{ictlab}

\RCS $Revision: 1.1 $

\usepackage{alltt,key,color,answer2,float}
\usepackage[nolineno,noindent]{lgrind}
%\usepackage[leftnum,lineno5,noindent]{lgrind}
\ifx\pdftexversion\undefined \else
  \usepackage[pdfpagemode=None,pdfauthor={Nick Urbanik}]{hyperref}
\fi

\renewcommand*{\subject}{Operating Systems and Systems Integration}

\newcommand*{\labTitle}{Processes and Threads in Windows}


\definecolor{light-blue}{rgb}{0.4,0.4,1}
\newcommand*{\gl}[1]{\textcolor{light-blue}{#1}} % good link
\newcommand*{\ex}[1]{\textcolor{green}{#1}} % executable file
\newcommand*{\bl}[1]{\colorbox{red}{\textcolor{white}{\textbf{#1}}}} % bad link

\renewcommand{\floatpagefraction}{0.75} % default is .5, to increase
% density.
\renewcommand*{\bottomfraction}{0.6} % default is 0.3
\renewcommand*{\topfraction}{0.85} % default is 0.7
\renewcommand*{\textfraction}{0.1} % default is 0.2

\setlength{\extrarowheight}{1pt}
\floatstyle{ruled}
\floatname{program}{Program}
\newfloat{program}{tbh}{lop}
\begin{document}
\section{Generic Procedure for Creating Win32 Console Applications}
\label{sec:generic-instructions}


\begin{enumerate}
\item In Windows, open the Visual \Cpp \IDE (Start $\to$ Programs
  $\to$ Microsoft Visual Studio 6.0 $\to$ Microsoft Visual \Cpp 6.0)

\item Open a new  Win32 \emph{Console} Application project (File $\to$
  New $\to$ Project $\to$ Win32 Console Application).  Note that you
  need to do this \emph{for each of the three applications}.

\item Specify a project name (i.e., ``print'', ``callprint'' or ``threads'')

\item Click on the ``Empty Project'' radio button, click the various
  confirmation buttons (\key{Finish}, \key{OK}, etc., etc.,\ldots)
\item Select Project $\to$ Add to Project $\to$ Files
\item Enter the name of your source file
\item Compile and link your program with Build $\to$ Build
  \meta{project name}.exe
    
\item Execute it with Build $\to$ Execute \meta{project name}.exe
      
\item Note that for \texttt{print.c}, you should create a project name
  that matches the directory in the program file
  \texttt{win-call-print.c}, so that \texttt{win-call-print.c} can
  find \texttt{print.exe}.
\item Note that the ``normal'' place to put your source code for each
  project is \texttt{C:\bs{}Program Files\bs{}Microsoft Visual
    Studio\bs{}MyProjects\bs\meta{project name}}
\item The software will put the executable program in \texttt{C:\bs{}Program Files\bs{}Microsoft Visual
    Studio\bs{}MyProjects\bs\meta{project name}\bs{}Debug}
\item Note that the \IDE executes the program in the directory
  \emph{above} the \texttt{Debug} directory, i.e., above where it puts
  the executable.  This is important when executing
  program~\vref{prg:win-call-print}.
\end{enumerate}


\section{Procedure}
\label{sec:procedure}

\begin{program}
     %\smallskip%
\vspace*{-2ex}
%[
#include <stdio.h>
#include <stdlib.h>

int main( int argc, char *argv[] )
{
        // argv[0] is the program name
        int num = atoi( argv[1] );
        int loops = atoi( argv[2] );
        int i;
        for ( i = 0; i < loops; ++i )
                printf( "%d ", num );
}
%]
\caption{The program \texttt{print.c}.  This is identical to the
  program \texttt{print.c} that you experimented with in your last
  lab.}
\label{prg:print}
\end{program}

\begin{program}
     %\smallskip%
\vspace*{-2ex}
%[
#include <windows.h>
#include <stdio.h>

void main() {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        memset( &si, 0, sizeof( si ) );
        si.cb = sizeof( si );
        if ( ! CreateProcess( NULL,
                              "..\\print\\Debug\\print.exe 5 100",
                              NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ) ) {
                fprintf( stderr, "CreateProcess failed with %d\n", GetLastError() );
                exit( 1 );
        }
        WaitForSingleObject( pi.hProcess, INFINITE );
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
}
%]
\caption{The program \texttt{win-call-print.c}.  This is like the
  program \texttt{call-print.c} that you experimented with in
  your last lab.}
\label{prg:win-call-print}
\end{program}

\begin{program}
    %\smallskip%
%\begin{verbatim}
\vspace*{-2ex}
%[
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_THREADS 5

DWORD WINAPI print_hello( void *threadid )
{
        printf( "\n%d: Hello World!\n", threadid );
        return 0;
}

int main()
{
        static DWORD threads[ NUM_THREADS ];
        static HANDLE handles[ NUM_THREADS ];
        unsigned int t;
        for ( t = 0; t < NUM_THREADS; ++t ) {
                printf( "Creating thread %d\n", t );
                handles[ t ] = CreateThread( NULL, 0,
                      ( LPTHREAD_START_ROUTINE ) print_hello,
                      ( LPVOID ) t, 0, (LPDWORD) &threads[ t ] );
                if ( ! handles[ t ] ) {
                        printf( "Error: failed to create process %d\n", t );
                        exit( 1 );
                }
        }
        WaitForMultipleObjects( NUM_THREADS, handles, 1, INFINITE );
        return 0;
}
%]
\vspace*{-3ex}
%\end{verbatim}
\caption{A simple program \texttt{win-hello.c} that works like the
  program \texttt{hello.c} given in the lecture.  We assume that it
  executes in a directory at the same level as the source code, not in
  the \texttt{Debug} directory.}
\label{prg:win-hello}
\end{program}

\begin{enumerate}
\item Download the source code for each of these programs from the
  subject web site.
\item For each of program~\ref{prg:print}, \ref{prg:win-call-print}
  and \vref{prg:win-hello}, compile and run them, using the generic
  instructions given in section~\vref{sec:generic-instructions}.
\item Modify program~\ref{prg:win-call-print} so that it creates two
  processes, both running the program \texttt{print.c}.
\item See if you can modify a copy of program \ref{prg:win-call-print}
  so that you can start \texttt{notepad.exe}.
\item Modify \texttt{win-hello.c}, increasing the number of threads
  until you find the maximum number of threads that your system can
  support.
\item The first student who could give me the way to
  compile any of these programs on the command line in Windows 2000,
  including all the command line parameters to the compiler, was
  awarded a prize of \$50 HK\e.  The name of the winner is Wendell
  Lam: his work is shown on the subject web page.
%%   \begin{explanation}
%%     Note: it is ``cheating'' to copy system header files or system
%%     libraries to different locations; to do this, you will need to add
%%     two directories to the \texttt{PATH}, and add options to \texttt{cl} that
%%     include \texttt{/I}\meta{include path} and
%%     \texttt{/L}\meta{library path}, among other options.  One of the
%%     directories to add to the \texttt{PATH} is \texttt{C:\bs{}Program Files\bs{}Microsoft Visual
%%     Studio\bs{}VC98\bs{}Bin}\e.  You may find
%%     it easier to use the option Project $\to$ Export Makefile (or mabe
%%     not \texttt{:-)}.  You may find it easier to use Visual Studio
%%     .NET (or maybe not \texttt{:-)}.
%%   \end{explanation}
\end{enumerate}
\end{document}
