From: 001 on 12 Nov 2009 09:34 On 12 nov, 15:22, David Resnick <lndresn...(a)gmail.com> wrote: > On Nov 12, 8:20 am, 001 <snthib...(a)gmail.com> wrote: > > > > > > > I tried to make a producer of 'items' but my implementation crashes at > > pthread_cond_wait ... I really tried looking at everything and put > > print statements throughout my code, but there it just crashes. I did > > put the wait within a mutex. This code isn't complete, but the > > relevant parts are in there (I assume). Any idea what I did wrong? > > This is the first time I used condition variables. Oh yeah... another > > question: is it possible to wait on multiple condition variables (and > > continue when one of them changes)? So that I can stop a thread > > independent of whether or not it is waiting for something? > > > Sincerely, > > > Stéphane Thibaud > > > #include <stdio.h> > > #include <stdlib.h> > > #include <stdbool.h> > > #include <pthread.h> // needed for pthreads > > #include <unistd.h> // for usleep() > > > #include "prodcons.h" > > > static unsigned int prodCount = 0; // The number of produces items > > static unsigned int bufferHead = 0; // Indicates the first free place > > in buffer or undefined when prodCount = BUFFER_SIZE > > static unsigned int inBufferCnt = 0; // Number of items in buffer > > static pthread_mutex_t bufferLock; > > static pthread_cond_t bufferNotFull; > > static pthread_cond_t availForCons[NROF_CONSUMERS]; // Conditions > > variables for the availability of items on the belt (per consumer) > > static const unsigned short int ALL_ONES = 0xFFFF; > > static int producing = 1; > > > static void rsleep (int t); > > > static void * producer (/*void * arg*/) > > { > > ITEM item; // a produced item > > > while (prodCount < NROF_ITEMS) // While not all items are produced > > { > > rsleep (PRODUCER_SLEEP_FACTOR); > > > item = (random() % NROF_CONSUMERS) + (prodCount << NROF_BITS_DEST); > > prodCount++; > > pthread_mutex_lock(&bufferLock); > > printf("justlocked\n"); > > if(inBufferCnt == BUFFER_SIZE) > > { > > printf("full buffer\n"); > > pthread_cond_wait(&bufferNotFull, &bufferLock); > > printf("not full anymore\n"); > > } > > buffer[bufferHead] = item; > > bufferHead = (bufferHead + 1) % BUFFER_SIZE; > > inBufferCnt++; > > if(inBufferCnt == 1) > > { > > printf("consumer signaled\n"); > > pthread_cond_signal(&availForCons[buffer[bufferHead - 1] & ~ > > (ALL_ONES << NROF_BITS_DEST)]); > > } > > printf("%04x\n", item); // write info to stdout, putting it inside > > the CS ensures no two threads write to stdout at the same time > > printf("unlockingnext\n"); > > pthread_mutex_unlock(&bufferLock); > > } > > > producing = 0; > > > return NULL; > > > } > > The stuff quoted below from the linux man page *may* apply. Followups > set to comp.unix.programmer, which is a better place for you to get > help on this. I'd also suggest running it under valgrind if you have > it available, if you do have uninitialized variables/overruns/etc that > will help you discover them. You could also check the returns of the > lock/cond_wait calls for failure, as it is possible under some > circumstances and it could help you figure out what is going on. > > **************************** > Some implementations, particularly on a multi-processor, > may sometimes cause multiple threads to wake up when the condition > variable is signaled simultaneously on different processors. > > In general, whenever a condition wait returns, the thread has > to re-evaluate the predicate associated with the condition wait to > determine whether it can safely proceed, should wait again, > or should declare a timeout. A return from the wait does not imply > that the associated predicate is either true or false. > > It is thus recommended that a condition wait be enclosed in the > equivalent of a "while loop" that checks the predicate. > ***************************** > > -David- Masquer le texte des messages précédents - > > - Afficher le texte des messages précédents - Thanks for your reply. This isn't the problem however... the pthread_create simply segfaults and doesn't return. Multiple cpu's or cores aren't present in my system either. Is it possible that this doesn't work because I'm using cygwin?
From: David Schwartz on 12 Nov 2009 11:08 On Nov 12, 6:34 am, 001 <snthib...(a)gmail.com> wrote: > Thanks for your reply. This isn't the problem however... the > pthread_create simply segfaults and doesn't return. Multiple cpu's or > cores aren't present in my system either. Is it possible that this > doesn't work because I'm using cygwin? I assume you mean pthread_cond_timedwait segfaults. Make sure you properly initialize the c.v. and don't create it on the stack of a function that returns! Post the code that signals the c.v. DS
From: 001 on 12 Nov 2009 11:25 On 12 nov, 17:08, David Schwartz <dav...(a)webmaster.com> wrote: > On Nov 12, 6:34 am, 001 <snthib...(a)gmail.com> wrote: > > > Thanks for your reply. This isn't the problem however... the > > pthread_create simply segfaults and doesn't return. Multiple cpu's or > > cores aren't present in my system either. Is it possible that this > > doesn't work because I'm using cygwin? > > I assume you mean pthread_cond_timedwait segfaults. Make sure you > properly initialize the c.v. and don't create it on the stack of a > function that returns! Post the code that signals the c.v. > > DS Thanks for looking... This is the whole code... There is no timedwait but just a wait. The code that would send a signal is never reached however (probably because of a long sleep in that thread and it thus segfaults before a signal is received). Sincerely, Stéphane #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <pthread.h> // needed for pthreads #include <unistd.h> // for usleep() #include "prodcons.h" static unsigned int prodCount = 0; // The number of produces items static unsigned int bufferHead = 0; // Indicates the first free place in buffer or undefined when prodCount = BUFFER_SIZE static unsigned int inBufferCnt = 0; // Number of items in buffer static pthread_mutex_t bufferLock; static pthread_cond_t bufferNotFull; static pthread_cond_t availForCons[NROF_CONSUMERS]; // Conditions variables for the availability of items on the belt (per consumer) static const unsigned short int ALL_ONES = 0xFFFF; static int producing = 1; static void rsleep (int t); /* producer thread */ static void * producer (void * arg) { ITEM item; // a produced item arg = arg; while (prodCount < NROF_ITEMS) // While not all items are produced { rsleep (PRODUCER_SLEEP_FACTOR); // TODO: produce new item and put it into buffer[] item = (random() % NROF_CONSUMERS) + (prodCount << NROF_BITS_DEST); prodCount++; printf("m%d\n",pthread_mutex_lock(&bufferLock)); printf("justlocked\n"); if(inBufferCnt == BUFFER_SIZE) { printf("full buffer\n"); printf("c%d\n",pthread_cond_wait(&bufferNotFull, &bufferLock)); printf("not full anymore\n"); } buffer[bufferHead] = item; bufferHead = (bufferHead + 1) % BUFFER_SIZE; inBufferCnt++; if(inBufferCnt == 1) { printf("consumer signaled\n"); pthread_cond_signal(&availForCons[buffer[bufferHead - 1] & ~ (ALL_ONES << NROF_BITS_DEST)]); } printf("%04x\n", item); // write info to stdout, putting it inside the CS ensures no two threads write to stdout at the same time printf("unlockingnext\n"); pthread_mutex_unlock(&bufferLock); } producing = 0; return NULL; } /* consumer thread */ void * consumer (void * arg) { ITEM item; // a consumed item int id; // identifier of this consumer (value 0..NROF_CONSUMERS-1) // Set the id id = *(int*)arg; printf("%d",id); while (producing || inBufferCnt > 0) { rsleep (100 * NROF_CONSUMERS); printf("cLock\n\n\n\n"); if(inBufferCnt == 0 || (buffer[bufferHead - 1] & ~(ALL_ONES << NROF_BITS_DEST)) != id) // inBufferCnt == 0 or the item might be for another consumer (caused by a previous iteration) { printf("c%d\n",pthread_cond_wait(&availForCons[id], &bufferLock)); } item = buffer[bufferHead - 1]; bufferHead = (bufferHead + BUFFER_SIZE - 1) % BUFFER_SIZE; inBufferCnt--; if(inBufferCnt == BUFFER_SIZE - 1) { pthread_cond_signal(&bufferNotFull); } else if(inBufferCnt > 0 && (buffer[bufferHead - 1] & ~(ALL_ONES << NROF_BITS_DEST)) != id) { pthread_cond_signal(&availForCons[buffer[bufferHead - 1] & ~ (ALL_ONES << NROF_BITS_DEST)]); } printf("%*s C%d:%04x\n", 7*id, "", id, item); // write info to stdout (with indentation) printf("cUnlock\n"); pthread_mutex_unlock(&bufferLock); } return NULL; } int main (/*int argc, char * argv[]*/) { int consumerCount = 0; int consumerIter; int exitcode = 0; pthread_t producerTh; pthread_t consumerTh[NROF_CONSUMERS]; // Initializations srandom (time(NULL)); pthread_mutex_init(&bufferLock, NULL); pthread_cond_init(&bufferNotFull, NULL); for(consumerIter = 0; consumerIter < NROF_CONSUMERS; consumerIter++) { pthread_cond_init(&availForCons[consumerIter], NULL); } // Create a producer-thread and NROF_CONSUMERS consumer-threads while(consumerCount < NROF_CONSUMERS && !pthread_create(&consumerTh [consumerCount], NULL, consumer, (void *)consumerCount)) { consumerCount++; } if(consumerCount != NROF_CONSUMERS || pthread_create(&producerTh, NULL, producer, NULL)) { printf("Some thread could not be created. There might have been insufficient resources available. Now quitting..."); exitcode = -1; } // Wait until all threads are finished for(consumerIter = 0; consumerIter < consumerCount; consumerIter++) { pthread_join(consumerTh[consumerIter], NULL); } pthread_join(producerTh, NULL); // Close everything pthread_mutex_destroy(&bufferLock); pthread_cond_destroy(&bufferNotFull); for(consumerIter = 0; consumerIter < NROF_CONSUMERS; consumerIter++) { pthread_cond_destroy(&availForCons[consumerIter]); } return (exitcode); } /* * rsleep(int t) * * The calling thread will be suspended for a random amount of time between 0 and t microseconds */ static void rsleep (int t) { usleep (random () % t); }
From: David Schwartz on 12 Nov 2009 12:31 On Nov 12, 8:25 am, 001 <snthib...(a)gmail.com> wrote: > > /* consumer thread */ > void * consumer (void * arg) > { > ITEM item; // a consumed item > int id; // identifier of this consumer (value > 0..NROF_CONSUMERS-1) > > // Set the id > id = *(int*)arg; > printf("%d",id); > while (producing || inBufferCnt > 0) > { > rsleep (100 * NROF_CONSUMERS); > > printf("cLock\n\n\n\n"); > if(inBufferCnt == 0 || (buffer[bufferHead - 1] & ~(ALL_ONES << > NROF_BITS_DEST)) != id) // inBufferCnt == 0 or the item might be for > another consumer (caused by a previous iteration) > { > printf("c%d\n",pthread_cond_wait(&availForCons[id], > &bufferLock)); Boom. Here you call 'pthread_cond_wait', but don't hold the mutex. You also access 'bufferHead' and many other shared variables without holding the mutex that protects them. DS
From: 001 on 12 Nov 2009 12:46
On 12 nov, 18:31, David Schwartz <dav...(a)webmaster.com> wrote: > On Nov 12, 8:25 am, 001 <snthib...(a)gmail.com> wrote: > > > > > > > > > /* consumer thread */ > > void * consumer (void * arg) > > { > > ITEM item; // a consumed item > > int id; // identifier of this consumer (value > > 0..NROF_CONSUMERS-1) > > > // Set the id > > id = *(int*)arg; > > printf("%d",id); > > while (producing || inBufferCnt > 0) > > { > > rsleep (100 * NROF_CONSUMERS); > > > printf("cLock\n\n\n\n"); > > if(inBufferCnt == 0 || (buffer[bufferHead - 1] & ~(ALL_ONES << > > NROF_BITS_DEST)) != id) // inBufferCnt == 0 or the item might be for > > another consumer (caused by a previous iteration) > > { > > printf("c%d\n",pthread_cond_wait(&availForCons[id], > > &bufferLock)); > > Boom. Here you call 'pthread_cond_wait', but don't hold the mutex. You > also access 'bufferHead' and many other shared variables without > holding the mutex that protects them. > > DS- Masquer le texte des messages précédents - > > - Afficher le texte des messages précédents - Wow, I hadn't noticed that... changed it like seen below, but still no success... the same failure... I have posted the output as well... regards, Stéphane /* consumer thread */ void * consumer (void * arg) { ITEM item; // a consumed item int id; // identifier of this consumer (value 0..NROF_CONSUMERS-1) // Set the id id = *(int*)arg; printf("%d",id); while (prodCount < NROF_ITEMS || inBufferCnt > 0) { rsleep (100 * NROF_CONSUMERS); pthread_mutex_lock(&bufferLock); printf("cLock\n"); if(inBufferCnt == 0 || (buffer[bufferHead - 1] & ~(ALL_ONES << NROF_BITS_DEST)) != id) // inBufferCnt == 0 or the item might be for another consumer (caused by a previous iteration) { printf("c%d\n",pthread_cond_wait(&availForCons[id], &bufferLock)); } item = buffer[bufferHead - 1]; bufferHead = (bufferHead + BUFFER_SIZE - 1) % BUFFER_SIZE; inBufferCnt--; if(inBufferCnt == BUFFER_SIZE - 1) { pthread_cond_signal(&bufferNotFull); } else if(inBufferCnt > 0 && (buffer[bufferHead - 1] & ~(ALL_ONES << NROF_BITS_DEST)) != id) { pthread_cond_signal(&availForCons[buffer[bufferHead - 1] & ~ (ALL_ONES << NROF_BITS_DEST)]); } printf("%*s C%d:%04x\n", 7*id, "", id, item); // write info to stdout (with indentation) printf("cUnlock\n"); pthread_mutex_unlock(&bufferLock); } return NULL; } //Output: m0 justlocked consumer signaled 0002 unlockingnext m0 justlocked 0102 unlockingnext m0 justlocked 0201 unlockingnext m0 justlocked 0300 unlockingnext m0 justlocked 0400 unlockingnext m0 justlocked 0501 unlockingnext m0 justlocked 0602 unlockingnext m0 justlocked 0702 unlockingnext m0 justlocked 0800 unlockingnext m0 justlocked 0901 unlockingnext m0 justlocked full buffer 804755 [unknown (0x3C4)] prodcons 2620 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack) Segmentation fault (core dumped) |