[En-Nut-Discussion] Nut/OS Simulation on Host PC
Matthias Ringwald
mringwal at inf.ethz.ch
Wed Mar 3 14:47:50 CET 2004
Hi Ralph,
thanks for sending the source file. I did hand it over to a colleague
who is using windows to try out.
he just started playing using nut/os.
I feel obliged to support darwin/ppc and linux/x86 and don't know
enough for going your way
with those platforms.
I did a quick glance over pthreads (which are more or less portable)
and will simulate the
nut/os threads with pthreads.
the scheme looks like this:
globals:
there is a thread switching mutex (mutex) and a thread switching
condition variable (cv)
thread create:
for a new nut/os task, I create a pthread and a conditional variable,
lock the mutex and wait for the main cv to get signaled by the newly
created task.
my thread startup:
lock mutex
signal main cv
wait for my cv to get signaled.
unlock mutex
CALL the thread itself
exit pthread
thread switching:
lock mutex
signal next cv of next thread
wait for my cv to get signaled
unlock mutex
For a better/different understand I add my test code below.
next will be to plug this into nut/os.
I'll tell, when a simple app runs on my mac.
cheers,
Matthias
, called
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
#define TCOUNT 10
int thread_ids[NUM_THREADS] = {0,1,2,3,4};
pthread_t threads[NUM_THREADS];
pthread_mutex_t thread_mutex;
pthread_cond_t thread_cv[NUM_THREADS];
pthread_cond_t main_cv;
pthread_attr_t attr;
void *inc_count(void *idp) ;
void *my_thread(void *arg);
void yield(int n)
{
int i;
pthread_cond_t *cv = &main_cv;
// get my cv (hack)
for (i = 0; i < NUM_THREADS; i++) {
if ( pthread_equal(pthread_self(), threads[i]) ){
cv = &thread_cv[i];
break;
}
}
printf("yield(): from thread %i, switching to thread %i\n", i, n);
// switching cal
pthread_mutex_lock(&thread_mutex);
pthread_cond_signal(&thread_cv[n]);
printf("yield(): signaled to thread %i and wait to be signaled \n", n
);
pthread_cond_wait(cv, &thread_mutex);
pthread_mutex_unlock(&thread_mutex);
printf("yield() returned for thread %i\n", i);
}
void create_thread(int i)
{
// I'm to lazy to pass all required data here and to new created
threaad, so
// I just ignore the function pointer and just enumerate my threads
pthread_cond_init (&thread_cv[i], NULL);
printf("Creating thread: %i \n", i);
pthread_create(&threads[i], &attr, my_thread, (void *)&thread_ids[i]);
// start first thread
printf("main(): mutex locked\n" );
pthread_mutex_lock(&thread_mutex);
printf("main(): waiting for ack\n");
pthread_cond_wait(&main_cv, &thread_mutex);
printf("main(): acked\n");
pthread_mutex_unlock(&thread_mutex);
printf("main(): mutex unlocked\n" );
}
void *my_thread(void *idp)
{
// again, using default values
int *my_id = idp;
// thread entry routine (goes into thread.c)
pthread_mutex_lock(&thread_mutex);
printf("inc_count(): thread %d, locked\n", *my_id );
pthread_cond_signal(&main_cv);
printf("inc_count(): thread %d, signal and wait\n", *my_id );
pthread_cond_wait(&thread_cv[*my_id], &thread_mutex);
printf("inc_count(): thread %d, was signaled \n", *my_id );
pthread_mutex_unlock(&thread_mutex);
printf("inc_count(): thread %d, unlocked \n", *my_id );
// call real function
inc_count( idp );
// thread exit routine
pthread_exit(NULL);
}
void *inc_count(void *idp)
{
int i;
int *my_id = idp;
for (i=0; i < TCOUNT; i++) {
// do something
printf("inc_count(): thread %d, count = %d\n", *my_id, i);
sleep( 1 );
yield( ((*my_id) +1 ) % NUM_THREADS);
}
}
int main (int argc, char *argv[])
{
// init
int i, rc;
/* Initialize mutex and condition variable objects */
pthread_mutex_init(&thread_mutex, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_cond_init (&main_cv, NULL);
// start of real app
for (i = 0; i < NUM_THREADS; i++) {
create_thread( i );
};
// start first one
yield(0);
printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS);
// end of
/* Clean up and exit */
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&thread_mutex);
for (i = 0; i < NUM_THREADS; i++) {
pthread_cond_destroy(&thread_cv[i]);
}
pthread_exit(NULL);
}
On 02.03.2004, at 04:37, Ralph Mason wrote:
> I can't make it fully available yet.
> I did thread switching the exact same way as nutos does except I use a
> single OS thread to simulate all the nut threads and manually switch
> the stack pointer of the Win32 thread. This technique should work
> with any OS though.
>
> Yes, I 'emulated' the serial drivers (well really just wrote a nut
> driver that called the OS driver) so when running on the hardware you
> call fopen('uarta') on a windows box you would call fopen('com1')
>
> Attached is thread.c that does switching of threads for 80x86.
>
> Ralph
>
>
> * Redistribution and use in source and binary forms, with or without
More information about the En-Nut-Discussion
mailing list