The top software developers are more productive than
average software developers not by a factor of 10X or
100X or even 1000X but by 10,000X.
Nathan Myhrvold
Review and Overview
| wait: | down ( mutex ); |
| access_CS(); | |
| signal: | up ( mutex ); |
Example
Let us look at an example of semaphores. In figure A, there are three semaphores: S1 has a value of zero and process P1 is blocked on S1; S2 has a value of three, meaning three more processes may execute a down operation on S2 without being put to sleep; S3 has a value of zero, and has two sleeping processes, P4 and P5, blocked on it.

Now let us look at what happens when a process executes an UP on S1. In figure B, process P1 is activated by an UP operation. It executes a DOWN on S1 and enters its critical section. The state of the semaphores after these actions has now changed.

Weakness:
Procedures |
Hollow Region( multiple processes can be active here ) |
| |
Hollow Region( multiple processes can be active here ) |
| |
path S end
S : execution history
; sequencing -- statement executions are in sequence
+ selection -- only one statement can be executed at a time
Output command = <destination process id> ! <expression>
Concurrent processes :
[process P1's code||process P2's code||
..... ||process Pn's code||
basically :
if ( G )
CL
evaluate G, if false, ( i.e. guard fails ), CL won't be evaluated
Alternative command
G2 -->CL2
.....
Gn -->CLn
Repetitive command
G2 -->CL2
.....
Gn -->CLn ]
Example
start with i = 0, then repetitively scan until either i ≥ size or some content( i ) equals n
Example
? -- output, ! -- input
reads all characters output by process P1 to c which becomes input of process P2
Weakness of CSP
Two tasks may rendezvous at once in Ada -- a caller and a server
server accepts calls from any caller but only one caller
may rendezvous with the server, others wait
First-come-first-served
Ada Task:
task ResourceController is --task specification entry GetControl; entry RelinquishControl; end ResourceController task body ResourceController is --body begin loop accept GetControl; accept RelinquishControl; end loop; end ResourceController; . . . |
Example: producer-consumer with single buffer
task SingleBuffer is entry Store ( x:buffer ); entry Remove ( y:buffer ); end; task body SingleBuffer is temp:buffer; --shared variable begin loop accept Store ( x:buffer ); --Store and remove temp = x; --are executed alternately end Store; accept Remove ( y:buffer ); y = temp; end Remove; end loop end SingleBuffer; |
select -- make tasks to accept calls in a more flexible way
select when Condition 1 => accept Entry 1 statements; or when Condition 2 => accept Entry 2 statements; or . . . else statements; end select |
Example: producer-consumer with bounded buffer
task bounded-buffer is entry store( x:buffer ); entry remove( y:buffer ); end; task body bounded-buffer is ring:[0..9] of buffer; head, tail: integer; head = 0; tail = 0; begin loop select when tail < head + 10 = > --queue not full yet accept store( x:buffer ); ring[tail mod 10] = x; --put item in buffer tail = tail + 1; --next slot end store; or when head < tail = > --queue not empty accept remove( y:buffer ); y = ring[head mod 10]; --get item from ring head = head + 1; --next slot end remove; end select; end loop end bounded-buffer; |
![]() |
Simulating path expressions in Ada
entries A, B B must follow A: accept A; accept B; specifying either A or B ( not both ) can be executed: select when ( x > 0 ) = > accept A; or when ( x <= 0 ) = > accept B; end select; specifying any number ( including 0 ) of calls to A: loop select when ( x > 0 ) = > accept A; else exit; end select; end loop |