// This program is Operation System's first project. // This proejct's name is producer-consumer relationship problem. // °ú ¸ñ : Operation System // ±³¼ö´Ô : ±è Á¤±¹ ±³¼ö´Ô // ÇÐ °ú : ÄÄÇ»ÅÍ °øÇаú // ÇÐ ³â : 4 Çгâ // ÇÐ ¹ø : 19980220 // ÀÌ ¸§ : ÀÌ ½Â ÀÍ #include #include #define MAX 10 #define MIN 0 void Initialize(void); // function declaration void c_push(int push_data); // function declaration void c_pop(); // function declaration pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t buffer_has_space = PTHREAD_COND_INITIALIZER; pthread_cond_t buffer_has_data = PTHREAD_COND_INITIALIZER; typedef struct Circular_queue circular_queue; typedef struct Data_type data_type; struct Circular_queue { data_type* pFirst; data_type* pEnd; int max; }; struct Data_type { int data; data_type* pNext; }; circular_queue c_queue; // Shared variables void* producer(void* p_id) { int i; for(i=0; i<5000; i++) { printf("Go in the Critical Section by pid=%d == ", &p_id); fflush(stdout); pthread_mutex_lock(&mutex); // Critical Section while (c_queue.max >= MAX) { printf("pid=%d | c_queue.max =%d == ", &p_id, c_queue.max); fflush(stdout); printf("pid=%d now sleeping! \n", &p_id); fflush(stdout); if (pthread_cond_wait(&buffer_has_space, &mutex) == -1 ) { printf("cond_wait error\n"); fflush(stdout); } printf("pid=%d wake up == ",&p_id); fflush(stdout); printf("c_queue.max=%d == ", c_queue.max); fflush(stdout); } printf("pid=%d == ", &p_id); fflush(stdout); c_push(i); pthread_cond_signal(&buffer_has_data); pthread_mutex_unlock(&mutex); printf("pid=%d loop count %d\n", &p_id, i); fflush(stdout); } printf("pid=%d pthread exit == loop count %d\n", &p_id, i); fflush(stdout); pthread_exit(NULL); } void* consumer(void* c_id) { int i; for(i=0; i<10000; i++) { printf("Go in the Critical Section by cid=%d == ", &c_id); fflush(stdout); pthread_mutex_lock(&mutex); //Critical Section while(c_queue.max <= MIN) { printf("cid=%d | c_queue.max =%d == ", &c_id, c_queue.max); fflush(stdout); printf(" cid=%d now sleeping! \n", &c_id); fflush(stdout); if(pthread_cond_wait(&buffer_has_data, &mutex) == -1 ) { printf("cond_wait_error\n"); fflush(stdout); } printf("cid=%d wake up == ",&c_id); fflush(stdout); printf("c_queue.max=%d == ", c_queue.max); fflush(stdout); } printf("cid=%d == ", &c_id); fflush(stdout); c_pop(); printf("consumer c_queue.max = %d", c_queue.max); fflush(stdout); pthread_cond_signal(&buffer_has_space); // pthread_cond_broadcast(&buffer_has_space); pthread_mutex_unlock(&mutex); printf("cid=%d loop count %d \n", &c_id, i); fflush(stdout); } printf("cid=%d pthread exit == loop count %d\n", &c_id, i); fflush(stdout); pthread_exit(NULL); } int main() { int i=0; int process_id[3]; Initialize(); // Initialize c_queue pthread_t threads[3]; pthread_create(&threads[0], NULL, producer, (void *)&process_id[0]); pthread_create(&threads[1], NULL, producer, (void *)&process_id[1]); pthread_create(&threads[2], NULL, consumer, (void *)&process_id[2]); for(i=0; i<3; i++) { pthread_join(threads[i], NULL); } } // c_queue's initializing function void Initialize() { c_queue.pFirst = NULL; c_queue.pEnd = NULL; c_queue.max = MIN; } void c_push(int push_data) { if( c_queue.max < MAX ) { if( c_queue.pFirst == NULL ) { // first push data_type* temp; temp = (data_type* )malloc(sizeof(data_type)); temp->data = push_data; c_queue.pFirst = temp; temp->pNext = c_queue.pEnd; c_queue.pEnd = temp; } else { data_type* temp; data_type* position = c_queue.pFirst; temp = (data_type* )malloc(sizeof(data_type)); temp->data = push_data; temp->pNext = position->pNext; position->pNext = temp; c_queue.pFirst = temp; } printf("** push %d ***", push_data); c_queue.max++; } else // if c_queue.max is true { printf("can't push data in queue because this queue is full! : max is %d \n", c_queue.max); } } void c_pop() { if( c_queue.max == MIN ) { printf("can't pop data in queue because this queue is empty!\n"); } else { data_type* temp; // if( c_queue.max == 1 ) // when this queue have one data if( c_queue.pFirst == c_queue.pEnd) { temp = c_queue.pFirst; c_queue.pFirst = NULL; c_queue.pEnd = NULL; } else { // when this queue have data more than one data_type* temp2; temp = c_queue.pEnd; temp2 = c_queue.pEnd->pNext; c_queue.pEnd = temp2; } printf("*** pop %d ***", temp->data); c_queue.max--; free(temp); } }