From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 966 invoked by alias); 18 Aug 2005 17:43:29 -0000 Mailing-List: contact ecos-discuss-help@ecos.sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: ecos-discuss-owner@ecos.sourceware.org Received: (qmail 944 invoked by uid 22791); 18 Aug 2005 17:43:18 -0000 Received: from sta-204-188-98-138.rockynet.com (HELO hermes.chez-thomas.org) (204.188.98.138) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Thu, 18 Aug 2005 17:43:18 +0000 Received: by hermes.chez-thomas.org (Postfix, from userid 2000) id F0033100023; Thu, 18 Aug 2005 11:42:54 -0600 (MDT) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by hermes.chez-thomas.org (Postfix) with ESMTP id 094AB100022; Thu, 18 Aug 2005 11:42:52 -0600 (MDT) From: Gary Thomas To: "R. Vamshi Krishna" Cc: eCos Discussion In-Reply-To: <4304B9C9.2080604@cse.iitb.ac.in> References: <4304B9C9.2080604@cse.iitb.ac.in> Content-Type: multipart/mixed; boundary="=-tK3Bd0euborSfTVAAvTo" Date: Thu, 18 Aug 2005 17:43:00 -0000 Message-Id: <1124386971.12287.32.camel@hermes> Mime-Version: 1.0 Subject: Re: [ECOS] Alarms and Threads Program Problem :: Help Required X-SW-Source: 2005-08/txt/msg00212.txt.bz2 --=-tK3Bd0euborSfTVAAvTo Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-length: 3533 On Thu, 2005-08-18 at 22:09 +0530, R. Vamshi Krishna wrote: > Hello, > > I am trying to write a program that has 3 threads executing for 1,2,1 > seconds each. > These threads must each execute every 5,6,4 seconds respectively. > > (Actually in Program I have multiplied these by a factor of 40 ). > > I have tried the following program. One might expect the timing to get > screwed up, but > actually the application hangs after saying the following : > > "Thread 2A :: Time Before Execution is 1" > hal_isr_default(33) : data (0) > "Thread 2A :: Time After Execution is 27" > "Thread 3 finished at :: 27" > > Then I get something like > $..thread .. and some weird numbers ... This means that your code crashed and GDB is trying to tell you why. > > PS : Note that it is Thread 3 that says it is finishing. Which if you read your code, just means that thread 3's alarm went off before it had a chance to actually execute. > > Can someone tell me where am I going wrong ?? > > - Vamshi > > Misc Data : > - Using Bitmap Scheduler > - Template is Kernel > - Turned Cache Off > - i386 Target with Realtek NIC card. A few questions/observations: * Are you sure that the stack size of 4096 is adequate? There are HAL defines for these which would be much safer to use. * Whenever you have a number of threads trying to print on the console, you can get scrambled results. There are many ways around this, but if you want to print from DSR context (your alarm functions run in DSR context), you'll need special protection. * Hard coding your loops, etc, is fraught with problems. You can easily compute these things at runtime. I made a few modifications to your code (none that changed your basic code, just some improvements) and it runs just fine on my platform. The modified version is attached - perhaps you want to try it. Here are the first few lines of output: Thread 1A :: Time Before Processing :: is 3 Thread 1A :: Time After Processing :: 44 Thread 2A :: Time Before Processing is 44 Thread 2A :: Time After Processing is 125 Thread 3A :: Time Before Processing is 126 Thread 3A :: Time After Processing is 167 Thread 1 finished at :: 203 Thread 1A :: Time Before Processing :: is 203 Thread 1A :: Time After Processing :: 244 Thread 2 finished at :: 284 Thread 2A :: Time Before Processing is 284 Thread 3 finished at :: 286 Thread 2A :: Time After Processing is 365 Thread 3A :: Time Before Processing is 366 Thread 1 finished at :: 403 Thread 1A :: Time Before Processing :: is 403 Thread 1A :: Time After Processing :: 444 Thread 3 finished at :: 446 Thread 3A :: Time After Processing is 450 Thread 3A :: Time Before Processing is 450 Thread 3A :: Time After Processing is 491 Thread 2 finished at :: 524 Thread 2A :: Time Before Processing is 524 Thread 1 finished at :: 603 Thread 1A :: Time Before Processing :: is 603 Thread 3 finished at :: 606 Thread 1A :: Time After Processing :: 644 Thread 2A :: Time After Processing is 648 Thread 3A :: Time Before Processing is 648 Thread 3A :: Time After Processing is 689 It kept running happily until I killed it. Note that you're not getting exactly the thread behaviour that you specified. This is because of thread priorities and preemptive scheduling. -- ------------------------------------------------------------ Gary Thomas | Consulting for the MLB Associates | Embedded world ------------------------------------------------------------ --=-tK3Bd0euborSfTVAAvTo Content-Disposition: attachment; filename=alarm-test.c Content-Type: text/x-csrc; name=alarm-test.c; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-length: 6040 #include #include #include #include #include #define RVK 40 /* Thread Data-Structure for 3 threads. */ cyg_thread thread_s[3]; /* Stack Space for 3 threads */ char stack[3][CYGNUM_HAL_STACK_SIZE_TYPICAL]; /* Handles for threads. Also thread entry functions */ cyg_handle_t modeA_thread1, modeA_thread2, modeA_thread3; cyg_thread_entry_t thread1A_entry, thread2A_entry, thread3A_entry; /* Forward-Definition of functions */ void thread1A_alarm_func(cyg_handle_t, cyg_addrword_t); void thread2A_alarm_func(cyg_handle_t, cyg_addrword_t); void thread3A_alarm_func(cyg_handle_t, cyg_addrword_t); /* Alarms and Counters related Data Structures */ cyg_handle_t thread_counter[3], system_clockH[3], thread_alarmH[3]; cyg_alarm thread_alarm[3]; void safe_printf(char *fmt, ...) { CYG_INTERRUPT_STATE old_intr; va_list ap; HAL_DISABLE_INTERRUPTS(old_intr); va_start(ap, fmt); diag_vprintf(fmt, ap); HAL_RESTORE_INTERRUPTS(old_intr); } int loops_per_tick; void init_loops_per_tick(void) { int old_ticks, new_ticks; int j; if (loops_per_tick != 0) return; loops_per_tick = 0; old_ticks = (int) cyg_current_time(); // Wait for time to roll while ((new_ticks = (int)cyg_current_time()) == old_ticks) ; // Now, see how many loops can happen before the next tick old_ticks = new_ticks; // Wait for time to roll while ((new_ticks = (int)cyg_current_time()) == old_ticks) { for (j = 0; j < 10000; j++) ; loops_per_tick++; } safe_printf("%d loops per tick\n", loops_per_tick); } /* Kernel Flags */ cyg_flag_t flag[3]; /* Starting the application. */ void cyg_user_start(void) { /* Create 3 threads 1A, 2A, 3A . */ cyg_thread_create(3,thread1A_entry,(cyg_addrword_t) 0,"Mode A thread 1", (void *) stack[0],CYGNUM_HAL_STACK_SIZE_TYPICAL,&modeA_thread1,&thread_s[0]); cyg_thread_create(4,thread2A_entry,(cyg_addrword_t) 0,"Mode A thread 2", (void *) stack[1],CYGNUM_HAL_STACK_SIZE_TYPICAL,&modeA_thread2,&thread_s[1]); cyg_thread_create(5,thread3A_entry,(cyg_addrword_t) 0,"Mode A thread 3", (void *) stack[2],CYGNUM_HAL_STACK_SIZE_TYPICAL,&modeA_thread3,&thread_s[2]); /* Intialize the Kernel Flags */ cyg_flag_init(&flag[0]); cyg_flag_init(&flag[1]); cyg_flag_init(&flag[2]); /* Initialize the alarms Period of each thread is (200/240/120) ticks of real-time clock. */ cyg_thread_resume(modeA_thread1); cyg_thread_resume(modeA_thread2); cyg_thread_resume(modeA_thread3); } void thread1A_entry(cyg_addrword_t data) { int i,j; init_loops_per_tick(); system_clockH[0] = cyg_real_time_clock(); cyg_clock_to_counter(system_clockH[0], &thread_counter[0]); cyg_alarm_create(thread_counter[0],thread1A_alarm_func, (cyg_addrword_t) 0, &thread_alarmH[0], &thread_alarm[0]); cyg_alarm_initialize(thread_alarmH[0],cyg_current_time()+200,200); for(;;) { /* The following code executes for 40 ticks (approx) . This was determined experimentally. */ safe_printf("Thread 1A :: Time Before Processing :: is %u\n", (unsigned int) cyg_current_time()); for(i=0;i<40*loops_per_tick;i++) { for(j=0;j<10000;j++) { ; } } safe_printf("Thread 1A :: Time After Processing :: %u\n", (unsigned int) cyg_current_time()); /* Wait for Kernel Flag to Signal. */ cyg_flag_wait(&flag[0],0x1, CYG_FLAG_WAITMODE_AND | CYG_FLAG_WAITMODE_CLR); } } void thread2A_entry(cyg_addrword_t data) { int i,j; init_loops_per_tick(); system_clockH[1] = cyg_real_time_clock(); cyg_clock_to_counter(system_clockH[1], &thread_counter[1]); cyg_alarm_create(thread_counter[1],thread2A_alarm_func, (cyg_addrword_t) 0, &thread_alarmH[1], &thread_alarm[1]); cyg_alarm_initialize(thread_alarmH[1],cyg_current_time()+240,240); for(;;) { /* The following code executes for 80 ticks (approx) . This was determined experimentally. */ safe_printf("Thread 2A :: Time Before Processing is %u \n", (unsigned int) cyg_current_time()); for(i=0;i<80*loops_per_tick;i++) { for(j=0;j<10000;j++) { ; } } safe_printf("Thread 2A :: Time After Processing is %u \n", (unsigned int) cyg_current_time()); /* Wait for Kernel Flag to Signal. */ cyg_flag_wait(&flag[1],0x1, CYG_FLAG_WAITMODE_AND | CYG_FLAG_WAITMODE_CLR); } } void thread3A_entry(cyg_addrword_t data) { int i,j; init_loops_per_tick(); system_clockH[2] = cyg_real_time_clock(); cyg_clock_to_counter(system_clockH[2], &thread_counter[2]); cyg_alarm_create(thread_counter[2],thread3A_alarm_func, (cyg_addrword_t) 0, &thread_alarmH[2], &thread_alarm[2]); cyg_alarm_initialize(thread_alarmH[2],cyg_current_time()+160,160); for(;;) { /* The following code executes for 40 ticks (approx) . This was determined experimentally. */ safe_printf("Thread 3A :: Time Before Processing is %u \n", (unsigned int) cyg_current_time()); for(i=0;i<40*loops_per_tick;i++) { for(j=0;j<10000;j++) { ; } } safe_printf("Thread 3A :: Time After Processing is %u \n", (unsigned int) cyg_current_time()); /* Wait for Kernel Flag to Signal. */ cyg_flag_wait(&flag[2],0x1, CYG_FLAG_WAITMODE_AND | CYG_FLAG_WAITMODE_CLR); } } /* Alarm-Handlers that suspend the various threads. */ void thread1A_alarm_func(cyg_handle_t alarm, cyg_addrword_t data) { safe_printf("Thread 1 finished at :: %u \n", (unsigned int) cyg_current_time()); cyg_flag_setbits(&flag[0], 0x1); } void thread2A_alarm_func(cyg_handle_t alarm, cyg_addrword_t data) { safe_printf("Thread 2 finished at :: %u \n", (unsigned int) cyg_current_time()); cyg_flag_setbits(&flag[1], 0x1); } void thread3A_alarm_func(cyg_handle_t alarm, cyg_addrword_t data) { safe_printf("Thread 3 finished at :: %u \n", (unsigned int) cyg_current_time()); cyg_flag_setbits(&flag[2], 0x1); } --=-tK3Bd0euborSfTVAAvTo Content-Type: text/plain; charset=us-ascii Content-length: 148 -- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss --=-tK3Bd0euborSfTVAAvTo--