У меня есть приложение Contiki, которое сводит меня с ума.
Я должен вычислить энергетическое потребление Tmote Sky. Я использую энергию, и это часть кода, которую я использую в функции оценки потребления энергии, которая периодически называется:
lpm_time = energest_type_time(ENERGEST_TYPE_LPM);
cpu_time = energest_type_time(ENERGEST_TYPE_CPU);
rx_time = energest_type_time(ENERGEST_TYPE_LISTEN);
tx_time = energest_type_time(ENERGEST_TYPE_TRANSMIT);
lpm = lpm_time - prev_times.lpm_time;
cpu = cpu_time - prev_times.cpu_time;
rx = rx_time - prev_times.rx_time;
tx = tx_time - prev_times.tx_time;
consumed_energy = (I_LPM * lpm + I_CPU * cpu + I_RX * rx + I_TX * tx) * VOLTS / RTIMER_ARCH_SECOND; /* mJ = mA * seconds * volts */
/*printf("lpm %lu, cpu %lu, rx %lu, tx %lu, prl %lu, prc %lu, prr %lu, prt %lu\n",
lpm_time, cpu_time, rx_time, tx_time, prev_times.lpm_time, prev_times.cpu_time, prev_times.rx_time, prev_times.tx_time);*/
prev_times.lpm_time = lpm_time;
prev_times.cpu_time = cpu_time;
prev_times.rx_time = rx_time;
prev_times.tx_time = tx_time;
Проблема в том, что приложение работает правильно, только если printf
который теперь прокомментирован, включен. Если он остается прокомментированным, я могу либо получить бессмысленные значения для переменной consumed_energy
, либо симуляция COOJA прекращается с сообщением о недопустимости Illegal read - out of bounds
Java.
Почему это происходит? В чем причина? Это очень странно.
Заранее спасибо.
Полный код этого файла:
volatile static struct energest_times prev_times;
float update_consumption()
{
uint32_t lpm_time;
uint32_t cpu_time;
uint32_t rx_time;
uint32_t tx_time;
uint32_t lpm;
uint32_t cpu;
uint32_t rx;
uint32_t tx;
float consumed_energy;
lpm_time = energest_type_time(ENERGEST_TYPE_LPM);
cpu_time = energest_type_time(ENERGEST_TYPE_CPU);
rx_time = energest_type_time(ENERGEST_TYPE_LISTEN);
tx_time = energest_type_time(ENERGEST_TYPE_TRANSMIT);
lpm = lpm_time - prev_times.lpm_time;
cpu = cpu_time - prev_times.cpu_time;
rx = rx_time - prev_times.rx_time;
tx = tx_time - prev_times.tx_time;
consumed_energy = (I_LPM * lpm + I_CPU * cpu + I_RX * rx + I_TX * tx) * VOLTS / RTIMER_ARCH_SECOND; /* mJ = mA * seconds * volts */
printf("lpm %lu, cpu %lu, rx %lu, tx %lu, prl %lu, prc %lu, prr %lu, prt %lu\n",
lpm_time, cpu_time, rx_time, tx_time, prev_times.lpm_time, prev_times.cpu_time, prev_times.rx_time, prev_times.tx_time);
prev_times.lpm_time = lpm_time;
prev_times.cpu_time = cpu_time;
prev_times.rx_time = rx_time;
prev_times.tx_time = tx_time;
printf("Consumed energy: %ld\n", (int32_t) consumed_energy);
return consumed_energy;
}
Функция периодически вызывается другой функцией, каждую минуту.
Вы можете увидеть это на Java или C, если у вас есть несколько потоков, используя библиотеку, которая не является потокобезопасной. В этой ситуации вы несколько раз получаете правильное значение, а иногда получаете половину права, а иногда получаете бесчувственный смысл.
Если вы добавите printf, например System.out.printf() или любой IO или sleep() или выполните код с помощью отладки, это действительно замедлит ваше приложение, так что каждый поток затрачивает очень небольшой процент времени в библиотеке и, таким образом, косвенно избегает конфликтов.
Вы используете несколько потоков? Является ли библиотека/методы, которые вы называете потоком безопасными?
volatile
, используемое в объявлении prev_times
, имеет значение, близкое к значению Java, я бы сказал, что printf фактически изменяет значение prev_times
, видимое текущим потоком.
volatile
в C означает, что его нельзя оптимизировать. Это не подразумевает безопасность видимости / темы.
printf()
.