/* 1-Producer 1-Consumer Problem (pthread) Env.: ・Cygwin (もしくはPOSIX準拠のコンパイル・実行環境) Compile: % gcc sem01.c -o sem01 -lpthread Exec: % ./sem01 Note: ・TODO (2カ所) のコードを埋めてからコンパイル・実行すること ・使用した関数の意味や使い方は各自で調べ、理解すること ・threadに与えるデータ(動作停止時間)を変え、動作を確認すること */ #include #include #include #include /* for POSIX semaphore */ #include /* for POSIX thread */ #include #define N 8 /* リングバッファサイズ */ #define LEN 40 /* 生成メッセージ長 */ sem_t S; /* セマフォ M */ sem_t M; /* セマフォ S */ char Buffer[N]; /* リングバッファ用共有メモリ領域 */ struct threaddata { pthread_t th; struct timespec t; }; void *thread_producer(void *tdata) { struct threaddata *priv = (struct threaddata *)tdata; int I = 0; int count = 0; char mes; while(count<=LEN) { if((count/10)%2==0) { mes = '0' + (count % 10); /* メッセージ生成 */ } else { mes = 'A' + (count % 10); /* メッセージ生成 */ } sem_wait(&S); /* P(S) */ Buffer[I] = mes; sem_post(&M); /* V(M) */ I = ( I + 1 ) % N; count++; //printf("producer: [%c] count=%d, I=%d\n",mes,count,I); nanosleep(&priv->t,NULL); /* 指定時刻だけ実行停止 */ } /* done */ return (void *) NULL; } void *thread_consumer(void *tdata) { struct threaddata *priv = (struct threaddata *)tdata; int J = 0; int count = 0; char mes; while(count<=LEN) { /* TODO: P(M) */ mes = Buffer[J]; /* TODO: V(S) */ J = ( J + 1 ) % N; //printf("consumer: [%c] count=%d, J=%d\n",mes,count,J); printf("%c",mes); count++; fflush(stdout); nanosleep(&priv->t,NULL); /* 指定時刻だけ実行停止 */ } printf("\n"); /* done */ return (void *) NULL; } int main (void) { int r; struct threaddata data_producer; /* Producerスレッドに渡すデータ */ struct threaddata data_consumer; /* Consumerスレッドに渡すデータ */ /* スレッド初期化 */ /*** producerの待ち時間 */ data_producer.t.tv_sec = 0; /* 秒 */ data_producer.t.tv_nsec = 100*1000*1000; /* ナノ秒 */ /*** consumerの待ち時間 */ data_consumer.t.tv_sec = 0; /* 秒 */ data_consumer.t.tv_nsec = 500*1000*1000; /* ナノ秒 */ /*** 2種のsemaphorの初期化 */ sem_init(&S, 0, N); sem_init(&M, 0, 0); /*** thread生成 */ r = pthread_create(&data_producer.th, NULL, thread_producer, (void *) (&data_producer)); if (r != 0) { fprintf(stderr, "pthread_create() [%s] failed for %d.", "producer", r); exit(EXIT_FAILURE); } r = pthread_create(&data_consumer.th, NULL, thread_consumer, (void *) (&data_consumer)); if (r != 0) { fprintf(stderr, "pthread_create() [%s] failed for %d.", "consumer", r); exit(EXIT_FAILURE); } /* スレッド終了待ち + 終了処理 */ pthread_join(data_producer.th, NULL); pthread_join(data_consumer.th, NULL); sem_destroy(&S); sem_destroy(&M); exit(EXIT_SUCCESS); } /* EOF (sem01.c) */