Back to index

courier  0.68.2
Classes | Defines | Typedefs | Functions
pthread.c File Reference
#include "threadlib.h"
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

Go to the source code of this file.

Classes

struct  cthread_t
struct  cthreadinfo
struct  cthreadlock

Defines

#define PTHREAD_CHK(x)   (errno=(x))

Typedefs

typedef struct cthreadinfo

Functions

static void mutexcleanup (void *vp)
static void * threadfunc (void *p)
static int initcondmutex (pthread_cond_t *c, pthread_mutex_t *m)
cthreadinfo_t * cthread_init (unsigned nthreads_, unsigned metasize, void(*workfunc_)(void *), void(*cleanupfunc_)(void *))
void cthread_wait (cthreadinfo_t *cit)
int cthread_go (cthreadinfo_t *cit, void(*gofunc)(void *, void *), void *arg)
struct cthreadlockcthread_lockcreate (void)
void cthread_lockdestroy (struct cthreadlock *p)
int cthread_lock (struct cthreadlock *p, int(*func)(void *), void *arg)

Class Documentation

struct cthread_t

Definition at line 15 of file pthread.c.

Collaboration diagram for cthread_t:
Class Members
pthread_cond_t gocond
int goflag
pthread_mutex_t gomutex
unsigned me
void * metadata
struct cthreadinfo * myinfo
pthread_t pt
struct cthreadlock

Definition at line 44 of file nopthread.c.

Class Members
int dummy
pthread_mutex_t mutex

Define Documentation

#define PTHREAD_CHK (   x)    (errno=(x))

Definition at line 52 of file pthread.c.


Typedef Documentation

typedef struct cthreadinfo

Definition at line 43 of file pthread.c.


Function Documentation

int cthread_go ( cthreadinfo_t *  cit,
void(*)(void *, void *)  gofunc,
void *  arg 
)

Definition at line 337 of file pthread.c.

{
       int    n=0;
       int    err=0;

       if (PTHREAD_CHK(pthread_mutex_lock(&cit->newtask_mutex)))
              return (-1);

       pthread_cleanup_push(&mutexcleanup, (void *)&cit->newtask_mutex);

       while (cit->newcnt == 0)
       {
              if (PTHREAD_CHK(pthread_cond_wait(&cit->newtask_cond,
                                            &cit->newtask_mutex)))
              {
                     err=1;
                     break;
              }
       }

       if (!err)
              n=cit->newbuf[ --cit->newcnt ];

       if (PTHREAD_CHK(pthread_mutex_unlock(&cit->newtask_mutex)))
              err=1;

       pthread_cleanup_pop(0);
       if (err)      return (-1);

       (*gofunc)( cit->threads[n].metadata, arg);

       if (PTHREAD_CHK(pthread_mutex_lock(&cit->threads[n].gomutex)))
              return (-1);
       cit->threads[n].goflag=1;
       if (PTHREAD_CHK(pthread_mutex_unlock(&cit->threads[n].gomutex)))
              return (-1);
       if (PTHREAD_CHK(pthread_cond_signal( &cit->threads[n].gocond )))
              return (-1);
       return (0);
}

Here is the call graph for this function:

cthreadinfo_t* cthread_init ( unsigned  nthreads_,
unsigned  metasize,
void(*)(void *)  workfunc_,
void(*)(void *)  cleanupfunc_ 
) [read]

Definition at line 156 of file pthread.c.

{
unsigned i;
pthread_attr_t       pat;
cthreadinfo_t *cit;

       if ((cit=(cthreadinfo_t *)malloc(sizeof(cthreadinfo_t))) == 0)
              return (0);

       cit->nthreads=nthreads_;
       cit->cleanupfunc=cleanupfunc_;
       cit->workfunc=workfunc_;
       if ( (cit->threads=(cthread_t *)malloc(cit->nthreads * sizeof(cthread_t))) == 0)
       {
              free((char *)cit);
              return (0);
       }
       if ( (cit->metadata_buf=malloc(metasize * cit->nthreads)) == 0)
       {
              free( (char *)cit->threads);
              free( (char *)cit );
              return (0);
       }

       cit->newcnt=cit->nthreads;
       if ( (cit->newbuf=(int *)malloc(cit->nthreads * sizeof(int))) == 0)
       {
              free(cit->metadata_buf);
              free( (char *)cit->threads);
              free( (char *)cit );
              return (0);
       }
       for (i=0; i<cit->nthreads; i++)
       {
              cit->newbuf[i]=i;
       }

       if (initcondmutex(&cit->newtask_cond, &cit->newtask_mutex))
       {
              free(cit->newbuf);
              free(cit->metadata_buf);
              free( (char *)cit->threads);
              free( (char *)cit );
              return (0);
       }

       if (initcondmutex(0, &cit->cleanup_mutex))
       {
              pthread_cond_destroy(&cit->newtask_cond);
              pthread_mutex_destroy(&cit->newtask_mutex);

              free(cit->newbuf);
              free(cit->metadata_buf);
              free( (char *)cit->threads);
              free( (char *)cit );
              return (0);
       }

       if (PTHREAD_CHK(pthread_attr_init(&pat)))
       {
              pthread_mutex_destroy(&cit->cleanup_mutex);
              pthread_cond_destroy(&cit->newtask_cond);
              pthread_mutex_destroy(&cit->newtask_mutex);
              free(cit->newbuf);
              free(cit->metadata_buf);
              free( (char *)cit->threads);
              free( (char *)cit );
              return (0);
       }

       for (i=0; i<cit->nthreads; i++)
       {
              cit->threads[i].me=i;
              cit->threads[i].metadata=(void *) (cit->metadata_buf+i*metasize);
              cit->threads[i].myinfo=cit;

              if (initcondmutex(&cit->threads[i].gocond,
                     &cit->threads[i].gomutex))
                     break;

              cit->threads[i].goflag=0;

              if (PTHREAD_CHK(pthread_create(&cit->threads[i].pt, &pat,
                                          &threadfunc,
                                          (void *)&cit->threads[i])))
              {
                     pthread_cond_destroy(&cit->threads[i].gocond);
                     pthread_mutex_destroy(&cit->threads[i].gomutex);
                     break;
              }
       }

       if ( i >= cit->nthreads)
       {
              pthread_attr_destroy(&pat);
              return (cit);
       }

       while (i)
       {
              --i;
              if (PTHREAD_CHK(pthread_cancel(cit->threads[i].pt)))
                     perror("pthread_cancel");
              
              if (PTHREAD_CHK(pthread_join(cit->threads[i].pt, NULL)))
                     perror("pthread_join");

              pthread_cond_destroy(&cit->threads[i].gocond);
              pthread_mutex_destroy(&cit->threads[i].gomutex);
       }

       pthread_attr_destroy(&pat);
       pthread_mutex_destroy(&cit->cleanup_mutex);
       pthread_cond_destroy(&cit->newtask_cond);
       pthread_mutex_destroy(&cit->newtask_mutex);
       free(cit->newbuf);
       free(cit->metadata_buf);
       free( (char *)cit->threads);
       free( (char *)cit );
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int cthread_lock ( struct cthreadlock p,
int(*)(void *)  func,
void *  arg 
)

Definition at line 413 of file pthread.c.

{
int    rc;

       while (pthread_mutex_lock(&p->mutex))
       {
              perror("pthread_mutex_lock");
              sleep(3);
       }

       pthread_cleanup_push(&mutexcleanup, (void *)&p->mutex);

       rc= (*func)(arg);

       if (PTHREAD_CHK(pthread_mutex_unlock( &p->mutex )))
              perror("pthread_mutex_unlock");
       pthread_cleanup_pop(0);
       return (rc);
}

Here is the call graph for this function:

struct cthreadlock* cthread_lockcreate ( void  ) [read]

Definition at line 382 of file pthread.c.

{
struct cthreadlock *p= (struct cthreadlock *)malloc(sizeof(struct cthreadlock));
pthread_mutexattr_t mattr;

       if (!p)       return (0);

       if (PTHREAD_CHK(pthread_mutexattr_init(&mattr)))
       {
              errno=EIO;
              free( (char *)p );
              return (0);
       }

       if (PTHREAD_CHK(pthread_mutex_init(&p->mutex, &mattr)))
       {
              pthread_mutexattr_destroy(&mattr);
              errno=EIO;
              free( (char *)p );
              return (0);
       }
       pthread_mutexattr_destroy(&mattr);
       return (p);
}
void cthread_lockdestroy ( struct cthreadlock p)

Definition at line 407 of file pthread.c.

{
       pthread_mutex_destroy(&p->mutex);
       free( (char *)p );
}
void cthread_wait ( cthreadinfo_t *  cit)

Definition at line 280 of file pthread.c.

{
       unsigned i;

       if (PTHREAD_CHK(pthread_mutex_lock(&cit->newtask_mutex)))
       {
              perror("pthread_mutex_lock");
              return;
       }

       pthread_cleanup_push(&mutexcleanup, (void *)&cit->newtask_mutex);

       while (cit->newcnt < cit->nthreads)
       {
              if (PTHREAD_CHK(pthread_cond_wait(&cit->newtask_cond,
                                            &cit->newtask_mutex)))
              {
                     perror("pthread_cond_wait");
                     sleep(3);
              }
       }

       if (PTHREAD_CHK(pthread_mutex_unlock(&cit->newtask_mutex)))
              perror("pthread_mutex_unlock");

       pthread_cleanup_pop(0);

       for (i=0; i<cit->nthreads; i++)
       {
              if (PTHREAD_CHK(pthread_cancel(cit->threads[i].pt) ))
                     perror("pthread_cancel");

              if (PTHREAD_CHK(pthread_join(cit->threads[i].pt, NULL)))
                     perror("pthread_join");

              if (PTHREAD_CHK(pthread_cond_destroy(&cit->threads[i].gocond)))
                     perror("pthread_cond_destroy(gocond)");

              if (PTHREAD_CHK(pthread_mutex_destroy(&cit->threads[i]
                                                .gomutex)))
                     perror("pthread_mutex_destroy");
       }

       if (PTHREAD_CHK(pthread_mutex_destroy(&cit->cleanup_mutex)))
              perror("pthread_mutex_destroy");

       if (PTHREAD_CHK(pthread_cond_destroy(&cit->newtask_cond)))
              perror("pthread_cond_destroy(newtask_cond)");

       if (PTHREAD_CHK(pthread_mutex_destroy(&cit->newtask_mutex)))
              perror("pthread_mutex_destroy");
       free(cit->newbuf);
       free(cit->metadata_buf);
       free( (char *)cit->threads);
       free( (char *)cit);
}

Here is the call graph for this function:

static int initcondmutex ( pthread_cond_t *  c,
pthread_mutex_t *  m 
) [static]

Definition at line 123 of file pthread.c.

{
pthread_condattr_t cattr;
pthread_mutexattr_t mattr;

       if (c)
       {
              if ( PTHREAD_CHK(pthread_condattr_init(&cattr))) return (-1);
              if ( PTHREAD_CHK(pthread_cond_init(c, &cattr)))
              {
                     pthread_condattr_destroy(&cattr);
                     return (-1);
              }
              pthread_condattr_destroy(&cattr);
       }

       if ( PTHREAD_CHK(pthread_mutexattr_init(&mattr)))
       {
              if (c) pthread_cond_destroy(c);
              return (-1);
       }

       if ( PTHREAD_CHK(pthread_mutex_init(m, &mattr)))
       {
              pthread_mutexattr_destroy(&mattr);

              if (c) pthread_cond_destroy(c);
              return (-1);
       }
       pthread_mutexattr_destroy(&mattr);
       return (0);
}

Here is the caller graph for this function:

static void mutexcleanup ( void *  vp) [static]

Definition at line 45 of file pthread.c.

{
pthread_mutex_t *mp=(pthread_mutex_t *)vp;

       pthread_mutex_unlock( mp );
}

Here is the caller graph for this function:

static void* threadfunc ( void *  p) [static]

Definition at line 60 of file pthread.c.

{
cthread_t     *c= (cthread_t *)p;
cthreadinfo_t *i= c->myinfo;

       for (;;)
       {
              while (PTHREAD_CHK(pthread_mutex_lock(&c->gomutex)))
              {
                     perror("pthread_mutex_lock");
                     sleep(3);
              }

              pthread_cleanup_push(&mutexcleanup, (void *)&c->gomutex);

              while (!c->goflag)
              {
                     if (PTHREAD_CHK(pthread_cond_wait(&c->gocond,
                                                   &c->gomutex)))
                     {
                            perror("pthread_cond_wait");
                            sleep(3);
                     }
              }
              c->goflag=0;
              if (PTHREAD_CHK(pthread_mutex_unlock( &c->gomutex )))
                     perror("pthread_mutex_unlock");

              pthread_cleanup_pop(0);

              (*i->workfunc)(c->metadata);

              while (PTHREAD_CHK(pthread_mutex_lock(&i->cleanup_mutex)))
              {
                     perror("pthread_mutex_lock");
                     sleep(3);
              }

              pthread_cleanup_push(&mutexcleanup, (void *)&i->cleanup_mutex);

              (*i->cleanupfunc)(c->metadata);

              if (PTHREAD_CHK(pthread_mutex_unlock( &i->cleanup_mutex )))
                     perror("pthread_mutex_unlock");

              pthread_cleanup_pop(0);

              while (PTHREAD_CHK(pthread_mutex_lock(&i->newtask_mutex)))
              {
                     perror("pthread_mutex_lock");
                     sleep(3);
              }

              i->newbuf[i->newcnt++] = c->me;

              if (PTHREAD_CHK(pthread_mutex_unlock( &i->newtask_mutex )))
                     perror("pthread_mutex_unlock");

              if (PTHREAD_CHK(pthread_cond_signal( &i->newtask_cond )))
                     perror("pthread_cond_signal");
       }
}

Here is the call graph for this function:

Here is the caller graph for this function: