From mboxrd@z Thu Jan 1 00:00:00 1970 From: Peter Graf To: ecos-discuss@sources.redhat.com Subject: [ECOS] sscanf() vs. fgetc() Date: Thu, 12 Jul 2001 01:54:00 -0000 Message-id: <3.0.5.32.20010712104805.00914420@128.128.128.220> References: X-SW-Source: 2001-07/msg00337.html Hi, after problems in a large context, I have cut things down to a short example for a phenomenon I can't explain myself. I create and resume a new thread which uses fgetc() on a serial port, in an infinite loop. This new thread has a higher priority than the old one. If no characters are received, fgetc blocks and the old thread continues. So far so good. But when I use sscanf() in the old thread, it hangs. Even if the new process completes fgetc(), because characters are received, the old process won't get any further. My first explanation was, that fgetc() might poll and doesn't allow to schedule lower priority threads. Obviously, this was wrong, because the old thread runs fine, as long as it doesn't use sscanf(), even if it calls C Library functions like sprintf(). My second explanation was that there might be a resource conflict between fgetc() and sscanf(). (I have no idea why there should be such a conflict!) So I placed a scheduler lock around sscanf(). It still hangs. (And the higher priority task as well.) I found two ways to keep sscanf() from hanging, which is giving the fgetc() thread a lower priority, or add a cyg_thread_delay() after the fgetc(). It is not that I could not work around this phenomenon, but I am concerned of unexpected conflicts between C Library functions running in different tasks. So I would be happy if someone can enlighten me... (Assertions give no clue. Target is Hitachi SH3.) Peter Code to reproduce this: ---------------------------------------------------------------------------- -------- #include #include #include #include FILE* serin; FILE* serout; /* This thread uses fgetc() */ void trans_serial( cyg_addrword_t setup_data ) { char ch; while (1) { diag_printf("fgetc()...\n\r"); ch = fgetc(serin); diag_printf("fgetc() done.\n\r"); // cyg_thread_delay(10); } } cyg_thread SerInputProc; cyg_handle_t SerInputProcHandle; unsigned int SerInput_WSP[2048]; #define SER_INPUT_PRIO 9 int main(void) { char theIPAddressPtr[16] = "128.128.128.121"; int theIP[4]; volatile int i; serin = fopen("/dev/ser2","r"); serout = fopen("/dev/ser2","w"); fprintf(serout,"Hallo\n\r"); diag_printf("cyg_thread_create()...\n\r"); cyg_thread_create( SER_INPUT_PRIO, trans_serial, (cyg_addrword_t) 0, "SerialInputProcess", (void*) SerInput_WSP, 2048, &SerInputProcHandle, &SerInputProc ); diag_printf("cyg_thread_resume...\n\r"); cyg_thread_resume( SerInputProcHandle ); diag_printf("loop...\n\r"); for (i=0; i++; i<1000); diag_printf("sprintf...\n\r"); sprintf( theIPAddressPtr, "128.128.128.122" ); // cyg_scheduler_lock(); diag_printf("sscanf...\n\r"); sscanf( theIPAddressPtr, "%d.%d.%d.%d", &theIP[0], &theIP[1], &theIP[2], &theIP[3] ); diag_printf("sscanf done.\n\r"); // cyg_scheduler_unlock(); diag_printf("loop...\n\r"); for (i=0; i++; i<1000); diag_printf("main() finished\n\r"); while (1) cyg_thread_delay(100); return 0; }