P10 lab code added

This commit is contained in:
Andreas Gieriet
2020-05-10 02:07:29 +02:00
parent c7d4ec972e
commit 382018f539
40 changed files with 1917 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
//******************************************************************************
// 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);
for (int i = 0; i < nBranches; i++) {
Bank[i].accounts = (Account *)malloc(nAccounts * sizeof(Account));
pthread_mutex_init(&(Bank[i].branchLock), &attr);
for (int j = 0; j < nAccounts; j++) {
Bank[i].accounts[j].balance = 0;
pthread_mutex_init((&(Bank[i].accounts[j].acntLock)), &attr);
}
}
}
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);
if (money >= 0)
deposit(toB, accountNr, money);
}
void checkAssets(void) {
static long assets = 0;
long sum = 0;
for (int i = 0; i < nBranches; i++) {
for (int j = 0; j < nAccounts; j++) {
sum += (long)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);
}
}
//******************************************************************************
+19
View File
@@ -0,0 +1,19 @@
//******************************************************************************
// 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 int withdraw(int branchNr, int accountNr, long int value) ;
void deposit(int branchNr, int accountNr, long int value);
void transfer(int fromB, int toB, int accountNr, long int value);
void checkAssets(void);
//******************************************************************************
+93
View File
@@ -0,0 +1,93 @@
//******************************************************************************
// 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 4
#define TRANSFERS (16*1024*1024)
#define ACCOUNTS (2048)
#define BRANCHES (128)
//******************************************************************************
// globals
int nThreads;
//******************************************************************************
// pusher
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));
val = withdraw(from, account, val);
if (val > 0)
deposit(to, account, val);
}
}
//******************************************************************************
// 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
for (long i = 0; i < nThreads; i++)
pthread_create(&th[i], NULL, pusher, (void *)i);
// wait for threads to terminate
for (int i = 0; i < nThreads; i++)
pthread_join(th[i], NULL);
stopGTimer(timer);
checkAssets();
printGTime(timer);
}
//******************************************************************************
+32
View File
@@ -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
#-----------------------------------------------------------------------------
+74
View File
@@ -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
+42
View File
@@ -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
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
./main.e 1
./main.e 2
./main.e 4