2010-02-05 2 views
5

마이크로 컨트롤러 시뮬레이션을 구현하려고합니다. 이 시뮬레이션은 하나의 특정 마이크로 컨트롤러의 클럭 사이클 정밀 표현을 의미하는 것이 아니라 코드의 일반적인 정확성을 확인하는 것을 의미합니다.다른 스레드 (현재 스레드가 아닌 스레드)를 일시 중단하려면 어떻게합니까?

정상적인 코드를 실행하는 "주 스레드"와 ISR 코드를 실행하는 두 번째 스레드가 있다고 생각했습니다. ISR을 실행해야 할 때마다 ISR 스레드가 "주 스레드"를 일시 중단합니다.

물론 인터럽트를 차단하는 기능이 필요합니다. "인터럽트가 차단 된"동안 주 스레드가 ISR 코드를 실행할 때마다 ISR 스레드가 보유하는 뮤텍스를 사용하여이 문제를 해결할 생각입니다.

주 스레드를 일시 중단하지만 죽이고 POR 기능을 실행하는 새 스레드를 시작하여 POR (power on reset)을 구현할 수 있습니다.

windows API는 필요한 기능을 제공합니다. 하지만 posix 스레드 (리눅스에서)를 사용하여 위와 같은 작업을 수행하는 것은 불가능한 것처럼 보입니다.

저는 실제 하드웨어 독립적 인 마이크로 컨트롤러 코드를 변경하고 싶지 않습니다. 보류중인 인터럽트를 확인하기 위해 아무 것도 삽입하지 않아도됩니다.

잘 작동하지 않는 지점에서 인터럽트를 수신하는 것이 바람직합니다. 이는 인터럽트를 차단하지 않는 한 마이크로 컨트롤러에서도 마찬가지입니다.

Linux에서 다른 스레드를 일시 중단 할 수있는 방법이 있습니까? (디버거는 어떻게 든 그 옵션을 사용해야한다고 생각합니다.)

제발,이 말은 나쁜 생각입니다. 나는 그것이 대부분의 상황에서 사실임을 압니다. 그러나 주 코드는 표준 라이브러리 또는 잠금/뮤텍스/세마포어를 사용하지 않습니다.

+0

오, 이런. 다른 스레드를 죽이는 것은 매우 위험한 사업입니다. 프로그램에서 잠 그거나 다른 리소스를 영구히 망칠 수 있습니다. 임의의 지점에서 다른 스레드를 일시 중단해도 그다지 좋지는 않지만 여전히 ... – ephemient

+0

주 스레드 코드는 잠금을 사용하지 않으며 (일시 중단 또는 강제 종료를 막는 설명 된 것을 제외하고) 동적 리소스를 할당합니다. 표준 라이브러리를 사용하지 않습니다. –

+0

이것은 glibc 메일 링리스트 [여기] (http : //sources.redhat.com/ml/libc-help/2010-05/msg00014.html). 그러나 아무런 결과없이. – Albert

답변

3

어떻게 든 나는 다른 스레드 SIGSTOP을 보내는 것 같아요.

그러나 senaogires.mutexes 및 전역 변수가 포함 된 스레드 통신을 작성하는 것이 훨씬 낫습니다.

malloc()에서 다른 스레드를 일시 중단하고 malloc() -> deadlock을 호출하면 알 수 있습니다.

내가 사용하는 다른 라이브러리는 물론, 많은 C 표준 라이브러리 함수가 malloc()을 등 뒤에서 호출한다는 것을 언급 했습니까?

편집 :

흠, 표준 라이브러리 코드가 없습니다. 어쩌면 신호 처리기에서 setjmp/longjump()를 사용하여 POR을 시뮬레이트하고 인터럽트를 시뮬레이트하는 신호 처리기를 사용할 수 있습니다.

계속 하시겠습니까? 다른 시나리오에서는 사용할 수없는 특정 시나리오 인 EDIT 이후의 내용에 대한 답변이 받아 들여졌습니다.

+0

글쎄, 이론 상으로는 재진입 메모리 할당자가 존재하며, libc는 기본적으로 하나를 사용합니다. 하지만 예, OP의 요청은 매우 위험합니다. – ephemient

+0

표준 라이브러리를 사용하지 않습니다. 시뮬레이션 할 코드는 C 표준 라이브러리를 기반으로하지 않는 완전한 미니 OS입니다. –

+0

linux (kernel 2.6)에서 알 수 있듯이 SIGSTOP을 단일 스레드로 보낼 수 없습니다. 대신 프로세스의 모든 스레드가 중지됩니다. 그건 내 문제를 해결하지 못할거야. –

1

Solaris에는 원하는대로 수행 할 수있는 thr_suspend (3C) 호출이 있습니다. Solaris로 전환 할 수 있습니까?

그 외의 경우 뮤텍스 및/또는 세마포어로 체조를해야 할 수도 있습니다. 문제는 뮤텍스를 확인할 때만 일시 중지된다는 점입니다. 뮤텍스는 정상적으로 작동하는 지점에있을 것입니다. 실제로 무엇을 성취하려고하는지에 따라, 이것이 바람직 할 수 있습니다.

+0

우분투는 집에서 사용합니다. 다른 OS로 전환해야한다면 Windows로 전환 할 수도 있습니다. 하지만 힌트를 주셔서 감사합니다. 뮤텍스 및 세마포는 현재 스레드에만 영향을줍니다. 그리고 시뮬레이션을위한 계측 코드를 삽입하고 싶지 않습니다. –

1

실제 컨트롤러가 (아마도) 작동하는 방식이기 때문에 주 스레드가 ISR을 실행하는 것이 더 합리적입니다. 보류중인 인터럽트와 인터럽트가 현재 활성화 된 경우 각 에뮬레이트 된 명령어를 확인한 후 ISR에 대한 호출을 에뮬레이션합니다.

두 번째 스레드는 여전히 사용되지만 인터럽트를 유발하는 조건을 수신하고 해당 인터럽트를 보류 중으로 표시합니다 (다른 스레드가 나중에 선택하기 위해).

+0

물론 "통신 쓰레드"가 분리되어 있다고 생각했지만 일반적인 프로세스에서는 중요하지 않습니다. 인터럽트를 검사하는 코드에서 계측을 원하지 않습니다. 나는 또한 마이크로 컨트롤러에 그러한 것을 가지고 있지 않다. 특정 마이크로 컨트롤러를 시뮬레이션하고 싶지 않습니다. 따라서 마이크로 컨트롤러 에뮬레이트 된 명령은 없습니다. –

+0

그건 그렇고, 내 질문에 대답이 없습니다. –

5

핫스팟 JAVA VM은 SIGUSR2를 사용하여 Linux에서 JAVA 스레드의 일시 중단/다시 시작을 구현합니다.

SIGUSR2하는 신호 핸들러에 기초한 절차 결과 :

SIGUSR2하기위한 신호 처리기를 제공하는 스레드는 (이미 신호 송신 스레드에 의해 획득 된) 잠금 를 요청할 수있다.

스레드를 일시 중단합니다.

일시 중단 스레드가 잠금을 해제하자마자 신호 처리기는 (가능합니까?) 잠금을받을 수 있습니다. 신호 처리기는 즉시 잠금을 해제하고 은 신호 처리기를 벗어납니다.

스레드를 다시 시작합니다.

ISR의 실제 처리를 시작하기 전에 주 스레드가 신호 처리기에 있는지 확인하기 위해 제어 변수를 도입해야 할 수도 있습니다. (신호 처리기가 동 기적으로 또는 비동기 적으로 호출되는지 여부에 따라 세부 사항이 달라집니다.)

정확히 어떻게 Java VM에서 수행되는지는 모르겠지만 위의 절차는 필요한 것 같아요. .

9

SIGSTOP이 작동하지 않습니다 - 항상 전체 프로세스를 중지합니다. 이 대신 당신이 다른 신호를 사용할 수 재개 중단과 SIGUSR2에 대한 SIGUSR1 말 :

// at process start call init_pthread_suspending to install the handlers 
// to suspend a thread use pthread_kill(thread_id, SUSPEND_SIG) 
// to resume a thread use pthread_kill(thread_id, RESUME_SIG) 

#include <signal.h> 

#define RESUME_SIG SIGUSR2 
#define SUSPEND_SIG SIGUSR1 

static sigset_t wait_mask; 
static __thread int suspended; // per-thread flag 

void resume_handler(int sig) 
{ 
    suspended = 0; 
} 

void suspend_handler(int sig) 
{ 
    if (suspended) return; 
    suspended = 1; 
    do sigsuspend(&wait_mask); while (suspended); 
} 

void init_pthread_suspending() 
{ 
    struct sigaction sa; 

    sigfillset(&wait_mask); 
    sigdelset(&wait_mask, SUSPEND_SIG) 
    sigdelset(&wait_mask, RESUME_SIG); 

    sigfillset(&sa.sa_mask); 
    sa.sa_flags = 0; 
    sa.sa_handler = resume_handler; 
    sigaction(RESUME_SIG, &sa, NULL); 

    sa.sa_handler = suspend_handler; 
    sigaction(SUSPEND_SIG, &sa, NULL); 
} 

나는 "당신이 그 나쁜 또 다른 스레드를 중단해서는 안"과 같은 응답하여 매우 화가입니다. 사람들은 왜 다른 사람들이 바보라고 생각하고 그들이 무엇을하고 있는지 모릅니다. 다른 사람들도 교착 상태에 대해 듣고 여전히 의식을 가지고 다른 스레드를 일시 중단하려고한다고 상상해보십시오. 자신의 질문에 대한 진정한 대답이없는 경우 왜 독자와 독자의 시간을 낭비합니까?

그렇습니다. IMO pthread는 POSIX에 대한 불만 인 매우 근시안적인 API입니다.

+0

이 C++ 컨텍스트에서 예외를 삽입하여 스레드를 인터럽트, RAII 개체의 정리 일으키는 사용하고 싶습니다. 나는 Windows에서 포트 스레드를 시도하고 있는데, 문제 스레드를 일시 중단하고 명령 포인터를 예외 처리 시작 부분으로 수정 한 다음 다시 시작합니다. 그것은 잘 작동하고 공유 상태의 수동 정리 (예 : 뮤텍스 재설정)를 최소화하면서 무한 루프에 들어가더라도 서브 시스템을 다시 시작한 후에 대부분 복구 할 수 있습니다. 이 기능을 내 Linux 버전으로 이식하는 방법은 무엇입니까? 내가 본 대부분의 기사는 핸들러 스택 프레임으로 인해 핸들러에서 던지지 않도록 지정합니다. –

0

pthread_kill (3) 및 SIGUSR1, SIGUSER2 신호를 사용하는 솔루션은 좋은 해결책이지만 여전히 동시성 문제를 일으킬 수 있습니다. 안전 지점에서 모든 스레드 (메인 스레드 제외)를 일시 중단하는 방법이 있습니까? 즉, 일시 중지 된 스레드가 시스템 호출에서 잠금을 얻지 않았거나 실행 중이 어서는 안됩니다.

+0

이 대답이 적합합니까? 그것은 결국 나에게 질문처럼 들린다. 편집하고 명확하게 작성하십시오. – Freakyuser

관련 문제