View difference between Paste ID: HpyBpnwU and g3f4MWw4
SHOW: | | - or go back to the newest paste.
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include "pthread.h"
4
#include "semaphore.h"
5
6
typedef struct GlobalState {
7
	pthread_mutex_t   ActMutex;	
8
	int               iFanPerType[2];	
9
	int               MustJoinCaptain;
10
	int               FansRemaining;
11
	pthread_t         aFanCarThread[4];
12
	pthread_mutex_t   BeginNewCar;
13
	pthread_barrier_t JoinTheCar;	
14
	sem_t             DoneSemaphore;
15
} GlobalState;
16
17
GlobalState g_tState;
18
19
void *FanThread(void *arg) {
20
	int n, iFan = (int)arg, iFansInCar;
21
	pthread_t tid = pthread_self();	
22
	
23
	//show the looking for message right after thread creation
24
	pthread_mutex_lock(&g_tState.ActMutex);
25
  printf("Thread ID: %lli, Team: %c, I am looking for a car\n",tid,'A'+iFan);	
26
	pthread_mutex_unlock(&g_tState.ActMutex);
27
		
28
	while (1) { 	
29
	  pthread_mutex_lock(&g_tState.ActMutex);		
30
	  //clean up last captain thread if any
31
		if (g_tState.MustJoinCaptain) {
32
		  pthread_join(g_tState.aFanCarThread[3], NULL );
33
			g_tState.MustJoinCaptain = 0;
34
	  }
35
		//number of fans on car is #A + #B
36
		iFansInCar = g_tState.iFanPerType[0]+g_tState.iFanPerType[1];		
37
		//allowed combinatios are 2:2 or 4:0
38
		if ((iFansInCar < 3) || (g_tState.iFanPerType[iFan] & 1)) {			
39
      //set the TID for this fan on a car slot (so we can wait & cleanup)
40
			g_tState.aFanCarThread[iFansInCar] = tid;
41
			g_tState.iFanPerType[iFan]++;
42
			
43
			//printf("Thread ID: %lli, Team: %c, I am looking for a car\n",tid,'A'+iFan);	
44
			
45
			// wait for 4 compatible fans to arrive before entering the car
46
			pthread_mutex_unlock(&g_tState.ActMutex);			
47
			pthread_barrier_wait( &g_tState.JoinTheCar );						
48
			pthread_mutex_trylock(&g_tState.BeginNewCar);
49
			pthread_mutex_lock(&g_tState.ActMutex);
50
			
51
			printf("Thread ID: %lli, Team: %c, I have found a spot in a car\n",tid,'A'+iFan);	
52
			pthread_mutex_unlock(&g_tState.ActMutex);
53
			//if this fan will fill a car, then it becomes the captain and a car is finished
54
			if (iFansInCar==3) {				
55
				//so then we can "join" the previous 3 fan threads that finished (thread cleanup)				
56
				for (n=0 ; n<iFansInCar ; n++) {
57
					pthread_join(g_tState.aFanCarThread[n], NULL );
58
				}				
59
				pthread_mutex_lock(&g_tState.ActMutex);			
60
				printf("Thread ID: %lli, Team: %c, I am the captain and driving the car\n",tid,'A'+iFan);
61
				g_tState.iFanPerType[0] = g_tState.iFanPerType[1] = 0;
62
				g_tState.MustJoinCaptain = 1;
63
				g_tState.FansRemaining -= 4;
64
				if (!g_tState.FansRemaining) { sem_post( &g_tState.DoneSemaphore ); }
65
				pthread_mutex_unlock(&g_tState.ActMutex);
66
				pthread_mutex_unlock(&g_tState.BeginNewCar);
67
				//when finishing a car a new one can start...				
68
			}
69
			//fan is inside a car so exit the thread			
70
			break;
71
		} else {			
72
			//printf("Thread ID: %lli, Team: %c, waiting for a new car...\n",tid,'A'+iFan);
73
			pthread_mutex_unlock(&g_tState.ActMutex);
74
			//wait for a new car
75
			pthread_mutex_lock(&g_tState.BeginNewCar);
76
			pthread_mutex_unlock(&g_tState.BeginNewCar);			
77-
	sem_post( &g_tState.DoneSemaphore );
77+
78
	}
79
		
80
}
81
82
void ManageThreads(int iNumA,int iNumB) {
83
	
84
	int i;
85
	pthread_t tid;
86
	
87
  //number of fans on each group must be even
88
	if ((iNumA & 1) || (iNumB & 1)) return;
89
	//total number must be a multiple of 4
90
	if ((iNumA+iNumB) & 3) return;	
91
	
92
	//initialize global state
93
	g_tState.FansRemaining = iNumA+iNumB;
94
	g_tState.MustJoinCaptain = 0;
95
	pthread_mutex_init(&g_tState.ActMutex, NULL);	
96
	pthread_mutex_init(&g_tState.BeginNewCar, NULL);	
97
	//pthread_mutex_lock(&g_tState.BeginNewCar);
98
	pthread_barrier_init(&g_tState.JoinTheCar, NULL, 4);	
99
	sem_init(&g_tState.DoneSemaphore, 0, 0);
100
	
101
	// creating threads
102
	for ( i=0 ; i<iNumA ; i++ ) {
103
    pthread_create(&tid, NULL, &FanThread, (void*)0);	
104
	}	
105
	
106
	for ( i=0 ; i<iNumB ; i++ ) {
107
    pthread_create(&tid, NULL, &FanThread, (void*)1);	
108
	}
109-
	for ( i=0 ; i<(iNumA+iNumB) ; i++ ) {
109+
110-
		sem_wait( &g_tState.DoneSemaphore );
110+
111
	sem_wait( &g_tState.DoneSemaphore );	
112
	//waiting for last thread to finish
113
	pthread_join(g_tState.aFanCarThread[3], NULL );	
114
	
115
	//free resources
116
	pthread_barrier_destroy(&g_tState.JoinTheCar);	
117
	sem_destroy(&g_tState.DoneSemaphore);
118
	pthread_mutex_destroy(&g_tState.ActMutex);
119
	pthread_mutex_destroy(&g_tState.BeginNewCar);
120
}
121
122
int main(int argc, char *argv[]) {
123
	int iNumA,iNumB;
124
		
125
	//number of arguments must be 3...
126
	//ProgramName , FansA , FansB
127
	if (argc == 3) {	
128
		//fans of different members
129
		iNumA = atoi(argv[1]);
130
		iNumB = atoi(argv[2]);	
131
	  ManageThreads( iNumA , iNumB );
132
	}
133
			
134
	puts("main terminates");	
135
	return 0;
136
}
137