add labs
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
//******************************************************************************
|
||||
// Course: BSy
|
||||
// File: banking.c
|
||||
// Author: M. Thaler, ZHAW
|
||||
// Purpose: locking mechanisms
|
||||
// Version: v.fs20
|
||||
//******************************************************************************
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "banking.h"
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
typedef struct account_struct_ {
|
||||
long int balance;
|
||||
pthread_mutex_t acntLock;
|
||||
} Account;
|
||||
|
||||
typedef struct branch_struct {
|
||||
Account *accounts;
|
||||
pthread_mutex_t branchLock;
|
||||
} Branch;
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
static Branch *bank;
|
||||
static int nBranches, nAccounts;
|
||||
|
||||
//******************************************************************************
|
||||
// banking functions
|
||||
|
||||
void makeBank(int num_branches, int num_accounts) {
|
||||
nBranches = num_branches;
|
||||
nAccounts = num_accounts;
|
||||
bank = (Branch *)malloc(nBranches * sizeof(Branch));
|
||||
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
//pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
|
||||
for (int i = 0; i < nBranches; i++) {
|
||||
bank[i].accounts = (Account *)malloc(nAccounts * sizeof(Account));
|
||||
for (int j = 0; j < nAccounts; j++) {
|
||||
pthread_mutex_init(&bank[i].accounts[j].acntLock, NULL);
|
||||
bank[i].accounts[j].balance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deletebank(void) {
|
||||
for (int i = 0; i < nBranches; i++)
|
||||
free(bank[i].accounts);
|
||||
free(bank);
|
||||
nBranches = nAccounts = 0;
|
||||
}
|
||||
|
||||
long int withdraw(int branchNr, int accountNr, long int value) {
|
||||
int rv, tmp;
|
||||
rv = 0;
|
||||
tmp = bank[branchNr].accounts[accountNr].balance - value;
|
||||
if (tmp >= 0) {
|
||||
bank[branchNr].accounts[accountNr].balance = tmp;
|
||||
rv = value;
|
||||
};
|
||||
return rv;
|
||||
}
|
||||
|
||||
void deposit(int branchNr, int accountNr, long int value) {
|
||||
bank[branchNr].accounts[accountNr].balance += value;
|
||||
}
|
||||
|
||||
void transfer(int fromB, int toB, int accountNr, long int value) {
|
||||
int money = withdraw(fromB, accountNr, value);
|
||||
deposit(toB, accountNr, money);
|
||||
}
|
||||
|
||||
void checkAssets(void) {
|
||||
static long assets = 0;
|
||||
long int sum = 0;
|
||||
for (int i = 0; i < nBranches; i++) {
|
||||
for (int j = 0; j < nAccounts; j++) {
|
||||
sum += (long int)bank[i].accounts[j].balance;
|
||||
}
|
||||
}
|
||||
if (assets == 0) {
|
||||
assets = sum;
|
||||
printf("Balance of accounts is: %ld\n", sum);
|
||||
}
|
||||
else {
|
||||
if (sum != assets) {
|
||||
printf("Balance of accounts is: %ld ... not correct\n", sum);
|
||||
}
|
||||
else
|
||||
printf("Balance of accounts is: %ld ... correct\n", assets);
|
||||
}
|
||||
}
|
||||
|
||||
int checkIBC(void) {
|
||||
static long ibcError = 0;
|
||||
long sum = 0;
|
||||
|
||||
for (int i = 0; i < nBranches; i++) {
|
||||
pthread_mutex_lock(&bank[i].branchLock);
|
||||
for (int j = 0; j < nAccounts; j++) {
|
||||
pthread_mutex_lock(&bank[i].accounts[j].acntLock);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nBranches; i++) {
|
||||
for (int j = 0; j < nAccounts; j++) {
|
||||
sum += (long)bank[i].accounts[j].balance;
|
||||
}
|
||||
}
|
||||
for (int i = nBranches - 1; i >= 0; i--) {
|
||||
pthread_mutex_unlock(&bank[i].branchLock);
|
||||
for (int j = 0; j < nAccounts; j++) {
|
||||
pthread_mutex_unlock(&bank[i].accounts[j].acntLock);
|
||||
}
|
||||
}
|
||||
if (ibcError == 0) ibcError = sum;
|
||||
return (ibcError != sum);
|
||||
}
|
||||
//******************************************************************************
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
//******************************************************************************
|
||||
// Course: BSy
|
||||
// File: banking.h
|
||||
// Author: M. Thaler, ZHAW
|
||||
// Purpose: locking mechanisms
|
||||
// Version: v.fs20
|
||||
//******************************************************************************
|
||||
// banking functions
|
||||
|
||||
void makeBank(int num_branches, int num_accounts);
|
||||
void deleteBank(void);
|
||||
|
||||
long withdraw(int branch, int account, long int value) ;
|
||||
void deposit(int branch, int account, long int value);
|
||||
void transfer(int fromB, int toB, int account, long int value);
|
||||
void checkAssets(void);
|
||||
int checkIBC(void);
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
//******************************************************************************
|
||||
// Course: BSy
|
||||
// File: main.c
|
||||
// Author: M. Thaler, ZHAW
|
||||
// Purpose: locking mechanisms
|
||||
// Version: v.fs20
|
||||
//******************************************************************************
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "banking.h"
|
||||
#include "mtimer.h"
|
||||
#include "mrandom.h"
|
||||
|
||||
//******************************************************************************
|
||||
// constant values
|
||||
|
||||
#define MAX_THREADS 16
|
||||
#define NUM_THREADS 5
|
||||
|
||||
#define TRANSFERS (16*1024*1024L)
|
||||
#define ACCOUNTS (2048)
|
||||
#define BRANCHES (128)
|
||||
|
||||
//******************************************************************************
|
||||
// globals
|
||||
|
||||
int nThreads;
|
||||
int ibc = 0;
|
||||
|
||||
//******************************************************************************
|
||||
// customers
|
||||
|
||||
void *pusher(void *arg) {
|
||||
int idx = (int)(long)(arg);
|
||||
mrand_t rand;
|
||||
unsigned int seed = 17*idx;
|
||||
mrandInit(seed, &rand);
|
||||
int account, from, to, val;
|
||||
int count = TRANSFERS / nThreads;
|
||||
for (int i = 0; i < count; i++) {
|
||||
account = (int)(mrandUInt(&rand) % ACCOUNTS);
|
||||
from = (int)(mrandUInt(&rand) % BRANCHES);
|
||||
to = (int)(mrandUInt(&rand) % BRANCHES);
|
||||
val = (int)(mrandRange(1000, 100000, &rand));
|
||||
transfer(from, to, account, val);
|
||||
}
|
||||
}
|
||||
|
||||
void *checker(void *arg) {
|
||||
for (int i = 0; i < 1000; i = i) {
|
||||
ibc += checkIBC();
|
||||
usleep(100*1000);
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// main program
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
gtimer_t timer;
|
||||
mrand_t ranvar;
|
||||
long assets;
|
||||
|
||||
// thread id's
|
||||
pthread_t th[MAX_THREADS];
|
||||
|
||||
// get number of threads or default
|
||||
if (argc > 1)
|
||||
nThreads = atoi(argv[1]);
|
||||
else
|
||||
nThreads = NUM_THREADS;
|
||||
nThreads = (nThreads > MAX_THREADS) ? MAX_THREADS : nThreads;
|
||||
|
||||
mrandInit((MAX_THREADS + 1)*333, &ranvar);
|
||||
|
||||
printf("\nRunning %d threads\n", nThreads);
|
||||
makeBank(BRANCHES, ACCOUNTS);
|
||||
for (int i = 0; i < ACCOUNTS; i++)
|
||||
deposit(0, i, mrandRange(10, 1000*1000, &ranvar));
|
||||
checkAssets();
|
||||
|
||||
startGTimer(timer);
|
||||
// create threads and pass thread number
|
||||
pthread_create(&th[0], NULL, checker, (void *)0);
|
||||
sleep(1);
|
||||
for (long i = 1; i < nThreads; i++)
|
||||
pthread_create(&th[i], NULL, pusher, (void *)i);
|
||||
// wait for threads to terminate
|
||||
for (int i = 1; i < nThreads; i++)
|
||||
pthread_join(th[i], NULL);
|
||||
stopGTimer(timer);
|
||||
|
||||
checkAssets();
|
||||
printGTime(timer);
|
||||
|
||||
if (ibc)
|
||||
printf("\n\033[41mYou do not comply with the IBC rules \033[0m\n\n");
|
||||
else
|
||||
printf("\n\033[42mYou do comply with the IBC rules \033[0m\n\n");
|
||||
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
@@ -0,0 +1,32 @@
|
||||
# ---------------------------------------------------------------------------
|
||||
# Makefile
|
||||
# Course: BSy
|
||||
# Date: M. Thaler, 1/2016
|
||||
# File: makefile
|
||||
# Version: v.fs20
|
||||
# ---------------------------------------------------------------------------
|
||||
#macros
|
||||
|
||||
CC = gcc
|
||||
CFLGS = -std=gnu99
|
||||
LIBS = -pthread
|
||||
OFILES = main.o banking.o
|
||||
HFILES = banking.h
|
||||
|
||||
main: $(OFILES) $(HFILES)
|
||||
$(CC) $(CFLGS) $(LIBS) $(OFILES) -o $@.e
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLGS) -c $<
|
||||
|
||||
.cc.o:
|
||||
$(CC) $(CFLGS) -c $<
|
||||
|
||||
clean:
|
||||
rm -f *.o *.e
|
||||
@echo "directory cleaned"
|
||||
|
||||
all:
|
||||
@rm -f *.o
|
||||
make --no-print-directory main
|
||||
#-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef MY_RANDOMGENERATOR_DEFINITIONS
|
||||
#define MY_RANDOMGENERATOR_DEFINITIONS
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
|
||||
//******************************************************************************
|
||||
// Course: BSy
|
||||
// File: mrandom.h
|
||||
// Author: M. Thaler, ZHAW
|
||||
// Purpose: thread safe random functions (reentrant)
|
||||
// Version: v.fs20
|
||||
//******************************************************************************
|
||||
// date type: mrand_t
|
||||
//
|
||||
// functions:
|
||||
// - void mrandInit(mrand_t *mrt) -> initialize with fixed seed
|
||||
// - unsigned int mrandUInt(mrand_t *mrt) -> unsigned random number
|
||||
// - unsigned int mrandRange(int low, int high, mrand_t *mrt)
|
||||
// -> random number within range
|
||||
//
|
||||
/******************************************************************************/
|
||||
// constanst for ecuyer generator: length approx 8 x 10^12
|
||||
|
||||
#define M1 2147483563
|
||||
#define M2 2147483399
|
||||
#define A1 40014
|
||||
#define A2 40692
|
||||
#define Q1 53668
|
||||
#define Q2 52774
|
||||
#define R1 12211
|
||||
#define R2 3791
|
||||
#define MRAND_MAX M1-1
|
||||
|
||||
/******************************************************************************/
|
||||
typedef struct mrand_t { unsigned int s1; \
|
||||
unsigned int s2; } mrand_t;
|
||||
|
||||
void mrandInit(unsigned int seed, mrand_t *mrt) {
|
||||
mrt->s1 = 33777 + seed * 777;
|
||||
mrt->s2 = 9777572 + seed * 33775;
|
||||
}
|
||||
|
||||
unsigned int mrandUInt(mrand_t *mrt) {
|
||||
unsigned int rv;
|
||||
mrt->s1 = A1 * (mrt->s1 % Q1) - mrt->s1 * (mrt->s1/Q1);
|
||||
if (mrt->s1 <= 0) mrt->s1 += M1;
|
||||
mrt->s2 = A2 * (mrt->s2 % Q2) - mrt->s2 * (mrt->s2/Q2);
|
||||
if (mrt->s2 <= 0) mrt->s2 += M2;
|
||||
rv = (mrt->s1 + mrt->s2) % M1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
double mrandDouble(mrand_t *mrt) {
|
||||
unsigned int rv;
|
||||
double dv;
|
||||
mrt->s1 = A1 * (mrt->s1 % Q1) - mrt->s1 * (mrt->s1/Q1);
|
||||
if (mrt->s1 <= 0) mrt->s1 += M1;
|
||||
mrt->s2 = A2 * (mrt->s2 % Q2) - mrt->s2 * (mrt->s2/Q2);
|
||||
if (mrt->s2 <= 0) mrt->s2 += M2;
|
||||
rv = (mrt->s1 + mrt->s2) % M1;
|
||||
dv = (double)rv / ((double)(M1-1));
|
||||
return dv;
|
||||
}
|
||||
|
||||
unsigned int mrandRange(unsigned int low, unsigned int high, mrand_t *mrt) {
|
||||
assert(low <= high);
|
||||
double drv = mrandDouble(mrt);
|
||||
unsigned int av = (unsigned int)(drv * (double)(high-low) + 0.5);
|
||||
return low + av;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef TIMER_MACRO_DEFINITIONS
|
||||
#define TIMER_MACRO_DEFINITIONS
|
||||
|
||||
/******************************************************************************/
|
||||
// Course: BSy
|
||||
// File: mtimer.h
|
||||
// Purpose: timer functions gettimeofday()
|
||||
// Author: M. Thaler, ZHAW, 1/2016
|
||||
// Version: v.fs20
|
||||
/******************************************************************************/
|
||||
// gettimeofday()
|
||||
// function: elapsed time: between start and stop
|
||||
// data type: gtimer_t
|
||||
// functions: startGTimer(gtimer_t tdata) -> start timer
|
||||
// stopGTimer(gtimer_t tdata) -> stop timer
|
||||
// double getWallGTime(gtimer_t tdata) -> get time in s
|
||||
// printGTime(X) -> print time in s
|
||||
//
|
||||
// -> see also "man gettimeofday"
|
||||
/******************************************************************************/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
typedef struct gtimer_t { struct timeval sT; \
|
||||
struct timeval eT; } gtimer_t;
|
||||
|
||||
#define startGTimer(X) gettimeofday(&X.sT, NULL)
|
||||
#define stopGTimer(X) gettimeofday(&X.eT, NULL)
|
||||
#define getGTime(X) ((double)(X.eT.tv_sec) - (double)(X.sT.tv_sec)) +\
|
||||
((double)X.eT.tv_usec - (double)X.sT.tv_usec)/1e6
|
||||
#define printGTime(X) printf("Run time %3.2lfs\n", getGTime(X))
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
./main.e 1
|
||||
./main.e 2
|
||||
./main.e 4
|
||||
Reference in New Issue
Block a user