Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Уменьшение минимального кол-ва стека
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы
DASM
Боюсь уже автора задолбать, поэтому спрашиваю у всех.
Есть такая штука.. tn_switch_context
Там такой код
Код
tn_sw_restore
        ldmfd  sp!, {r0}
        ldmfd  sp!, {r1}
        msr    CPSR_cxsf, r1; с этой точки прерывания разрешены ! Комментарий мой
        msr    SPSR_cxsf, r0

        mrs    r4, CPSR
        bic    r4, r4, #NOINT
        msr    CPSR_c, r4

        ldmfd  sp!, {r0-r12,lr,pc}

То есть стек задачи еще не развернут, прерывания разрешены. Наступление прерывания, требующего переключения контекста в нем затребует у этой задачи еще 15*4=60 байт стека. (вернее надо будет 68 байт, но 8 мы уже отыграли назад) Вот дальше у меня сомнения - сколько раз такое может произойти...
В реалии раза 3-4 я точно наблюдаю - хорошо видно по использованию стека. Как уменьшить тоже понятно - перенести восстановление CPSR после развертывания большей части стека через ldmfd sp!, {r0-r12,lr,pc}.
Но вот по идее то все равно, сколько раз такое может произойти - вобщем-то определить невозможно, а значит и минимальный требуемый стек для потока должен стремиться к бесконечности ?
Замена вышепреведенного кода на вот такой (жутко наивный, но все же)
Код
     ldmfd  sp!, {r0}        
        ldr r1, =t_spsr
        str r0, [r1]
        ldmfd  sp!, {r0}
        ldr r1, =t_cpsr
        str r0, [r1]

        ldmfd  sp!, {r0-r12,lr}
        push {r1}
        ldr r1, =t_spsr
        ldr r1,[r1]
        msr    SPSR_cxsf, r1
        ldr r1, =t_cpsr
        ldr r1,[r1]
        msr    CPSR_cxsf, r1
        pop {r1}    
        ldmfd  sp!, {pc}

уменьшила требуемый стек очень прилично.
Вопрос возник не праздно, прокачивю через USB большой поток.. и в результате например банальная tn_idle_task благополучно через перваливала за 96 слов требуемого стека, при том что по умолчанию он 48. Но все равно как я понимаю не застрахован и в этом случае. Какие будут соображения ?
yuri_t
Подумаю, поэксперементирую и обязательно отвечу. Если выяснится, что это
существенно, изменения будут сделаны уже в следующей версии (2.4).
В любом случае спасибо за тщательный анализ - вещи, кажущиеся банальными,
открываются с новой стороны...
yuri_t
Отвечаю по-порядку...

Цитата
Но вот по идее то все равно, сколько раз такое может произойти - вобщем-то
определить невозможно, а значит и минимальный требуемый стек для потока должен
стремиться к бесконечности ?


Нет, стек не стремится к бесконечности. Здесь вот в чем соль - чтобы при прерывании
стек задачи(task) использовался для сохранения регистров, эта задача должна
прежде всего быть активной(curr_run). A когда задача становится активной,
то ее стек выгружается в регистры и соответственно ОПУСТОШАЕТСЯ. Отсюда -
не бесконечное увеличение стека, а лишь бесконечный цикл - заполнение/опустошение.

Цитата
Наступление прерывания, требующего переключения контекста в нем затребует у этой задачи еще 15*4=60 байт стека. (вернее надо будет 68 байт, но 8 мы уже отыграли назад)


Здесь Вы, Дмитрий, совершенно правы.
Существующий код выглядит так
Код
tn_sw_restore:

        ldmfd  sp!, {r0}
        ldmfd  sp!, {r1}
        msr    CPSR_cxsf, r1
        msr    SPSR_cxsf, r0

  /*   Эти 3 сроки  можно исключить, т.к. фактически прерывания уже разрешены
     после команды  msr CPSR_cxsf, r1,  как справедливо заметил DASM */

        mrs    r4, CPSR
        bic    r4, r4, #NOINT
        msr    CPSR_c, r4

   /* stack  опустошен */
        ldmfd  sp!, {r0-r12,lr,pc}


Код, уменьшающий использование стека, выглядит так:

Код
tn_sw_restore:

        ldmfd  sp!, {r0}
        ldmfd  sp!, {r1}

        orr    r1, r1, #NOINT /* disable int */
        msr    CPSR_cxsf, r1  /*restore CPSR, but int are off*/
        msr    SPSR_cxsf, r0  /*restore SPSR*/

        ldmfd  sp!, {r0-r12,lr}/* restore all regs, execept pc*/

    /* Enable interrupts */
        stmfd  sp!,{r0}      /* save r0- tmp*/
        mrs    r0, CPSR
        bic    r0, r0, #NOINT
        msr    CPSR_c, r0  /* точка разрешения прерываний */
        ldmfd  sp!,{r0}     /* restore r0*/

        ldmfd  sp!, {pc} /* new pc*/


И тот, и другой варианты функционируют корректно. Здесь лишь вечная задача выбора ("Вчера по 3, но маленькие, сегодня по 5, но большие"(с)) - или занимать больше памяти (стека),
но работать быстрее, или занимать меньше памяти, но работать медленнее.

Цитата
например банальная tn_idle_task благополучно через перваливала за 96 слов
требуемого стека, при том что по умолчанию он 48.


Ф-ция у задачи tn_idle_task выглядит так:

Код
static void tn_idle_task_func(void * par)
{
    for(;;)
    {
        tn_idle_count++;
    }
}

После создания tn_idle_task стек занимает 17 слов, сама задача стек или не использует или использует максимум 2-3 слова(зависит от компилятора).
В худшем варианте с прерываниями, который Вы рассмотрели, понадобится еще,
скажем,17 слов - итого 34(37) и мы явно укладываемся в 48 слов стека этой задачи.
Я запускал под отладчиком множество своих проектов и нигде не видел, чтобы
стек в tn_idle_task неконтролируемо возрастал.
Cовершенно не могу представить, откуда могут взятся здесь 96 слов ???
IMHO, здесь у Вас есть где-то проблемы в Вашем коде.
Alex B._
>> После создания tn_idle_task стек занимает 17 слов, сама задача
>> стек или не использует или использует максимум 2-3 слова
>> (зависит от компилятора). В худшем варианте с прерываниями, >> который Вы рассмотрели, понадобится еще, скажем,17 слов
>> - итого 34(37) и мы явно укладываемся в 48 слов стека этой
>> задачи.

А вложенные прерывания?
yuri_t
В авторском варианте TNKernel вложенные прерывания не поддерживаются
DASM
msr CPSR_c, r0 /* точка разрешения прерываний */
ldmfd sp!,{r0} /* restore r0*/

ldmfd sp!, {pc} /*
Тот же вараиант, что я и привел выше по-сути. Прерывания разрешаются, когда еще в стеке задачи два int - а (R0 и PC). Далее ситуация - прерывания, требующее irq_context_int. Задача вытесняется на этой точке. Потом задача делается опять планируемой (через обычный switch_context уже ) Выполнение продолжается с точки ldmfd sp!,{r0}. НО ТУТ же задача опять вытесняется вышеназванным методом. И так далее. Я не вижу тут ограничения для бесконечного роста стека в вытесненной задаче, т.к. вытеснение происходит многократно в точке, где стек еще несбалансирован. Изучение стека задачи, кушающей так много стека это подтверждает. Там сплошные точки возврата в эти две команды.
"В худшем варианте с прерываниями, который Вы рассмотрели, понадобится еще,
скажем,17 слов - итого 34(37) и мы явно укладываемся в 48 слов стека этой задачи."
Тут не понял... при вытеснении этой задачи в ей стек будут сохранены все R0-R12, PC, LR, SPSR и CPSR.
Проверить это все просто. В примере USB_BULK через USBIO закидать допустим 2-ую endpoint мегабайтами траффика. Для нагляндности в USBIO размер буффера лучше поставить например 5-ть байт, так прерываний больше будет. ( Упростил код только до ожидания очереди от приема 2-ой endpoint и тут же release_mem, ьессмысленный но отладочный вариант). А потом поглядеть насколько опускался стек idle_task. И мы НЕ уложимся в стек задачи именно из-за множественного вытеснения. В исправленном варианте все намного лучше - стек будет увеличиваться не более чем на два слова. Но вот сколько раз это рекуррентно произойдет ?
Alex B._
>> В авторском варианте TNKernel вложенные прерывания
>> не поддерживаются
Тогда не понимаю, зачем нужен tn_int_counter и его проверка на >1 (я так думал, чтобы разрешить переключение контекста только из первого прервания - что логично):

Код
tn_cpu_irq_isr:

        stmfd  sp!,{r0-r12,lr}   /* Save ALL registers */

       /*--  interrupt_counter++ */

        ldr    r2, =tn_int_counter
        ldr    r3, [r2]                /* interrupt_counter -> r3 */
        add    r0, r3,#1               /* interrupt_counter++     */
        str    r0, [r2]

        bl     tn_cpu_irq_handler      /* Actually  Handle interrupt */

        /* interrupt_counter-- */

        ldr    r2, =tn_int_counter
        ldr    r1, [r2]
        sub    r3, r1,#1
        str    r3, [r2]
        cmp    r3, #0x00               /* if it is nested int - return */
                                               /* ваш комментарий ^^^^^^^ */

        bne    exit_irq_int            /* return from int*/
        ldr    r0, =tn_context_switch_request  /* see if we need to do a context switch */
        ldr    r1, [R0]
        cmp    r1, #0                  /* if 0 - return */
        beq    exit_irq_int
        mov    r1, #0                  /* else - clear req flag and  goto context switch */
        str    r1, [r0]
        b      tn_int_ctx_switch


Еще, Дмитрий, пока не забыл -
В версии с сайта (2.3) есть небольшой баг - при возникновении любого прерывания, переключающего контекст во время выполнения tn_task_exit() задача по activate не восстанавливается. Мы с Юрием это обсуждали, он прислал код 2.3.1, но на сайт его почему-то не выложил...
DASM
А я допишу пока для ясности..
"A когда задача становится активной,
то ее стек выгружается в регистры и соответственно ОПУСТОШАЕТСЯ."
Так в том то и дело, что он не успевает полностью выгрузиться в регистры, как задача снова вытесняется. Проблему полностью бы решила атомарная загрузка регистров +CPSR через {la-la} ^
Но пока я не очень представляю как это сделать, в CPSR надо не содержимое SPSR отнюдь загружать.
Сергей Борщ
Цитата(DASM @ Mar 30 2007, 23:08) *
Но пока я не очень представляю как это сделать, в CPSR надо не содержимое SPSR отнюдь загружать.
"Я Пастернака не читал...", в смысле исходники TNKernel не изучал, но если SPSR после восстановления не нужен, то значит в него и надо перед восстановлением всех регистров занести требуемое значение для CPSR. И при его восстановлении операцией ldmfd xx, {...}^ разрешать прерывания. Глянь мой порт scmRTOS, может там мысль почерпнешь.

P.S. Там долго думал как организовать восстановление из SPSR когда смена контекста вызывается из User/System Mode, в которых SPSR нет. Не нашел ничего лучше чем принудительно одновременно с запретом прерываний irq переключиться в IRQ Mode и использовать неиспользуемый (по причине запрещенных прерываний) в этот момент SPSR_irq.
DASM
Цитата(Сергей Борщ @ Mar 31 2007, 02:05) *
"Я Пастернака не читал...", в смысле исходники TNKernel не изучал, но если SPSR после восстановления не нужен, то значит в него и надо перед восстановлением всех регистров занести требуемое значение для CPSR. И при его восстановлении операцией ldmfd xx, {...}^ разрешать прерывания. Глянь мой порт scmRTOS, может там мысль почерпнешь.

Надо подумать.. Кстати по-моему в UCOS засада со стеком точно такая же сидит
.
Проверил ! Все замечательно работает, и стека не кушает :-) Немного тяжко думать, прав ли я теряя SPSR и записывая в него на самом деле CPSR, но раз работает - значит можно :-) Возможно Юрий лучше ответит на этот вопрос, я в АРМовском асме дня три три только копаться начал. Но со стеком теперь совсем хорошо - 18 байт скушал idle_task и больше ни словом больше, несмотря ни на какие вытеснения. Вопрос решен !!!!!!!!!!!!!!!!!!!!!!!!!!!!
Вот итоговый код.
Код
tn_sw_restore
        add sp, sp, #4; easy adjust stack pointer, since we don't need restore original  SPCR
        ldmfd  sp!, {r1}
        msr    SPSR_cxsf, r1; transfer saved CPSR to SPSR        
        ldmfd  sp!, {r0-r12,lr,pc}^
spf
Цитата(yuri_t @ Mar 31 2007, 02:34) *
В авторском варианте TNKernel вложенные прерывания не поддерживаются

Существенное ограничение. Это затрудняет появление портов операцинки на других МК, где имеется более развитый, чем у ARM7, контроллер прерываний.
DASM
Цитата(spf @ Mar 31 2007, 06:22) *
Существенное ограничение. Это затрудняет появление портов операцинки на других МК, где имеется более развитый, чем у ARM7, контроллер прерываний.

да это ограничение обойти то не вопрос. Да и не нада нам ваших процев tongue.gif
spf
Цитата(DASM @ Mar 31 2007, 10:43) *
да это ограничение обойти то не вопрос.

Это понятно, но зачем обходить, если можно взять другую, в которой об этом позаботились сразу.
(отношение к "собственным" вариантам ОС уже высказывал)
Почему это не реализовано сразу? Хотя в первой строке записано
"TNKernel is a compact and very fast real-time kernel for the embedded 32/16 bits microprocessors."
т.е. предлагается забыть об аппаратных возможностях большинства 32/16 МК?

PS:Прошу отнестись к моему вопросу с пониманием, а не бравым отрицанием НЕarm'ов.

Цитата
Да и не нада нам ваших процев tongue.gif

Не горячись раньше времени wink.gif
DASM
Цитата(spf @ Mar 31 2007, 09:41) *
Это понятно, но зачем обходить, если можно взять другую, в которой об этом позаботились сразу.
(отношение к "собственным" вариантам ОС уже высказывал)
Почему это не реализовано сразу? Хотя в первой строке записано
"TNKernel is a compact and very fast real-time kernel for the embedded 32/16 bits microprocessors."
т.е. предлагается забыть об аппаратных возможностях большинства 32/16 МК?

PS:Прошу отнестись к моему вопросу с пониманием, а не бравым отрицанием НЕarm'ов.
Не горячись раньше времени wink.gif

Ну так заведи свою ветку как плох TNKernel и почему ты выбрал не её. Тут обсуждаем расход памяти потоком
yuri_t
По материалам дискуссии буду делать v.2.4. Туда же войдет исправление
бага в ф-ции tn_task_exit(), который нашел Alex_B.
Alex B._
>> Существенное ограничение. Это затрудняет появление
>> портов операцинки на других МК, где имеется более
>> развитый, чем у ARM7, контроллер прерываний.

не затрудняет. В моем порте PIC24/dsPIC вложение явно разрешено. Только как правильно тут заметили - при активных прерываниях стека вам нужно будет очень много. Подтверждаю =(

Кстати, хороший контроллер прерываний (например как в PIC24, каждое прерывание физически на свой вектор, 7 пользовательских приоритетов) не всегда совместим с вытеснением: при возникновении прерывания стек автоматом сохраняется адрес возврата и часть SR (вход в обработчик прерывания - 5 тактов). Если в этот момент возникнет более приоритетное прерывание (в котором разрешено переключение контекста) будут кранты, так как счетчик вложенности инкрементировать некому.
Так что в следующей версии порта PIC24 прерывания с сервисами RTOS будут иметь только один фиксированный приоритет.
spf
Цитата(Alex B._ @ Mar 31 2007, 12:55) *
не затрудняет.
[ skip ]
Так что в следующей версии порта PIC24 прерывания с сервисами RTOS будут иметь только один фиксированный приоритет.


Противоречишь сам себе. Если бы было без затруднений, то не пришлось бы отказываться от вложенных прерываний с сервисами.
Alex B._
>> Противоречишь сам себе. Если бы было без затруднений,
>> то не пришлось бы отказываться от вложенных прерываний
>> с сервисами.

Читай внимательнее. TNKernel - обычная вытесняющая RTOS с отличной реализацией. Портировать ее на другую архитектуру проблем нет.
Проблемы есть с совместимостью контроллеров с аппаратной вложенностью прерваний с вытеснением задач из вложенного прервания - с uCOS, например, будет то же самое.

Если бы все прерывания в PIC24 аппаратно запрещались до момента выполнения первой инструкции в обработчике прерывания - проблем бы не было, так как в этой архитектуре можно запретить прерывания одной инструкцией на нужное количество тактов
spf
Цитата(Alex B._ @ Mar 31 2007, 14:48) *
Проблемы есть с совместимостью контроллеров с аппаратной вложенностью прерваний с вытеснением задач из вложенного прервания - с uCOS, например, будет то же самое.

Может мы о разном?
В uCOS-II вытеснение из любого уровня вложенного прерывания выполняется нормально, без крантов, проверено.
DASM
Господа, а не пойти ли вам в другую ветку ? Я серьезно. Бегло оглядел код порта ЮКОС под АРМ - вроде засада таже самая. Но может и нет - не важно. Кстати - никто не забыл, сколько ЮКОС стоит ? Надеюсь тут все законопослушны и купили её? А TNKernel - бесплатна, и при этом хороша. Господа, эта ветка про неконтролируемый расход стека в TNKernel при неудачном стечении обстоятельств. Как автор ветки - закрою нафик, от флуда. Давайте по делу. Пока что единственное чего я не услышал от Юрия - так это что проблема не надуманна - и в новых версиях исправления будут. Все остальное - ПЛИЗ - НЕ сюда
yuri_t
Дело в том, что ситуация, когда OS не может полностью войти в задачу, а уже вытесняется
прерыванием и это происходит постоянно, а не изредка, говорит о том, что OS работает очень близко к пределу своей производительности.
Эта ситуация нежелательна. Поэтому и в uCOS, и во многих других OS (коммерческих и
свободных) проблема, которую вычислил DASM, тоже присутствует. Ну просто никто не использовал OS на пределе...
Надо ли устранять проблему или просто уменьшить нагрузку на OS + увеличить стек ? Как я сейчас вижу, надо устранять - молодые люди любят выжимать из системы все и, наверное, они правы...


P.S To spf - Порт uCOS для ARM, кстати, не поддерживает вложенных прерываний. Там для отслеживания вложенности есть специальная переменная. Вступать в дискуссию на эту тему я не стану: хотите - верте, хотите - нет...
zltigo
Цитата(yuri_t @ Mar 31 2007, 18:02) *
Дело в том, что ситуация, когда OS не может полностью войти в задачу, а уже вытесняется
прерыванием, говорит о том что OS работает очень близко к пределу своей производительности.

Нагрузка на систему со сторны обработчика прерывания естественно увеличивает вероятность 'эффекта' и меру пожирания стека, но сам эффект принципиально не исчезает sad.gif и при слабой загрузке. В общем-то надо устранять, ибо никакими внешними организационными мерами 100% гарантии добиться не удастся sad.gif.
zltigo
Цитата(DASM @ Mar 31 2007, 15:32) *
Бегло оглядел код порта ЮКОС под АРМ - вроде засада таже самая.

Посмотрел - нет. Там везде такое:
Код
        LDMFD   SP!, {R4}        ;    Pop new task's CPSR
        MSR     SPSR_cxsf, R4
        LDMFD   SP!, {R0-R12,LR,PC}^;    Pop new task's context

cpsr одновременно с pc восстанавливается из spsr, соответственно никаких неуместных разрешений прерываний не образуется.
yuri_t
Цитата
Посмотрел - нет. Там везде такое:

LDMFD SP!, {R4} ; Pop new task's CPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^; Pop new task's context


В uCOS это исправлено только в последних версиях, а в версии,
например, uCOS 2.76 проблема присутствует в полный рост.

Ноги у этой проблемы растут из кода (свободного), написанного
Michael Anburaj. Он использовался как основа для context switch как в
ранних версиях uCOS, так и в TNKernel. И Jean J. Labrosse, и я, наехали
на одни и те же грабли...

В uCOS это уже исправлено, в версии 2.4 TNKernel это будет исправлено.
IgorKossak
Цитата(yuri_t @ Mar 31 2007, 09:30) *
По материалам дискуссии буду делать v.2.4. Туда же войдет исправление
бага в ф-ции tn_task_exit(), который нашел Alex_B.

А поддержка вложенности прерываний туда войдёт как вариант?
zltigo
Цитата(IgorKossak @ Apr 3 2007, 08:45) *
А поддержка вложенности прерываний туда войдёт как вариант?

Я бы не стал - вложенные в приличной системе это уже в большей части отрыжка бессистемного писания. Практически при наличии у ARMов FIQ и использовании приличной операционной системы об использовании вложенных прерываний нужно ОЧЕНЬ крепко думать, прежде чем использовать. Если кому надо - пусть сам делает и заодно подумает а оно это надо такие навороты делать и цену которую платит за вложенность осознает.
IgorKossak
zltigo, ну если цена высока, то может и не надо.
С другой стороны эту функциональность можно было бы добавить через условную компиляцию, кому как понадобится.
И в третьих Юрию самому виднее целесообразность этого шага и я бы не стал чуть что советовать всё делать самому, мало ли в какой степени мы все специалисты, а то уж больно смахивает на расхожую фразу: "Не нравится Windows (Linux, ...) - напиши себе лучше".

Прошу прощения у DASM за отклонение от темы.
zltigo
Цитата(IgorKossak @ Apr 3 2007, 14:16) *
С другой стороны эту функциональность можно было бы добавить через условную компиляцию, кому как понадобится.

Против такого подхода возразить сложно smile.gif, разве только не провоцировать пользователей на потенциально туманное использование системы...
spf
Цитата(zltigo @ Apr 3 2007, 13:11) *
Я бы не стал - вложенные в приличной системе это уже в большей части отрыжка бессистемного писания.

Приличная -- с многократным запасом производительности?
А как же золотая середина ? wink.gif
Случаи бывают разные - http://electronix.ru/forum/index.php?showtopic=29678
zltigo
Цитата(spf @ Apr 4 2007, 06:03) *
Приличная -- с многократным запасом производительности?

"Запас по производительности" это даже не совсем характеристика системы.
В данном случае это система с малыми затратами на переключение задач.
По ссылке собственно случай и не описан. Только "хочу" что-бы каждое из восьми прерываний немедленно прерывало предыдущее. Вот такой "случай" и точка.
prottoss
Привет всем! Начал разбираться с TNKernel. Почитав форум и погуглиФ, решил, что ОСь вполне подходит. Скомпилил пример, потом пренес один проект. Все прекрасно работает. Проект живет без зависонов почти неделю. И тут черт меня дернул перенести два поля в структуре typedef struct _TN_TCB... конкретно поля

Код
unsigned int * stk_start;          //-- Base address of task's stack space
   int   stk_size;           //-- Task's stack size (in sizeof(void*),not bytes)


из родного места под поле

Код
unsigned int * task_stk;  //-- Pointer to task's top of stack
.

И Фсе.... Система рухнула...Думал, только на моем проекте. Попробовал сделать тоже в примерах - то же самое. Толком я еще проблему не анализировал но программа улетает в неизвестном, пока, мне направлении после завершения кода tn_start_exe: в файле tn_port_asm.s79.

Камень AT91SAM7X256.



Кто нибудь может прокомментировать проблему.
prottoss
Цитата(prottoss @ Mar 25 2008, 21:14) *
разобрался... smile.gif Блин, все верхние поля завязаны c портом под камень... По крайней мере разобрался как все ЭТО фунциклирует, так как хочу портировать на AVR
prottoss
Вобщем "неправильное" использование полей мне не давало покоя и я модернизировал код TNKernel.

1. В структуру CDLL_QUEUE добавил еще одно поле - void *value - это адрес родительского объекта.

2. Во всех инициализациях объектов ОС, содержащих поля типа CDLL_QUEUE, в этих полях инициализируется поле void *value. адресом родительского объекта



Преимущества очевидны - избавились от методов:

TNT_TCB * get_task_by_timer_queque(CDLL_QUEUE *que);
TNT_TCB * get_task_by_block_queque(CDLL_QUEUE *que);
TNT_TCB * get_task_by_tsk_queue(CDLL_QUEUE *que);
TN_MUTEX *get_mutex_by_mutex_queque(CDLL_QUEUE *que);
TN_MUTEX *get_mutex_by_wait_queque(CDLL_QUEUE *que);
TN_MUTEX *get_mutex_by_lock_mutex_queque(CDLL_QUEUE *que);

Возвращающих объект по адресу списка que. Теперь все вызовы вышеперечисленых методов заменены на строку:

que->value;



Таким образом получили более меньше кода, больше скорости:-)

Хотелось бы, конечно, послушать комментарии автора сей замечательной RTOS. Возможно, из-за недопонимания я где то ошибаюсь. Хотя мой проект, имеющий четыре задачи, и использующий события, семафоры и мьютексы пережил сутки без сбоев.
VslavX
Цитата(prottoss @ Mar 26 2008, 17:30) *
Преимущества очевидны - избавились от методов:

TNT_TCB * get_task_by_timer_queque(CDLL_QUEUE *que);
...

Возвращающих объект по адресу списка que. Теперь все вызовы вышеперечисленых методов заменены на строку:

que->value;

Это делается еще проще:

#define CONTAINING_RECORD(address, type, field) ((type *)( (PBYTE)(address) - (PBYTE)(&((type *)0)->field)))

#define get_task_by_tsk_queue(que) CONTAINING_RECORD(que, TN_TCB, task_queue)

ну и остальные методы также - и никаких дополнительных полей и обращений к памяти
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.