tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: pthread_rwlock starvation



On Fri, 16 Apr 2010 19:46:32 -0700
Steve Woodford <steve%mctavish.co.uk@localhost> wrote:

> 
> On 16 Apr 2010, at 16:01, Sad Clouds wrote:
> > 
> > Any ideas?
> 
> What's the observed behaviour with a kernel compiled with "options
> HZ=1000" in the kernel config file?
> 
> Steve
> 

Same again, one CPU sitting idle for up to 30 seconds. This all happens
very randomly. I think HZ=1000 reduces the frequency of when this
happens, but doesn't fix it.

I've attached a program that reproduces the issue. Run it a couple of
times and watch top, or vmstat. Sooner or later one CPU will sit idle
100% for 10-30 seconds, until something nudges it back into work.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define NDATA 1000
#define NLOCK 500
#define NTHREADS 2

pthread_rwlock_t lock[NLOCK];
int data[NDATA];

void *thread(void *arg)
{
        unsigned int seed = time(NULL);
        int lock_index, data_index;

        for(;;)
        {
                /* Calculate random index value */
                data_index = rand_r(&seed) % NDATA;
                lock_index = data_index % NLOCK;

                /* Get a read lock on this index */
                if(pthread_rwlock_rdlock(&(lock[lock_index])) != 0)
                {
                        printf("pthread_rwlock_wrlock() error\n");
                        exit(1);
                }
                if(data[data_index] != data_index)
                {
                        printf("Error on line %d\n", __LINE__);
                }
                if(pthread_rwlock_unlock(&(lock[lock_index])) != 0)
                {
                        printf("pthread_rwlock_wrlock() error\n");
                        exit(1);
                }

                /* Get a write lock on this index */
                data_index = rand_r(&seed) % NDATA;
                lock_index = data_index % NLOCK;

                if(pthread_rwlock_wrlock(&(lock[lock_index])) != 0)
                {
                        printf("pthread_rwlock_wrlock() error\n");
                        exit(1);
                }
                if(data[data_index] != data_index)
                {
                        printf("Error on line %d\n", __LINE__);
                }
                if(pthread_rwlock_unlock(&(lock[lock_index])) != 0)
                {
                        printf("pthread_rwlock_wrlock() error\n");
                        exit(1);
                }
        }
}

int main(void)
{
        int i;
        pthread_t tid[NTHREADS];

        /*
        Initialise locks and data
        */

        for(i = 0; i < NLOCK; i++)
        {
                if(pthread_rwlock_init(&(lock[i]), NULL) != 0)
                {
                        printf("pthread_rwlock_init() error\n");
                        exit(1);
                }

        }
        for(i = 0; i < NDATA; i++)
                data[i] = i;


        /*
        Create threads, 1 second apart
        */

        for(i = 0; i < NTHREADS; i++)
        {
                printf("Creating thread: %d\n", i);
                if(pthread_create(&tid[i], NULL, thread, NULL) != 0)
                {
                        printf("pthread_create() error\n");
                        exit(1);
                }
                sleep(1);
        }

        printf("Waiting for all threads\n", i);
        for(i = 0; i < NTHREADS; i++)
                pthread_join(tid[i], NULL);

        exit(0);
}


Home | Main Index | Thread Index | Old Index