Skip to content

Instantly share code, notes, and snippets.

@ProfAvery
Last active February 12, 2021 22:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ProfAvery/efff2b2f7f5292c9ee35627e9fedd3c3 to your computer and use it in GitHub Desktop.
Save ProfAvery/efff2b2f7f5292c9ee35627e9fedd3c3 to your computer and use it in GitHub Desktop.
In-class exercise: Resource Allocation Graph
*.o
resource-allocation
CXXFLAGS = -g -std=c++17 -Wall -Wextra -Wpedantic -pthread
TARGETS = resource-allocation
.PHONY: test clean
all: $(TARGETS)
resource-allocation: resource-allocation.o sync.o
$(CXX) $(CXXFLAGS) -o $@ $^
test: $(TARGETS)
./try.sh ./resource-allocation 1000
clean:
rm -f *.o $(TARGETS)
#include <cstdlib>
#include <iostream>
#include <tuple>
#include <pthread.h>
#include <semaphore.h>
#include "sync.h"
using std::cout;
using std::endl;
using std::ignore;
Semaphore r1, r2(2), r3;
void *do_t1(void *);
void *do_t2(void *);
void *do_t3(void *);
int main()
{
Thread t1, t2, t3;
t1.create(do_t1);
t2.create(do_t2);
t3.create(do_t3);
t1.join();
t2.join();
t3.join();
return EXIT_SUCCESS;
}
void *do_t1(void *param)
{
ignore = param;
r2.wait();
r1.wait();
cout << "I am t1" << endl;
r1.post();
r2.post();
pthread_exit(NULL);
}
void *do_t2(void *param)
{
ignore = param;
r1.wait();
r2.wait();
r3.wait();
cout << "I am t2" << endl;
r3.post();
r2.post();
r1.post();
pthread_exit(NULL);
}
void *do_t3(void *param)
{
ignore = param;
r3.wait();
r2.wait();
cout << "I am t3" << endl;
r2.post();
r3.post();
pthread_exit(NULL);
}
#include <cstdlib>
#include <iostream>
#include <string>
#include <tuple>
#include <sys/stat.h>
#include <pthread.h>
#include "sync.h"
void Thread::create(void *(*routine)(void *), void *arg)
{
errno = pthread_create(&tid, NULL, routine, arg);
if (errno != 0) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
void Thread::join()
{
errno = pthread_join(tid, NULL);
if (errno != 0) {
perror("pthread_join");
exit(EXIT_FAILURE);
}
}
Mutex::Mutex()
{
errno = pthread_mutex_init(&mutex, NULL);
if (errno != 0) {
perror("pthread_mutex_init");
exit(EXIT_FAILURE);
}
}
Mutex::~Mutex()
{
errno = pthread_mutex_destroy(&mutex);
if (errno != 0) {
perror("pthread_mutex_destroy");
exit(EXIT_FAILURE);
}
}
void Mutex::lock()
{
errno = pthread_mutex_lock(&mutex);
if (errno != 0) {
perror("pthread_mutex_lock");
exit(EXIT_FAILURE);
}
}
void Mutex::unlock()
{
errno = pthread_mutex_unlock(&mutex);
if (errno != 0) {
perror("pthread_mutex_unlock");
exit(EXIT_FAILURE);
}
}
Semaphore::Semaphore(int value)
{
auto ok = sem_init(&sem, 0, value);
if (ok < 0) {
perror("sem_init");
exit(EXIT_FAILURE);
}
}
Semaphore::~Semaphore()
{
auto ok = sem_destroy(&sem);
if (ok < 0) {
perror("sem_destroy");
exit(EXIT_FAILURE);
}
}
void Semaphore::wait()
{
auto ok = sem_wait(&sem);
if (ok < 0) {
perror("sem_wait");
exit(EXIT_FAILURE);
}
}
void Semaphore::post()
{
auto ok = sem_post(&sem);
if (ok < 0) {
perror("sem_post");
exit(EXIT_FAILURE);
}
}
NamedSemaphore::NamedSemaphore(std::string name, int oflag, mode_t mode, int value)
{
psem = sem_open(name.c_str(), oflag, mode, value);
if (psem == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
}
NamedSemaphore::~NamedSemaphore()
{
auto ok = sem_close(psem);
if (ok < 0) {
perror("sem_destroy");
exit(EXIT_FAILURE);
}
}
void NamedSemaphore::wait()
{
auto ok = sem_wait(psem);
if (ok < 0) {
perror("sem_wait");
exit(EXIT_FAILURE);
}
}
void NamedSemaphore::post()
{
auto ok = sem_post(psem);
if (ok < 0) {
perror("sem_post");
exit(EXIT_FAILURE);
}
}
#ifndef SYNC_H
#define SYNC_H
#include <semaphore.h>
#include <sys/stat.h>
const auto DEFAULT_MODE = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
class Thread {
public:
void create(void *(*thread)(void *), void *arg = NULL);
void join();
private:
pthread_t tid;
};
class Mutex {
public:
Mutex();
~Mutex();
void lock();
void unlock();
private:
pthread_mutex_t mutex;
};
class Semaphore {
public:
Semaphore(int = 1);
~Semaphore();
void wait();
void post();
private:
sem_t sem;
};
class NamedSemaphore {
public:
NamedSemaphore(std::string, int, mode_t = DEFAULT_MODE, int = 1);
~NamedSemaphore();
void wait();
void post();
private:
sem_t *psem;
std::string name;
};
#endif
#!/bin/sh
executable="$1"
shift;
echo Will we lock up?
for i in $(seq 1 10000); do
timeout 5s "./$executable" "$@" > /dev/null
if [ $? -eq 124 ]; then
echo Hung on try "$i".
exit
fi
done
echo Apparently not.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment