fork() and exec()

advertisement

CS 201

Computer Systems Programming

Chapter 8

Unix fork(), execve(), getpid()

Herbert G. Mayer, PSU

Status 6/28/2015

1

Syllabus

 Process, Thread, Hyperthread

 Unix Process

 Interrupt

 Command ps

 Background Process

 Command fork()

 fork() Sample

 Command execve()

 execve() Sample

 References

2

Process – SW View

 [Bryant, 16] “A process is the operating system ’s abstraction of a running program.

 [Silberschatz, 10] “A process can be thought of as a program in execution …”

 [Silberschatz, 90] “Informally, a process is a program in execution. … A process is more than the program code. It also includes the current activity, as represented by the value of the program counter and the contents of the processor ’s registers.”

 [Tanenbaum, 72] “A process is just an executing program, including the current values of the program counter, registers, and variables.

3

Thread – SW View

 [Bryant, 947] “A thread is a logical flow that runs in the context of a process. Each thread has its own thread context, including a unique integer thread ID, stack, stack pointer, program counter, general-purpose registers, and condition codes. All threads running in a process share the entire virtual address space of that process.

 [Silberschatz, 103]

“A thread , sometimes called a lightweight process , is a basic unit of CPU utilization, and consists of a program counter, a register set, and a stack space. It shares with peer threads its code section, data section, and operating-system resources such as open files and signals.

 [Tanenbaum, 81] “A thread has a program counter that keeps track of which instruction to execute next. It has registers, which hold its current working variables. It has a stack, which contains the execution history, with one frame for each procedure called, but not yet returned from. ... A thread must execute in some process ”

4

Thread Creation

 Who makes threads? You, the programmer, or the OS, following your implicit or explicit instructions

 Programmer understands which portions of C program are dependent-, and which ones are independent of other parts of the same program –which, when executed, is a process

 MS and Intel compiler provide tools to support this analysis

 Some C and C++ compilers provide directives

 Directives can be hidden as comments, to be transparent to other compilers

 See lit ref [9] for Intel ’s Parallel Studio, helping programmer eliminated threading errors in C and C++ programs

 Or see Intel

’s [10] [12] to help programmer “to thread” SW

 Or Microsoft Multi-Threading support for existing C and C++ source code [11]

5

Hyperthread – HW View

 A processor may be single-core (UP), or have multiple cores, the latter meaning: all processor resources are replicated; e.g. Intel Core 2 Duo

 Or a processor may be single-core, hyperthreaded, e.g.

Intel Pentium 4e. Hyperthreaded means that only CPU registers and APIC are replicated , but not ALU units, such as integer unit, floating-point unit, branch unit, caches, etc.

 Or a processor may be multi-core, hyperthreaded , in which case each of several real cores has a hyperthread twin (or more), sharing the real core ’s ALU with all hyperthreads, but each hyperthread has own register + APIC; e.g. Intel Core i7

 Hyperthreading is an old idea, proposed decades ago by

Digital Equipment Corp. (DEC), implemented first in silicon by Intel in 2002 on Xeon ® server + Pentium ® 4 desktop CPUs

 Hyperthread is an overloaded term, referring to the reduced

Silicon core, as well as the active SW thread executing on it

 Should be named: Hypothread  since it is a threadsub set, but Hyperthread IS THE accepted technical term

6

Hyperthread – Per Intel Website

Ability of processor to run concurrent threads quickly

Some microprocessor hardware replication that creates the illusion to SW of Dual Processor (DP)

Yet such HW with some resource replication is NOT a true dual-core silicon implementation

The execution unit is still shared between multiple threads

Effect of Hyperthreading on Xeon

®

Processor:

Average CPU utilization increases to ~50%, down from ~35% for a typical uni-processor

Up to ~30% performance gain for some applications with the same processor frequency

Hyperthreading Technology Results:

1. More performance with enabled applications

2. Better responsiveness with existing applications

7

Hyperthread – Per Intel Website

Almost two Logical Processors

Architecture state (registers) and

APIC* replicated

On-Die

Caches

Shares execution units, caches, branch prediction, control logic and buses

Architecture State

Adv. Programmable

Interrupt Control

*APIC: Advanced Programmable

Interrupt Controller. Handles interrupts sent to a specified logical processor

Processor

Execution

Resource

Architecture State

Adv. Programmable

Interrupt Control

System Bus

8

Hyperthread

 Hyperthreaded core replicates in silicon all CPU resources essential to switching fast from one thread to another

 Those replicated resources are registers and the APIC. ALU units are not replicated on a hyperthread core

 SW hyperthreads are also threads, but execute concurrently on HW hyperthread cores; switch is efficient due to available registers; ALU-sharing is still necessary: Only a single ALU!

 This costs ~5% more HW (silicon) than a single core, but can gain up to 30% performance improvement; great ROI!

9

Delta Between Process & Thread

 Process is an OS-centric view of a running program. Due to the meaning of “running”, all machine resources are necessary to execute a process

 A thread is a subset of a process, not necessarily a proper subset

 One purpose for threading a process is to allow continued execution of that one process, even when some part of it has to wait; e.g. one thread waits for an IO operation to finish, but another thread can continue, being independent of the IO result

 Purpose for having threads execute a process is to speed up overall execution. Possible, if multiple threads of the same process are sufficiently data-independent to progress concurrently ; never simultaneously on a single core!

 A threaded process can –sometimes– execute faster on a single core unit due to reduced waits

10

Delta Between Thread & Hyperthread

 A hyperthreaded core almost creates illusion of a multicore CPU, though there is only 1 complete CPU

 Enables concurrent execution on a uni-processor, when one process thread stalls, but another is ready; switch to the other thread is cheap, since the other register set already has proper state –except the first time around

 But hyperthreading (or threading) per se never allows parallel execution ; only a multi-core architecture does

 A System Programmer must know: On MP OS not yet tuned for hyperthreading: best disable hyperthread

 scheduling; else under the right (i.e.

wrong ) circumstances performance degradation can result:

This is the case, when the “next core to be scheduled” happens to be regularly the hyperthreaded subset-core, while leaving other real cores idle, though a real core could work instead of the hyperthread

11

Unix Process

 Under Unix, a process is an instance of running a program. If you execute the ancient editor ed and your colleague does too, then there are 2 --very similar – different processes running

 All user a.out

programs and all Unix commands, when running, become processes; commands ll and g++ my_prog.cpp

create 2 different processes

 Processes are visible via ps command, and even that command is a process in its own right

 Issue the command ps , for process status, and you see your current processes, plus the ps processes

 Issue ps –a , and you see a very detailed list, including sleeping processes

 Issue the command man ps for your education

12

Unix Process

 When a command is issued, Unix starts new process, suspends the current OS process, generally the C-shell , until the new child process completes

 Exception: background processes with &

 Unix identifies every process by a Process

Identification Number (PID) assigned at initiation

 See getpid() function calls below

 Unix is a timesharing system, which grants each process time-slices

 Allocation of time-slices has to be fair , so that one long process cannot make other, shorter ones, wait for extended periods ( no starvation!

)

 Also, time-slicing has to be efficient, lest too much processing time migrates into overhead, like a typical state government 

13

Windows Process

 Under MS Windows, the process and thread concepts are almost identical to the ones under

Unix; see [14]

 But added terms under Windows include:

 Job object : group of processes, managed as one unit

 Thread pool : a collection of threads

 Fiber : execution unit to be scheduled manually by a running application –scheduled explicitly by running SW

 UMS : User Mode Scheduling. Thread scheduling managed by application

 In CS 201 we focus on Unix process model and Unix terminology

14

Interrupt

 Def: Program interrupt is a transparent, non-scheduled change in execution flow with specific cause outside the program, treated by an interrupt handler, ending up at the original program again

 Is unpredictable : Programmer does not know that, when, why, where interrupt happens

 Is unexpected : Programmer does not know when interrupt happens, or whether it happens

 Cannot be pinpointed (i.e. coded) by location: Programmer does not know where such an interrupt happens

 Cause is known when interrupt happens, passed to interrupt handler by HW, yet the SW program (i.e. process) does not know a-priori that it will happen; can be some external event like power-outage, or time-slice consumption (timer interrupt), numeric error

15

Interrupt Requirements

 After handling, execution continues at the place in the code right after the interrupt location

 Challenge: if interrupt happens during execution of some very long instruction, say move of a large portion of memory by a byte-move instruction!

 Challenge caused by general need of handling interrupt swiftly, more swiftly than the time needed for some long machine instructions!

 Interrupt handled in a way that the program never knows it was interrupted: transparent

16

Interrupt Requirements

 Interrupt has to be fast, after all, the cause ,may be some catastrophic event; e.g. power outrage!

 It will not be known that an interrupt has happened, except that execution ends up slower than expected; slower than if the interrupt had not happened

 Summary: the SW does not see that, why, when, how often an interrupt has happed; not a programmed event

 Note: x86 INT instruction is not an interrupt! Though it is named a “ software interrupt ” instruction; is it totally predictable, locatable!

17

Process-Related Unix Commands

18

Command ps

 Command ps without any option shows all processes with the same controlling terminal and same user id as the invoker of the ps command

 Complex command with numerous options!

 PID identifies the process, TT the controlling terminal, S the state, and TIME the CPU time consumed for that process

[process] ps

PID TT S TIME COMMAND

8687 pts/33 O 0:00 ps -- O running

19212 pts/33 S 0:00 –csh -- S sleeping

19

Command ps

The command ps –a prints information about all active processes; can result in a long list, e.g.: ps –a | more

PID TT S TIME COMMAND

12229 Z 0:00

16386 Z 0:00

523 console S 0:00 /usr/lib/saf/ttymon -g -d

/dev/console -l console -m ld

19668 pts/1 S 0:00 -tcsh

19691 pts/1 S 0:00 tcsh

19705 pts/1 S 0:07 pine

22394 pts/2 S 0:00 -bash

22412 pts/2 S 0:06 screen

. . .

20

Command kill

 To abort, AKA kill, any process in Unix whose PID is known, issue the command kill with argument

-9, e.g., the -9 meaning “death”  , see below: kill –9 19186

 Which in this particular case was the instructor ’s remote shell log-in to PSU ’s computer, and as a result he had to log in again  from home

 Process status Z means “zombie”, typically a child process that has terminated, but the parent process still needs to know its termination status

 Killing a Z process has no effect; good so, else parent would never know status of terminated child; see [8] for detail

21

Background Process &

 Some processes may run forever

 Others in your environment may run for a limited time but for quite long

 What if you do not wish to wait for long process completion before continuing with other work?

 Possible in Unix with background processes initiated by the & command modifier, such as: run_big &

 Which executes the long running program run_big in the background; making progress whenever CPU cycles are available

 Your real interactive work may proceed in parallel

–on a UP implied here: but concurrently!

22

Background Process &

 What happens if this program generates output, such as messages to stderr ?

 These would be interspersed with other output generated concurrently, causing confusion!

 To avoid mixing of messages, stderr can be redirected to a separate file using >& g++ big_program.cpp >& my_errors &

 . . . does accomplish that

 It redirects via >& all output from stderr to a new file, named: my_errors

 . . . and then runs in the background, caused by &

 So neither the messages nor the (long running) background process hold you up

23

Command

fork()

 Unix fork() creates a new process by cloning the current process issuing the fork() command

 Returns 0 to child, and returns child ’s PID to parent

 Peculiar about a child processes: it shares all attributes with the forking parent process, except the process id, AKA PID , the parent PID, AKA PPID , locks and a few attributes preventing infinite spawning!

 To compile the fork() command in your C program,

#include <unistd.h>

 Code and data space of child and parent process are shared for reading only ; when the child needs to write (stack, heap) it receives its own copy with the new modifications ; AKA copy-on-write

 Spawning a new process via fork() creates a second exit() action; i.e. both parent and child need to exit eventually

24

Sample getpid()

 Program getpid.cpp

below is trivial, it does:

Inquires about its own main() program process id

Runs in the background, via &

So user has a chance to monitor the process from console

 And get that processes id number via Unix ps command

 And by the time getpid exits, it also prints its pid number

 Just to demonstrate the getpid() function

25

getpid.cpp

Source Program

// program getpid.cpp

#include <iostream.h>

//#include <unistd.h> no fork() here

// I wish to get the PID of this main() program!

int main()

{ // main int pid = getpid(); int k, i;

// spend execution time, for chance to issue ps command for ( i = 0; i < 1000000; i++ ) { for ( int j = 0; j < 100; j++ ) { k = j;

} //end for

} //end for

// OK time wasted

// fake assignment to i: to fool optimizer!

i = k; printf( "My process id = %d\n", pid );

} //end main

26

getpid()

Result and Output

[process] a.out &

[1] 24366

[process] ps

PID TT S TIME COMMAND

23847 pts/49 S 0:00 -csh

24366 pts/49 O 0:00 a.out

24375 pts/49 O 0:00 ps

[process] My process id = 24366

^C

[1] Done a.out

27

Fork() Samples

 Now we run several programs that demonstrate the fork() Linux or Unix function

 Reminder of fork()

 Creates child process identical to parent process

 fork() returns pid of child to parent != 0

 But returns 0 to child process

If child process wishes to know its own pid, it must call function getpid()

If child wishes to know parent ’s process id, it must call function getppid()

 Child process starts executing after the fork() command, NOT repeating the fork() command

28

fork()

Sample1 in C

#include <unistd.h>

#define DEAD -1

// there are no shared global data, not shared data on heap!

void fork_sample1( void )

{ // fork_sample1 int local = 1; // just some data to track: which process?

pid_t pid = fork(); // from now on: 2 processes switch ( pid ) { case 0:

// this is thread through child process printf( “++local value in child = %d\n", ++local ); break; case DEAD:

// this is en error process, dead, zombie?

printf( “<><> local in dead process = %d\n", local ); default: break;

// clearly thread through parent process printf( ”parent pid = %d, --local = %d\n", pid, --local );

} //end switch

// strange? switch statement has multiple clauses executed! By design!

printf( "Ending process %d\n", pid );

} //end fork_sample1

29

fork()

Sample1 Output

[process] a.out

parent pid = 22853, --local = 0

Ending process 22853

++local value in child = 2

Ending process 0

[process]

• Note that local is 2, and not 1 in child process, and it happens to be executed after parent; arbitrarily!

• So you infer: child has its own copy . It does not share local with parent; else it would be 1, since parent decreased local to 0

• Students: Are other outputs possible? How many?

30

fork()

Sample2 in C++

#define DEAD -1

#include <unistd>

// define DEAD as before

// make fork() available

// Bryant & O'Halleron's "Computer Systems", chapter 8 void fork_sample2()

{ // fork_sample2 switch ( fork() ) { case 0:

// child process cout << 'C'; break; case DEAD: cout << " <><> DEAD process?"; break; default:

// parent process cout << 'P';

} //end switch

// in all cases, indicate end by emitting 'E' cout << 'E'; // note: no endl

} //end fork_sample2

31

fork()

Sample2 Output

[process] a.out

PECE[process]  note no carriage return: no endl!

• Would CEPE be possible?

• Would EECP be possible?

• Would CPEE be possible?

• Would PECE be possible?

• Would ECPE be possible?

32

fork()

Sample2 Output ’

 Challenge: How to modify fork_sample2() into for_sample2() ’ such that:

 The end message for the parent process will be pe

 And for the child it will be ce ?

 The run the modified program fork_sample2() ’

[process] a.out

CPpece

CPcepe

PpeCce

CcePpe or: or: or:

… just few more outputs possible!

33

fork()

Sample2 ’ in C++

void fork_sample2()’

{ // fork_sample2’ pid_t pid; switch ( pid = fork() ) { case 0:

// child process cout << 'C'; break; case DEAD: cout << " <><> DEAD process?"; break; default:

// parent process cout << 'P';

} //end switch

// ok to omit break

// indicate end via string "pe" or "ce" if ( pid ) { cout << "pe";

}else{ cout << "ce";

} //end if

} //end fork_sample2’

// note: no endl

34

// doesn’t catch DEAD!

fork()

Sample3 in C++

#include <iostream.h>

#include <unistd.h> int main( void )

{ // main int number = 0; // Note number on stack if ( 0 == fork() ) { cout << "PID: " << getpid()

<< " child process number = "

<< ++number << endl;

} //end if cout << "PID: " << getpid()

<< " exiting with number = "

<< --number << endl; return 0;

} //end main

// how many output lines, students?

// Which will be the different values for "number"?

35

fork()

Sample3 Output

[process] a.out

PID: 5587 exiting with number = -1

PID: 5588 child process number = 1

PID: 5588 exiting with number = 0

36

fork()

Sample4 –Getting Interesting

#include <iostream.h>

#include <unistd.h> int main()

{ // main int number = 100; // Note number on stack if ( 0 == fork() ) { // first child creation cout << "PID: " << getpid()

<< " 1st child, number = "

<< ++number << endl;

} //end if if ( 0 == fork() ) { // second child creation cout << "PID: " << getpid()

<< " 2nd child. PPID: "

<< getppid() << ". ++number = "

<< ++number << endl;

} //end if cout << "PID: " << getpid()

<< " exiting with number = "

<< --number << endl; return 0;

} //end main

37

fork()

Sample4 Output

[process] a.out

PID: 4432 exiting with number = 99

PID: 4433 1st child, number = 101

PID: 4434 2nd child. PPID: 4432. ++number = 101

PID: 4434 exiting with number = 100

PID: 4433 exiting with number = 100

[process] PID: 4435 2nd child. PPID: 4433. ++number = 102

PID: 4435 exiting with number = 101

 had to enter CR-LF

[process]

38

fork()

Sample4 Variation

#include <iostream.h>

#include <unistd.h> int main()

{ // main int number = 100; // Note number on stack if ( 0 == fork() ) { // first child creation cout << "PID: " << getpid()

<< " 1st child, number = "

<< ++number << endl;

} //end if if ( 0 == fork() ) { // second child creation cout << "PID: " << getpid()

<< " 2nd child. PPID: "

<< getppid() << ". ++number = "

<< ++number << endl; return 0 ; // Which program output now?

} //end if cout << "PID: " << getpid()

<< " exiting with number = "

<< --number << endl; return 0;

} //end main

39

fork()

Sample5 –Is Interesting

#include <iostream.h>

#include <unistd.h> void fork_sample()

{ // fork_sample pid_t pid1 = fork() ; // pid1 not same as getpid() pid_t pid2 = fork() ; // pid2 not same as getpid() pid_t pid3 = fork() ; // pid3 not same as getpid() cout << " pid1 = " << pid1

<< " pid2 = " << pid2

<< " pid3 = " << pid3

<< endl;

} //end fork_sample int main()

{ // main fork_sample(); exit( 0 );

} //end main

40

fork()

Sample5 Output

[process] a.out

pid1 = 24583 pid2 = 24584 pid3 = 24585 pid1 = 24583 pid2 = 24584 pid3 = 0 pid1 = 24583 pid2 = 0 pid3 = 24587 pid1 = 0 pid2 = 24586 pid3 = 24588

[process] pid1 = 24583 pid2 = 0 pid3 = 0 pid1 = 0 pid2 = 24586 pid3 = 0 pid1 = 0 pid2 = 0 pid3 = 0 pid1 = 0 pid2 = 0 pid3 = 24589

 had to enter CR-LF, came out early!

[process]

Why are there 8 lines of output?

Why do you see only 7 different pid numbers?

Which is the original parent ’s pid number?

Which line above is printed by original parent process?

41

fork()

Sample5 Answers

Why are there 8 lines of output?

8 processes:

1 parent

3 child processes from parent: c1, c2, c3

2 child processes from c1: c12, c13

1 child process from c12: c13

1 child process from c2: c23

Why do you see only 7 different pid numbers?

original parent never acquires via getpid(), its own pid, so never prints it

Which is the original parent ’s pid number?

not known here; not programmed in!

Which line above is printed by original parent process?

the one printing 3 non-zero pid numbers, happens to be first line during another execution, this could be a different output line number

42

fork()

Sample6

#include <iostream.h>

#include <unistd.h> void fork_sample()

{ // fork_sample pid_t pid1 = fork(); // 1 pid_t pid2 = fork(); // 2 pid_t pid3 = fork(); // 3 pid_t pid4 = fork(); // 4 printf( "I am %5d, parent= %5d, pid1= %5d, pid2= %5d, pid3= %5d, pid4= %5d\n”, getpid(), getppid(), pid1, pid2, pid3, pid4 );

} //end fork_sample int main()

{ // main fork_sample(); exit ( 0 );

} //end main

43

fork()

Sample6 Output

I am 22255, parent= 21528, pid1= 22256, pid2= 22257, pid3= 22258, pid4= 22260

I am 22260, parent= 22255, pid1= 22256, pid2= 22257, pid3= 22258, pid4= 0

I am 22256, parent= 22255, pid1= 0, pid2= 22259, pid3= 22261, pid4= 22264

I am 22258, parent= 22255, pid1= 22256, pid2= 22257, pid3= 0, pid4= 22265

I am 22264, parent= 22256, pid1= 0, pid2= 22259, pid3= 22261, pid4= 0

I am 22257, parent= 22255, pid1= 22256, pid2= 0, pid3= 22263, pid4= 22268

I am 22261, parent= 22256, pid1= 0, pid2= 22259, pid3= 0, pid4= 22266

I am 22265, parent= 22258, pid1= 22256, pid2= 22257, pid3= 0, pid4= 0

I am 22259, parent= 22256, pid1= 0, pid2= 0, pid3= 22262, pid4= 22267

I am 22266, parent= 22261, pid1= 0, pid2= 22259, pid3= 0, pid4= 0

I am 22263, parent= 22257, pid1= 22256, pid2= 0, pid3= 0, pid4= 22270

I am 22268, parent= 22257, pid1= 22256, pid2= 0, pid3= 22263, pid4= 0

I am 22269, parent= 22262, pid1= 0, pid2= 0, pid3= 0, pid4= 0

I am 22270, parent= 22263, pid1= 22256, pid2= 0, pid3= 0, pid4= 0

I am 22267, parent= 22259, pid1= 0, pid2= 0, pid3= 22262, pid4= 0

I am 22262, parent= 22259, pid1= 0, pid2= 0, pid3= 0, pid4= 22269

44

fork()

Sample6 Graph

28

Shell Process

4 children of Parent

60

61 59

56

55

58

Parent Process

57

64

65 68 63

70

67 62

66

69

45

Command

execve()

 So why does the fork() command exist, if all it does is: make a copy of the current process?

 fork() is just the first step of creating new processes , including the execution of any Unix commands, but also user programs, such as a.out

 Therefore, code and data space have to be replaced to spawn off a new, separate process

 Unix command execve() accomplishes this

 A clever resource saving: pages in memory are not duplicated for new process; only modified pages are: AKA copy-on-write

 Side-effect of any fork() command is eventual execution of two returns or exits, namely of parent and child process; correspondingly, execve() command creates no new return or exit

46

execve()

Sample

void fork_exec_sample( char * argv[], char * envp[] )

{ // fork_exec_sample pid_t pid = fork (); // parent + child exist now if ( 0 == pid ) {

// child process

// strange order of: 0 == . . .

cout << "run 'herb.o' program." << endl;

// must yield complete path; giving relative path also OK if ( execve ( "/u/herb/progs/process/herb.o", argv, envp ) < 0 ) { cout << "Aborting " << endl; exit( 0 );

} //end if

} //end if cout << "Created process " << pid << endl;

} //end fork_exec_sample int main( int argc, char * argv[], char * envp[] )

{ // main fork_exec_sample( argv, envp ); return 0;

} //end main

47

execve()

Sample, uses

herb.o

// new program = process to be initiated by execve()

// source named: herb.cpp

#include <stdio.h> int main()

{ // main printf( "<> SUCCESS <> You executed Herb\n" ); return 0; // exits main()

} //end main

1.

Compile this, and rename: a.out

--> herb.o

2.

Move herb.o

into directory /u/herb/progs/process

[process] a.out

Created process 21010  students: why printed only once?

run 'herb.o' program.

[process] <> SUCCESS <> You executed Herb

48

References

1.

IBM literature about Unix 8: http://www.ibm.com/developerworks/aix/library/au-speakingunix8/

2.

Computer Systems, a Programmer ’s Perspective , Bryant and O ’Halleron , Prentice Hall © 2011, 2 nd ed.

3.

Modern Operating Systems , Andrew S. Tanenbaum , Prentice Hall © 2011, 2. ed.

4.

Operating System Concepts , Silberschatz and Galvin, Addison Wesley © 1998, 5. ed.

5.

Posix Threa d: https://computing.llnl.gov/tutorials/pthreads/#Thread

6.

Thread, Hyperthread, Process : http://decipherinfosys.com/HyperthreadedDualCore.pdf

7.

Intel Hyperthreading : http://www.intel.com/technology/itj/2002/volume06issue01/vol6iss1_hyper_threading_technology.

pdf

8.

Zombie process : http://en.wikipedia.org/wiki/Zombie_process

9.

Eliminate threading errors : http://download-software.intel.com/en-us/sites/default/files/eliminatethreading-errors_studioxe-evalguide.pdf

10.

Intel Timebase Utility for multi-threading and concurrency: http://software.intel.com/enus/forums/topic/304224

11.

MS multi-threading : http://msdn.microsoft.com/en-us/library/vstudio/172d2hhw.aspx

12.

Threading help : http://software.intel.com/en-us/articles/automatic-parallelization-with-intelcompilers

13.

Threading instructions from Intel: http://software.intel.com/en-us/articles/intel-guide-fordeveloping-multithreaded-applications

14.

MW Windows process and thread concept: https://msdn.microsoft.com/enus/library/windows/desktop/ms684841(v=vs.85).aspx

49

Download