Мобильное программирование приложений реального времени в стандарте POSIX

и уничтожения атрибутных объектов потоков


#include <trace.h> int posix_trace_attr_init ( trace_attr_t *attr); int posix_trace_attr_destroy ( trace_attr_t *attr);
Листинг 8.1. Описание функций создания и уничтожения атрибутных объектов потоков трассировки.
Закрыть окно




#include <trace.h> int posix_trace_attr_getgenversion ( const trace_attr_t *attr, char *genversion); int posix_trace_attr_getname ( const trace_attr_t *attr, char *tracename); int posix_trace_attr_setname ( trace_attr_t *attr, const char *tracename); #include <time.h> #include <trace.h> int posix_trace_attr_getcreatetime ( const trace_attr_t *attr, struct timespec *createtime);
Листинг 8.2. Описание функций манипулирования атрибутами, идентифицирующими поток трассировки.
Закрыть окно




#include <time.h> #include <trace.h> int posix_trace_attr_getclockres ( const trace_attr_t *attr, struct timespec *resolution);
Листинг 8.3. Описание функции опроса разрешающей способности часов, с помощью которых проставляются временные штампы.
Закрыть окно






#include <trace.h> int posix_trace_attr_getinherited ( const trace_attr_t *restrict attr, int *restrict inheritancepolicy); int posix_trace_attr_setinherited ( trace_attr_t *attr, int inheritancepolicy); int posix_trace_attr_getstreamfullpolicy ( const trace_attr_t *restrict attr, int *restrict streampolicy); int posix_trace_attr_setstreamfullpolicy ( trace_attr_t *attr, int streampolicy); int posix_trace_attr_getlogfullpolicy ( const trace_attr_t *restrict attr, int *restrict logpolicy); int posix_trace_attr_setlogfullpolicy ( trace_attr_t *attr, int logpolicy);
Листинг 8.4. Описание функций манипулирования значениями поведенческих атрибутов потоков и журналов в атрибутных объектах.
Закрыть окно




#include <sys/types.h> #include <trace.h> int posix_trace_attr_getmaxdatasize ( const trace_attr_t *restrict attr, size_t *restrict maxdatasize); int posix_trace_attr_setmaxdatasize ( trace_attr_t *attr, size_t maxdatasize); int posix_trace_attr_getmaxsystemeventsize ( const trace_attr_t *restrict attr, size_t *restrict eventsize); int posix_trace_attr_getmaxusereventsize ( const trace_attr_t * restrict attr, size_t data_len, size_t *restrict eventsize); int posix_trace_attr_getstreamsize ( const trace_attr_t *restrict attr, size_t *restrict streamsize); int posix_trace_attr_setstreamsize ( trace_attr_t *attr, size_t streamsize); int posix_trace_attr_getlogsize ( const trace_attr_t *restrict attr, size_t *restrict logsize); int posix_trace_attr_setlogsize ( trace_attr_t *attr, size_t logsize);
Листинг 8.5. Описание функций манипулирования размерами событий, потоков и журналов в атрибутных объектах.
Закрыть окно




#include <sys/types.h> #include <trace.h> int posix_trace_create (pid_t pid, const trace_attr_t *restrict attr, trace_id_t *restrict trid); int posix_trace_create_withlog (pid_t pid, const trace_attr_t * restrict attr, int fildes, trace_id_t *restrict trid);
Листинг 8.6. Описание функций создания потоков трассировки.
Закрыть окно




#include <trace.h> int posix_trace_start (trace_id_t trid); int posix_trace_stop (trace_id_t trid);
Листинг 8.7. Описание функций активизации и приостановки трассировки.
Закрыть окно




#include <sys/types.h> #include <trace.h> int posix_trace_shutdown (trace_id_t trid);
Листинг 8.8. Описание функции завершения трассировки.
Закрыть окно




#include <sys/types.h> #include <trace.h> int posix_trace_flush (trace_id_t trid);
Листинг 8.9. Описание функции сброса потока трассировки в журнал.
Закрыть окно




#include <trace.h> int posix_trace_get_status (trace_id_t trid, struct posix_trace_status_info *statusinfo);
Листинг 8.10. Описание функции опроса статуса потока трассировки.
Закрыть окно




#include <trace.h> int posix_trace_get_attr ( trace_id_t trid, trace_attr_t *attr);
Листинг 8.11. Описание функции опроса атрибутов потока трассировки.
Закрыть окно




#include <sys/types.h> #include <trace.h> int posix_trace_clear (trace_id_t trid);
Листинг 8.12. Описание функции очистки потока трассировки.
Закрыть окно




#include <trace.h> int posix_trace_get_filter ( trace_id_t trid, trace_event_set_t *set); int posix_trace_set_filter ( trace_id_t trid, const trace_event_set_t *set, int how);
Листинг 8.13. Описание функций опроса и установки фильтров событий трассировки.
Закрыть окно




#include <trace.h> int posix_trace_eventset_empty ( trace_event_set_t *set); int posix_trace_eventset_fill ( trace_event_set_t *set, int what); int posix_trace_eventset_add ( trace_event_id_t event_id, trace_event_set_t *set); int posix_trace_eventset_del ( trace_event_id_t event_id, trace_event_set_t *set); int posix_trace_eventset_ismember ( trace_event_id_t event_id, const trace_event_set_t *restrict set, int *restrict ismember);
Листинг 8.14. Описание функций для работы с множествами событий трассировки.
Закрыть окно




#include <trace.h> int posix_trace_trid_eventid_open ( trace_id_t trid, const char *restrict event_name, trace_event_id_t *restrict event);
int posix_trace_eventid_get_name ( trace_id_t trid, trace_event_id_t event, char *event_name);
int posix_trace_eventid_equal ( trace_id_t trid, trace_event_id_t event1, trace_event_id_t event2);
Листинг 8.15. Описание функций для работы с идентификаторами типов событий трассировки.
Закрыть окно




#include <trace.h> int posix_trace_eventtypelist_getnext_id ( trace_id_t trid, trace_event_id_t *restrict event, int *restrict unavailable); int posix_trace_eventtypelist_rewind (trace_id_t trid);
Листинг 8.16. Описание функций для работы с совокупностью идентификаторов типов событий.
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * */ /* Программа выясняет подразумеваемые значения */ /* атрибутов потока трассировки */ /* * * * * * * * * * * * * * * * * * * * * * * */
#include <sys/types.h> #include <stdio.h> #include <trace.h> #include <time.h> #include <limits.h> #include <errno.h>
int main (void) { trace_attr_t attr; /* Атрибутный объект потока */ trace_id_t trid; /* Идентификатор потока */ char trbuf [TRACE_NAME_MAX]; /* Буфер для имен */ struct timespec tms; /* Структура для времен */ char dtbuf [LINE_MAX]; /* Буфер для данных о времени */ int res; /* Целочисленные результаты */ size_t mdatsz; /* Максимальный размер данных */ if ((errno = posix_trace_create (0, NULL, &trid)) != 0) { perror ("POSIX_TRACE_CREATE"); return (errno); }
if ((errno = posix_trace_get_attr (trid, &attr)) != 0) { perror ("POSIX_TRACE_GET_ATTR"); return (errno); }
if ((errno = posix_trace_attr_getgenversion (&attr, trbuf)) != 0) { perror ("POSIX_TRACE_ATTR_GETGENVERSION"); return (errno); } printf ("Версия системы трассировки: %s\n", trbuf);
if ((errno = posix_trace_attr_getname (&attr, trbuf)) != 0) { perror ("POSIX_TRACE_ATTR_GETNAME"); return (errno); } printf ("Имя потока трассировки: %s\n", trbuf);
if ((errno = posix_trace_attr_getcreatetime (&attr, &tms)) != 0) { perror ("POSIX_TRACE_ATTR_GETCREATETIME"); return (errno); } (void) strftime (dtbuf, sizeof (dtbuf), "%c", localtime (&tms.tv_sec)); printf ("Время создания потока трассировки: %s\n", dtbuf);
if ((errno = posix_trace_attr_getclockres (&attr, &tms)) != 0) { perror ("POSIX_TRACE_ATTR_GETCLOCKRES"); return (errno); } printf ("Разрешающая способность часов потока " "трассировки: %ld нсек\n", tms.tv_nsec);
if ((errno = posix_trace_attr_getstreamfullpolicy (&attr, &res)) != 0) { perror ("POSIX_TRACE_ATTR_GETSTREAMFULLPOLICY"); return (errno); } printf (" Правило обработки ситуации заполнения потока: "); switch (res) { case POSIX_TRACE_LOOP: printf ("POSIX_TRACE_LOOP\n"); break; case POSIX_TRACE_UNTIL_FULL: printf ("POSIX_TRACE_UNTIL_FULL\n"); break; case POSIX_TRACE_FLUSH: printf ("POSIX_TRACE_FLUSH\n"); break; default: printf ("неизвестно\n"); }
if ((errno = posix_trace_attr_getlogfullpolicy (&attr, &res)) != 0) { perror ("POSIX_TRACE_ATTR_GETLOGFULLPOLICY"); return (errno); } printf ("Правило обработки ситуации заполнения " "журнала трассировки: "); switch (res) { case POSIX_TRACE_LOOP: printf ("POSIX_TRACE_LOOP\n"); break; case POSIX_TRACE_UNTIL_FULL: printf ("POSIX_TRACE_UNTIL_FULL\n"); break; case POSIX_TRACE_APPEND: printf ("POSIX_TRACE_APPEND\n"); break; default: printf ("неизвестно\n"); }
if ((errno = posix_trace_attr_getmaxdatasize (&attr, &mdatsz)) != 0) { perror ("POSIX_TRACE_ATTR_GETMAXDATASIZE"); return (errno); } printf ("Максимальный размер данных в пользовательском " "событии: %d\n", mdatsz);
if ((errno = posix_trace_attr_getmaxusereventsize (&attr, mdatsz, &mdatsz)) != 0) { perror ("POSIX_TRACE_ATTR_GETMAXUSEREVENTSIZE"); return (errno); } printf ("Максимальный размер пользовательского события: " "%d\n", mdatsz);
if ((errno = posix_trace_attr_getmaxsystemeventsize (&attr, &mdatsz)) != 0) { perror ("POSIX_TRACE_ATTR_GETMAXSYSTEMEVENTSIZE"); return (errno); } printf ("Максимальный размер системного события: " "%d\n", mdatsz);
if ((errno = posix_trace_attr_getstreamsize (&attr, &mdatsz)) != 0) { perror ("POSIX_TRACE_ATTR_GETSTREAMSIZE"); return (errno); } printf ("Размер потока трассировки: %d\n", mdatsz);
return 0; }
Листинг 8.17. Пример программы, выясняющей подразумеваемые значения атрибутов потока трассировки.
Закрыть окно




Версия системы трассировки: 2. 17 Имя потока трассировки: trace Время создания потока трассировки: Пн 19 АПР 2004 11:54:07 Разрешающая способность часов потока трассировки: 41904 нсек Правило обработки ситуации заполнения потока: POSIX_TRACE_UNTIL_FULL Правило обработки ситуации заполнения журнала трассировки: POSIX_TRACE_LOOP Максимальный размер данных в пользовательском событии: 100 Максимальный размер пользовательского события: 128 Максимальный размер системного события: 84 Размер потока трассировки: 409600
Листинг 8.18. Возможные результаты работы программы, выясняющей подразумеваемые значения атрибутов потока трассировки.
Закрыть окно




#include <sys/types.h> #include <trace.h>
void posix_trace_event ( trace_event_id_t event_id, const void *restrict data_ptr, size_t data_len);
int posix_trace_eventid_open ( const char *restrict event_name, trace_event_id_t *restrict event_id);
Листинг 8.19. Описание функций для оборудования трассируемых пользовательских приложений.
Закрыть окно




#include <trace.h> int posix_trace_open ( int fildes, trace_id_t *trid); int posix_trace_close (trace_id_t trid); int posix_trace_rewind (trace_id_t trid);
Листинг 8.20. Описание функций для работы с журналами трассировки.
Закрыть окно




#include <sys/types.h> #include *lt;trace.h>
int posix_trace_getnext_event ( trace_id_t trid, struct posix_trace_event_info *restrict event, void * restrict data_ptr, size_t num_bytes, size_t *restrict data_len, int *restrict unavailable);
int posix_trace_timedgetnext_event ( trace_id_t trid, struct posix_trace_event_info *restrict event, void *restrict data_ptr, size_t num_bytes, size_t *restrict data_len, int *restrict unavailable, const struct timespec *restrict abstime);
int posix_trace_trygetnext_event ( trace_id_t trid, struct posix_trace_event_info *restrict event, void *restrict data_ptr, size_t num_bytes, size_t *restrict data_len, int *restrict unavailable);
Листинг 8.21. Описание функций чтения событий трассировки.
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Многопотоковый вариант обеда философов с использованием */ /* сигналов реального времени и таймера для контроля */ /* длительности обеда как пример применения средств трассировки */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
. . . #include <trace.h>
. . . /* Идентификаторы генерируемых пользовательских событий */ static trace_event_id_t pev1; /* Заявка на захват вилок */ static trace_event_id_t pev2; /* Захват вилок */ static trace_event_id_t pev3; /* Освобождение вилок */
. . . /* * * * * * * * * * * * * * * * * * * * * * */ /* Попытка выполнить заявку на захват вилок */ /* от философа номер no, если она есть */ /* * * * * * * * * * * * * * * * * * * * * * */ static void fork_lock (int no) {
. . . phil_req [no – 1] = 0; /* Сгенерируем событие – захват вилок */ posix_trace_event (pev2, &no, sizeof (no));
. . . }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Стартовая функция потока, обслуживающего заявки на захват */ /* и освобождение вилок. Заявка передается в виде значения, */ /* ассоциированного с сигналом signo. Значение no > 0 */ /* запрашивает захват вилок для философа с номером no, */ /* no < 0 – освобождение философа -no */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void *start_waiter (void *signo) { int no; /* Номер философа, приславшего заявку */
. . . /* Заявка на захват вилок. */ /* Запомним ее ... */ phil_req [no – 1] = 1; /* Сгенерируем событие – заявка на захват вилок ... */ posix_trace_event (pev1, &no, sizeof (no)); /* ... и попробуем выполнить заявку */ fork_lock (no); } else { /* Освобождение вилок */ no = -no; fork_busy [no – 1] = fork_busy [no % QPH] = 0; /* Сгенерируем событие – освобождение вилок */ posix_trace_event (pev3, &no, sizeof (no));
. . . }
/* * * * * * * * * * * * * */ /* Организация обеда */ /* (бывшая функция main()) */ /* * * * * * * * * * * * * */ void *dinorg (void *dummy) {
. . . return (NULL); }
/* * * * * * * * * * * * * * * * */ /* Управление трассировкой, */ /* выборка и распечатка событий */ /* * * * * * * * * * * * * * * * */ int main (void) { trace_id_t trid; /* Идентификатор потока трассировки */ trace_event_set_t fltr; /* Множество фильтруемых событий */ pthread_t pt_dinorg; /* Идентификатор потока управления, */ /* ведающего организацией обеда */ /* Информация о событии */ struct posix_trace_event_info evinf; size_t datsz; /* Размер данных в событии */ /* Буфер для имени события */ char evnam [TRACE_EVENT_NAME_MAX]; int evdat [BUFSIZ]; /* Данные "вилочных" событий */ int res; /* Целочисленные результаты */ if ((errno = posix_trace_create (0, NULL, &trid)) != 0) { perror ("POSIX_TRACE_CREATE"); return (errno); }
/* Установим фильтр на все системные события ... */ (void) posix_trace_eventset_fill (&fltr, POSIX_TRACE_SYSTEM_EVENTS); /* ... и удалим из него события с сигналами */ (void) posix_trace_eventset_del (traceSigGeneration, &fltr); (void) posix_trace_eventset_del (traceSigDelivery, &fltr); (void) posix_trace_eventset_del (traceSigCatchFunc, &fltr); if ((errno = posix_trace_set_filter (trid, &fltr, POSIX_TRACE_SET_EVENTSET)) != 0) { perror ("POSIX_TRACE_SET_FILTER"); return (errno); }
/* Зарегистрируем три типа пользовательских событий */ if (((errno = posix_trace_eventid_open ( "Заявка на вилки философа", &pev1)) != 0) || ((errno = posix_trace_eventid_open ( "Захват вилок философа", &pev2)) != 0) || ((errno = posix_trace_eventid_open ( "Освобождение вилок философа", &pev3)) != 0)) { perror ("POSIX_TRACE_TRID_EVENTID_OPEN"); return (errno); }
/* Активизируем трассировку */ if ((errno = posix_trace_start (trid)) != 0) { perror ("POSIX_TRACE_START"); return (errno); }
/* Организуем обед */ if ((errno = pthread_create (&pt_dinorg, NULL, dinorg, NULL)) != 0) { perror ("PTHREAD_CREATE-dinorg"); return (errno); }
/* Дождемся завершения обеда */ (void) pthread_join (pt_dinorg, NULL);
/* Остановим трассировку */ if ((errno = posix_trace_stop (trid)) != 0) { perror ("POSIX_TRACE_STOP"); return (errno); }
/* Прочитаем и распечатаем сгенерированные события */ printf ("Помещенные в поток трассировки события " "с вилками:\n"); while (posix_trace_getnext_event (trid, &evinf, &evdat, sizeof (evdat), &datsz, &res), res == 0) { if (evinf.posix_event_id == traceSigGeneration) { printf ("Потоком %p порожден сигнал с номером %d " "и значением %d " "для потока %p\n", (void *) evdat [0], evdat [2], evdat [3], (void *) evdat [5]); else if (evinf.posix_event_id == traceSigDelivery) { printf ("Потоку %p доставлен сигнал с номером %d " "и значением %d\n", (void *) evdat [0], evdat [1], evdat [2]); } else if (evinf.posix_event_id == traceSigCatchFunc) { printf ("В контексте потока %p вызван обработчик " "сигнала с номером %d " "и значением %d\n", (void *) evdat [0], evdat [1], evdat [2]); } else if (posix_trace_eventid_get_name (trid, evinf.posix_event_id, evnam) == 0) { printf (" %s %d\n", evnam, evdat [0]); } }
return 0; }
Листинг 8.22. Фрагмент исходного текста программы обеда философов с трассировкой.
Закрыть окно




Помещенные в поток трассировки события с вилками: Потоком 0xf10b34 порожден сигнал с номером 24 и значением 1 для потока 0xf14d54 Потоку 0xf14d54 доставлен сигнал с номером 24 и значением 1 Заявка на вилки философа 1 Захват вилок философа 1 Потоком 0xf14d54 порожден сигнал с номером 2 и значением 0 для потока 0xf10b34 Потоку 0xf10b34 доставлен сигнал с номером 2 и значением 0 В контексте потока 0xf10b34 вызван обработчик сигнала с номером 2 и значением 0 Потоком 0xf0c914 порожден сигнал с номером 24 и значением 2 для потока 0xf14d54 Потоку 0xf14d54 доставлен сигнал с номером 24 и значением 2 Потоком 0xf10b34 порожден сигнал с номером 24 и значением -1 для потока 0xf14d54 Потоку 0xf14d54 доставлен сигнал с номером 24 и значением -1 Заявка на вилки философа 2 Освобождение вилок философа 1 . . .
Листинг 8.23. Фрагмент возможных результатов трассировки обеда двух философов на операционной платформе oc2000.
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Трассировка системных событий, связанных с мьютексами. */ /* Демонстрируется, что один поток управления */ /* не дает второму захватить мьютекс */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h> #include <pthread.h> #include <time.h> #include <trace.h> #include <errno.h>
enum { TimeFirstThreadCritical, TimeFirstThreadNonCritical, TimeSecondThreadInit, TimeSecondThreadWait, TimeSecondThreadCritical, TimeSecondThreadNonCritical, TimeTest, TIME_SIZE };
/* Массив задержек всех видов */ static struct timespec my_times [TIME_SIZE];
/* Мьютекс, охраняющий вход в критический интервал */ static pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
/* * * * * * * * * * * * * * * */ /* Заполнение массива задержек */ /* * * * * * * * * * * * * * * */ void init_times (void) { struct timespec resolution; int i;
for (i = 0; i < TIME_SIZE; i++) { my_times [i].tv_sec = 0; my_times [i].tv_nsec = 0; }
if (clock_getres (CLOCK_REALTIME, &resolution) != 0) { perror ("CLOCK_GETRES"); resolution.tv_nsec = 20000000; }
my_times [TimeFirstThreadCritical].tv_nsec = resolution.tv_nsec * 3; my_times [TimeFirstThreadNonCritical].tv_nsec = resolution.tv_nsec * 7; my_times [TimeSecondThreadInit].tv_nsec = resolution.tv_nsec * 2; my_times [TimeSecondThreadWait].tv_nsec = resolution.tv_nsec * 10; my_times [TimeSecondThreadCritical].tv_nsec = resolution.tv_nsec * 4; my_times [TimeSecondThreadNonCritical].tv_nsec = resolution.tv_nsec * 8; my_times [TimeTest].tv_sec = 3; }
/* * * * * * * * * * * * * * * * * */ /* Поток, монополизирующий мьютекс */ /* * * * * * * * * * * * * * * * * */ void *tf1 (void *dummy) { while (1) { if ((errno = pthread_mutex_lock (&my_mutex)) != 0) { perror ("PTHREAD_MUTEX_LOCK"); return ((void *) errno); } /* Критический интервал */ if (nanosleep (&my_times [TimeFirstThreadCritical], NULL) != 0) { perror ("NANOSLEEP-1-1"); return ((void *) errno); } if ((errno = pthread_mutex_unlock (&my_mutex)) != 0) { perror ("PTHREAD_MUTEX_UNLOCK"); return ((void *) errno); }
/* Действия вне критического интервала */ if (nanosleep (&my_times [TimeFirstThreadNonCritical], NULL) != 0) { perror ("NANOSLEEP-1-2"); return ((void *) errno); } }
return (NULL); }
/* * * * * * * * * * * * * * * * * * * * * * * * * */ /* Поток, безуспешно пытающийся захватить мьютекс */ /* * * * * * * * * * * * * * * * * * * * * * * * * */ void *tf2 (void *dummy) {
/* Подготовительные действия */ if (nanosleep (&my_times [TimeSecondThreadInit], NULL) != 0) { perror ("NANOSLEEP-2-1"); return ((void *) errno); }
while (1) { if (pthread_mutex_trylock (&my_mutex) != 0) { /* Ожидание освобождения мьютекса */ if (nanosleep (&my_times [TimeSecondThreadWait], NULL) != 0) { perror ("NANOSLEEP-2-2"); return ((void *) errno); } } else { /* Критический интервал */ if (nanosleep (&my_times [TimeSecondThreadCritical], NULL) != 0) { perror ("NANOSLEEP-2-3"); return ((void *) errno); } if ((errno = pthread_mutex_unlock (&my_mutex)) != 0) { perror ("PTHREAD_MUTEX_UNLOCK"); return ((void *) errno); }
/* Действия вне критического интервала */ if (nanosleep (&my_times [TimeSecondThreadNonCritical], NULL) != 0) { perror ("NANOSLEEP-2-4"); return ((void *) errno); } } }
return (NULL); }
/* * * * * * * * * * * * * * * * */ /* Создание потоков управления, */ /* управление трассировкой, */ /* выборка и распечатка событий */ /* * * * * * * * * * * * * * * * */ int main (void) { pthread_t pt1, pt2; /* Идентификаторы потоков управления */ trace_id_t trid; /* Идентификатор потока трассировки */ trace_event_set_t fltr; /* Множество фильтруемых событий */ /* Информация о событии */ struct posix_trace_event_info evinf; size_t datsz; /* Размер данных в событии */ void *evdat [BUFSIZ]; /* Данные событий */ int res; /* Целочисленные результаты */
if ((errno = posix_trace_create (0, NULL, &trid)) != 0) { perror ("POSIX_TRACE_CREATE"); return (errno); } /* Установим фильтр на системные события, */ /* не связанные с захватом мьютексов */ (void) posix_trace_eventset_fill (&fltr, POSIX_TRACE_SYSTEM_EVENTS); (void) posix_trace_eventset_del (traceMutexLock, &fltr); (void) posix_trace_eventset_del (traceMutexTryLock, &fltr); (void) posix_trace_eventset_del (traceMutexUnlock, &fltr); if ((errno = posix_trace_set_filter (trid, &fltr, POSIX_TRACE_SET_EVENTSET)) != 0) { perror ("POSIX_TRACE_SET_FILTER"); return (errno); }
/* Заполним массив задержек */ init_times ();
/* Активизируем трассировку */ if ((errno = posix_trace_start (trid)) != 0) { perror ("POSIX_TRACE_START"); return (errno); }
/* Создадим потоки управления, конкурирующие за мьютекс */ (void) pthread_create (&pt1, NULL, tf1, NULL); (void) pthread_create (&pt2, NULL, tf2, NULL);
/* Дадим созданным потокам повыполняться */ (void) nanosleep (&my_times [TimeTest], NULL);
/* Терминируем потоки управления */ (void) pthread_cancel (pt2); (void) pthread_cancel (pt1); /* Дождемся завершения */ (void) pthread_join (pt1, NULL); (void) pthread_join (pt2, NULL);
/* Остановим трассировку */ if ((errno = posix_trace_stop (trid)) != 0) { perror ("POSIX_TRACE_STOP"); return (errno); } printf ("Помещенные в поток трассировки события " "с мьютексом %p:\n", &mamp;y_mutex); while (posix_trace_getnext_event (trid, &evinf, &evdat, sizeof (evdat), &datsz, &res), res == 0) { /* Нас интересуют только операции с мьютексом */ /* my_mutex */ if (evdat [3] != &my_mutex) { continue; } if (evinf.posix_event_id == traceMutexLock) { printf ("%ld сек. %ld нсек. Попытка захвата " "мьютекса:\n" "код ошибки %d, поток %p, " "владелец %p\n", evinf.posix_timestamp.tv_sec, evinf.posix_timestamp.tv_nsec, (int) evdat [0], evinf.posix_thread_id, evdat [4]); } else if (evinf.posix_event_id == traceMutexTryLock) { printf ("%ld сек. %ld нсек. Попытка захвата без " "ожидания мьютекса:\n" "код ошибки %d, " "поток %p, владелец %p\n", evinf.posix_timestamp.tv_sec, evinf.posix_timestamp.tv_nsec, (int) evdat [0], evinf.posix_thread_id, evdat [4]); } else if (evinf.posix_event_id == traceMutexUnlock) { printf ("%ld сек. %ld нсек. Освобождение " "мьютекса:\n" "код ошибки %d, поток %p\n", evinf.posix_timestamp.tv_sec, evinf.posix_timestamp.tv_nsec, (int) evdat [0], evinf.posix_thread_id); } }
return 0; }
Листинг 8.24. Программа, демонстрирующая трассировку системных событий, связанных с мьютексами, на операционной платформе oc2000.
Закрыть окно




Помещенные в поток трассировки события с мьютексом 0xf34dcc . . . 18 сек. 200100569 нсек. Попытка захвата мьютекса: код ошибки 0, поток 0xf18f74, владелец 0xf18f74 18 сек. 240099731 нсек. Попытка захвата без ожидания мьютекса: код ошибки 6, поток 0xf14d54, владелец 0xf18f74 18 сек. 260103084 нсек. Освобождение мьютекса: код ошибки 0, поток 0xf18f74 18 сек. 400098893 нсек. Попытка захвата мьютекса: код ошибки 0, поток 0xf18f74, владелец 0xf18f74 18 сек. 440100569 нсек. Попытка захвата без ожидания мьютекса: код ошибки 6, поток 0xf14d54, владелец 0xf18f74 18 сек. 460102246 нсек. Освобождение мьютекса: код ошибки 0, поток 0xf18f74 . . .
Листинг 8.25. Фрагмент возможных результатов трассировки системных событий, связанных с мьютексами, на операционной платформе oc2000.
Закрыть окно



Содержание раздела