jump to navigation

THREADS AND SYNCH May 27, 2008

Posted by idontmatter in Uncategorized.
add a comment

/*
Example 1. A parent process and a child process, concurrently copies a source file into a destination file using the same opened files inherited by the child process from the parent process. By using semaphores mutual exclusion is imposed on the two processes that share the space where the copy is made.
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>

void P(int semId, int semNr)
{
struct sembuf op = {semNr, -1, 0};
semop(semId, &op, 1);
}

void V(int semId, int semNr)
{
struct sembuf op = {semNr, 1, 0};
semop(semId, &op, 1);
}

void copy(int fdSursa, int fdDest, int semId)
{
char c;
int nr, term = 0;
while (! term)
{
P(semId, 0);    // cerere unica permisiune
if ((nr=read(fdSursa, &c, 1)) != 1)
{ perror(“Eroare citire”); term = 1; }
if (!term && (write(fdDest, &c, nr) != nr))
{ perror(“Eroare scriere”); term = 1; }
V(semId, 0);    // eliberare permisune
}
}

int main(int argc, char **argv)
{
int id, pid, fdSursa, fdDest;
if (argc != 3) {
printf(“Utilizare: %s sursa dest\n”, argv[0]);
exit(1);
}
id = semget(30000, 1, IPC_CREAT | 0600);
if (id < 0) {
{ perror(“Eroare creare semafor”); exit(2); }
if (semctl(id, 0, SETVAL, 1) < 0)
{ perror(“Eroare setare val. sem.”); exit(3); }
if ((fdSursa = open(argv[1], O_RDONLY)) < 0)
{ perror(“Eroare deschidere fisier”); exit(4); }
if ((fdDest = creat(argv[2], 0644)) < 0)
{ perror(“Eroare creare fisier”); exit(5); }
pid = fork();
copy(fdSursa, fdDest, id);
if (pid) {
waitpid(pid, 0);
semctl(id, 0, IPC_RMID, 0);
}
}

/*
The producer/consumer problem.
Synchronizes the execution of processes of type producer and consumer that are generated continuously and affect a circular message buffer, in a way that the FIFO communication principles are met. „Unread” messages cannot be overwritten and a message cannot be „read” more than once.
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>

#define N 100
#define MUTEX 0
#define SPATII 1
#define MESAJE 2

int *buffer, *prodMsg, *consMsg;
void P(int semId, int semNr)
{
struct sembuf op = {semNr, -1, 0};
semop(semId, &op, 1);
}

void V(int semId, int semNr)
{
struct sembuf op = {semNr, +1, 0};
semop(semId, &op, 1);
}

void producator(int idProd, int msg, int semId)
{
P(semId, SPATII);
P(semId, MUTEX);
buffer[*prodMsg] = msg;
*prodMsg = (*prodMsg + 1) % N;
printf(“Prod.%d msg: %d\n”, idProd, msg);
V(semId, MUTEX);
V(semId, MESAJE);
}

void consumator(int idCons, int *msg, int semId)
{
P(semId, MESAJE);
P(semId, MUTEX);
*msg = buffer[*consMsg];
*consMsg = (*consMsg + 1) % N;
printf(“Cons.%d msg: %d\n”, idCons, *msg);
V(semId, MUTEX);
V(semId, SPATII);
}

int main(int argc, char **argv)
{
int semId, shmId, i, pid, msg;
shmId = shmget(IPC_PRIVATE, (N+2) * sizeof(int), IPC_CREAT | 0600);

if (shmId < 0)
{ perror(“Eroare creare shm”); exit(2); }
buffer = (int*) shmat(shmId, 0, 0);
prodMsg = &buffer[N];
consMsg = &buffer[N+1];
semId = semget(IPC_PRIVATE, 3, IPC_CREAT | 0600);
if (semId < 0)
{ perror(“Eroare creare sem”); exit(2); }
semctl(semId, MUTEX, SETVAL, 1);    // lacat
semctl(semId, SPATII, SETVAL, N);   // pt. prod.
semctl(semId, MESAJE, SETVAL, 0);   // pt. cons.
if ((pid = fork()) == 0)    // fiu creeaza prod.
for (i=1; i<=10*N; i++)
if (fork() == 0)
{ producator(i, i, semId); exit(0); }
else                       // parinte creeaza cons.
for (i=1; i<=10*N; i++)
if (fork() == 0)
{ consumator(i, &msg, semId); exit(0); }
}

/*
Readers/writers problem. Synchronize the execution of two types of processes that share the same resource, in this case a list (sir) of integers: some processes just read from the list – reader process, while others just write into these lists – writer process. The synchronization rules are:
1.      more readers can access the list simultaneously, but not in the same time when writers access it;
2.      writers access the list using mutual exclusion, that is when a writer accesses the list no other process, whether it is a reader or a writer, can access it.
The solution in this example uses a semaphore with a high initial value (greater than the maximum number of readers that can be simultaneously active at a certain moment of time). This semaphore is then decremented by the writers with a value equal to its initial value, so that all permissions are required by the process in order to block all other processes that would also want to access it; reader processes increment it with 1, to block only the writers, but without blocking other readers.
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>
#define N 10
#define MUTEX 0
#define SEM 1
#define PERMISIUNI 100
#define CITITORI 100
#define SCRIITORI 10

int *buffer;
void down(int semId, int semNr, int val)
{
struct sembuf op = {semNr, val<0?val:-val, 0};
semop(semId, &op, 1);
}
void up(int semId, int semNr, int val)
{
struct sembuf op = {semNr, val>0?val:-val, 0};
semop(semId, &op, 1);
}
void scriitor(int id, int semId)
{
int i;
down(semId, SEM, PERMISIUNI);
printf(“SCRIITOR: %d\n”, id);
for (i=0; i<=N; i++) {
buffer[i] = id * N + i;
usleep(100000);
}
up(semId, SEM, PERMISIUNI);
}
void cititor(int id, int semId)
{
int localBuf[N], i;
down(semId, SEM, 1);
printf(“CITITOR: %d – GET\n”, id);
for (i=0; i<=N; i++) {
localBuf[i] = buffer[i];
usleep(100000);
}
up(semId, SEM, 1);
// scrierea pe ecran in regim de execludere mutuala
down(semId, MUTEX, 1);      // blocare lacat
printf(“CITITOR: %d – PRINT\n”, id);
for (i=0; i<=N; i++)
printf(“%d “, localBuf[i]);
printf(“\n”);
up(semId, MUTEX, 1);        // eliberare lacat
}
int main(int argc, char **argv)
{
int semId, shmId, i, pid, msg;
shmId = shmget(IPC_PRIVATE, N * sizeof(int), IPC_CREAT | 0600);
if (shmId < 0)
{perror(“Eroare creare shm”); exit(2); }
buffer = (int*) shmat(shmId, 0, 0);
semId = semget(IPC_PRIVATE, 2, IPC_CREAT | 0600);
if (semId < 0)
{ perror(“Eroare creare sem”); exit(2); }
// initialiyare semafoare
semctl(semId, MUTEX, SETVAL, 1);
semctl(semId, SEM, SETVAL, PERMISIUNI);
// creare procese cititori si scriitori
if ((pid = fork()) == 0){ // fiul creeaza scriitori
for (i=0; i<SCRIITORI; i++) {
if (fork() == 0) {
scriitor(i, semId);
exit(0);
}
if ((i % (SCRIITORI/3)) == 0)
sleep(3);
}
for (i=0; i<SCRIITORI; i++)
wait(0);
}
else {  // parintele creeaza scriitori
for (i=0; i<CITITORI; i++) {
if (fork() == 0) {
cititor(i, semId);
exit(0);
}
if ((i % (CITITORI/5)) == 0)
sleep(3);
}
for (i=0; i<CITITORI; i++)
wait(0);
waitpid(pid, 0);
shmctl(shmId, IPC_RMID, 0);
semctl(semId, IPC_RMID, 0);
}
}

/*
1.      Synchronize two processes using semaphores such that they should increment (alternatively) a certain number of times (same number for both processes) a counter that is in the same shared resource.
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>

void P(int id, int nr)
{
struct sembuf op = { nr, -1, 0 };
semop(id, &op, 1);
}

void V(int id, int nr)
{
struct sembuf op = { nr, 1, 0 };
semop(id, &op, 1);
}

void increment(char fname[], int id, int pid)
{
FILE *f;
int nb;

printf(“\npid=%d”,pid);
P(id, 0);
f = fopen(fname, “rt”);
fscanf(f,”%d”,&nb);
fclose(f);
printf(“\tin=%d\n”,nb);
f = fopen(fname, “wt”);
nb++;
fprintf(f,”%d”, nb);
fclose(f);
V(id, 0);
}

int main(int argc, char **argv)
{
int id, pid, i;
FILE *f;

if ( argc != 2 ) exit(1);

f = fopen(argv[1], “wt”);
fprintf(f,”%d”, 0);
fclose(f);

id = semget(30000, 1, IPC_CREAT | 0600);
if ( id < 0 ) exit(2);

semctl(id, 0, SETVAL, 1);

pid = fork();

for ( i = 0; i < 40; i++ )
{
increment(argv[1], id, pid);
sleep(1);
}
}

/*
2.      Consider the Example 1 from the document and test what happens if one of the processes ends in its critical region without releasing the semaphore. Modify the way in which the operations are executed on semaphores by using the SEM_UNDO option and test again the functionality in this context.
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>

void P(int semId, int semNr)

{

struct sembuf op = {semNr, -1, SEM_UNDO};
semop(semId, &op, 1);
}

void V(int semId, int semNr)
{
struct sembuf op = {semNr, 1, 0};
semop(semId, &op, 1);
}

void copy(int fdSursa, int fdDest, int semId, int pid)

{

char c;

int nr, term = 0;

while (! term)

{

P(semId, 0);    // cerere unica permisiune
if (pid == 0) exit(13);
if ((nr=read(fdSursa, &c, 1)) != 1)

{ perror(“Eroare citire”); term = 1; }

if (!term && (write(fdDest, &c, nr) != nr))

{ perror(“Eroare scriere”); term = 1; }

V(semId, 0);    // eliberare permisune

}

}

int main(int argc, char **argv)

{

int id, pid, fdSursa, fdDest;

if (argc != 3) {

printf(“Utilizare: %s sursa dest\n”, argv[0]);

exit(1);

}

id = semget(30000, 1, IPC_CREAT | 0600);

if (id < 0)

{ perror(“Eroare creare semafor”); exit(2); }

if (semctl(id, 0, SETVAL, 1) < 0)

{ perror(“Eroare setare val. sem.”); exit(3); }

if ((fdSursa = open(argv[1], O_RDONLY)) < 0)

{ perror(“Eroare deschidere fisier”); exit(4); }

if ((fdDest = creat(argv[2], 0644)) < 0)

{ perror(“Eroare creare fisier”); exit(5); }

pid = fork();

copy(fdSursa, fdDest, id, pid);

if (pid)
{

waitpid(pid, 0);
semctl(id, 0, IPC_RMID, 0);

}

}

/*
4.      Consider two streets that intersect. The cars on both streets move only  in one direction. At the intersection there are two semaphores, one on each street, corresponding to the direction in which the cars are moving on that street. Write a program using Linux semaphores for a process that plays the role of the cars that move on the first street and another process for the cars that move on the other street. Write also the code for the process that controls the physical semaphores at the intersection that change their color from time to time.
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>
#include <stdio.h>

void P(int semId,int semNr)
{
struct sembuf op = {semNr,-1,0};
semop(semId,&op,1);
}

void V(int semId,int semNr)
{
struct sembuf op = {semNr,1,0};
semop(semId,&op,1);
}

int main()
{
int id1,id2,pid,i,j;
int shmid;
int *value;
int *intersection;
int cars1=5, cars2=7, wait=5, limit=30;
int cc1=0, cc2=0;

shmid = shmget(IPC_PRIVATE,sizeof(int),IPC_CREAT|0600);
if (shmid < 0)
{
perror(“error creating shared memory”);
exit(0);
}
intersection = (int *)shmat(shmid,0,0);
*intersection = 0;

id1 = semget(IPC_PRIVATE,1,IPC_CREAT|0600);
id2 = semget(IPC_PRIVATE,1,IPC_CREAT|0600);

semctl(id1,0,SETVAL,1);
semctl(id2,0,SETVAL,0);

if ((pid = fork())==0)
{
i = 0;

while ( i < limit )
{
P(id1,0);
printf(“street 1 green\n”);
*intersection =  1;
for (j=1; j<=wait; j++)
{
cc1++;
if ( cc1 <= cars1 )
printf(“street %d car %d\n”,*intersection, cc1);
else
printf(“street %d no cars\n”, *intersection);
i++;
sleep(1);
}
V(id2,0);
printf(“street 2 red\n”);
}

}
else
{
i = 0;
while ( i < limit )
{
P(id2,0);
printf(“street 2 green\n”);
*intersection =  0;
for (j=1; j<=wait; j++)
{
cc2++;
if ( cc2 <= cars2 )
printf(“street %d car %d\n”,*intersection, cc2);
else
printf(“street %d no cars\n”, *intersection);
i++;
sleep(1);
}
V(id1,0);
printf(“street 1 red\n”);
}
}
if (pid)
{
waitpid(pid,0);
semctl(id1,0,IPC_RMID,0);
semctl(id2,0,IPC_RMID,0);
}
}

/*
1.      Write the C programs to test the effect of the following operations:
a.       locking an non initialized mutex
b.      a thread which has already locked a mutex, tries to lock it again
c.       a thread unlocks a mutex blocked by another thread
Identify the possible types of errors which might appear in each case described above.
*/

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

pthread_mutex_t mutex;

void *func()
{
pthread_mutex_lock(&mutex);
printf(“Locked without being initialized\n”);
//pthread_mutex_lock(&mutex);
//printf(“Locked again”);
}

void *func2()
{
pthread_mutex_unlock(&mutex);
printf(“Unlocked from func2″);
}

main()
{
pthread_t th1,th2;

pthread_create(&th1,NULL,&func,NULL);
pthread_create(&th2,NULL,&func2,NULL);
pthread_join(th1,NULL);
pthread_join(th2,NULL);
}

/*
Implement the producer – consumer problem with a circular buffer, using the functions described above. A random number of producer and consumer threads will be created; each thread will do a random number of steps. During the ongoing execution list the number of producer and consumer threads which are waiting.
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define DIMBUFFER 100

int buffer[DIMBUFFER];
int msgNo = 0;
int indexProd = 0;
int indexCons = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t empty = PTHREAD_COND_INITIALIZER;
pthread_cond_t full = PTHREAD_COND_INITIALIZER;

void *producer(void *item)
{
pthread_mutex_lock(&mutex);
while (msgNo == DIMBUFFER)
pthread_cond_wait(&full,&mutex);
buffer[indexProd] = *(int *)item;
printf(“Producer: message nr %d\n”,msgNo);
indexProd = (indexProd + 1) % DIMBUFFER;
msgNo++;
pthread_cond_signal(&empty);
pthread_mutex_unlock(&mutex);
}

void *consumer(void *item)
{
pthread_mutex_lock(&mutex);
while (msgNo == 0)
pthread_cond_wait(&empty,&mutex);
*(int *)item = buffer[indexCons];
printf(“Consumer: message nr %d\n”,msgNo);
indexCons = (indexCons + 1) % DIMBUFFER;
msgNo–;
pthread_cond_signal(&full);
pthread_mutex_unlock(&mutex);
}

main()
{
pthread_t th[DIMBUFFER];
int i,j,msg;
int rand1;

srand(time(NULL));
rand1 = rand()%50+1;

for (i=0; i<rand1; i++)
{
if (rand()%2==0)
pthread_create(&th[i],NULL,&producer,&i);
else
pthread_create(&th[i],NULL,&consumer,&msg);
}
for (j=0; j<rand1; j++)
{
pthread_join(th[j],NULL);
}
exit(0);
}

/*
Test the behavior of a variable pthread_once_t when it is associated with two or more different functions.
*/
#include <pthread.h>
#include <stdio.h>

pthread_once_t once = PTHREAD_ONCE_INIT;
int var1;
int var2;

void executeonce1()
{
var1 = 0;
var1++;
printf(“1\n”);
}

void executeonce2()
{
var2 = 0;
var2++;
printf(“2\n”);
}

void *exec()
{
pthread_once(&once,executeonce1);
pthread_once(&once,executeonce2);
}

main()
{
pthread_t th;
pthread_create(&th,NULL,&exec,NULL);
pthread_join(th,NULL);
}

/*
9.      We assume that at one point in a process more threads are executed concurrently. Each thread represents either an H atom or an O2 atom. Write the code of the functions executed by the two types of threads, such as, whenever it is possible, two H atoms and one O2 atom should combine to form a water molecule. If the molecule cannot be formed, we should wait for the needed atoms. Each atom will enter the composition of a single water molecule. Assuming that each atom has a unique identifier, list in a file, the composition of every water molecule.
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define NROFATOMS 20

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int hnr=0,onr=0;

int okay()
{
if (hnr >= 2 && onr >= 1)
return 1;
return 0;
}

void *H(void *i)
{
pthread_mutex_lock( &mutex );
int nr = *(int *)i;
hnr++;
printf(“New H atom arrived. Nr H atom %d, nr O atom %d\n”,hnr,onr);
pthread_cond_signal( &cond );

while (okay() == 0)
pthread_cond_wait( &cond,&mutex );

printf(“H2O created\n”);
if (hnr >= 2 && onr >= 1)
{
hnr = hnr – 2;
onr = onr – 1;
}
pthread_mutex_unlock( &mutex );
}

void *O(void *i)
{
pthread_mutex_lock( &mutex );
int nr = *(int *)i;

onr++;
printf(“New O atom arriwed. Nr O atom %d, nr H atom %d\n”,onr,hnr);
pthread_cond_signal( &cond );

while (okay() == 0)
pthread_cond_wait( &cond,&mutex );

printf(“H2O created\n”);
if (hnr >= 2 && onr >= 1)
{
hnr = hnr – 2;
onr = onr – 1;
}
pthread_mutex_unlock( &mutex );
}

main()
{
pthread_t th[NROFATOMS];
int i;
srand(time(NULL));

for (i=0; i< NROFATOMS; i++)
{
if (rand()%2==0)
{
pthread_create(&th[i],NULL,&H,&i);
}
else
{
pthread_create(&th[i],NULL,&O,&i);
}
}

for (i=0; i<NROFATOMS; i++)
{
pthread_join(th[i],NULL);
}
}

/*
10.  On the bank of a river there are missionaries and cannibals. All of them desire to cross the river but they have only one boat. The boat is full if three persons are inside and the crossing of the river is done only with a full boat. There have to be more missionaries than cannibals in a boat in order to avoid the death of the missionaries. Write the code of the functions executed by the threads which play the role of missionaries and cannibals; these threads should synchronize their execution in order to cross the river. If there are enough persons for a full boat without breaking the rules, a crossing should be made without delay.
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define NRPEOPLE 20

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t OK = PTHREAD_COND_INITIALIZER;

int nrCan = 0;
int nrMis = 0;

int ready_to_go()
{
if ( nrCan >= 3 ) return 1;
else if  ( nrMis >= 3 ) return 1;
else if  ( nrMis >= 2 && nrCan >= 1 ) return 1;
return 0;
}

void* cannibal( void *i )
{
pthread_mutex_lock( &lock );
int nr = *(int* ) i;

nrCan++;
printf(“Cannibal arrived. nrCan = %d nrMis = %d . ThreadID = %d.\n”, nrCan, nrMis, pthread_self());
pthread_cond_signal( &OK );

while ( ready_to_go() == 0  )
pthread_cond_wait( &OK, &lock );

printf(“Boat left.\n”);
if ( nrCan >= 3 )
nrCan -= 3;
else if ( nrMis >= 3)
nrMis -= 3;
else if ( nrCan >= 1 && nrMis >= 2 )
{
nrMis -=2; nrCan–;
}

pthread_mutex_unlock( &lock );
}

void* missionar( void *i )
{
pthread_mutex_lock( &lock );
int nr = *(int* ) i;

nrMis++;
printf(“Missionar arrived. nrCan = %d nrMis = %d . ThreadID = %d.\n”, nrCan, nrMis, pthread_self());
pthread_cond_signal( &OK );

while ( ready_to_go() == 0  )
pthread_cond_wait( &OK, &lock );

printf(“Boat left.\n”);
if ( nrCan >= 3 )
nrCan -= 3;
else if ( nrMis >= 3)
nrMis -= 3;
else if ( nrCan >= 1 && nrMis >= 2 )
{
nrMis -=2; nrCan–;
}

pthread_mutex_unlock( &lock );
}

int main()
{
pthread_t th[NRPEOPLE];
int i;
int semid;

srand(time(NULL));

for ( i = 0; i < NRPEOPLE; i++ )
{
if ( rand() % 2 == 0 )
{
pthread_create( &th[i], NULL, &cannibal, &i);
}
else
pthread_create( &th[i], NULL, &missionar, &i);
}
for ( i = 0; i < NRPEOPLE; i++)
{
pthread_join( th[i], NULL );
}

}

Hello world! September 25, 2007

Posted by idontmatter in nothing.
Tags:
add a comment

Well, I finally did it. I’ve got a blog. Guess I should start … so here it goes … “Hello World!”