2014-11-11 2 views
0

원샷 타이머의 경우 세마포어를 사용하여 타이머 콜백 완료를 기다릴 수 있습니다. 그러나 타이머가 여러 번 실행되면 도움이되지 않습니다. 단지 타이머를 무장 해제 (이 경우 무장했다)와 타이머 자원 assocoated을 해제한다모든 스레드 타이머 콜백 완료를 기다리는 안전한 방법

#include <stdlib.h> 
#include <stdint.h> 
#include <stdio.h> 
#include <signal.h> 
#include <time.h> 
#include <unistd.h> 
#include <pthread.h> 

#define N 10 

void timer_threaded_function(sigval_t si) 
{ 
    uint8_t *shared_resource = si.sival_ptr; 

    sleep(rand() % 7); 

    /* ... manipulate with shared_resource */ 

    return; 
} 

int main() 
{ 
    struct sigevent sig_ev = {0}; 
    uint8_t *shared_resource = malloc(123); 
    timer_t timer_id; 
    int i; 

    sig_ev.sigev_notify = SIGEV_THREAD; 
    sig_ev.sigev_value.sival_ptr = shared_resource; 
    sig_ev.sigev_notify_function = timer_threaded_function; 
    sig_ev.sigev_notify_attributes = NULL; 

    timer_create(CLOCK_REALTIME, &sig_ev, &timer_id); 

    for (i = 0; i < N; i++) { 
     /* arm timer for 1 nanosecond */ 
     timer_settime(timer_id, 0, 
         &(struct itimerspec){{0,0},{0,1}}, NULL); 

     /* sleep a little bit, so timer will be fired */ 
     usleep(1); 
    } 

    /* only disarms timer, but timer callbacks still can be running */ 
    timer_delete(timer_id); 

    /* 
    * TODO: safe wait for all callbacks to end, so shared resource 
    * can be freed without races. 
    */ 
    ... 

    free(shared_resource); 

    return 0; 
} 

timer_delete() : 다음 코드를 고려하십시오. 그러나 타이머 콜백은 여전히 ​​실행 중일 수 있습니다. 그래서 우리는 shared_resource를 해제 할 수 없습니다. 그렇지 않으면 경쟁 조건이 발생할 수 있습니다. 이 상황에 대처할 수있는 방법이 있습니까?

레퍼런스 카운팅에 대해서는 언급하고 있지만 실제로 쓰레드가 실제로 공유 리소스에 액세스하려고 시도하는 양 (타이머 오버런의 원인)을 알지 못하기 때문에 도움이되지 않습니다.

+0

일부 분리 된 스레드가 공유 자원을 조작하는 것을 어떻게 확인하겠습니까? 문제를 해결하고이 문제를 해결했습니다. 'timer_' API는 약간의 붉은 청어입니다. '분리 된 쓰레드는 타이머, 시그널, 루프가'pthread_create()'를 호출함으로써 생성된다는 사실을 염두에 두어야합니다. – pilcrow

답변

0

완전히 불만족 스럽습니다. 나는 보았고, (a)가 해고되지 않았거나, (b) 보류 중이거나, (c)가 계류 중인지를 발견 할 방법이없는 것처럼 보입니다. 실행, 또는 (d)는 완료

내가 제안 할 수 있습니다 베스트 간접 여분의 수준 및 공유 자원의 점에 정적 그래서 :.. foo_t이의 유형입니다

static foo_t* p_shared ; 
    .... 
    p_shared = shared_resourse ; 
    ..... 
    sig_ev.sigev_value.sival_ptr = &p_shared ; 

을 공유 리소스

이제 우리는 일부 원자를 사용할 수 있습니다 ... timer_threaded_function() :

foo_t** pp_shared ; 
    foo_t* p_locked ; 
    foo_t* p_shared ; 

    pp_shared = so.sival_ptr ; 
    p_locked = (void*)UINPTR_MAX ; 
    p_shared = atomic_swap(pp_shared, p_locked) ; 

    if (p_shared == p_locked) 
    return ;     // locked already. 

    if (p_shared == NULL) 
    return ;     // destroyed already. 

    .... proceed to do the usual work ... 

    if (atomic_cmp_swap(pp_shared, &p_locked, p_shared)) 
    return ;     // was locked and is now restored 

    assert(p_locked == NULL) ; 

    ... the shared resource needs to be freed ... 

그리고

제어 스레드 : 이벤트 스레드가 공유 RESOURSE가 해제 될 필요가 있음을 발견하면

timer_delete(timer_id) ;    // no more events, thank you 

    p_s = atomic_swap(&p_shared, NULL) ; // stop processing events 

    if (p_s == (void*)UINTPTR_MAX) 
    // an event is being processed. 

    if (p_s != NULL) 
    ... the shared resource needs to be freed ... 

는, 그것 자체를 수행하거나 제어 스레드에 신호를 수있는 이벤트가 처리되었으므로 제어 스레드가 진행되어 자유를 수행 할 수 있습니다. 그것은 주로 맛의 문제입니다.

기본적으로 이것은 원자가를 사용하여 값이 3 상태 인 잠금을 제공합니다. NULL < => destroyed; UINTPTR_MAX < => 잠김; 다른 것 < => 잠금 해제. 사람들은 알 수없는있다 정확하게 일이기 때문에

아래쪽 측 static p_shared 효과적으로하는 고정되면, timer_threaded_function()이 완료 될 때까지 존재에 남아 있고 다시 호출되지 않을 것이다 static p_shared, ... 그리고 :-(.

+0

고맙습니다. 원자 변수 p_shared 포인터 일 수도 있습니다. 종류의 뮤텍스/sp 일부 보호 상태 플래그와 잠금. –

관련 문제