This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

sscanf() vs. fgetc()


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 <cyg/kernel/kapi.h>
#include <cyg/infra/diag.h>
#include <stdio.h>
#include <string.h>

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;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]