Возможный косяк в boost::mutex
От: ioni Россия  
Дата: 13.04.11 10:53
Оценка: :)
Рассмотрим реализацию boost::mutex (последняя версия)

            bool timed_lock(::boost::system_time const& wait_until)
            {
(1)                if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
                {
                    return true;
                }
                long old_count=active_count;
(2)                for(;;)
                {
                    long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
                    long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
                    if(current==old_count)
                    {
                        break;
                    }
                    old_count=current;
                }

                if(old_count&lock_flag_value)
                {
                    bool lock_acquired=false;
                    void* const sem=get_event();

                    do
                    {
(3)                        if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
                        {
                            BOOST_INTERLOCKED_DECREMENT(&active_count);
                            return false;
                        }
                        old_count&=~lock_flag_value;
                        old_count|=event_set_flag_value;
                        for(;;)
                        {
                            long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
                            long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
                            if(current==old_count)
                            {
                                break;
                            }
                            old_count=current;
                        }
                        lock_acquired=!(old_count&lock_flag_value);
                    }
                    while(!lock_acquired);
                }
                return true;
            }

            void unlock()
            {
                long const offset=lock_flag_value;
(4)                long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
                if(!(old_count&event_set_flag_value) && (old_count>offset))
                {
(5)                    if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
                    {
                        win32::SetEvent(get_event());
                    }
                }
            }


рассмотрим такую ситуацию
Имеем три потока с приоритетами Low, Medium, High
в начальном состоянии поток Low захватил mutex в точке 1 потому что он первый,
далее начинает работать стартует поток Medium система передает ему управление так как он имеет более высокий приоритет
потом начинает работать поток High и пытается захватить mutex, так как mutex уже захвачен доходит до точки 3 и ждет
так как поток High ждет, управление передается потоку Medium и пока он не отработает не произойдет инверсии приоритета для
потока Low и поток High не получит управления.
Вот такая дыра обнаружилась
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.