Re: real-time process

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>>>>> "Nagaraj" == Nagaraj  <nagaraj@smartyantra.com> writes:
>> Why the "blocking call" variant performed so poorly ?

Nagaraj> i told it in prev mails..( READ THEM WELL ! )

Nagaraj> look at the sequence: suppose u do a blocking write,
Nagaraj> probably the driver does interruptible_sleep_on()
Nagaraj> and waits for irq_handler() wake it up.

Nagaraj> When data xfer is complete, irq_handler wakes it up.
Nagaraj> NOTE: Now the xfer is stopped. then blocking write returns to application
Nagaraj> THEN application starts filling in the data into the buffer ( Time reqd to
Nagaraj> fill in
Nagaraj> the buffer ). Then again driver calls write.

Nagaraj> This fill time of application is goin to screw up ur display.
Nagaraj> as xfer is in terms of Mbits even small delay means large data.

Nagaraj> So idea is if u can make use of multiple buffers,
Nagaraj> make write non blocking. when device xfers from
Nagaraj> first buffer...( DMA does it, so CPU neednt worry )
Nagaraj> fill in next buffers simulteneously. When xfer is complete
Nagaraj> DMA gives control to irq_handler, which sets up the next
Nagaraj> DMA and also kill_fasync() the application. So the delay between
Nagaraj> two DMA xfers is just the interrupt latency. ( which would be around 100us
Nagaraj> max )

Ok, I understand the task and I must say there is a problem with the
described solution.

Nagaraj>  for(  buff_index = i = 0; i < xfer_count; i++, buff_index =
Nagaraj> (buff_index+1)%MAX_BUFFERS ) {

Nagaraj>     sleep(1000);

Nagaraj>    read( buff_fd, (mbuff +buff_index*BUFF_SIZE), BUFF_SIZE );

Nagaraj> }

First, the above code has a race condition, which can add up to 1000 sec (!)
latency per frame!

Second, there's no need for multiple buffers in the application as it
copies only one buffer at a time.  Multiple buffers are needed inside
the driver, so it can fill some buffers, which the application empties
other buffers by copying them to the application's own buffer.

Sleeping with ``sleep'' (or ``usleep'' or ``nanosleep'' for that
matter) is not an adequate solution.  The right way would be to block
with ``sigwait.

int signo;
sigset_t set;

sigprocmask (SIG_SETMASK, 0, &set);
sigaddset (&set, SIGIO); /* or SIGwhatever */
sigprocmask (SIG_SETMASK, &set, 0);

sigfillset (&set);
sigdelset (&set, SIGIO);

configure_number_of_driver_buffers_and_kick_it_to_start_xfer ();

for (i = 0; i < xfer_count; i++)
  {
    sigwait (&set, &sig);

    /* Read the buffer. After the driver finishes copying
       into the user buffer, it knows the driver's buffer
       is available.  */
    read (buff_fd, mbuff, BUFF_SIZE);
    do_something (mbuff);
  }

Isn't that code better ? Or I have misunderstood the problem ? Or I
have understood the problem, but produced a crap myself ? :)

~velco

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux