public inbox for pthreads-win32@sourceware.org
 help / color / mirror / Atom feed
From: Breght Boschker <breght@gmail.com>
To: pthreads-win32@sourceware.org
Subject: Deadlock on WinCE
Date: Fri, 27 Jan 2006 12:05:00 -0000	[thread overview]
Message-ID: <c1c745ef0601270405t7e706254x@mail.gmail.com> (raw)

Hi,

taking a well-known example (the so-called 'producer-consumer'
problem) with a relatively small queue, we have observed a deadlock.
(See below for code) - the results we get:

Pthread test
request_queue_put: # of elements: 1
request_queue_put: # of elements: 2
request_queue_put: # of elements: 3
request_queue_put: # of elements: 4
request_queue_put: # of elements: 5
***********************************************
put: queue FULL. waiting for free space
***********************************************
request_queue_get: # of elements: 4
request_queue_get: # of elements: 3
request_queue_get: # of elements: 2
request_queue_get: # of elements: 1
request_queue_get: # of elements: 0
===============================================
get: queue EMPTY, waiting for data
===============================================
request_queue_put: # of elements: 1
request_queue_put: # of elements: 2
 request_queue_put: # of elements: 3
request_queue_put: # of elements: 4
request_queue_put: # of elements: 5
***********************************************
put: queue FULL. waiting for free space
***********************************************
request_queue_get: # of elements: 4
request_queue_get: # of elements: 3
request_queue_get: # of elements: 2
request_queue_get: # of elements: 1
request_queue_get: # of elements: 0
===============================================
get: queue EMPTY, waiting for data
===============================================

***** at this point, the program stops (the WinCE Remote Kernel
Tracker reports all threads of the application to be in 'blocked'
state). If the queue size is increased (say to 20 elements), the first
thread (the 'producer') completely fills the queue, *then* sends a
signal, the consumer thread is released from its pthread_cond_wait and
consumes a number of elements. After this, the two threads alternate
(put & get) and we have seen no deadlock so far.

Furthermore, the Remote Kernel Tracker shows that signals ('SetEvent')
are sent, but these do not result in the other thread becoming
unblocked. Also, we have noticed a lot of 'CreateEvent' calls during
the running period of one of either threads. Some background
information on our system:

Compiler: MS eMbedded Visual C++ 4.0 (SP4)
Target machine: ARMv4I / WinCE 5.00
PThread-WIN32 version: 2.7.0 (we had to put some defines around e.g.
<errno.h> in some files and in errno.c needed to put a typecast in
order to satisfy the compiler).

Any help/leads or ideas would be appreciated.


We use the following code:

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

#define QUEUESIZE 5
typedef struct rs { int type; } REQUEST_STRUCT;

typedef struct rq {
    int full;
    int empty;
    int head;
    int tail;
    int elt_count;
    pthread_mutex_t mut;
    pthread_cond_t not_full;
    pthread_cond_t not_empty;
    REQUEST_STRUCT buf[QUEUESIZE];
} REQUEST_QUEUE;


#include "windows.h"
void cenav_pthread_create(HANDLE a, HANDLE b) {}
void cenav_pthread_exit() { }

void *producer (void *args);
void *consumer (void *args);
extern REQUEST_QUEUE *request_queue_create (void);
extern void request_queue_delete (REQUEST_QUEUE *q);
extern void request_queue_put (REQUEST_QUEUE *q, REQUEST_STRUCT *rs);
extern void request_queue_get (REQUEST_QUEUE *q,  REQUEST_STRUCT *rs);


int request_test ()
{
    REQUEST_QUEUE *fifo;
    pthread_t pro, con;

    fifo = request_queue_create ();
    if (fifo ==  NULL) {
        fprintf (stderr, "main: Queue Init failed.\n");
        exit (1);
    }
    pthread_create (&pro, NULL, producer, fifo);
    pthread_create (&con, NULL, consumer, fifo);
    pthread_join (pro, NULL);
    pthread_join (con, NULL);
    request_queue_delete (fifo);

    return 0;
}

void *producer (void *q)
{
    REQUEST_QUEUE *fifo;
        REQUEST_STRUCT rs;
    int i;

    fifo = (REQUEST_QUEUE *)q;

    while (1)
    {
        request_queue_put (fifo, &rs);
    }
    return (NULL);
}

void *consumer (void *q)
{
    REQUEST_QUEUE *fifo;
        REQUEST_STRUCT rs;
    int i;

    fifo = (REQUEST_QUEUE *)q;

    while(1)
    {
        request_queue_get (fifo, &rs);
    }
    return (NULL);
}


extern REQUEST_QUEUE *request_queue_create (void)
{
    REQUEST_QUEUE *q;

    q = (REQUEST_QUEUE *)malloc (sizeof (REQUEST_QUEUE));
    if (q == NULL) return (NULL);

    q->empty = 1;
    q->full = 0;
    q->head = 0;
    q->tail = 0;

    q->mut       = PTHREAD_MUTEX_INITIALIZER;
    q->not_full  = PTHREAD_COND_INITIALIZER;
    q->not_empty = PTHREAD_COND_INITIALIZER;
    q->elt_count = 0;
    return (q);
}

extern void request_queue_delete (REQUEST_QUEUE *q)
{
    free (q);
}

extern void request_queue_put (REQUEST_QUEUE *q, REQUEST_STRUCT *rs)
{
     int result = 0;

    result = pthread_mutex_lock(&(q->mut));

    while (q->full) {
        printf ("put: queue FULL. waiting for free space\n");
        pthread_cond_wait(&q->not_full, &q->mut);
    }
    q->buf[q->tail] = *rs;
    q->tail++;
    if (q->tail == QUEUESIZE)
        q->tail = 0;
    if (q->tail == q->head)
        q->full = 1;
    q->empty = 0;
     q->elt_count++;

    printf("request_queue_put: # of elements: %d\n", q->elt_count);

    pthread_cond_signal(&q->not_empty);
    result = pthread_mutex_unlock(&(q->mut));
     return;
}

extern void request_queue_get (REQUEST_QUEUE *q,  REQUEST_STRUCT *rs)
{
    int result = 0;

    result = pthread_mutex_lock(&q->mut);

    while (q->empty) {
        printf ("get: queue EMPTY, waiting for data\n");
        pthread_cond_wait(&q->not_empty, &q->mut);
    }
    *rs = q->buf[q->head];

    q->head++;
    if (q->head == QUEUESIZE)
        q->head = 0;
    if (q->head == q->tail)
        q->empty = 1;
    q->full = 0;
    q->elt_count--;
    printf("request_queue_get: # of elements: %d\n", q->elt_count);

    pthread_cond_signal(&q->not_full);
    result = pthread_mutex_unlock(&(q->mut));
    return;
}

int main(int argc, char **argv)
{
    printf("Pthread test\n");
    request_test();
}

Thanks in advance,
   Breght Boschker

                 reply	other threads:[~2006-01-27 12:05 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c1c745ef0601270405t7e706254x@mail.gmail.com \
    --to=breght@gmail.com \
    --cc=pthreads-win32@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).