views:

268

answers:

4

I'm trying to implement a simulation of a microcontroller. This simulation is not meant to do a clock cycle precise representation of one specific microcontroller but check the general correctness of the code.

I thought of having a "main thread" executing normal code and a second thread executing ISR code. Whenever an ISR needs to be run, the ISR thread suspends the "main thread".

Of course, I want to have a feature to block interrupts. I thought of solving this with a mutex that the ISR thread holds whenever it executes ISR code while the main thread holds it as long as "interrupts are blocked".

A POR (power on reset) can then be implemented by not only suspending but killing the main thread (and starting a new one executing the POR function).

The windows API provides the necessary functions. But it seems to be impossible to do the above with posix threads (on linux).

I don't want to change the actual hardware independent microcontroller code. So inserting anything to check for pending interrupts is not an option.

Receiving interrupts at non well behaved points is desirable, as this also happens on microcontrollers (unless you block interrupts).

Is there a way to suspend another thread on linux? (Debuggers must use that option somehow, I think.)

Please, don't tell me this is a bad idea. I know that is true in most circumstances. But the main code does not use standard libs or lock/mutexes/semaphores.

+1  A: 

Solaris has the thr_suspend(3C) call that would do what you want. Is switching to Solaris a possibility?

Other than that, you're probably going to have to do some gymnastics with mutexes and/or semaphores. The problem is that you'll only suspend when you check the mutex, which will probably be at a well-behaved point. Depending on what you're actually trying to accomplish, this might now be desirable.

jfawcett
I use ubuntu at home. If I have to switch to a different OS, I might as well switch to Windows. But thanks for the hint.Mutexes and semaphores only influence the current thread. And I don't want to insert instrumentation code for the simulation.
Werner Mathé
+1  A: 

Somehow I think sending the other thread SIGSTOP works.

However, you are far better off writing some thread communication involving senaogires.mutexes and global variables.

You see, if you suspend the other thread in malloc() and you call malloc() -> deadlock.

Did I mention that lots of C standard library functions, let alone other libraries you use, will call malloc() behind your back?

EDIT:

Hmmm, no standard library code. Maybe use setjmp/longjump() from signal handler to simulate the POR and a signal handier to simulate interrupt.

Joshua
Well, in theory there exist re-entrant memory allocators, and your libc might even use one by default. But yes, OP's request is very hazardous.
ephemient
I don't intend to use any standard library. The code to simulate is a complete mini-OS not based on C standard libraries.
Werner Mathé
As far as I know on linux (kernel 2.6) it is not possible to send SIGSTOP to a single thread. Instead all threads of a process are stopped. That would not solve my problem.
Werner Mathé
Werner Mathe: There doesn't seem to be anything in the kernel code stopping you from using `pthread_kill` to send `SIGSTOP` to an individual thread.
caf
Unfortunately this will pause the complete process, including the calling thread, if the implementation is POSIX compliant. And as far as I know the implementation in linux is.
Werner Mathé
Using a different signal (SIGUSR2) might do the trick.
Werner Mathé
+1  A: 

It makes more sense to have the main thread execute the ISRs - because that's how the real controller works (presumably). Just have it check after each emulated instruction if there is both an interrupt pending, and interrupts are currently enabled - if so, emulate a call to the ISR.

The second thread is still used - but it just listens for the conditions which cause an interrupt, and mark the relevant interrupt as pending (for the other thread to later pick up).

caf
Of course, I thought of having separate "communication threads" but they are not important for the general process.I don't want any instrumentation in the code that checks for interrupts. I also don't have that on the microcontroller.I dont want so simulate a specific microcontroller. So there is no such thing as an emulated instruction of the microcontroller.
Werner Mathé
By the way, this is no answer to my question.
Werner Mathé
+1  A: 

The Hotspot JAVA VM uses SIGUSR2 to implement suspend/resume for JAVA threads on linux.

A procedure based on on a signal handler for SIGUSR2 might be:

Providing a signal handler for SIGUSR2 allows a thread to request a lock (which has already been acquired by the signal sending thread).

This suspends the thread.

As soon as the suspending thread releases the lock, the signal handler can (and will?) get the lock. The signal handler releases the lock immediately and leaves the signal handler.

This resumes the thread.

It will probably be necessary to introduce a control variable to make sure that the main thread is in the signal handler before starting the actual processing of the ISR. (The details depend on whether the signal handler is called synchronously or asynchronously.)

I don't know, if this is exactly how it is done in the Java VM, but I think the above procedure does what I need.

Werner Mathé