You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.5 KiB
125 lines
3.5 KiB
/* 1-Producer 1-Consumer Problem (pthread)
|
|
|
|
Env.:
|
|
・Cygwin (もしくはPOSIX準拠のコンパイル・実行環境)
|
|
|
|
Compile:
|
|
% gcc sem01.c -o sem01 -lpthread
|
|
|
|
Exec:
|
|
% ./sem01
|
|
|
|
Note:
|
|
・TODO (2カ所) のコードを埋めてからコンパイル・実行すること
|
|
・使用した関数の意味や使い方は各自で調べ、理解すること
|
|
・threadに与えるデータ(動作停止時間)を変え、動作を確認すること
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <semaphore.h> /* for POSIX semaphore */
|
|
#include <pthread.h> /* for POSIX thread */
|
|
#include <time.h>
|
|
|
|
#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) */
|
|
|