Thread performing a write does not wake up fast enough on RHEL-6
Issue
- A program has 2 thread, one reads from a mmapped file while the other writes to it. There is a difference in the way these two threads are scheduled in RHEL-5 and RHEL-6.
- Delays can reach up to 1 second or more when there is high I/O load on the server.
- Following program is an example for this:
/*-----------------------------------------------------------------------*/
#include <stdio.h>
#include <err.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>void* thread_runhigh(void *arg);
void* thread_runlow(void *arg);
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char* mem_shared;
int rw_index = 0;
int count=0;
int main()
{
int res;
pthread_t thread_high;
pthread_t thread_mid;
void *status;
int fd;
char *tmp;
char name[1000];sprintf(name, "/tmp/pthreadmmap.share%d", getpid());
printf ("create file %s\n", name);
fd = open(name, O_RDWR | O_CREAT,
S_IRUSR|S_IWUSR| S_IRGRP| S_IROTH);
tmp = (char*) malloc(300*1000);
memset(tmp, 0, 300*1000);
write(fd, tmp, 300*1000);
mem_shared = mmap(NULL, 300*1000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);res = pthread_create(&thread_high, NULL, thread_runhigh, NULL);
thread_runlow(NULL);pthread_join(thread_high, status);
munmap(mem_shared, 300*1000);
close(fd);
return 0;
}void* thread_runhigh(void *arg)
{
struct timeval pre;
volatile int a = 0;
printf("start run high\n");
while(1)
{
a++;
struct timeval time;
time.tv_sec = 0;
time.tv_usec = 10000;
(void)select( 0, NULL, NULL, NULL, &time );
pthread_mutex_lock(&mutex);
count++;
gettimeofday(&pre, NULL);
char temp[300];
memcpy(mem_shared, temp, 300);
rw_index += 300;
rw_index = rw_index%(300*1000);
pthread_mutex_unlock(&mutex);struct timeval now;
gettimeofday(&now, NULL);
long dela = now.tv_sec * 1000000 + now.tv_usec - pre.tv_sec*1000000 - pre.tv_usec;
if ( dela > 1000) {
printf("high task:(%ld) %d runs\n", dela, count);
}
}
}void* thread_runlow(void *arg)
{struct timeval pre;
volatile int a = 0;
printf("start run low in main\n");
while(1)
{
//read
pthread_mutex_lock(&mutex);
gettimeofday(&pre, NULL);
char temp[300];
memcpy(temp , mem_shared, 300);struct timeval now;
gettimeofday(&now, NULL);
long dela = now.tv_sec * 1000000 + now.tv_usec - pre.tv_sec*1000000 - pre.tv_usec;
if ( dela > 1000*20) {
printf("low task:(%ld)\n", dela);
}
pthread_mutex_unlock(&mutex);
}
}/*-----------------------------------------------------------------------*/
Environment
- Red Hat Enterprise Linux 6
- kernel
Subscriber exclusive content
A Red Hat subscription provides unlimited access to our knowledgebase of over 48,000 articles and solutions.
Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.
