From: 001 on
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
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
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
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
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)