急切求教如何条配mutex和RR的timeslice

xtang的大侠们,又要麻烦你们了,请帮我一把:

我的程序1个server,1个client。每25ms server中的taskleader执行一次,每次server的taskleader执行后的10ms client的taskleader执行一次。我如果想达到目的:这么做可以吗?
在server的main()程序中创建两个时钟,一个设定为 25ms/25ms(发pulse 给server_taskleader),一个设定为35ms/25ms(发pulse给client_taskleader).我觉得这样做可能不准确,但想不到更好的solution,请明示。


我编的一个子线程示这样:
void *pthread (void *arg)
{
initialization
system("…");
com1=open("/dev/ser1", o_rdwr);
initialize_serial(com1, …);
while
{
pthread_mutex_liock (&mutex)
while(data_ready!)
{pthread_cond_wait(&condvar,&mutex);}
//process data…
data_ready=0;
pthread_cond_signal(&condvar);
pthread_mutex_unlock(&mutex);
}


问题是我想设定这个线程为RR, 所以要设定他的timeslice, 如果这个线程正在某个循环中,mutex已经被这个线程锁住,但这是timeslice用完了, 这是会发生什么呢? 如果这样,是不是和他对应的taskleader就不可能再次锁这个mutex并检验data_ready了(因为mutex已经被锁,且这个锁它的线程没在运行)?请您们指教一种方法避免这个问题的发生。


如果timeslice没有用尽就退出了,那么这个RRthread再次运行的话,是不是要重新被分配一个timeslice?

最后是一个关于优先级的问题,请问一个process的main thread的优先级是多少? 我有下面的程序

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <neutrino.h>
#include <sync.h>
int data_ready=0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;



void *
producer(void *notused)
{
printf(“In producer thread…\n”);

//get data from hardware
//we’ll simulate this with a sleep(1)
sleep(1);
printf(“producer: got data from h/w\n”);
pthread_mutex_lock(&mutex);
// while(data_ready){
// pthread_cond_wait(&condvar,&mutex);

// }
data_ready=1;
pthread_cond_signal (&condvar);
pthread_mutex_unlock (&mutex);
printf(“producer unlock mutex…\n”);

}

void *
consumer (void *notused)
{
printf(“In consumer thread…\n”);
while(1){
printf(“consumer lock mutex…\n”);
pthread_mutex_lock (&mutex);
while(!data_ready){
pthread_cond_wait(&condvar,&mutex);
printf(“consumer relock mutex…\n”); }
//process data
printf(“consumer: got data from producer\n”);
data_ready=0;
// pthread_cond_signal(&condvar);
pthread_mutex_unlock(&mutex);
printf(“consumer unlock mutex…\n”);

}
}

main ()
{
pthread_t producerid,consumerid;
pthread_attr_t producerattr,consumerattr;
pthread_attr_init(&consumerattr);
pthread_attr_init(&producerattr);
consumerattr.param.sched_priority=40;
producerattr.param.sched_priority=30;
printf(“Starting consumer/producer example…\n”);

//create the producer and consumer threads

pthread_create(&consumerid,&consumerattr,consumer,NULL);
pthread_create(&producerid,&producerattr,producer,NULL);

//let the threads run for a bit
sleep(6);
}


结果是



producer unlock mutex…
consumer relock mutex…

不明白为什么是这个顺序,既然consumer的优先级高,那么当producer unlock mutex之后,consumer就应该开始运行了,所以应该先出先consumer relock mutex 之后consumer运行完之后才会出现producer unlock mutex, 我发现只有用sched-yield才能达到这个目的,但这样靠优先级来preempt不行,究竟为什么呢?



问题很愚,麻烦您们受累了,实在是困扰了好极天,就是想不通!!!!谢谢xtang等专家们!!!

Server Task Leader = STL, Client Task Leader = CTL.

从你的描述,有两种情况:

  1. STL在这些时刻运行:0ms, 25ms, 50ms, 75ms, 100ms, 125ms …
    CTL在这些时刻运行:10ms, 35ms, 60ms, 75ms, 110ms, …
    如果是这样的话,设一个5ms的时钟就可以了,用一个计数器,满5次STL运行;满7次CTL运行,同时把计数器清0。

  2. STL在这些时刻运行:0ms, 25ms, 50ms, 75ms, 100ms, 125ms …
    CTL则在每次STL结束“后”的10ms后再运行。因为不知道STL运行要多少时间,只有用两个时钟。
    第一个每25ms到一次,启动STL。STL运行“结束后”,timer_settime()第二个时钟10ms后到时。第二个时钟不用interval,一旦到时后只要不再timer_settime(),就不会再走了。

这些事情,都与优先级无关。

main线程的优先级是从它的parent (启动进程的process)那里继承的。

你的程序的问题是pthread_attr_init()时,已经设定了线程会继承main线程的优先级。那个attr.param会被忽略掉。所以,新生成的两个线程都同主线程一样,在优先级10上。所以会出现你看到的现象。仔细看看pthread_attr_setschedparam()的说明,里面有提到这个问题。

你需要在pthread_attr_init()之后,设优先级之前,先做下面的事。

pthread_attr_setinheritsched(&consumerattr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setinheritsched(&producerattr, PTHREAD_EXPLICIT_SCHED);

这样你的程序应该就可以了。

谢谢您的悉心讲解 我的情况属于第一种 我会按您说的进行改进 如果这样那么我就将两个server&client的pulse signal通道都连在这个时钟上,当count=5时,通过server的通道发pulse,当count满7时,通过client的通道发pulse 我觉得这样就可以满足要求了。谢谢您

如果不麻烦,请您简单讲解一下刚才这三个问题,实际这辆个和第一个问题是不同的问题

对于下面的问题1,我想了三天一点收获也没有,是不是这种情况就不能mutex和RR scheduling method共用?
1。 我编的一个子线程示这样:
void *pthread (void *arg)
{
initialization
system("…");
com1=open("/dev/ser1", o_rdwr);
initialize_serial(com1, …);
while
{
pthread_mutex_liock (&mutex)
while(data_ready!)
{pthread_cond_wait(&condvar,&mutex);}
//process data…
data_ready=0;
pthread_cond_signal(&condvar);
pthread_mutex_unlock(&mutex);
}


问题是我想设定这个线程为RR, 所以要设定他的timeslice, 如果这个线程正在某个循环中,mutex已经被这个线程锁住,但这是timeslice用完了, 这是会发生什么呢? 如果这样,是不是和他对应的taskleader就不可能再次锁这个mutex并检验data_ready了(因为mutex已经被锁,且这个锁它的线程没在运行)?请您们指教一种方法避免这个问题的发生。


如果timeslice没有用尽就退出了,那么这个RRthread再次运行的话,是不是要重新被分配一个timeslice?

2。另一个关于优先级的问题,请问一个process的main thread的优先级默认是多少?
3。我看了rob kreten的书,他说pthread_cond_singal做的就是wake uppthread_cond_wait的线程,既然这样,线程1一旦执行pthread_cond_singal唤醒线程2,(线程2优先级高于线程1),则线程1 pthread_cond_singal后的语句就因被preempted而不被执行,对吗?

这一阵子一直麻烦您和这里的很多朋友,感激不尽!

谢谢xtang先生的指点, 最后这个问题 如果您有时间请指导一下

void *pthread (void *arg)
{
initialization
system("…");
com1=open("/dev/ser1", o_rdwr);
initialize_serial(com1, …);
while
{
pthread_mutex_liock (&mutex)
while(data_ready!)
{pthread_cond_wait(&condvar,&mutex);}
//process data…
data_ready=0;
pthread_cond_signal(&condvar);
pthread_mutex_unlock(&mutex);
}


问题是我想设定这个线程为RR, 所以要设定他的timeslice, 如果这个线程正在某个循环中,mutex已经被这个线程锁住,但这是timeslice用完了, 这是会发生什么呢? 如果这样,是不是和他对应的taskleader就不可能再次锁这个mutex并检验data_ready了(因为mutex已经被锁,且这个锁它的线程没在运行)?请您们指教一种方法避免这个问题的发生。


如果timeslice没有用尽就退出了,那么这个RRthread再次运行的话,是不是要重新被分配一个timeslice?

Mutex/Condvar是“同步部件”,它们是用来同步线程,并保护数据块或是程序段的。这些东西和“线程运行时间”没有很大的关系。

线程的最主要的3个运行状态是: Block, Ready, Running。Running 表示线程正占用着CPU,Ready表示线程可以执行,但还没有获得CPU(或许有更高优先级的线程正在运行,或许同优先级Running线程还没有放弃CPU)。Block表示线程正在等什么资源而无法执行。

现在再回到你的问题,如果一个正在RUNNING的RR线程mutex_lock()以后timeslice用完了,会发生什么事呢?系统会寻找还有没有同优先级的别的线程READY,如果有,那么你的线程被从RUNNING转去READY,而那个别的线程被从READY转为RUNNING并占有CPU。这个新的线程如果试图去锁同一个mutex的话,(因为无法锁住),它会被从RUNNING转成BLOCK,然后系统再寻找别的READY线程。

我不知道你上面用condvar的线程到底要做什么,所以也不知道你的问题。到底你想要解决什么问题呢?

原则上对,但是,线程1在cond_signal时,还锁着mutex,所以线程2即使优先级高,但它从cond_wait()醒过来的第一件事是要锁mutex而锁不住(线程1占有mutex),所以一直要到线程1mutex_unlock()以后,线程2才能抢到mutex,从cond_wait()里出来,执行你下面的程序。