[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