diff --git a/P10_Sync/Sync/advancedSequence/coffeeTeller.c b/P10_Sync/Sync/advancedSequence/coffeeTeller.c new file mode 100644 index 0000000..4b96adb --- /dev/null +++ b/P10_Sync/Sync/advancedSequence/coffeeTeller.c @@ -0,0 +1,46 @@ +/******************************************************************************* +* File: coffeTeller.c +* Purpose: simple sequence with semaphores +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012, 7/2013 +* Version: v.fs20 +*******************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "commonDefs.h" + +//****************************************************************************** + +int main(void) { + + int i; + sem_t *coin, *coffee, *ready; + + // set up a semaphore + coin = sem_open(COIN_SEMAPHOR, 0); + coffee = sem_open(COFFEE_SEMAPHOR, 0); + ready = sem_open(READY_SEMAPHOR, 0); + + // start teller machine + printf("\nCoffee teller machine starting\n\n"); + + i = 0; + while (i < ITERS) { + printf("teller (%d): waiting for coin\n", i); + printf(" (%d): got coin\n", i); + printf(" (%d): dispense coffee\n", i); + i++; + } +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/advancedSequence/commonDefs.h b/P10_Sync/Sync/advancedSequence/commonDefs.h new file mode 100644 index 0000000..597278d --- /dev/null +++ b/P10_Sync/Sync/advancedSequence/commonDefs.h @@ -0,0 +1,31 @@ +#ifndef MY_DEFINITIONS_HEADER +#define MY_DEFINITIONS_HEADER + +/******************************************************************************* +* File: commonDefs.h +* Purpose: common definitions +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012, 7/2013, 4/2014 +* Version: v.fs20 +*******************************************************************************/ + +#define MYTURN_SEMAPHOR "/my_semaphor_1_name_advaneced_seq" +#define COIN_SEMAPHOR "/my_semaphor_2_name_advaneced_seq" +#define COFFEE_SEMAPHOR "/my_semaphor_3_name_advaneced_seq" +#define READY_SEMAPHOR "/my_semaphor_4_name_advaneced_seq" + +#define ITERS (100*1000*1000) +#define CUSTOMERS 4 +#define NUM_COIN 3 + +//****************************************************************************** + +#define checkSem(X) {if (X == SEM_FAILED) {perror("sem_open"); exit(-1);}} + +#define drinkingCoffee(X) {usleep((((1+X)*rand())+100000)&0xFFFFF);} + +//****************************************************************************** + +#endif + diff --git a/P10_Sync/Sync/advancedSequence/customer.c b/P10_Sync/Sync/advancedSequence/customer.c new file mode 100644 index 0000000..a4609e5 --- /dev/null +++ b/P10_Sync/Sync/advancedSequence/customer.c @@ -0,0 +1,50 @@ +/******************************************************************************* +* File: customer.c +* Purpose: simple sequence with semaphores +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012, 7/2013 +* Version: v.fs20 +*******************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include "commonDefs.h" + +//****************************************************************************** + +int main(int argc, char *argv[]) { + + int i, myID; + sem_t *myTurn, *coin, *coffee, *ready; + + if (argc > 1) + myID = atoi(argv[1]); + else + myID = 0; + + // set up a semaphore + myTurn = sem_open(MYTURN_SEMAPHOR, 0); + coin = sem_open(COIN_SEMAPHOR, 0); + coffee = sem_open(COFFEE_SEMAPHOR, 0); + ready = sem_open(READY_SEMAPHOR, 0); + + // start customer + printf("Customer starting (%d)\n", myID); + + // now check the sum + for (i = 0; i < ITERS; i++) { + printf("\t\t\t\tcustomer(%d) put coin %d\n", myID, i); + printf("\t\t\t\tcustomer(%d) waiting for coffee %d\n", myID, i); + printf("\t\t\t\tcustomer(%d) got coffee %d\n", myID, i); + drinkingCoffee(myID); + } +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/advancedSequence/makefile b/P10_Sync/Sync/advancedSequence/makefile new file mode 100644 index 0000000..2891669 --- /dev/null +++ b/P10_Sync/Sync/advancedSequence/makefile @@ -0,0 +1,40 @@ +# BSy M. Thaler +# Version v.fs20 + +CMP= gcc -std=gnu99 +CMPFLAGS= -Wall -g +LIB= -pthread +EXENAME0= startApp.e +EXENAME1= coffeeTeller.e +EXENAME2= customer.e + +doit: + @make --no-print-directory clean + @make --no-print-directory startApp + @make --no-print-directory coffeeTeller + @make --no-print-directory customer + +startApp: startApp.o + $(CMP) $(CMPFLAGS) startApp.o $(LIB) -o $(EXENAME0) + +coffeeTeller: coffeeTeller.o + $(CMP) $(CMPFLAGS) coffeeTeller.o $(LIB) -o $(EXENAME1) + +customer: customer.o + $(CMP) $(CMPFLAGS) customer.o $(LIB) -o $(EXENAME2) + +.c.o: + $(CMP) -c $(CMPFLAGS) $< + +.cc.o: + $(CMP) -c $(CMPFLAGS) $< + +all: + @make clean + make doit + +clean: + @rm -f *.e *.o + +purge: + @make clean diff --git a/P10_Sync/Sync/advancedSequence/startApp.c b/P10_Sync/Sync/advancedSequence/startApp.c new file mode 100644 index 0000000..a1f3a6b --- /dev/null +++ b/P10_Sync/Sync/advancedSequence/startApp.c @@ -0,0 +1,72 @@ +/******************************************************************************* +* File: startApp.c +* Purpose: ice cream teller, basic sequence +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012, 7/2013 +* Version: v.fs20 +*******************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "commonDefs.h" + +//****************************************************************************** + +int main(void) { + + int j; + char string[8]; + sem_t *access, *coin, *coffee, *ready; + pid_t tellerPID; + + sem_unlink(MYTURN_SEMAPHOR); // delete seamphor if it still exists + sem_unlink(COIN_SEMAPHOR); // delete seamphor if it still exists + sem_unlink(COFFEE_SEMAPHOR); // delete seamphor if it still exists + sem_unlink(READY_SEMAPHOR); // delete seamphor if it still exists + + // set up a semaphore (? -> initial value of semaphor) + // checkSem() -> macro defined in commonDefs.h + + /* + access = sem_open(MYTURN_SEMAPHOR, O_CREAT, 0700, ?); checkSem(access); + coin = sem_open(COIN_SEMAPHOR, O_CREAT, 0700, ?); checkSem(coin); + coffee = sem_open(COFFEE_SEMAPHOR, O_CREAT, 0700, ?); checkSem(coffee); + ready = sem_open(READY_SEMAPHOR, O_CREAT, 0700, ?); checkSem(ready); + */ + + // now that the resources are set up, the supervisor can be started + for (j = 1; j <= CUSTOMERS; j++) { + if (fork() == 0) { + sprintf(string, "%d", j); + execl("./customer.e", "customer.e", string, NULL); + printf("*** could not start customer.e ***\n"); + } + } + + if ((tellerPID = fork()) == 0) { + execl("./coffeeTeller.e", "coffeeTeller.e", "0", NULL); + printf("*** could not start coffeTeller ***\n"); + } + + waitpid(tellerPID, NULL, 0); + system("killall coffeeTeller.e"); + system("killall customer.e"); // kill all customers + + // clean up resources + sem_unlink(MYTURN_SEMAPHOR); + sem_unlink(COIN_SEMAPHOR); + sem_unlink(COFFEE_SEMAPHOR); + sem_unlink(READY_SEMAPHOR); + printf("\n"); +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/banking/a1/banking.c b/P10_Sync/Sync/banking/a1/banking.c new file mode 100644 index 0000000..fbf20c1 --- /dev/null +++ b/P10_Sync/Sync/banking/a1/banking.c @@ -0,0 +1,103 @@ +//****************************************************************************** +// Course: BSy +// File: banking.c +// Author: M. Thaler, ZHAW +// Purpose: locking mechanisms +// Version: v.fs20 +//****************************************************************************** + +#include +#include +#include +#include + +#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); + } +} + +//****************************************************************************** + diff --git a/P10_Sync/Sync/banking/a1/banking.h b/P10_Sync/Sync/banking/a1/banking.h new file mode 100644 index 0000000..1b8ea98 --- /dev/null +++ b/P10_Sync/Sync/banking/a1/banking.h @@ -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); + +//****************************************************************************** + diff --git a/P10_Sync/Sync/banking/a1/main.c b/P10_Sync/Sync/banking/a1/main.c new file mode 100644 index 0000000..4efe5c6 --- /dev/null +++ b/P10_Sync/Sync/banking/a1/main.c @@ -0,0 +1,93 @@ +//****************************************************************************** +// Course: BSy +// File: main.c +// Author: M. Thaler, ZHAW +// Purpose: locking mechanisms +// Version: v.fs20 +//****************************************************************************** + +#include +#include +#include + +#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); +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/banking/a1/makefile b/P10_Sync/Sync/banking/a1/makefile new file mode 100644 index 0000000..889b1e5 --- /dev/null +++ b/P10_Sync/Sync/banking/a1/makefile @@ -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 +#----------------------------------------------------------------------------- diff --git a/P10_Sync/Sync/banking/a1/mrandom.h b/P10_Sync/Sync/banking/a1/mrandom.h new file mode 100644 index 0000000..3d91f4d --- /dev/null +++ b/P10_Sync/Sync/banking/a1/mrandom.h @@ -0,0 +1,74 @@ +#ifndef MY_RANDOMGENERATOR_DEFINITIONS +#define MY_RANDOMGENERATOR_DEFINITIONS + +#include +#include + +//****************************************************************************** +// 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 diff --git a/P10_Sync/Sync/banking/a1/mtimer.h b/P10_Sync/Sync/banking/a1/mtimer.h new file mode 100644 index 0000000..63aa950 --- /dev/null +++ b/P10_Sync/Sync/banking/a1/mtimer.h @@ -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 +#include +#include +#include + + +/******************************************************************************/ + +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 + diff --git a/P10_Sync/Sync/banking/a1/startApp b/P10_Sync/Sync/banking/a1/startApp new file mode 100755 index 0000000..211c509 --- /dev/null +++ b/P10_Sync/Sync/banking/a1/startApp @@ -0,0 +1,4 @@ +#!/bin/bash +./main.e 1 +./main.e 2 +./main.e 4 diff --git a/P10_Sync/Sync/banking/a2/banking.h b/P10_Sync/Sync/banking/a2/banking.h new file mode 100644 index 0000000..1b8ea98 --- /dev/null +++ b/P10_Sync/Sync/banking/a2/banking.h @@ -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); + +//****************************************************************************** + diff --git a/P10_Sync/Sync/banking/a2/main.c b/P10_Sync/Sync/banking/a2/main.c new file mode 100644 index 0000000..a7645e5 --- /dev/null +++ b/P10_Sync/Sync/banking/a2/main.c @@ -0,0 +1,92 @@ +//****************************************************************************** +// Course: BSy +// File: main.c +// Author: M. Thaler, ZHAW +// Purpose: locking mechanisms +// Version: v.fs20 +//****************************************************************************** + +#include +#include +#include + +#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); + 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); +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/banking/a2/makefile b/P10_Sync/Sync/banking/a2/makefile new file mode 100644 index 0000000..889b1e5 --- /dev/null +++ b/P10_Sync/Sync/banking/a2/makefile @@ -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 +#----------------------------------------------------------------------------- diff --git a/P10_Sync/Sync/banking/a2/mrandom.h b/P10_Sync/Sync/banking/a2/mrandom.h new file mode 100644 index 0000000..3d91f4d --- /dev/null +++ b/P10_Sync/Sync/banking/a2/mrandom.h @@ -0,0 +1,74 @@ +#ifndef MY_RANDOMGENERATOR_DEFINITIONS +#define MY_RANDOMGENERATOR_DEFINITIONS + +#include +#include + +//****************************************************************************** +// 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 diff --git a/P10_Sync/Sync/banking/a2/mtimer.h b/P10_Sync/Sync/banking/a2/mtimer.h new file mode 100644 index 0000000..63aa950 --- /dev/null +++ b/P10_Sync/Sync/banking/a2/mtimer.h @@ -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 +#include +#include +#include + + +/******************************************************************************/ + +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 + diff --git a/P10_Sync/Sync/banking/a2/startApp b/P10_Sync/Sync/banking/a2/startApp new file mode 100755 index 0000000..211c509 --- /dev/null +++ b/P10_Sync/Sync/banking/a2/startApp @@ -0,0 +1,4 @@ +#!/bin/bash +./main.e 1 +./main.e 2 +./main.e 4 diff --git a/P10_Sync/Sync/banking/a3/banking.c b/P10_Sync/Sync/banking/a3/banking.c new file mode 100644 index 0000000..e9694ce --- /dev/null +++ b/P10_Sync/Sync/banking/a3/banking.c @@ -0,0 +1,119 @@ +//****************************************************************************** +// Course: BSy +// File: banking.c +// Author: M. Thaler, ZHAW +// Purpose: locking mechanisms +// Version: v.fs20 +//****************************************************************************** + +#include +#include +#include +#include + +#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++) { + 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 i = 0; i < nBranches; i++) { + for (int j = 0; j < nAccounts; j++) { + sum += (long)bank[i].accounts[j].balance; + } + } + for (int i = 0; i < nBranches; i++) { + pthread_mutex_unlock(&bank[i].branchLock); + } + if (ibcError == 0) ibcError = sum; + return (ibcError != sum); +} +//****************************************************************************** + diff --git a/P10_Sync/Sync/banking/a3/banking.h b/P10_Sync/Sync/banking/a3/banking.h new file mode 100644 index 0000000..e8a4017 --- /dev/null +++ b/P10_Sync/Sync/banking/a3/banking.h @@ -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); + +//****************************************************************************** + diff --git a/P10_Sync/Sync/banking/a3/main.c b/P10_Sync/Sync/banking/a3/main.c new file mode 100644 index 0000000..623de36 --- /dev/null +++ b/P10_Sync/Sync/banking/a3/main.c @@ -0,0 +1,107 @@ +//****************************************************************************** +// Course: BSy +// File: main.c +// Author: M. Thaler, ZHAW +// Purpose: locking mechanisms +// Version: v.fs20 +//****************************************************************************** + +#include +#include +#include + +#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"); + +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/banking/a3/makefile b/P10_Sync/Sync/banking/a3/makefile new file mode 100644 index 0000000..889b1e5 --- /dev/null +++ b/P10_Sync/Sync/banking/a3/makefile @@ -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 +#----------------------------------------------------------------------------- diff --git a/P10_Sync/Sync/banking/a3/mrandom.h b/P10_Sync/Sync/banking/a3/mrandom.h new file mode 100644 index 0000000..3d91f4d --- /dev/null +++ b/P10_Sync/Sync/banking/a3/mrandom.h @@ -0,0 +1,74 @@ +#ifndef MY_RANDOMGENERATOR_DEFINITIONS +#define MY_RANDOMGENERATOR_DEFINITIONS + +#include +#include + +//****************************************************************************** +// 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 diff --git a/P10_Sync/Sync/banking/a3/mtimer.h b/P10_Sync/Sync/banking/a3/mtimer.h new file mode 100644 index 0000000..63aa950 --- /dev/null +++ b/P10_Sync/Sync/banking/a3/mtimer.h @@ -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 +#include +#include +#include + + +/******************************************************************************/ + +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 + diff --git a/P10_Sync/Sync/banking/a3/startApp b/P10_Sync/Sync/banking/a3/startApp new file mode 100755 index 0000000..211c509 --- /dev/null +++ b/P10_Sync/Sync/banking/a3/startApp @@ -0,0 +1,4 @@ +#!/bin/bash +./main.e 1 +./main.e 2 +./main.e 4 diff --git a/P10_Sync/Sync/basicSequence/coffeeTeller.c b/P10_Sync/Sync/basicSequence/coffeeTeller.c new file mode 100644 index 0000000..4b96adb --- /dev/null +++ b/P10_Sync/Sync/basicSequence/coffeeTeller.c @@ -0,0 +1,46 @@ +/******************************************************************************* +* File: coffeTeller.c +* Purpose: simple sequence with semaphores +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012, 7/2013 +* Version: v.fs20 +*******************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "commonDefs.h" + +//****************************************************************************** + +int main(void) { + + int i; + sem_t *coin, *coffee, *ready; + + // set up a semaphore + coin = sem_open(COIN_SEMAPHOR, 0); + coffee = sem_open(COFFEE_SEMAPHOR, 0); + ready = sem_open(READY_SEMAPHOR, 0); + + // start teller machine + printf("\nCoffee teller machine starting\n\n"); + + i = 0; + while (i < ITERS) { + printf("teller (%d): waiting for coin\n", i); + printf(" (%d): got coin\n", i); + printf(" (%d): dispense coffee\n", i); + i++; + } +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/basicSequence/commonDefs.h b/P10_Sync/Sync/basicSequence/commonDefs.h new file mode 100644 index 0000000..bf53a72 --- /dev/null +++ b/P10_Sync/Sync/basicSequence/commonDefs.h @@ -0,0 +1,30 @@ +#ifndef MY_DEFINITIONS_HEADER +#define MY_DEFINITIONS_HEADER + +/******************************************************************************* +* File: commonDefs.h +* Purpose: common definitions +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012, 7/2013, 4/2014 +* Version: v.fs20 +*******************************************************************************/ + +#define MYTURN_SEMAPHOR "/my_semaphor_1_name_simple_seq" +#define COIN_SEMAPHOR "/my_semaphor_2_name_simple_seq" +#define COFFEE_SEMAPHOR "/my_semaphor_3_name_simple_seq" +#define READY_SEMAPHOR "/my_semaphor_4_name_simple_seq" + +#define ITERS (100*1000*1000) +#define CUSTOMERS 4 + +//****************************************************************************** + +#define checkSem(X) {if (X == SEM_FAILED) {perror("sem_open"); exit(-1);}} + +#define drinkingCoffee(X) {usleep((((1+X)*rand())+100000)&0xFFFFF);} + +//****************************************************************************** + +#endif + diff --git a/P10_Sync/Sync/basicSequence/customer.c b/P10_Sync/Sync/basicSequence/customer.c new file mode 100644 index 0000000..a4609e5 --- /dev/null +++ b/P10_Sync/Sync/basicSequence/customer.c @@ -0,0 +1,50 @@ +/******************************************************************************* +* File: customer.c +* Purpose: simple sequence with semaphores +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012, 7/2013 +* Version: v.fs20 +*******************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include "commonDefs.h" + +//****************************************************************************** + +int main(int argc, char *argv[]) { + + int i, myID; + sem_t *myTurn, *coin, *coffee, *ready; + + if (argc > 1) + myID = atoi(argv[1]); + else + myID = 0; + + // set up a semaphore + myTurn = sem_open(MYTURN_SEMAPHOR, 0); + coin = sem_open(COIN_SEMAPHOR, 0); + coffee = sem_open(COFFEE_SEMAPHOR, 0); + ready = sem_open(READY_SEMAPHOR, 0); + + // start customer + printf("Customer starting (%d)\n", myID); + + // now check the sum + for (i = 0; i < ITERS; i++) { + printf("\t\t\t\tcustomer(%d) put coin %d\n", myID, i); + printf("\t\t\t\tcustomer(%d) waiting for coffee %d\n", myID, i); + printf("\t\t\t\tcustomer(%d) got coffee %d\n", myID, i); + drinkingCoffee(myID); + } +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/basicSequence/makefile b/P10_Sync/Sync/basicSequence/makefile new file mode 100644 index 0000000..4b2726a --- /dev/null +++ b/P10_Sync/Sync/basicSequence/makefile @@ -0,0 +1,40 @@ +# Author M. Thaler InIT/ZHAW +# Version v.fs20 + +CMP= gcc -std=gnu99 +CMPFLAGS= -Wall -g +LIB= -pthread +EXENAME0= startApp.e +EXENAME1= coffeeTeller.e +EXENAME2= customer.e + +doit: + @make --no-print-directory clean + @make --no-print-directory startApp + @make --no-print-directory coffeeTeller + @make --no-print-directory customer + +startApp: startApp.o + $(CMP) $(CMPFLAGS) startApp.o $(LIB) -o $(EXENAME0) + +coffeeTeller: coffeeTeller.o + $(CMP) $(CMPFLAGS) coffeeTeller.o $(LIB) -o $(EXENAME1) + +customer: customer.o + $(CMP) $(CMPFLAGS) customer.o $(LIB) -o $(EXENAME2) + +.c.o: + $(CMP) -c $(CMPFLAGS) $< + +.cc.o: + $(CMP) -c $(CMPFLAGS) $< + +all: + @make clean + make doit + +clean: + @rm -f *.e *.o + +purge: + @make clean diff --git a/P10_Sync/Sync/basicSequence/startApp.c b/P10_Sync/Sync/basicSequence/startApp.c new file mode 100644 index 0000000..06717b6 --- /dev/null +++ b/P10_Sync/Sync/basicSequence/startApp.c @@ -0,0 +1,72 @@ +/******************************************************************************* +* File: startApp.c +* Purpose: ice cream teller, basic sequence +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012, 7/2013 +* Version: v.fs20 +*******************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "commonDefs.h" + +//****************************************************************************** + +int main(void) { + + int j; + char string[8]; + sem_t *myTurn, *coin, *coffee, *ready; + pid_t tellerPID; + + sem_unlink(MYTURN_SEMAPHOR); // delete seamphor if it still exists + sem_unlink(COIN_SEMAPHOR); // delete seamphor if it still exists + sem_unlink(COFFEE_SEMAPHOR); // delete seamphor if it still exists + sem_unlink(READY_SEMAPHOR); // delete seamphor if it still exists + + // set up a semaphore (? -> initial value of semaphor) + // checkSem() -> macro defined in commonDefs.h + + /* + myTurn = sem_open(MYTURN_SEMAPHOR, O_CREAT, 0700, ?); checkSem(myTurn); + coin = sem_open(COIN_SEMAPHOR, O_CREAT, 0700, ?); checkSem(coin); + coffee = sem_open(COFFEE_SEMAPHOR, O_CREAT, 0700, ?); checkSem(coffee); + ready = sem_open(READY_SEMAPHOR, O_CREAT, 0700, ?); checkSem(ready); + */ + + // now that the resources are set up, the supervisor can be started + for (j = 1; j <= CUSTOMERS; j++) { + if (fork() == 0) { + sprintf(string, "%d", j); + execl("./customer.e", "customer.e", string, NULL); + printf("*** could not start customer.e ***\n"); + } + } + + if ((tellerPID = fork()) == 0) { + execl("./coffeeTeller.e", "coffeeTeller.e", "0", NULL); + printf("*** could not start coffeTeller ***\n"); + } + + waitpid(tellerPID, NULL, 0); + system("killall coffeeTeller.e"); + system("killall customer.e"); // kill all customers + + // clean up resources + sem_unlink(MYTURN_SEMAPHOR); + sem_unlink(COIN_SEMAPHOR); + sem_unlink(COFFEE_SEMAPHOR); + sem_unlink(READY_SEMAPHOR); + printf("\n"); +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/multiCPUs b/P10_Sync/Sync/multiCPUs new file mode 100755 index 0000000..f7cd5bc --- /dev/null +++ b/P10_Sync/Sync/multiCPUs @@ -0,0 +1,56 @@ +#!/bin/bash +#****************************************************************************** +# Purpose: turn off all CPU's but one (CPU 0), turn on all CPU's +# Linux only +# Author: M. Thaler, BSy 4/2014 + +# Usage: multiCPUs off: turn off all CPUs but one +# multiCPUs on: turn all CPUs on +# +# Version: v.fs20 +#****************************************************************************** + +theDir="/sys/devices/system/cpu" + +# check if sys exists +if test ! -d $theDir +then + echo "*** cannot set to single CPU ***" + exit 1 +fi + +# figure out what to do: multi CPUs off (single CPU) or all CPU's on +let status=1 +if test "$1" = "on" +then + let status=1 +else + if test "$1" = "off" + then + let status=0 + else + echo "*** what do you want: ... on or off? ***" + exit 1 + fi +fi + +# turn CPU's on or off + +cd $theDir + +CPUs=`ls -d cpu* | grep 'cpu[0-9][0-9]*'` +for CPU in $CPUs +do + if test ! "$CPU" = "cpu0" + then + echo "$CPU on = $status" + currVal=`cat ./$CPU/online` + # only change if different ... avoid error message + if test ! "$currVal" = "$status" + then + echo "$status" > "./$CPU/online" + fi + fi +done + +#****************************************************************************** diff --git a/P10_Sync/Sync/mutex/README_MAC_OSX b/P10_Sync/Sync/mutex/README_MAC_OSX new file mode 100644 index 0000000..fdf5c02 --- /dev/null +++ b/P10_Sync/Sync/mutex/README_MAC_OSX @@ -0,0 +1,7 @@ +For Mac users + +"pthread_mutex_lock(&lock)" is slow on MACs compared to Linux: + +use instead: "while (pthread_mutex_trylock(&lock) > 0) {} ;" + +which implements a spin lock diff --git a/P10_Sync/Sync/mutex/coffeeTeller.c b/P10_Sync/Sync/mutex/coffeeTeller.c new file mode 100644 index 0000000..de41d50 --- /dev/null +++ b/P10_Sync/Sync/mutex/coffeeTeller.c @@ -0,0 +1,46 @@ +/******************************************************************************* +* File: coffeTeller.c +* Purpose: coffe teller with pthreads +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012 +* Version: v.fs20 +*******************************************************************************/ + +#include +#include +#include +#include +#include + +#include + +#include "commonDefs.h" + +//****************************************************************************** + +void *coffeeTeller(void* data) { + + int i; + cData *cD = (cData *) data; + + // now start selling coffee + printf("\nCoffee teller machine starting\n\n"); + + i = 0; + while (i < ITERATIONS) { + if (cD->coinCount != cD->selCount1 + cD->selCount2) { + printf("error c = %5d s1 =%6d s2 =%6d diff: %4d\ti = %d\n", + cD->coinCount, cD->selCount1, cD->selCount2, + cD->coinCount - cD->selCount1 - cD->selCount2, + i); + cD->coinCount = 0; + cD->selCount1 = cD->selCount2 = 0; + } + if (i%1000000 == 0) printf("working\n"); + i++; + } + pthread_exit(0); +} + +//****************************************************************************** diff --git a/P10_Sync/Sync/mutex/coffeeTeller.h b/P10_Sync/Sync/mutex/coffeeTeller.h new file mode 100644 index 0000000..3cf9274 --- /dev/null +++ b/P10_Sync/Sync/mutex/coffeeTeller.h @@ -0,0 +1,17 @@ +#ifndef MY_DEFINITIONS_TELLER_H +#define MY_DEFINITIONS_TELLER_H + +/******************************************************************************* +* File: coffeTeller.h +* Purpose: coffe teller with pthreads +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012 +* Version: v.fs20 +*******************************************************************************/ + +void *coffeeTeller(void* data); + +//****************************************************************************** + +#endif diff --git a/P10_Sync/Sync/mutex/commonDefs.h b/P10_Sync/Sync/mutex/commonDefs.h new file mode 100644 index 0000000..074dc86 --- /dev/null +++ b/P10_Sync/Sync/mutex/commonDefs.h @@ -0,0 +1,32 @@ +#ifndef MY_DEFINITIONS_HEADER +#define MY_DEFINITIONS_HEADER + +/******************************************************************************* +* File: commonDefs.h +* Purpose: header file for common definitions +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012 +* Version: v.fs20 +*******************************************************************************/ + +#define ITERATIONS (100*1000*1000) + +//****************************************************************************** + +#define CUSTOMERS 4 // number of customers to be started + +//****************************************************************************** +// common data + +typedef struct { + int coinCount; // number of paid coffees + int selCount1; // number of chosen coffees of type 1 + int selCount2; // number of chosen coffees of type 2 + pthread_mutex_t lock; // common lock +} cData; + +//****************************************************************************** + +#endif + diff --git a/P10_Sync/Sync/mutex/customer.c b/P10_Sync/Sync/mutex/customer.c new file mode 100644 index 0000000..f340905 --- /dev/null +++ b/P10_Sync/Sync/mutex/customer.c @@ -0,0 +1,44 @@ +/******************************************************************************* +* File: customer.c +* Purpose: customer thread +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012 +* Version: v.fs20 +*******************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "commonDefs.h" +#include "mrand.h" + +//***************************************************************************** + +void *customer(void* data) { + float ranNum; + int i; + rand_t randnum; + + cData *cD = (cData *) data; + + rand_seed(&randnum, 0); + + // put coin and select coffee + for (i = 0; i < ITERATIONS; i++) { + ranNum = rand_float(&randnum); + cD->coinCount += 1; + if (ranNum < 0.5) + cD->selCount1 += 1; + else + cD->selCount2 += 1; + } + + pthread_exit(0); +} + +//***************************************************************************** diff --git a/P10_Sync/Sync/mutex/customer.h b/P10_Sync/Sync/mutex/customer.h new file mode 100644 index 0000000..58a2298 --- /dev/null +++ b/P10_Sync/Sync/mutex/customer.h @@ -0,0 +1,16 @@ +#ifndef MY_DEFINITIONS_CUSTOMER_H +#define MY_DEFINITIONS_CUSTOMER_H + +/******************************************************************************* +* File: customer.h +* Purpose: customer thread +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012 +* Version: v.fs20 +*******************************************************************************/ + +void *customer(void* data); + +//****************************************************************************** +#endif diff --git a/P10_Sync/Sync/mutex/makefile b/P10_Sync/Sync/mutex/makefile new file mode 100644 index 0000000..744e460 --- /dev/null +++ b/P10_Sync/Sync/mutex/makefile @@ -0,0 +1,33 @@ +# Author M. Thaler +# Version v.fs20 + +CMP= gcc -std=gnu99 +CMPFLAGS= -Wall -g +LIB= -pthread +EXENAME1= startApp.e + +INCLS= commonDefs.h +FILES= startApp.o coffeeTeller.o customer.o + +doit: + @make --no-print-directory clean + @make --no-print-directory coffeeTeller + +coffeeTeller: $(FILES) + $(CMP) $(CMPFLAGS) $(FILES) $(LIB) -o $(EXENAME1) + +.c.o: $(INCLS) + $(CMP) -c $(CMPFLAGS) $< + +.cc.o: $(INCLS) + $(CMP) -c $(CMPFLAGS) $< + +all: + @make clean + make doit + +clean: + @rm -f *.e *.o + +purge: + @make clean diff --git a/P10_Sync/Sync/mutex/mrand.h b/P10_Sync/Sync/mutex/mrand.h new file mode 100644 index 0000000..0535f7f --- /dev/null +++ b/P10_Sync/Sync/mutex/mrand.h @@ -0,0 +1,102 @@ +#ifndef MY_THREADSAVE_RANDOM_GENERATOR +#define MY_THREADSAVE_RANDOM_GENERATOR + +/****************************************************************************** +* File: mrand.h +* Purpose: simple portable thread save random generator +* ccording to Schrage +* Author: M. Thaler, 5/2012, BSy +* Version: v.fs20 +******************************************************************************/ + +#include + +//****************************************************************************** + +#define MMM_MR 2147483563 +#define AAA_MR 40014 +#define QQQ_MR 53668 +#define RRR_MR 12211 + +#define MRAND_MAX (MMM_MR-1) + +//****************************************************************************** + +typedef int rand_t; + +// seed ------------------------------------------------------------------------ + +void rand_seed(rand_t *srand, int seed) { + struct timeval prandom_seed; + gettimeofday(&prandom_seed, NULL); + if (seed > 0) + *srand = seed; + else + *srand = (prandom_seed.tv_usec); + +} + +// integer random value ------------------------------------------------------- +// range 0 .. MRAND_MAX (inclusive) + +int rand_int(rand_t *srand) { + int nx; + nx = AAA_MR * (*srand % QQQ_MR) - RRR_MR * (*srand / QQQ_MR); + *srand = (nx > 0) ? nx : nx + MMM_MR; + return (*srand); +} + +// float random value --------------------------------------------------------- +// range 0.0 .. 1.0 (inclusive) + +float rand_float(rand_t *srand) { + float fx; + *srand = rand_int(srand); + fx = (float)(*srand) / ((float)MRAND_MAX); + return (fx); +} + +// double random value -------------------------------------------------------- +// range 0.0 .. 1.0 (inclusive) + +double rand_double(rand_t *srand) { + double fx; + *srand = rand_int(srand); + fx = (double)(*srand) / ((double)MRAND_MAX); + return (fx); +} + +// unsigned int random range -------------------------------------------------- +// range low .. high + +unsigned int rand_range(unsigned int low, unsigned int high, rand_t *srand) { + unsigned int rv; + double prop; + prop = ((double)(high - low)) * rand_double(srand); + rv = low + ((unsigned int) prop); + return(rv); +} + +// unsigned int probability --------------------------------------------------- +// returns 0 or 1 + +unsigned int rand_prob(double prob, rand_t *srand) { + if (rand_double(srand) >= 1.0-prob) + return 1; + else + return 0; +} + +// unsigned int toss coin ----------------------------------------------------- +// returns 0 or 1 + +unsigned int toss_coin(rand_t *srand) { + if (rand_float(srand) >= 0.5) + return 1; + else + return 0; +} + +//****************************************************************************** + +#endif diff --git a/P10_Sync/Sync/mutex/startApp.c b/P10_Sync/Sync/mutex/startApp.c new file mode 100644 index 0000000..13ef658 --- /dev/null +++ b/P10_Sync/Sync/mutex/startApp.c @@ -0,0 +1,59 @@ +/******************************************************************************* +* File: startApp.c +* Purpose: mutex with locks +* Course: bsy +* Author: M. Thaler, 2011 +* Revision: 5/2012 +* Version: v.fs20 +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "commonDefs.h" +#include "coffeeTeller.h" +#include "customer.h" + +//****************************************************************************** +// common data + +cData cD; + +//****************************************************************************** + +int main(void) { + + unsigned int j; + int pthr; + + pthread_t tellerThread, customerThreads[CUSTOMERS]; + + cD.coinCount = 0; + cD.selCount1 = 0; + cD.selCount2 = 0; + pthread_mutex_init(&(cD.lock), NULL); + + // start teller and customers now that everything is set up + pthr = pthread_create(&tellerThread, NULL, coffeeTeller, &cD); + assert(pthr == 0); + for (j = 0; j < CUSTOMERS; j++) { + pthr = pthread_create(&(customerThreads[j]), NULL, customer, &cD); + assert(pthr == 0); + } + + // wait for all threads to terminate + pthread_join(tellerThread, NULL); + + for (j = 0; j < CUSTOMERS; j++) { + pthr = pthread_join(customerThreads[j], NULL); + assert(pthr == 0); + } +} + +//******************************************************************************