C’de ve POSIX ile Multithreading

Bu sene Doç. Dr. Aylin Kantarcı hocamızın verdiği İşletim Sistemleri 2 dersinde, süreç (process) ve iş parçacıklarının (thread) neler olduklarını ve nasıl işlediklerini ayrıntılı bir şekilde öğrendik. Bize verilen ikinci ödevde, iki matrisin çarpma işleminin her satırını bir iş parçacığına yaptıracağımız bir program istendi.

Ödevde, yaratılan bir thread çalışmaya başlamadan önce diğer tüm threadlerin yaratılmasını beklemeliydi. Biz de bu ödevi POSIX kütüphanesi ile hayata geçirdik.

POSIX: Linuxgiller. Onun için aşağıdaki kod Windows’ta çalışmaz.

Kaynak kodlarında mutex kullanımına örnek bulabilirsiniz. Kaynak kodlarını, ödev metnini ve ödev raporunu aşağıdan indirebilirsiniz. Kaynak kodu indirmek istemezseniz yazının devamına göz atabilirsiniz.

Dipnot: Kaynak kodları eğitim amaçlı olup, acemisi olduğum bir konu üzerinde yazılmış olduğundan bu kodları geliştirip Max Payne 3 yazarsanız ve yazdığınız oyun çökerse beni suçlayıp topuğuma sıkamayacağınızı bilmenizi isterim.

 #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <errno.h>

/* Mutex ve cond değişkenleri */ pthread_mutex_t condition_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t condition_cond = PTHREAD_COND_INITIALIZER;

pthread_mutex_t creating_theads_mutex = PTHREAD_MUTEX_INITIALIZER; int creating_theads = 0;

int *sharedMatrisA; int *sharedMatrisB; int *sharedMatrisC; int m; int n; int k;

void *matrisHesapla(int satirno) {

printf("Thread #%d init.\n",satirno+1); fflush(stdout);

/* Hala thread yaratma asamasindaysak bekle. */ if(creating_theads > 0) { printf("Thread #%d digerlerinin yaratilmasini beklemek uzere kitlenecek.\n",satirno+1); fflush(stdout); /* Yaratılınca bir bekle önce. */ pthread_mutex_lock( &condition_mutex ); printf("Thread #%d mutex locked.\n",satirno+1); fflush(stdout); pthread_cond_wait( &condition_cond, &condition_mutex ); printf("Thread #%d cond wait ended.\n",satirno+1); fflush(stdout); pthread_mutex_unlock( &condition_mutex );

printf("Thread #%d calismaya devam ediyor.\n",satirno+1); fflush(stdout); } else { pthread_mutex_unlock(&creating_theads_mutex); printf("Thread #%d beklemeye fırsat bulamadan tüm threadler yaratılmış.\n",satirno+1); fflush(stdout); }

printf("Thread #%d hesaplamaya basladi.\n",satirno+1); int ic1,ic2; for(ic1=0; ic1<k; ic1++) { for(ic2=0; ic2<n; ic2++) { /* Her thread kendi satırına yazdıgı için problem olmaz, mutexe gerek yok. */ sharedMatrisC[(satirno*k) + ic1] += sharedMatrisA[(satirno*n) + ic2] * sharedMatrisB[(ic2*k)+ic1]; } } printf("Thread #%d hesaplamayi bitirdi ve sonlandi.\n",satirno+1); }

int main() {

/* Acilis yazilari BASLANGICI */ printf("Umut BENZER\n"); printf("05-06-7670\n"); printf("Ege Universitesi Bilgisayar Muhendisligi 3\. Sinif\n"); printf("http://www.ubenzer.com\n"); printf("Threads\n\n"); /* Acilis yazilari SONU */

FILE *fp; if((fp=fopen("input.txt","r")) == NULL) { printf ("Dosya acilamadi."); exit(-1); }

fscanf(fp,"%d %d %d",&m, &n, &k);

int matrisA[m][n]; int matrisB[n][k]; int matrisC[m][k]; sharedMatrisA = &matrisA; sharedMatrisB = &matrisB; sharedMatrisC = &matrisC;

int i; int j;

for(i=0;i<m;i++) { for(j=0;j<k;j++) { matrisC[i][j] = 0; } }

/* A MATRISINI OKU */ for(i=0;i<m;i++) { for(j=0;j<n;j++) { fscanf(fp,"%d",&matrisA[i][j]); } }

/* B MATRISINI OKU */ for(i=0;i<n;i++) { for(j=0;j<k;j++) { fscanf(fp,"%d",&matrisB[i][j]); } }

fclose(fp);

/* EKRANA MATRISLERI YAZDIR */ printf("Matris A:\n"); for(i=0;i<m;i++) { for(j=0;j<n;j++) { printf("%d\t", matrisA[i][j]); } printf("\n"); }

printf("\nMatris B:\n"); for(i=0;i<n;i++) { for(j=0;j<k;j++) { printf("%d\t", matrisB[i][j]); } printf("\n"); }

printf("\n"); pthread_t threads[m]; fflush(stdout);

creating_theads = 1; printf("Threadler yaratılıyor...\n"); fflush(stdout); for(i=0;i<m;i++) { printf("Thread #%d/%d yaratıldı.\n",i+1,m); fflush(stdout); pthread_create(&threads[i], NULL, &matrisHesapla, i); }

pthread_mutex_lock(&creating_theads_mutex); creating_theads = 0; pthread_mutex_unlock(&creating_theads_mutex);

printf("Thread yaratimi tamamlamdi. Simdi beklemelerin bitmesi icin mesaj gonderilecek.\n"); fflush(stdout);

/* Threadler çalışabilirler */ pthread_mutex_lock( &condition_mutex ); pthread_cond_broadcast( &condition_cond ); pthread_mutex_unlock( &condition_mutex );

printf("Beklemekte olabilecek threadlere isleme baslamasini soyleyen mesaj gonderildi.\n");

fflush(stdout); for(i=0;i<m;i++) { printf("Main thread #%d/%d'nin bitmesini bekliyor...\n",i+1,m); pthread_join(threads[i],NULL); }

printf("\nMatris C:\n"); for(i=0;i<m;i++) { for(j=0;j<k;j++) { printf("%d\t", matrisC[i][j]); } printf("\n"); }

printf("\n"); printf("...ve bize ayrilan surenin sonuna geldik...\n"); printf("...bir sonraki odevde gorusmek uzere, esen kalin efendim...\n"); exit(0);

}