I'm coding a multithreaded program for exercise. Given an array (100 positions) of random numbers, I have to divide it by 5 arrays and give them to 5 pthreads in order to find the maximum and return these values to the main function that find the maximum between them. These is my code so far:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define NUM_THREADS 5
#define DIM_VETTORE 100
void *Calcola_max(void* args){
}
int main(){
int vettore[DIM_VETTORE];
int t;
int i;
srand(time(NULL));
/*riempio il vettore con numeri random*/
for (i=0; i<DIM_VETTORE; i++){
vettore[i]=rand() % 500 + 1;
printf("Numero in posizione %d: %d\n", i,vettore[i]);
}
/*indico le dimensioni di ogni array splittato*/
int dimensione_split=DIM_VETTORE/NUM_THREADS;
printf("Dimensione degli array splittati: %d\n", dimensione_split);
/*creo tutti i thread*/
pthread_t thread[NUM_THREADS];
for (t=0;t<NUM_THREADS; t++){
printf("Main: creazione thread %d\n", t);
int rc;
rc=pthread_create(&thread[t], NULL, Calcola_max, &vettore);
if (rc) {
printf("ERRORE: %d\n", rc);
exit(-1);
}
}
}
My question are: how can I split the array? And how can I pass each array to each pthread? Thanks in advance
So, I've edited my code but this time it gives me segmentation fault after the pthread creation. IMO I'm wrong to pass the argument of thread function in this way:
...
pthread_create(&thread[t], NULL, Calcola_max, (void *)&start[i]);
...
void *Calcola_max(void *a){
...
s = *(int *)a;
...
Here is my entire code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define NUM_THREADS 5
#define DIM_VETTORE 100
int vettore[DIM_VETTORE];
int start[100];
int max[100]; //vettore dove vanno tutti i minimi calcolati dai pthread
void *Calcola_max(void *a){
int array;
int n=DIM_VETTORE/NUM_THREADS;
int s, i;
int start, stop;
int massimo;
s = *(int *)a;
start = s * n;
if ( s != (NUM_THREADS-1) )
{
stop = start + n;
}
else
{
stop = DIM_VETTORE;
}
massimo=vettore[start];
for (i = start+1; i < stop; i++ )
{
if ( vettore[i] > massimo )
massimo = vettore[i];
}
max[s] = massimo;
//array = (int) a;
int k;
int max=0;
for (k=0; k<DIM_VETTORE; k++){ //qui devo mettere il range corrente del vettore, o mettere uno split di vettore
printf("Massimo corrente: %d\n",max);
if (vettore[k]>max) max=vettore[k];
}
//return(NULL); /* Thread exits (dies) */
pthread_exit;
}
int main(){
//int vettore[DIM_VETTORE];
int massimo; //vettore dei minimi finale in cui opero confronto e calcolo il minimo
int t;
int i, j;
srand(time(NULL));
/*riempio il vettore con numeri random*/
for (i=0; i<DIM_VETTORE; i++){
//int num; //contenitore numero random
vettore[i]=rand() % 500 + 1;
//printf("Numero in posizione %d: %d\n", i,vettore[i]);
}
/*indico le dimensioni di ogni array splittato*/
int dimensione_split=DIM_VETTORE/NUM_THREADS;
printf("Dimensione degli array splittati: %d\n", dimensione_split);
/*creo tutti i thread*/
pthread_t thread[NUM_THREADS];
for (t=0;t<NUM_THREADS; t++){
start[i] = i;
printf("Main: creazione thread %d\n", t);
int rc;
//int pos_vettore;
//for (pos_vettore=0; pos_vettore<100; pos_vettore+20){
rc=pthread_create(&thread[t], NULL, Calcola_max, (void *)&start[i]);
if (rc) {
printf("ERRORE: %d\n", rc);
exit(-1);
}
//}
}
/*joino i threads*/
for (i = 0; i < NUM_THREADS; i++)
pthread_join(thread[i], NULL);
massimo= max[0];
sleep(3);
for (i = 1; i < NUM_THREADS; i++)
if ( max[i] > massimo )
massimo = max[i];
printf("Il massimo è: %d\n", massimo);
}
Your pthreads can access the array in your main program easily. You won't need to split the array for that. Just make sure that the pthreads are modifiying different parts of the main array. Use a struct or typedef to pass the relevant information to the pthread functions.
As mentioned, you don't split or copy the array.
Threads share the same regions of memory as the process that creates them, so you could just pass around the array.
If the aim of the game is to find some perf gain from using threads, then you almost certainly don't want to use heap allocated memory.
It's got to be said that there are probably better ways, I would probably look to SIMD or some other SSE extension before threads, but whatever ...
The following example, which has had about 5 minutes thought, and requires better error checking, and verification of the logic (because it's 9am on Sunday), demonstrates how I think the most efficient way to thread the calculations might be.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#define THREADS 5
#define DATA 100
typedef struct _pthread_arg_t {
pthread_t thread;
int *data;
unsigned int end;
int max;
} pthread_arg_t;
void* pthread_routine(void *arg) {
pthread_arg_t *info = (pthread_arg_t*) arg;
int *it = info->data,
*end = info->data + info->end;
while (it < end) {
if (*it > info->max) {
info->max = *it;
}
it++;
}
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_arg_t threads[THREADS];
int data[DATA],
thread = 0,
limit = 0,
result = 0;
memset(&threads, 0, sizeof(pthread_arg_t) * THREADS);
memset(&data, 0, sizeof(int) * DATA);
while (limit < DATA) {
/* you can replace this with randomm number */
data[limit] = limit;
limit++;
}
limit = DATA/THREADS;
while (thread < THREADS) {
threads[thread].data = &data[thread * limit];
threads[thread].end = limit;
if (pthread_create(&threads[thread].thread, NULL, pthread_routine, &threads[thread]) != 0) {
/* do something */
return 1;
}
thread++;
}
thread = 0;
while (thread < THREADS) {
if (pthread_join(threads[thread].thread, NULL) != 0) {
/* do something */
return 1;
}
thread++;
}
thread = 0;
result = threads[0].max;
printf("result:\n");
while (thread < THREADS) {
printf("\t%d - %d: %d\n",
thread * limit,
thread * limit + limit - 1,
threads[thread].max);
if (threads[thread].max > result) {
result = threads[thread].max;
}
thread++;
}
printf("max\t%d\n", result);
return 0;
}
Notice that this is lock and malloc free, you could probably reduce instructions further with more fiddling ...
Related
I have written a code for real-time logging. Here's the pseudo-code:
initialize Q; //buffer structure stores values to be printed
log(input)
{
push input to Q;
}
printLog() //infinte loop
{
loop(1)
{
if(Q is not empty)
{
values = pop(Q);
msg = string(values); //formating values into a message string
print(msg);
}
}
}
mainFunction()
{
loop(1)
{
/*
insert operations to be performed
*/
log(values); //log function called
}
}
main()
{
Create 4 threads; //1 mainFunction and 3 printLog
Bind them to CPUs;
}
I'm using atomic operations instead of locks.
When I print the output to the console, I see that each thread prints consecutively for a while. This must mean that once a thread enters printLog(), the other threads are inactive for a while.
What I want instead is while one thread is printing, another thread formats the next value popped from Q and prints it right after. How can this be achieved?
EDIT: I've realized the above information isn't sufficient. Here are some other details.
Buffer structure Q is a circular array of fixed size.
Pushing information to Q is faster than popping+printing. So by the time the Buffer structure is full, I want most of the information to be printed.
NOTE: mainFunction thread shouldn't wait to fill Buffer when it is full.
I'm trying to utilize all the threads at a given time. Currently, after one thread prints, the same thread reads and prints the next value (this means the other 2 threads are inactive).
Here's the actual code:
//use gcc main.c -o run -pthread
#define _GNU_SOURCE
#include <unistd.h>
#include <stdint.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <signal.h>
#include <stdlib.h>
#define N 3
/* Buffer size */
#define BUFFER_SIZE 1000
struct values
{
uint64_t num;
char msg[20];
};
struct values Q[BUFFER_SIZE];
int readID = -1;
int writeID = -1;
int currCount = 0;
void Log(uint64_t n, char* m)
{
int i;
if (__sync_fetch_and_add(&currCount,1) < BUFFER_SIZE)
{
i = __sync_fetch_and_add(&writeID,1);
i = i%BUFFER_SIZE;
Q[i].num = n;
strcpy(Q[i].msg, m);
}
else __sync_fetch_and_add(&currCount,-1);
}
void *printLog(void *x)
{
int thID = *((int*)(x));
int i;
while(1)
{
if(__sync_fetch_and_add(&currCount,-1)>=0)
{
i = __sync_fetch_and_add(&readID,1);
i = i%BUFFER_SIZE;
printf("ThreadID: %2d, count: %10d, message: %15s\n",thID,Q[i].num,Q[i].msg);
}
else __sync_fetch_and_add(&currCount,1);
}
}
void *mainFunction()
{
uint64_t i = 0;
while(1)
{
Log(i,"Custom Message");
i++;
usleep(50);
}
}
int main()
{
/* Set main() Thread CPU */
cpu_set_t cpusetMain;
CPU_ZERO(&cpusetMain);
CPU_SET(0, &cpusetMain);
if(0 != pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpusetMain))
printf("pthread_setaffinity_np failed for CPU: 0\n");
int LogThID[N+1];
pthread_t LogThreads[N+1];
/* Create Threads */
if (pthread_create(&LogThreads[0], NULL, &mainFunction, NULL) != 0){return 0;}
for(int i=1; i<N+1 ; i++)
{
LogThID[i] = i;
if (pthread_create(&LogThreads[i], NULL, &printLog, &LogThID[i]) != 0){return i;}
}
/* Set CPUs */
cpu_set_t cpuset[N+1];
for(int i=0; i<N+1; i++)
{
CPU_ZERO(&cpuset[i]);
CPU_SET(i+1, &cpuset[i]);
if(0 != pthread_setaffinity_np(LogThreads[i], sizeof(cpu_set_t), &cpuset[i]))
printf("pthread_setaffinity_np failed for CPU: %d\n", i+1);
}
struct sched_param param[N+1];
for(int i=0; i<N+1; i++)
{
param[i].sched_priority = 91;
if(0 != pthread_setschedparam(LogThreads[i],SCHED_FIFO,¶m[i]))
printf("pthread_setschedparam failed for CPU: %d\n", i);
}
/* Join threads */
for(int i=0; i<N+1; i++)
{
pthread_join(LogThreads[i], NULL);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <wait.h>
#include <pthread.h>
int item_to_produce, curr_buf_size;
int total_items, max_buf_size, num_workers, num_masters;
int consumed_items;
int *buffer;
pthread_mutex_t mutex;
pthread_cond_t has_data;
pthread_cond_t has_space;
void print_produced(int num, int master) {
printf("Produced %d by master %d\n", num, master);
}
void print_consumed(int num, int worker) {
printf("Consumed %d by worker %d\n", num, worker);
}
//consume items in buffer
void *consume_requests_loop(void *data)
{
int thread_id = *((int *)data);
while(1)
{
pthread_mutex_lock(&mutex); // mutex lock for consume
if(consumed_items == total_items) {
pthread_mutex_unlock(&mutex);
break;
}
while(curr_buf_size == 0) {
pthread_cond_wait(&has_data, &mutex);
}
print_consumed(buffer[(curr_buf_size--)-1], thread_id);
consumed_items++;
pthread_cond_signal(&has_space);
pthread_mutex_unlock(&mutex);
}
return 0;
}
//produce items and place in buffer
//modify code below to synchronize correctly
void *generate_requests_loop(void *data)
{
int thread_id = *((int *)data);
while(1) {
pthread_mutex_lock(&mutex); // mutex lock for consume
//all of items are produced
//master threads need to join
if(item_to_produce == total_items) {
pthread_mutex_unlock(&mutex);
break;
}
//there is no item to read
while (curr_buf_size == max_buf_size) {
pthread_cond_wait(&has_space, &mutex);
}
buffer[curr_buf_size++] = item_to_produce;
print_produced(item_to_produce, thread_id);
item_to_produce++;
pthread_cond_signal(&has_data);
pthread_mutex_unlock(&mutex); // mutex_produce unlock
}
return 0;
}
//write function to be run by worker threads
//ensure that the workers call the function print_consumed when they consume an item
int main(int argc, char *argv[])
{
int *master_thread_id; // array of master_thread_id
int *worker_thread_id; // array of worker_thread_id
pthread_t *master_thread; // array of master_thread
pthread_t *worker_thread; // array of worker_thread
item_to_produce = 0; // item will be produced by master_thread at next time
curr_buf_size = 0; // index of item will be saved in
consumed_items = 0;
int i;
if (argc < 5) {
printf("./master-worker #total_items #max_buf_size #num_workers #masters e.g. ./exe 10000 1000 4 3\n");
exit(1);
}
else {
num_masters = atoi(argv[4]);
num_workers = atoi(argv[3]);
total_items = atoi(argv[1]);
max_buf_size = atoi(argv[2]);
}
buffer = (int *)malloc (sizeof(int) * max_buf_size);
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&has_space, NULL);
pthread_cond_init(&has_data, NULL);
//create master producer threads
master_thread_id = (int *)malloc(sizeof(int) * num_masters);
master_thread = (pthread_t *)malloc(sizeof(pthread_t) * num_masters);
for (i = 0; i < num_masters; i++)
master_thread_id[i] = i;
for (i = 0; i < num_masters; i++)
pthread_create(&master_thread[i], NULL, generate_requests_loop, (void *)&master_thread_id[i]);
//create worker consumer threads
worker_thread_id = (int *)malloc(sizeof(int) * num_workers);
worker_thread = (pthread_t *)malloc(sizeof(pthread_t) * num_workers);
for (i = 0; i < num_workers; i++)
worker_thread_id[i] = i;
for (i = 0 ; i < num_workers; i++)
pthread_create(&worker_thread[i], NULL, consume_requests_loop, (void *)&worker_thread_id[i]);
//wait for all threads to complete
for (i = 0; i < num_masters; i++)
{
pthread_join(master_thread[i], NULL);
printf("master %d joined\n", i);
}
for (i = 0; i < num_workers; i++)
{
pthread_join(worker_thread[i], NULL);
printf("worker %d joined\n", i);
}
/*----Deallocating Buffers---------------------*/
free(buffer);
free(master_thread_id);
free(master_thread);
free(worker_thread_id);
free(worker_thread);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&has_data);
pthread_cond_destroy(&has_space);
return 0;
}
This code produces a number in the range of given numbers through the argument and consumes it.
But producer produces a number outside the range and doesn't join if it matches the condition. The consumer is too.
e.g when I give range of number like 0~39(total_item = 500), buff size 30(max_buf_size), num_workers 5, num_master 3, it doesn't produce and consume number only 0~39.
It produces and consumes numbers over 40.
In that way the thread is in a loop. To put the thread in sleep you can use, for example, the condition variables. (You can read this for more info https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_wait.html)
I am trying to square the numbers 1 - 10,000 with 8 threads. To clarify, I want the 1st thread to do 1^2, 2nd thread to do 2^2, ..., 8th thread to do 8^2, first thread to do 9^2... etc. The problem I am having is that instead of the above happening, each thread computes the squares of 1-10,000.
My code is below. I have marked sections that I'd rather those answering do not modify. Thanks in advance for any tips!
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#define NUMBER_OF_THREADS 8
#define START_NUMBER 1
#define END_NUMBER 10000
FILE *f;
void *sqrtfunc(void *tid) { //function for computing squares
int i;
for (i = START_NUMBER; i<=END_NUMBER; i++){
fprintf(f, "%lu squared = %lu\n", i, i*i);
}
}
int main(){
//Do not modify starting here
struct timeval start_time, end_time;
gettimeofday(&start_time, 0);
long unsigned i;
f = fopen("./squared_numbers.txt", "w");
//Do not modify ending here
pthread_t mythreads[NUMBER_OF_THREADS]; //thread variable
long mystatus;
for (i = 0; i < NUMBER_OF_THREADS; i++){ //loop to create 8 threads
mystatus = pthread_create(&mythreads[i], NULL, sqrtfunc, (void *)i);
if (mystatus != 0){ //check if pthread_create worked
printf("pthread_create failed\n");
exit(-1);
}
}
for (i = 0; i < NUMBER_OF_THREADS; i++){
if(pthread_join(mythreads[i], NULL)){
printf("Thread failed\n");
}
}
exit(1);
//Do not modify starting here
fclose(f);
gettimeofday(&end_time, 0);
float elapsed = (end_time.tv_sec-start_time.tv_sec) * 1000.0f + \
(end_time.tv_usec-start_time.tv_usec) / 1000.0f;
printf("took %0.2f milliseconds\n", elapsed);
//Do not modify ending here
}
Trying to use a bounded buffer from a separate file that I've coded and it seems like that's where the code goes all crazy. Fairly new to C, and I was wondering if I am using the buffer the right way. The concept of instantiation isn't here, so if I just call one of the functions such as bbuff_blocking_insert will the array get initialized? How do I make the appropriate calls in order to get this working?
candy.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "bbuff.h"
#include <stdbool.h>
#include <time.h>
_Bool stop_thread = false;
typedef struct {
int source_thread;
double time_stamp_in_ms;
} candy_t;
double current_time_in_ms (void) {
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return now.tv_sec * 1000.0 + now.tv_nsec/1000000.0;
}
void* createCandy(void* arg) {
int r;
int factoryNumber = *(int*)arg;
while(!stop_thread) {
r = rand() % 4;
printf("Random Number: %d\n", r);
printf("\tFactory %d ship candy & wait %ds\n", factoryNumber, r);
candy_t *candy = (candy_t*)malloc(sizeof(candy_t));
candy->source_thread = factoryNumber;
candy->time_stamp_in_ms = current_time_in_ms();
bbuff_blocking_insert((void *)candy);
sleep(r);
}
printf("Candy-factory %d done\n", factoryNumber);
return 0;
}
void* extractCandy(void* arg) {
int r;
candy_t* candy;
while(true) {
candy = (candy_t*)bbuff_blocking_extract();
printf("Candy Source Thread: %d\n", candy->source_thread);
r = rand() % 2;
sleep(r);
}
return 0;
}
int main(int argc, char* argv[]) {
//Extract Arguments
if (argc <= 1) {
printf("Insufficient Arguments\n");
exit(-1);
}
int NO_FACTORIES = atoi(argv[1]);
int NO_KIDS = atoi(argv[2]);
int NO_SECONDS = atoi(argv[3]);
bbuff_init();
//Spawn Factory Threads
pthread_t ftids[NO_FACTORIES];
int factoryNumber[NO_FACTORIES];
for (int i = 0; i < NO_FACTORIES; i++) {
factoryNumber[i] = i;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ftids[i], &attr, createCandy, &factoryNumber[i]);
}
//Spawn Kid Threads
pthread_t ktids [NO_KIDS];
for (int i = 0; i < NO_KIDS; i++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ktids[i], &attr, extractCandy, NULL);
}
//Wait for Requested Time
for (int i = 0; i < NO_SECONDS; i++) {
sleep(1);
printf("Time %ds\n", i+1);
}
//Stop Factory Threads
stop_thread = true;
for (int i = 0; i < NO_FACTORIES; i++) {
pthread_join(ftids[i], NULL);
}
//Wait until no more candy
while(bbuff_is_data_available()) {
printf("Waiting for all candy to be consumed");
sleep(1);
}
//Stop kid Threads
for (int i = 0; i < NO_KIDS; i++) {
pthread_cancel(ktids[i]);
pthread_join(ktids[i], NULL);
}
//Print Statistics
//Clean up any allocated memory
return 0;
}
bbuff.h
#ifndef BBUFF_H
#define BBUFF_H
#define QUEUE_SIZE 10
void bbuff_init(void);
void bbuff_blocking_insert(void* item);
void* bbuff_blocking_extract(void);
_Bool bbuff_is_data_available(void);
#endif
bbuff.c
#include "bbuff.h"
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int in = 0;
int out = 0;
int counter = 0;
void* buffer[QUEUE_SIZE];
void bbuff_init(void){
pthread_mutex_init(&mutex, NULL);
sem_init( &empty, 0, QUEUE_SIZE);
sem_init( &full, 0, 0);
}
void bbuff_blocking_insert(void* item) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);
counter++;
buffer[in] = item;
in = (in+1) % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
void* bbuff_blocking_extract(void) {
void* extractedItem;
sem_wait(&full);
pthread_mutex_lock(&mutex);
counter--;
extractedItem = buffer[out];
buffer[out] = NULL;
out = out % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
return extractedItem;
}
Output
$ ./candykids 1 1 10
Random Number: 3
Factory 0 ship candy & wait 3s
Candy Source Thread: 0
Time 1s
Time 2s
Random Number: 1
Factory 0 ship candy & wait 1s
Time 3s
Segmentation fault (core dumped)
In bbuff_blocking_extract(),
out = out % QUEUE_SIZE;
Should be:
out = (out+1) % QUEUE_SIZE;
So i am programming in c processes , and i need to create a timer that when it passes a certain point in my code it activates for x seconds, and then after the countdown timer hits 0 it does something. But in the meantime the code after the timer, needs to continue do to is work, following the flow of the code.
So in resume what i want to achieve is a countdown timer in c that when activated it creates another process were it counts the time and do something after.
Sorry if i did not explained this well enough.
Thanks in advance.
My code is the following so far i want to put the timer in the middle of the consumeTutuc method.
#include "sema.h"
#include <sys/shm.h>
//#include <sys/types.h>
#define MAX_CHILD 3 /* max. # of child processes */
#define LIFETIME 5 /* max. lifetime of a process */
#define MAX_NTIME 4 /* max. time for normal work */
#define MAX_CTIME 2 /* max. time for critical work */
#define N 10
#define SHMKEY (key_t) 0x10
#define SHMKEY2 (key_t) 0x11
#define SHMKEY3 (key_t) 0x12
#define SHMKEY4 (key_t) 0x13
//estruturas
typedef struct
{
int numeroPessoas;
char condicao;
}PESSOAS;
typedef struct
{
int id;
int espera;
}TUTUC;
int in, out, inP, outP, tt;
int *ptr; /*posicao do tuctuc*/
int *ptr2; /*numero disponiveis de tuctuc*/
PESSOAS *ptr3; /*fila de pessoas*/
int *ptr4; /*pessoas a espera*/
semaphore mutex, empty, full, emptyP, fullP, mutexP;
void produceTucTuc();
void consumeTucTuc();
void producePessoas();
void consumePessoas();
int main (void)
{
//MEMORIA
int shmid;
int shmid2;
int shmid3;
int shmid4;
char *addr;
char *addr2;
char *addr3;
char *addr4;
shmid = shmget(SHMKEY, N, 0777|IPC_CREAT);
shmid2 = shmget(SHMKEY2, N, 0777|IPC_CREAT);
shmid3 = shmget(SHMKEY3, N, 0777|IPC_CREAT);
shmid4 = shmget(SHMKEY4, N, 0777|IPC_CREAT);
addr=(char*)shmat(shmid,0,0);
addr2=(char*)shmat(shmid2,0,0);
addr3=(char*)shmat(shmid3,0,0);
addr4=(char*)shmat(shmid4,0,0);
ptr=(int*)addr;
ptr2=(int*)addr2;
ptr3=(PESSOAS*)addr3;
ptr4=(int*)addr4;
//MEMORIA
tt=1;
in=0;
out=0;
inP=0;
outP=0;
*ptr=0;
*ptr2=1;
//SEMAFOROS
full = init_sem(0);
empty = init_sem(N);
mutex = init_sem(1);
fullP = init_sem(0);
emptyP = init_sem(N);
mutexP = init_sem(1);
semaphore s;
//SEMAFOROS
int child_pid [MAX_CHILD], /* process ID's */
wait_pid;
int i, j,i2, /* loop variables */
child_stat; /* return status of child */
srand (time(NULL));
s = init_sem (1); /* create sem with value 1 */
for(i=0; i<10; i++){
produceTucTuc();
}
for (i = 0; i < MAX_CHILD; ++i)
{
child_pid [i] = fork ();
switch (child_pid [i])
{
case -1: /* error: no process created */
perror ("fork failed");
exit (1);
break;
case 0: /* child process */
/* up to Linux 2.0.x the process didn't terminate after
* LIFETIME seconds because "alarm()" and "sleep()" have
* used the same clock. This problem is solved in Linux 2.2.x
*/
if(i==0) produceTucTuc();
//if(i==1) consumeTucTuc();
if(i==1) producePessoas();
if(i==2) consumePessoas();
break;
default: /* parent process */
if (i == (MAX_CHILD - 1)) /* all childs created ? */
{ /* yes -> wait for termination */
for (j = 0; j < MAX_CHILD; ++j)
{
wait_pid = wait (&child_stat);
if (wait_pid == -1)
{
perror ("wait failed");
};
};
printf ("All child processes have terminated.\n");
//LIBERTA MEMORIA
rel_sem (s);
rel_sem (mutex);
rel_sem (empty);
rel_sem (full);
rel_sem (mutexP);
rel_sem (emptyP);
rel_sem (fullP);
shmdt(addr);
shmctl(shmid, IPC_RMID,NULL);
shmdt(addr2);
shmctl(shmid2, IPC_RMID,NULL);
shmdt(addr3);
shmctl(shmid3, IPC_RMID,NULL);
shmdt(addr4);
shmctl(shmid4, IPC_RMID,NULL);
//LIBERTA MEMORIA
};
}; /* end switch */
}; /* end for */
return 0;
}
void produceTucTuc(){
int ntuctuc;
alarm(LIFETIME);
//for(;;){
P(empty);
P(mutex);
*(ptr+in)=tt;
ntuctuc=*ptr2;
printf("------------------------------------\n");
printf("Produzi na pos %d o tuctuc %d\n",in,tt);
printf("Numero de TucTucs disponiveis:%d\n",ntuctuc);
in=(in+1)%N;
ntuctuc++;
*ptr2=ntuctuc;
tt=(tt+1)%N;
V(mutex);
V(full);
//}
}
void consumeTucTuc(){
int tuctuc;
int ntuctuc;
alarm(LIFETIME);
P(full);
P(mutex);
tuctuc=*(ptr+out);
ntuctuc=*ptr2;
ntuctuc--;
//printf("------------------------------------\n");
printf("Consumi na pos %d o tuctuc %d\n",out,tuctuc);
printf("Numero de TucTucs disponiveis:%d\n",ntuctuc);
out=(out+1)%N;
*ptr2=ntuctuc;
V(mutex);
V(empty);
}
void producePessoas(){
PESSOAS pessoa;
int espera =0;
alarm(LIFETIME);
for(;;){
P(emptyP);
P(mutexP);
if(rand()%5 == 0){
pessoa.numeroPessoas = 5;
}
else {
pessoa.numeroPessoas=rand()%5;
}
if(rand()%10<3){
pessoa.condicao = 'E';
}
else {
pessoa.condicao = 'N';
}
*(ptr3+inP)=pessoa;
espera=*ptr4;
espera=espera+pessoa.numeroPessoas;
*ptr4=espera;
printf("------------------------------------\n");
printf("Na pos %d entraram %d pessoas com %c condicao\n",inP,pessoa.numeroPessoas, pessoa.condicao);
printf("Estao %d pessoas à espera\n",*ptr4);
inP=(inP+1)%N;
V(mutexP);
V(fullP);
}
}
void consumePessoas(){
int pessoa;
int espera;
int p;
int aux;
alarm(LIFETIME);
while((*(ptr3 + outP)).numeroPessoas<(*ptr2)){
P(fullP);
P(mutexP);
pessoa=(*(ptr3+outP)).numeroPessoas;
espera=*ptr4;
espera=espera-pessoa;
*ptr4=espera;
printf("------------------------------------\n");
printf("Na pos %d sairam %d pessoas\n",inP,pessoa);
printf("Estao %d pessoas à espera\n",espera);
if(pessoa%2==1){
aux=(pessoa/2) + 1;
}else{
aux=pessoa/2;
}
for(p=0; p<aux; p++){
printf("%d\n",pessoa);
consumeTucTuc();
}
outP=(outP+1)%N;
V(mutexP);
V(emptyP);
}
}
This function you can call as a thread an it's a counter:
(You can build in a condition in the while loop and kill the thread!)
void counter( void *dummy ){
time_t start;
int weiter = 1,count = 0;
while (weiter) {
time(&start);
printf("\b\b\b\b%3i:",count);
while(difftime(time(NULL),start)<1);
count++;
//if condition kill thread
}
}