Hi
I have a problem in a quit big program.
So I have made a simple program to test for this, and the same problem
persist.
This is the situation :
three threads
thread 1 : priority 2 (lowest)
thread 2 : priority 0 (highest)
thread 3 : priority 1 (middle)
(BTW -> is the priority right?)
The three threads look like this.
thread 1
while(1) {
lock mutex
sleep for 1msec.
unlock mutex.
}
thread 2
while(1)
sleep for 0.7 msec
lock mutex
sleep for 0.7msec
unlock mutex
}
thread 3
while(1)
sleep for 0.5 msec
lock mutex
sleep for 0.7 msec
unlock mutex
}
The three threads is started at the same time (well allmost). I have
then messured the start and end time for the running part. This is what
i get for 5 samples.
thread 1 2 3
Jul 26 23:27:10 localhost kernel: TEST 1006880 2473600 1739232
Jul 26 23:27:10 localhost kernel: TEST 1006944 2473856 1739584
Jul 26 23:27:10 localhost kernel: TEST 1006944 2473888 1739488
Jul 26 23:27:10 localhost kernel: TEST 1008928 2479328 1742528
Jul 26 23:27:10 localhost kernel: TEST 1007104 2473344 1739680
And this is the problem. it should be close to 1ms, 1.7ms and 24ms.
thread 1 runs as ekspected. it capture the mutex first.
thread 2 and 3 is both locked and the are both ready to run, an one
would assume that the one with the highest priority would wakeup. Thread
2 have priority 0 and thread 3 have 1 -> 2 should go ..... but 3 is
running insted.
Thread 3 does capture the mutex first, but it should not start running,
because 2 have higer priority and is ready.
If I am right the mutex does not run the POSIX way, but in some kind of
fifo mode.
I have attached my code. it should be ready to run.
Anders Gnistrup.
BTW.
I can always insert the module, but sometimes when i try to remove it,
it halt the machine and complains about some interrupt error. Yep, I get
a kernel panic.
#include <rtl.h>
#include <time.h>
#include <pthread.h>
#include <rtl_printf.h>
#define SAMPLE_SIZE 5
pthread_t thread_id[3];
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void *thread1(void *arg);
void *thread2(void *arg);
void *thread3(void *arg);
void *thread[3];
int init_module(void) {
pthread_attr_t attr;
struct sched_param param;
int i;
thread[2] = thread1;
thread[0] = thread2;
thread[1] = thread3;
pthread_attr_init(&attr);
for(i=0;i<3;i++) {
param.sched_priority = i;
pthread_attr_setschedparam(&attr,¶m);
pthread_create(&thread_id[i],&attr,thread[i],(void *) i);
}
return 0;
}
hrtime_t Time[3][SAMPLE_SIZE][2];
void cleanup_module(void) {
int i,j;
for(i=0;i<3;i++) {
pthread_cancel(thread_id[i]);
pthread_join(thread_id[i],NULL);
}
for(i=0;i<SAMPLE_SIZE;i++) {
rtl_printf("TEST");
for(j=0;j<3;j++) {
rtl_printf(" %u ",(int) (Time[j][i][1]-Time[j][i][0])&0xffffffff);
}
rtl_printf("\n");
}
}
#define PERIOD 10000000
void *thread1(void *arg) {
int i;
struct timespec period = {0,1000000};
pthread_make_periodic_np(pthread_self(),gethrtime(),PERIOD);
while(1) {
pthread_wait_np();
for(i=0;i<SAMPLE_SIZE;i++) {
pthread_wait_np();
Time[0][i][0] = gethrtime();
pthread_mutex_lock(&mutex);
nanosleep(&period,NULL);
pthread_mutex_unlock(&mutex);
Time[0][i][1] = gethrtime();
}
}
}
void *thread2(void *arg) {
int i;
const struct timespec period2 = {0,700000};
pthread_make_periodic_np(pthread_self(),gethrtime(),PERIOD);
while(1) {
pthread_wait_np();
for(i=0;i<SAMPLE_SIZE;i++) {
pthread_wait_np();
Time[1][i][0] = gethrtime();
nanosleep(&period2,NULL);
pthread_mutex_lock(&mutex);
nanosleep(&period2,NULL);
pthread_mutex_unlock(&mutex);
Time[1][i][1] = gethrtime();
}
}
}
void *thread3(void *arg) {
int i;
const struct timespec
period3 = {0,500000},
period4 = {0,700000};
pthread_make_periodic_np(pthread_self(),gethrtime(),PERIOD);
while(1) {
pthread_wait_np();
for(i=0;i<SAMPLE_SIZE;i++) {
pthread_wait_np();
Time[2][i][0] = gethrtime();
nanosleep(&period3,NULL);
pthread_mutex_lock(&mutex);
nanosleep(&period4,NULL);
pthread_mutex_unlock(&mutex);
Time[2][i][1] = gethrtime();
}
}
}
TARGET = mutexT
CC = gcc
include /usr/src/rtlinux/rtl.mk
all: $(TARGET).o
$(TARGET).o: $(TARGET).c
$(CC) -Wall ${CFLAGS} -c $(TARGET).c
clean:
rm -f *.o