Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
Systems744
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
SHREYANSH JAIN
Systems744
Commits
2f69b239
Commit
2f69b239
authored
Aug 22, 2019
by
desiredeveloper
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
adding sync solutions
parent
e4ca1df5
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
676 additions
and
0 deletions
+676
-0
assignment2/sync-problems/.vscode/launch.json
assignment2/sync-problems/.vscode/launch.json
+29
-0
assignment2/sync-problems/.vscode/settings.json
assignment2/sync-problems/.vscode/settings.json
+5
-0
assignment2/sync-problems/.vscode/tasks.json
assignment2/sync-problems/.vscode/tasks.json
+19
-0
assignment2/sync-problems/Assignment2-Synchronization.pdf
assignment2/sync-problems/Assignment2-Synchronization.pdf
+0
-0
assignment2/sync-problems/Makefile
assignment2/sync-problems/Makefile
+32
-0
assignment2/sync-problems/README
assignment2/sync-problems/README
+35
-0
assignment2/sync-problems/a.out
assignment2/sync-problems/a.out
+0
-0
assignment2/sync-problems/cs744_thread.h
assignment2/sync-problems/cs744_thread.h
+115
-0
assignment2/sync-problems/metro.c
assignment2/sync-problems/metro.c
+58
-0
assignment2/sync-problems/metro_runner.c
assignment2/sync-problems/metro_runner.c
+186
-0
assignment2/sync-problems/reaction-runner.c
assignment2/sync-problems/reaction-runner.c
+139
-0
assignment2/sync-problems/reaction.c
assignment2/sync-problems/reaction.c
+58
-0
No files found.
assignment2/sync-problems/.vscode/launch.json
0 → 100644
View file @
2f69b239
{
//
Use
IntelliSense
to
learn
about
possible
attributes.
//
Hover
to
view
descriptions
of
existing
attributes.
//
For
more
information
,
visit:
https://go.microsoft.com/fwlink/?linkid=
830387
"version"
:
"0.2.0"
,
"configurations"
:
[
{
"name"
:
"gcc build and debug active file"
,
"type"
:
"cppdbg"
,
"request"
:
"launch"
,
"program"
:
"${fileDirname}/${fileBasenameNoExtension}"
,
"args"
:
[],
"stopAtEntry"
:
false
,
"cwd"
:
"${workspaceFolder}"
,
"environment"
:
[],
"externalConsole"
:
false
,
"MIMode"
:
"gdb"
,
"setupCommands"
:
[
{
"description"
:
"Enable pretty-printing for gdb"
,
"text"
:
"-enable-pretty-printing"
,
"ignoreFailures"
:
true
}
],
"preLaunchTask"
:
"gcc build active file"
,
"miDebuggerPath"
:
"/usr/bin/gdb"
}
]
}
\ No newline at end of file
assignment2/sync-problems/.vscode/settings.json
0 → 100644
View file @
2f69b239
{
"files.associations"
:
{
"cs744_thread.h"
:
"c"
}
}
\ No newline at end of file
assignment2/sync-problems/.vscode/tasks.json
0 → 100644
View file @
2f69b239
{
"tasks"
:
[
{
"type"
:
"shell"
,
"label"
:
"gcc build active file"
,
"command"
:
"/usr/bin/gcc"
,
"args"
:
[
"-g"
,
"${file}"
,
"-o"
,
"${fileDirname}/${fileBasenameNoExtension}"
],
"options"
:
{
"cwd"
:
"/usr/bin"
}
}
],
"version"
:
"2.0.0"
}
\ No newline at end of file
assignment2/sync-problems/Assignment2-Synchronization.pdf
0 → 100644
View file @
2f69b239
File added
assignment2/sync-problems/Makefile
0 → 100644
View file @
2f69b239
# Default to debugging flags. Set to -O3 if you want optimisations
# (either change it here, or type 'make CFLAGS=-O3' in the shell).
CFLAGS
?=
-g
-Wall
-Wno-unused-value
all
:
metro reaction
metro
:
metro_runner.c metro.c cs744_thread.h
$(CC)
$(CFLAGS)
-o
metro metro_runner.c
-lpthread
reaction
:
reaction-runner.c reaction.c cs744_thread.h
$(CC)
$(CFLAGS)
-o
reaction reaction-runner.c
-lpthread
run
:
metro reaction
./metro
./metro
./metro
./reaction 0
./reaction 0
./reaction 20
./reaction 20
./reaction 40
./reaction 40
./reaction 60
./reaction 60
./reaction 80
./reaction 80
./reaction 100
./reaction 100
clean
:
$(RM)
metro reaction
$(RM)
-r
*
.dSYM
assignment2/sync-problems/README
0 → 100644
View file @
2f69b239
This package contains cs744 assignment2 starter code. The included Makefile
will compile your solutions to the metro and reaction synchronisation
problems. The resulting binaries will try to stress-test what you
wrote and should hopefully help you to shake out any bugs.
You'll need to fill in metro.c and reaction.c appropriately to
complete this assignment (the tests will certainly fail before you do
so). These two files, and only these two files, should be submitted for
grading. See the moodle post for assignment details.
You are to use the cs744 lock and condition variable APIs. The following
types are defined already for your use:
struct lock
struct condition
As are the following functions:
void lock_init(struct lock *lock);
void lock_acquire(struct lock *lock);
void lock_release(struct lock *lock);
void cond_init(struct condition *cond);
void cond_wait(struct condition *cond, struct lock *lock);
void cond_signal(struct condition *cond, struct lock *lock);
void cond_broadcast(struct condition *cond, struct lock *lock);
No other files should need to be modified. Compile using 'make'. To
run a bunch of tests, you can try 'make run'.
The tests have a lot of randomness built in and aren't flawless (their
passing doesn't guarantee a perfect implementation). You may want to
run many times to get better assurance of your solution's sanity. You're
welcome to extend the tests any way you see fit, but they won't be
submitted. You should refrain from using any other libraries or functions
in your solutions. We should be able to untar this distribution, copy over
your metro.c and reaction.c files, and compile and run the original
tests.
assignment2/sync-problems/a.out
0 → 100755
View file @
2f69b239
File added
assignment2/sync-problems/cs744_thread.h
0 → 100644
View file @
2f69b239
/*
* Should run under Unix/Linux/OS X. Just #include this header
* in your code and compile with the '-lpthread' flag, e.g.:
* cc -o myBinary myCode.c -lpthread
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// So we can hopefully ensure that locks and condition variables
// are initialised before use.
#define LOCK_COND_INIT_MAGIC 0x4a3acd94
struct
lock
{
int
init
;
pthread_mutex_t
mutex
;
};
struct
condition
{
int
init
;
pthread_cond_t
cond
;
};
// Sush up -Wall if any of these are unused.
static
void
lock_init
(
struct
lock
*
lock
)
__attribute__
((
unused
));
static
void
lock_acquire
(
struct
lock
*
lock
)
__attribute__
((
unused
));
static
void
lock_release
(
struct
lock
*
lock
)
__attribute__
((
unused
));
static
void
cond_init
(
struct
condition
*
cond
)
__attribute__
((
unused
));
static
void
cond_wait
(
struct
condition
*
cond
,
struct
lock
*
lock
)
__attribute__
((
unused
));
static
void
cond_signal
(
struct
condition
*
cond
,
struct
lock
*
lock
)
__attribute__
((
unused
));
static
void
cond_broadcast
(
struct
condition
*
cond
,
struct
lock
*
lock
)
__attribute__
((
unused
));
static
void
__assert
(
int
satisfied
,
const
char
*
message
)
{
if
(
!
satisfied
)
{
fprintf
(
stderr
,
"FATAL ERROR: %s
\n
"
,
message
);
exit
(
1
);
}
}
static
void
lock_init
(
struct
lock
*
lock
)
{
lock
->
init
=
LOCK_COND_INIT_MAGIC
;
pthread_mutex_init
(
&
lock
->
mutex
,
NULL
);
}
static
void
lock_acquire
(
struct
lock
*
lock
)
{
__assert
(
lock
->
init
==
LOCK_COND_INIT_MAGIC
,
"lock_acquire used before lock was initialised!"
);
pthread_mutex_lock
(
&
lock
->
mutex
);
}
static
void
lock_release
(
struct
lock
*
lock
)
{
__assert
(
lock
->
init
==
LOCK_COND_INIT_MAGIC
,
"lock_release used before lock was initialised!"
);
__assert
(
pthread_mutex_trylock
(
&
lock
->
mutex
)
!=
0
,
"lock_release on unlocked lock!"
);
pthread_mutex_unlock
(
&
lock
->
mutex
);
}
static
void
cond_init
(
struct
condition
*
cond
)
{
cond
->
init
=
LOCK_COND_INIT_MAGIC
;
pthread_cond_init
(
&
cond
->
cond
,
NULL
);
}
static
void
cond_wait
(
struct
condition
*
cond
,
struct
lock
*
lock
)
{
// Assert the lock is already held. It should be held
// by this caller, so while this simple check won't
// catch all bad invocations (somebody else could have
// locked it, rather than us) at least it's a start...
__assert
(
pthread_mutex_trylock
(
&
lock
->
mutex
)
!=
0
,
"cond_wait not called with lock held!"
);
__assert
(
cond
->
init
==
LOCK_COND_INIT_MAGIC
,
"cond_wait used before cond was initialised!"
);
__assert
(
lock
->
init
==
LOCK_COND_INIT_MAGIC
,
"cond_wait used before lock was initialised!"
);
pthread_cond_wait
(
&
cond
->
cond
,
&
lock
->
mutex
);
}
static
void
cond_signal
(
struct
condition
*
cond
,
struct
lock
*
lock
)
{
// See comment in cond_wait().
__assert
(
pthread_mutex_trylock
(
&
lock
->
mutex
)
!=
0
,
"cond_signal not called with lock held!"
);
__assert
(
cond
->
init
==
LOCK_COND_INIT_MAGIC
,
"cond_signal used before cond was initialised!"
);
__assert
(
lock
->
init
==
LOCK_COND_INIT_MAGIC
,
"cond_signal used before lock was initialised!"
);
pthread_cond_signal
(
&
cond
->
cond
);
}
static
void
cond_broadcast
(
struct
condition
*
cond
,
struct
lock
*
lock
)
{
// See comment in cond_wait().
__assert
(
pthread_mutex_trylock
(
&
lock
->
mutex
)
!=
0
,
"cond_broadcast not called with lock held!"
);
__assert
(
cond
->
init
==
LOCK_COND_INIT_MAGIC
,
"cond_broadcast used before cond was initialised!"
);
__assert
(
lock
->
init
==
LOCK_COND_INIT_MAGIC
,
"cond_broadcast used before lock was initialised!"
);
pthread_cond_broadcast
(
&
cond
->
cond
);
}
assignment2/sync-problems/metro.c
0 → 100644
View file @
2f69b239
#include "cs744_thread.h"
int
local
;
struct
station
{
// FILL ME IN
struct
lock
m1
;
struct
condition
cond1
;
struct
condition
cond2
;
int
passengers
;
};
void
station_init
(
struct
station
*
station
)
{
station
->
passengers
=
0
;
lock_init
(
&
station
->
m1
);
cond_init
(
&
station
->
cond1
);
cond_init
(
&
station
->
cond2
);
// FILL ME IN
}
void
station_load_train
(
struct
station
*
station
,
int
count
)
{
// FILL ME IN
lock_acquire
(
&
station
->
m1
);
if
(
count
==
0
||
station
->
passengers
==
0
){
}
else
{
while
(
count
--
&&
(
station
->
passengers
)
--
){
local
++
;
cond_signal
(
&
station
->
cond1
,
&
station
->
m1
);
}
cond_wait
(
&
station
->
cond2
,
&
station
->
m1
);
}
lock_release
(
&
station
->
m1
);
}
void
station_wait_for_train
(
struct
station
*
station
)
{
// FILL ME IN
lock_acquire
(
&
station
->
m1
);
(
station
->
passengers
)
++
;
cond_wait
(
&
station
->
cond1
,
&
station
->
m1
);
lock_release
(
&
station
->
m1
);
}
void
station_on_board
(
struct
station
*
station
)
{
// FILL ME IN
lock_acquire
(
&
station
->
m1
);
if
(
--
local
==
0
)
cond_signal
(
&
station
->
cond2
,
&
station
->
m1
);
lock_release
(
&
station
->
m1
);
}
assignment2/sync-problems/metro_runner.c
0 → 100644
View file @
2f69b239
/*
* Note that passing these tests doesn't guarantee that your code is correct
* or meets the specifications given, but hopefully it's at least pretty
* close.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include "metro.c"
// Count of passenger threads that have completed (i.e. station_wait_for_train
// has returned) and are awaiting a station_on_board() invocation.
volatile
int
threads_completed
=
0
;
void
*
passenger_thread
(
void
*
arg
)
{
struct
station
*
station
=
(
struct
station
*
)
arg
;
station_wait_for_train
(
station
);
__sync_add_and_fetch
(
&
threads_completed
,
1
);
return
NULL
;
}
struct
load_train_args
{
struct
station
*
station
;
int
free_seats
;
};
volatile
int
load_train_returned
=
0
;
void
*
load_train_thread
(
void
*
args
)
{
struct
load_train_args
*
ltargs
=
(
struct
load_train_args
*
)
args
;
station_load_train
(
ltargs
->
station
,
ltargs
->
free_seats
);
load_train_returned
=
1
;
return
NULL
;
}
const
char
*
alarm_error_str
;
int
alarm_timeout
;
void
_alarm
(
int
seconds
,
const
char
*
error_str
)
{
alarm_timeout
=
seconds
;
alarm_error_str
=
error_str
;
alarm
(
seconds
);
}
void
alarm_handler
(
int
foo
)
{
fprintf
(
stderr
,
"Error: Failed to complete after %d seconds. Something's "
"wrong, or your system is terribly slow. Possible error hint: [%s]
\n
"
,
alarm_timeout
,
alarm_error_str
);
exit
(
1
);
}
#ifndef MIN
#define MIN(_x,_y) ((_x) < (_y)) ? (_x) : (_y)
#endif
/*
* This creates a bunch of threads to simulate arriving trains and passengers.
*/
int
main
()
{
struct
station
station
;
station_init
(
&
station
);
srandom
(
getpid
()
^
time
(
NULL
));
signal
(
SIGALRM
,
alarm_handler
);
// Make sure station_load_train() returns immediately if no waiting passengers.
_alarm
(
1
,
"station_load_train() did not return immediately when no waiting passengers"
);
station_load_train
(
&
station
,
0
);
station_load_train
(
&
station
,
10
);
_alarm
(
0
,
NULL
);
// Create a bunch of 'passengers', each in their own thread.
int
i
;
const
int
total_passengers
=
1000
;
int
passengers_left
=
total_passengers
;
for
(
i
=
0
;
i
<
total_passengers
;
i
++
)
{
pthread_t
tid
;
int
ret
=
pthread_create
(
&
tid
,
NULL
,
passenger_thread
,
&
station
);
if
(
ret
!=
0
)
{
// If this fails, perhaps we exceeded some system limit.
// Try reducing 'total_passengers'.
perror
(
"pthread_create"
);
exit
(
1
);
}
}
// Make sure station_load_train() returns immediately if no free seats.
_alarm
(
2
,
"station_load_train() did not return immediately when no free seats"
);
station_load_train
(
&
station
,
0
);
_alarm
(
0
,
NULL
);
// Tons of random tests.
int
total_passengers_boarded
=
0
;
const
int
max_free_seats_per_train
=
50
;
int
pass
=
0
;
while
(
passengers_left
>
0
)
{
_alarm
(
2
,
"Some more complicated issue appears to have caused passengers "
"not to board when given the opportunity"
);
int
free_seats
=
random
()
%
max_free_seats_per_train
;
printf
(
"Train entering station with %d free seats
\n
"
,
free_seats
);
load_train_returned
=
0
;
struct
load_train_args
args
=
{
&
station
,
free_seats
};
pthread_t
lt_tid
;
int
ret
=
pthread_create
(
&
lt_tid
,
NULL
,
load_train_thread
,
&
args
);
if
(
ret
!=
0
)
{
perror
(
"pthread_create"
);
exit
(
1
);
}
int
threads_to_reap
=
MIN
(
passengers_left
,
free_seats
);
int
threads_reaped
=
0
;
while
(
threads_reaped
<
threads_to_reap
)
{
if
(
load_train_returned
)
{
fprintf
(
stderr
,
"Error: station_load_train returned early!
\n
"
);
exit
(
1
);
}
if
(
threads_completed
>
0
)
{
if
((
pass
%
2
)
==
0
)
usleep
(
random
()
%
2
);
threads_reaped
++
;
station_on_board
(
&
station
);
__sync_sub_and_fetch
(
&
threads_completed
,
1
);
}
}
// Wait a little bit longer. Give station_load_train() a chance to return
// and ensure that no additional passengers board the train. One second
// should be tons of time, but if you're on a horribly overloaded system,
// this may need to be tweaked.
for
(
i
=
0
;
i
<
1000
;
i
++
)
{
if
(
i
>
50
&&
load_train_returned
)
break
;
usleep
(
1000
);
}
if
(
!
load_train_returned
)
{
fprintf
(
stderr
,
"Error: station_load_train failed to return
\n
"
);
exit
(
1
);
}
while
(
threads_completed
>
0
)
{
threads_reaped
++
;
__sync_sub_and_fetch
(
&
threads_completed
,
1
);
}
passengers_left
-=
threads_reaped
;
total_passengers_boarded
+=
threads_reaped
;
printf
(
"Train departed station with %d new passenger(s) (expected %d)%s
\n
"
,
threads_to_reap
,
threads_reaped
,
(
threads_to_reap
!=
threads_reaped
)
?
" *****"
:
""
);
if
(
threads_to_reap
!=
threads_reaped
)
{
fprintf
(
stderr
,
"Error: Too many passengers on this train!
\n
"
);
exit
(
1
);
}
pass
++
;
}
if
(
total_passengers_boarded
==
total_passengers
)
{
printf
(
"Looks good!
\n
"
);
return
0
;
}
else
{
// I don't think this is reachable, but just in case.
fprintf
(
stderr
,
"Error: expected %d total boarded passengers, but got %d!
\n
"
,
total_passengers
,
total_passengers_boarded
);
return
1
;
}
}
assignment2/sync-problems/reaction-runner.c
0 → 100644
View file @
2f69b239
/*
* This file tests the implementation in reaction.c. You shouldn't need to
* modify it, but you're welcome to do so. Please report any bugs to us via
* Piazza or email (cs140ta@cs).
*
* Note that passing these tests doesn't guarantee that your code is correct
* or meets the specifications given, but hopefully it's at least pretty
* close.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include "reaction.c"
volatile
int
water_molecules
=
0
;
volatile
int
hydrogen_atoms_bonded
=
0
;
volatile
int
oxygen_atoms_bonded
=
0
;
void
make_water
()
{
__sync_add_and_fetch
(
&
water_molecules
,
1
);
}
void
*
hydrogen_thread
(
void
*
arg
)
{
struct
reaction
*
reaction
=
(
struct
reaction
*
)
arg
;
reaction_h
(
reaction
);
__sync_add_and_fetch
(
&
hydrogen_atoms_bonded
,
1
);
return
NULL
;
}
void
*
oxygen_thread
(
void
*
arg
)
{
struct
reaction
*
reaction
=
(
struct
reaction
*
)
arg
;
reaction_o
(
reaction
);
__sync_add_and_fetch
(
&
oxygen_atoms_bonded
,
1
);
return
NULL
;
}
void
alarm_handler
(
int
foo
)
{
fprintf
(
stderr
,
"Error: Failed to complete after 10 seconds. Something's "
"wrong, or your system is terribly slow.
\n
"
);
exit
(
1
);
}
#ifndef MIN
#define MIN(_x,_y) ((_x) < (_y)) ? (_x) : (_y)
#endif
/*
* This creates a bunch of threads to simulate H and O molecules. Hopefully
* mother nature will be decent enough to bond them when asked.
*/
int
main
(
int
argc
,
char
**
argv
)
{
struct
reaction
reaction
;
reaction_init
(
&
reaction
);
if
(
argc
!=
2
||
atoi
(
argv
[
1
])
<
0
||
atoi
(
argv
[
1
])
>
100
)
{
fprintf
(
stderr
,
"usage: %s percentageOfHydrogenAtoms
\n
"
" e.g.: %s 50
\n
"
,
argv
[
0
],
argv
[
0
]);
exit
(
1
);
}
srandom
(
getpid
()
^
time
(
NULL
));
signal
(
SIGALRM
,
alarm_handler
);
alarm
(
10
);
int
i
;
const
int
total_atoms
=
200
;
int
hydrogen_atoms
=
0
;
int
oxygen_atoms
=
0
;
int
hydrogen_pct
=
atoi
(
argv
[
1
]);
for
(
i
=
0
;
i
<
total_atoms
;
i
++
)
{
pthread_t
tid
;
int
ret
;
if
((
random
()
%
100
)
<
hydrogen_pct
)
{
hydrogen_atoms
++
;
ret
=
pthread_create
(
&
tid
,
NULL
,
hydrogen_thread
,
&
reaction
);
}
else
{
oxygen_atoms
++
;
ret
=
pthread_create
(
&
tid
,
NULL
,
oxygen_thread
,
&
reaction
);
}
if
(
ret
!=
0
)
{
// If this fails, perhaps we exceeded some system limit.
// Try reducing 'total_atoms'.
perror
(
"pthread_create"
);
exit
(
1
);
}
}
int
expected_molecules
=
MIN
(
hydrogen_atoms
/
2
,
oxygen_atoms
);
printf
(
"Created %d H and %d O atoms (%.1f%% H), expecting %d H2O molecules
\n
"
,
hydrogen_atoms
,
oxygen_atoms
,
(
double
)
hydrogen_atoms
/
total_atoms
*
100
.
0
,
expected_molecules
);
// Wait for expected reactions to complete.
while
(
water_molecules
!=
expected_molecules
)
;
// Wait a little longer in case the student's implementation is buggy and
// we see too many reactions.
usleep
(
100000
);
if
(
water_molecules
!=
expected_molecules
)
{
fprintf
(
stderr
,
"Error: expected %d H20 molecules, but %d were created!
\n
"
,
expected_molecules
,
water_molecules
);
exit
(
1
);
}
if
(
hydrogen_atoms_bonded
!=
(
expected_molecules
*
2
))
{
fprintf
(
stderr
,
"Error: expected %d reaction_h() calls to return, but "
"%d did instead!
\n
"
,
expected_molecules
*
2
,
hydrogen_atoms_bonded
);
exit
(
1
);
}
if
(
oxygen_atoms_bonded
!=
expected_molecules
)
{
fprintf
(
stderr
,
"Error: expected %d reaction_o() calls to return, but "
"%d did instead!
\n
"
,
expected_molecules
,
oxygen_atoms_bonded
);
exit
(
1
);
}
printf
(
"Looks good!
\n
"
);
return
0
;
}
assignment2/sync-problems/reaction.c
0 → 100644
View file @
2f69b239
#include "cs744_thread.h"
// Forward declaration. This function is implemented in reaction-runner.c,
// but you needn't care what it does. Just be sure it's called when
// appropriate within reaction_o()/reaction_h().
void
make_water
();
int
hydrogen
,
oxygen
;
struct
reaction
{
// FILL ME IN
struct
lock
m1
;
struct
condition
oxygen
;
struct
condition
hydrogen
;
};
void
reaction_init
(
struct
reaction
*
reaction
)
{
// FILL ME IN
lock_init
(
&
reaction
->
m1
);
cond_init
(
&
reaction
->
oxygen
);
cond_init
(
&
reaction
->
hydrogen
);
}
void
reaction_h
(
struct
reaction
*
reaction
)
{
// FILL ME IN
lock_acquire
(
&
reaction
->
m1
);
hydrogen
++
;
if
(
hydrogen
>=
2
&&
oxygen
>=
1
){
cond_signal
(
&
reaction
->
hydrogen
,
&
reaction
->
m1
);
cond_signal
(
&
reaction
->
oxygen
,
&
reaction
->
m1
);
hydrogen
-=
2
;
oxygen
--
;
make_water
();
}
else
cond_wait
(
&
reaction
->
oxygen
,
&
reaction
->
m1
);
lock_release
(
&
reaction
->
m1
);
}
void
reaction_o
(
struct
reaction
*
reaction
)
{
// FILL ME IN
lock_acquire
(
&
reaction
->
m1
);
oxygen
++
;
if
(
hydrogen
>=
2
){
cond_signal
(
&
reaction
->
oxygen
,
&
reaction
->
m1
);
cond_signal
(
&
reaction
->
oxygen
,
&
reaction
->
m1
);
hydrogen
-=
2
;
oxygen
--
;
make_water
();
}
else
cond_wait
(
&
reaction
->
hydrogen
,
&
reaction
->
m1
);
lock_release
(
&
reaction
->
m1
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment