uIP 1.0
|
00001 /* 00002 * Copyright (c) 2004-2005, Swedish Institute of Computer Science. 00003 * Все права зарезервированы. * 00004 * Повторное распространение, использование в исходном и двоичном виде, 00005 * с модификацией или без - разрешается, если выполняются следующие 00006 * условия: 00007 * 1. Распространение исходного кода должно сохранить вышеуказанную пометку 00008 * копирайта, этот список условий и следующую правовую оговорку. 00009 * 2. Распространение исходного кода должно сохранить вышеуказанную пометку 00010 * копирайта, этот список условий и следующую правовую оговорку в 00011 * документации и/или других материалах, которые будут предоставлены 00012 * вместе с распространяемыми материалами. 00013 * 3. Имя автора не может использоваться, чтобы подтвердить или продвинуть 00014 * продукты, написанные с использованием этого программного обеспечения 00015 * без специального на то разрешения. 00016 * 00017 * ЭТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ АВТОРОМ ``КАК ЕСТЬ'', БЕЗ 00018 * КАКОЙ-ЛИБО ЛЮБОЙ РАСШИРЕННОЙ ИЛИ ПОДРАЗУМЕВАЕМОЙ ГАРАНТИИ, ВКЛЮЧАЯ, 00019 * НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ГАРАНТИИ ВЫСОКОГО СПРОСА И ПРИГОДНОСТИ 00020 * ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. АВТОР НИ ПРИ КАКИХ УСЛОВИЯХ НЕ ОТВЕТСТВЕНЕН 00021 * ЗА ЛЮБЫЕ УБЫТКИ - ПРЯМЫЕ, КОСВЕННЫЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ, ОБРАЗЦОВЫЕ 00022 * ИЛИ ПОСЛЕДОВАТЕЛЬНЫЕ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ТРЕБОВАНИЯ 00023 * ЗАМЕНЫ ТОВАРА ИЛИ СЕРВИСА; ПОТЕРИ ИСПОЛЬЗОВАНИЯ, ДАННЫХ ИЛИ ВЫГОДЫ; 00024 * ИЛИ ПРЕКРАЩЕНИЕ БИЗНЕСА), ОДНАКО ВЫЗВАННЫЕ ПО ЛЮБОЙ ТЕОРИИ ОТВЕТСТВЕННОСТИ, 00025 * ЛИБО В КОНТРАКТЕ, ПРЯМОЙ ОТВЕТСТВЕННОСТИ, ЛИБО В НАРУШЕНИИ ЗАКОННЫХ ПРАВ 00026 * (ВКЛЮЧАЯ ТАК ИЛИ ИНАЧЕ НЕБРЕЖНОСТЬ), ВОЗНИКАЮЩИЕ ВСЕГДА ИЗ ИСПОЛЬЗОВАНИЯ 00027 * ЭТОГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, ДАЖЕ ЕСЛИ БЫЛО ПРЕДУПРЕЖДЕНИЕ О ВОЗМОЖНОСТИ 00028 * ТАКОГО ПОВРЕЖДЕНИЯ. 00029 * 00030 * Этот файл является частью стека uIP TCP/IP. 00031 * 00032 * Author: Adam Dunkels <adam@sics.se> 00033 * 00034 * $Id: pt.h,v 1.2 2006/06/12 08:00:30 adam Exp $ 00035 */ 00036 00037 /** 00038 * \addtogroup pt 00039 * @{ 00040 */ 00041 00042 /** 00043 * \file 00044 * Реализация protothread-ов. 00045 * \author 00046 * Adam Dunkels <adam@sics.se> 00047 * 00048 */ 00049 00050 #ifndef __PT_H__ 00051 #define __PT_H__ 00052 00053 #include "lc.h" 00054 00055 struct pt { 00056 lc_t lc; 00057 }; 00058 00059 #define PT_WAITING 0 00060 #define PT_EXITED 1 00061 #define PT_ENDED 2 00062 #define PT_YIELDED 3 00063 00064 /** 00065 * \name Initialization 00066 * @{ 00067 */ 00068 00069 /** 00070 * Инициализация protothread. 00071 * 00072 * Инициализирует protothread. Инициализация должна быть выполнена до начала 00073 * выполнения protothread. 00074 * 00075 * \param pt Указатель на protothread control structure (структура управления). 00076 * 00077 * \sa PT_SPAWN() 00078 * 00079 * \hideinitializer 00080 */ 00081 #define PT_INIT(pt) LC_INIT((pt)->lc) 00082 00083 /** @} */ 00084 00085 /** 00086 * \name Декларация и определение 00087 * @{ 00088 */ 00089 00090 /** 00091 * Декларация protothread. 00092 * 00093 * Этот макрос используется для декларации protothread. Все protothread-ы должны 00094 * быть задекларированы с помощью этого макроса. 00095 * 00096 * \param name_args Имя и аргументы функции C, реализующей protothread. 00097 * 00098 * \hideinitializer 00099 */ 00100 #define PT_THREAD(name_args) char name_args 00101 00102 /** 00103 * Декларирует начало protothread внутри функции C, реализующей protothread. 00104 * 00105 * Этот макрос используется для декларирования стартовой точки для 00106 * protothread. Она должна быть размещена в начале функции, в которой 00107 * запускается protothread. Все операторы C до вызова PT_BEGIN() 00108 * будут выполнены каждый раз, когда назначается шедулинг для protothread. 00109 * 00110 * \param pt Указатель на protothread control structure. 00111 * 00112 * \hideinitializer 00113 */ 00114 #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc) 00115 00116 /** 00117 * Декларируется конец для protothread. 00118 * 00119 * Этот макрос используется для декларирования места, где заканчивается 00120 * protothread. Он должен всегда использоваться совместно с соответствующим 00121 * парным вызовом макроса PT_BEGIN(). 00122 * 00123 * \param pt Указатель на protothread control structure. 00124 * 00125 * \hideinitializer 00126 */ 00127 #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \ 00128 PT_INIT(pt); return PT_ENDED; } 00129 00130 /** @} */ 00131 00132 /** 00133 * \name Блокирующее ожидание. 00134 * @{ 00135 */ 00136 00137 /** 00138 * Блокирует выполнения и ждет, пока условие не станет true. 00139 * 00140 * Этот макрос блокирует выполнение protothread, пока указанное условие не 00141 * станет равным true. 00142 * 00143 * \param pt Указатель на protothread control structure. 00144 * \param condition Условие. 00145 * 00146 * \hideinitializer 00147 */ 00148 #define PT_WAIT_UNTIL(pt, condition) \ 00149 do { \ 00150 LC_SET((pt)->lc); \ 00151 if(!(condition)) { \ 00152 return PT_WAITING; \ 00153 } \ 00154 } while(0) 00155 00156 /** 00157 * Блокировка и ожидание, пока условие true. 00158 * 00159 * Эта функция блокирует выполнение и ждет, пока условие в состоянии true. 00160 * См. также PT_WAIT_UNTIL(). 00161 * 00162 * \param pt Указатель на protothread control structure. 00163 * \param cond Условие. 00164 * 00165 * \hideinitializer 00166 */ 00167 #define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond)) 00168 00169 /** @} */ 00170 00171 /** 00172 * \name Иераржия protothread-ов 00173 * @{ 00174 */ 00175 00176 /** 00177 * Блокирует и ждет, пока не завершится дочерний protothread. 00178 * 00179 * Этот макрос запускает шедулинг дочернего protothread. Текущий protothread 00180 * будет заблокирован, пока дочерний protothread не завершится. 00181 * 00182 * \note Дочерний protothread должен быть инициализирован вручную функцией 00183 * PT_INIT() до того, как будет использована функция PT_SPAWN. 00184 * 00185 * \param pt Указатель на protothread control structure. 00186 * \param thread Дочерний protothread с аргументами. 00187 * 00188 * \sa PT_SPAWN() 00189 * 00190 * \hideinitializer 00191 */ 00192 #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread)) 00193 00194 /** 00195 * Порождает дочерний protothread и ждет выхода из него. 00196 * 00197 * Этот макрос порождает дочерний protothread и ждет, пока он не выполнит 00198 * выход. Макрос может быть использован только в пределах protothread. 00199 * macro can only be used within a protothread. 00200 * 00201 * \param pt Указатель на protothread control structure. 00202 * \param child Указатель на protothread control structure дочернего protothread. 00203 * \param thread Дочерний protothread с аргументами. 00204 * 00205 * \hideinitializer 00206 */ 00207 #define PT_SPAWN(pt, child, thread) \ 00208 do { \ 00209 PT_INIT((child)); \ 00210 PT_WAIT_THREAD((pt), (thread)); \ 00211 } while(0) 00212 00213 /** @} */ 00214 00215 /** 00216 * \name Выход и рестарт 00217 * @{ 00218 */ 00219 00220 /** 00221 * Делает рестарт для protothread. 00222 * 00223 * Этот макрос заблокирует и перезапустит работающий protothread 00224 * с того места, где стоит вызов PT_BEGIN(). 00225 * 00226 * \param pt Указатель на protothread control structure. 00227 * 00228 * \hideinitializer 00229 */ 00230 #define PT_RESTART(pt) \ 00231 do { \ 00232 PT_INIT(pt); \ 00233 return PT_WAITING; \ 00234 } while(0) 00235 00236 /** 00237 * Выход из protothread. 00238 * 00239 * Этот макрос производит выход из protothread. Если protothread был 00240 * порожден другим protothread, то родительский protothread станет 00241 * разблокированным и сможет продолжить работу. 00242 * 00243 * \param pt Указатель на protothread control structure. 00244 * 00245 * \hideinitializer 00246 */ 00247 #define PT_EXIT(pt) \ 00248 do { \ 00249 PT_INIT(pt); \ 00250 return PT_EXITED; \ 00251 } while(0) 00252 00253 /** @} */ 00254 00255 /** 00256 * \name Вызов protothread 00257 * @{ 00258 */ 00259 00260 /** 00261 * Шедулинг для protothread. 00262 * 00263 * Эта функция осуществляет шедулинг для protothread. Возвращаемое значение 00264 * функции не рано 0, если protothread работает, или 0, если protothread 00265 * сделал выход. 00266 * 00267 * \param f Вызов C-функции, которая реализует шедулинг для protothread. 00268 * 00269 * \hideinitializer 00270 */ 00271 #define PT_SCHEDULE(f) ((f) == PT_WAITING) 00272 00273 /** @} */ 00274 00275 /** 00276 * \name Уступка контекста (Yielding) из protothread 00277 * @{ 00278 */ 00279 00280 /** 00281 * Уступка контекста управления (Yield) из текущего protothread. 00282 * 00283 * Эта функция уступает процессорное время этого protothread, что позволяет 00284 * другим protothread выполняться в системе. 00285 * 00286 * \param pt Указатель на protothread control structure. 00287 * 00288 * \hideinitializer 00289 */ 00290 #define PT_YIELD(pt) \ 00291 do { \ 00292 PT_YIELD_FLAG = 0; \ 00293 LC_SET((pt)->lc); \ 00294 if(PT_YIELD_FLAG == 0) { \ 00295 return PT_YIELDED; \ 00296 } \ 00297 } while(0) 00298 00299 /** 00300 * \brief Делает уступку процессорного времени из protothread, пока не 00301 * не будет выполнено условие. 00302 * \param pt Указатель на protothread control structure. 00303 * \param cond Условие. 00304 * 00305 * Эта функция будет приводить к уступке процессорного времени 00306 * для этого protothread, пока указанное условие вычисляется 00307 * как true. 00308 * 00309 * 00310 * \hideinitializer 00311 */ 00312 #define PT_YIELD_UNTIL(pt, cond) \ 00313 do { \ 00314 PT_YIELD_FLAG = 0; \ 00315 LC_SET((pt)->lc); \ 00316 if((PT_YIELD_FLAG == 0) || !(cond)) { \ 00317 return PT_YIELDED; \ 00318 } \ 00319 } while(0) 00320 00321 /** @} */ 00322 00323 #endif /* __PT_H__ */ 00324 00325 /** @} */