P10 lab code added
This commit is contained in:
		
							parent
							
								
									c7d4ec972e
								
							
						
					
					
						commit
						382018f539
					
				| 
						 | 
				
			
			@ -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 <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
 | 
			
		||||
#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++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
 | 
			
		||||
#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");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,92 @@
 | 
			
		|||
//******************************************************************************
 | 
			
		||||
// 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);
 | 
			
		||||
        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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,119 @@
 | 
			
		|||
//******************************************************************************
 | 
			
		||||
// 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++) {
 | 
			
		||||
            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);
 | 
			
		||||
}
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
 | 
			
		||||
#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++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
 | 
			
		||||
#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");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
#******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
* File:     customer.c
 | 
			
		||||
* Purpose:  customer thread
 | 
			
		||||
* Course:   bsy
 | 
			
		||||
* Author:   M. Thaler, 2011
 | 
			
		||||
* Revision: 5/2012
 | 
			
		||||
* Version:  v.fs20
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#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);  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//*****************************************************************************
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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 <sys/time.h>
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
* File:     startApp.c
 | 
			
		||||
* Purpose:  mutex with locks
 | 
			
		||||
* Course:   bsy
 | 
			
		||||
* Author:   M. Thaler, 2011
 | 
			
		||||
* Revision: 5/2012
 | 
			
		||||
* Version:  v.fs20
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//******************************************************************************
 | 
			
		||||
		Loading…
	
		Reference in New Issue