Changeset 1498 for trunk/libffado/src/libieee1394/IsoHandlerManager.cpp
- Timestamp:
- 12/07/08 05:50:41 (15 years ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/libffado/src/libieee1394/IsoHandlerManager.cpp
r1348 r1498 33 33 #include "libutil/SystemTimeSource.h" 34 34 #include "libutil/Watchdog.h" 35 #include "libutil/Configuration.h" 35 36 36 37 #include <cstring> … … 50 51 , m_running( false ) 51 52 , m_in_busreset( false ) 53 , m_activity_wait_timeout_nsec (ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS * 1000LL) 52 54 { 53 55 } … … 344 346 } 345 347 } 348 346 349 if(handler_died) { 347 350 m_running = false; … … 389 392 struct timespec ts; 390 393 int result; 391 long long int timeout_nsec = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS * 1000LL;392 394 393 395 if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { … … 396 398 } 397 399 398 ts.tv_nsec += timeout_nsec;400 ts.tv_nsec += m_activity_wait_timeout_nsec; 399 401 while(ts.tv_nsec >= 1000000000LL) { 400 402 ts.tv_sec += 1; … … 419 421 this, result); 420 422 debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n", 421 this, timeout_nsec, ts.tv_sec, ts.tv_nsec);423 this, m_activity_wait_timeout_nsec, ts.tv_sec, ts.tv_nsec); 422 424 return eAR_Error; 423 425 } else { … … 425 427 this, result, errno); 426 428 debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n", 427 this, timeout_nsec, ts.tv_sec, ts.tv_nsec);429 this, m_activity_wait_timeout_nsec, ts.tv_sec, ts.tv_nsec); 428 430 return eAR_Error; 429 431 } … … 533 535 debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority); 534 536 if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority 537 if (priority < THREAD_MIN_RTPRIO) priority = THREAD_MIN_RTPRIO; // cap the priority 535 538 m_realtime = rt; 536 539 m_priority = priority; 540 541 // grab the options from the parent 542 Util::Configuration *config = m_service.getConfiguration(); 543 int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE; 544 int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT; 545 int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV; 546 if(config) { 547 config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase); 548 config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit); 549 config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv); 550 } 537 551 538 552 if (m_IsoThreadTransmit) { 539 553 if (m_realtime) { 540 554 m_IsoThreadTransmit->AcquireRealTime(m_priority 541 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE542 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT);555 + ihm_iso_prio_increase 556 + ihm_iso_prio_increase_xmit); 543 557 } else { 544 558 m_IsoThreadTransmit->DropRealTime(); … … 548 562 if (m_realtime) { 549 563 m_IsoThreadReceive->AcquireRealTime(m_priority 550 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE551 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV);564 + ihm_iso_prio_increase 565 + ihm_iso_prio_increase_recv); 552 566 } else { 553 567 m_IsoThreadReceive->DropRealTime(); … … 565 579 debugError("Manager already initialized...\n"); 566 580 return false; 581 } 582 583 // grab the options from the parent 584 Util::Configuration *config = m_service.getConfiguration(); 585 int ihm_iso_prio_increase = ISOHANDLERMANAGER_ISO_PRIO_INCREASE; 586 int ihm_iso_prio_increase_xmit = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT; 587 int ihm_iso_prio_increase_recv = ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV; 588 int64_t isotask_activity_timeout_usecs = ISOHANDLERMANAGER_ISO_TASK_WAIT_TIMEOUT_USECS; 589 if(config) { 590 config->getValueForSetting("ieee1394.isomanager.prio_increase", ihm_iso_prio_increase); 591 config->getValueForSetting("ieee1394.isomanager.prio_increase_xmit", ihm_iso_prio_increase_xmit); 592 config->getValueForSetting("ieee1394.isomanager.prio_increase_recv", ihm_iso_prio_increase_recv); 593 config->getValueForSetting("ieee1394.isomanager.isotask_activity_timeout_usecs", isotask_activity_timeout_usecs); 567 594 } 568 595 … … 575 602 } 576 603 m_IsoTaskTransmit->setVerboseLevel(getDebugLevel()); 604 m_IsoTaskTransmit->m_activity_wait_timeout_nsec = isotask_activity_timeout_usecs * 1000LL; 577 605 m_IsoThreadTransmit = new Util::PosixThread(m_IsoTaskTransmit, "ISOXMT", m_realtime, 578 m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE579 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_XMIT,606 m_priority + ihm_iso_prio_increase 607 + ihm_iso_prio_increase_xmit, 580 608 PTHREAD_CANCEL_DEFERRED); 581 609 … … 594 622 m_IsoTaskReceive->setVerboseLevel(getDebugLevel()); 595 623 m_IsoThreadReceive = new Util::PosixThread(m_IsoTaskReceive, "ISORCV", m_realtime, 596 m_priority + ISOHANDLERMANAGER_ISO_PRIO_INCREASE597 + ISOHANDLERMANAGER_ISO_PRIO_INCREASE_RECV,624 m_priority + ihm_iso_prio_increase 625 + ihm_iso_prio_increase_recv, 598 626 PTHREAD_CANCEL_DEFERRED); 599 627 … … 759 787 // allocate a handler for this stream 760 788 if (stream->getType()==StreamProcessor::ePT_Receive) { 789 // grab the options from the parent 790 Util::Configuration *config = m_service.getConfiguration(); 791 int receive_mode_setting = DEFAULT_ISO_RECEIVE_MODE; 792 int bufferfill_mode_threshold = BUFFERFILL_MODE_THRESHOLD; 793 int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD; 794 int max_nb_buffers_recv = MAX_RECV_NB_BUFFERS; 795 int min_packetsize_recv = MIN_RECV_PACKET_SIZE; 796 if(config) { 797 config->getValueForSetting("ieee1394.isomanager.iso_receive_mode", receive_mode_setting); 798 config->getValueForSetting("ieee1394.isomanager.bufferfill_mode_threshold", bufferfill_mode_threshold); 799 config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period); 800 config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_recv", max_nb_buffers_recv); 801 config->getValueForSetting("ieee1394.isomanager.min_packetsize_recv", min_packetsize_recv); 802 } 803 761 804 // setup the optimal parameters for the raw1394 ISO buffering 762 805 unsigned int packets_per_period = stream->getPacketsPerPeriod(); 763 unsigned int max_packet_size = stream->getMaxPacketSize() + 8; // bufferfill takes another 8 bytes for headers 806 // reserve space for the 1394 header too (might not be necessary) 807 unsigned int max_packet_size = stream->getMaxPacketSize() + 8; 764 808 unsigned int page_size = getpagesize(); 809 810 enum raw1394_iso_dma_recv_mode receive_mode; 811 switch(receive_mode_setting) { 812 case 0: 813 if(packets_per_period < (unsigned)bufferfill_mode_threshold) { 814 debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (auto) [%d, %d]\n", 815 packets_per_period, bufferfill_mode_threshold); 816 receive_mode = RAW1394_DMA_PACKET_PER_BUFFER; 817 } else { 818 debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (auto) [%d, %d]\n", 819 packets_per_period, bufferfill_mode_threshold); 820 receive_mode = RAW1394_DMA_BUFFERFILL; 821 } 822 break; 823 case 1: 824 debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (config)\n"); 825 receive_mode = RAW1394_DMA_PACKET_PER_BUFFER; 826 break; 827 case 2: 828 debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (config)\n"); 829 receive_mode = RAW1394_DMA_BUFFERFILL; 830 break; 831 default: debugWarning("Bogus receive mode setting in config: %d\n", receive_mode_setting); 832 } 765 833 766 834 // Ensure we don't request a packet size bigger than the … … 771 839 return false; 772 840 } 841 if (max_packet_size < (unsigned)min_packetsize_recv) { 842 debugError("min packet size (%u) < MIN_RECV_PACKET_SIZE (%u), using min value\n", 843 max_packet_size, min_packetsize_recv); 844 max_packet_size = min_packetsize_recv; 845 } 773 846 774 847 // the interrupt/wakeup interval prediction of raw1394 is a mess... 775 int irq_interval = (packets_per_period-1) / MINIMUM_INTERRUPTS_PER_PERIOD;848 int irq_interval = (packets_per_period-1) / min_interrupts_per_period; 776 849 if(irq_interval <= 0) irq_interval=1; 777 850 778 851 // the receive buffer size doesn't matter for the latency, 779 // but it has a minimal value in order for libraw to operate correctly (300) 780 int buffers=400; 852 // it does seem to be confined to a certain region for correct 853 // operation. However it is not clear how many. 854 int buffers = max_nb_buffers_recv; 855 856 // ensure at least 2 hardware interrupts per ISO buffer wraparound 857 if(irq_interval > buffers/2) { 858 irq_interval = buffers/2; 859 } 781 860 782 861 // create the actual handler 862 debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n"); 783 863 h = new IsoHandler(*this, IsoHandler::eHT_Receive, 784 864 buffers, max_packet_size, irq_interval); 785 786 debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");787 865 788 866 if(!h) { … … 791 869 } 792 870 871 h->setReceiveMode(receive_mode); 872 793 873 } else if (stream->getType()==StreamProcessor::ePT_Transmit) { 874 // grab the options from the parent 875 Util::Configuration *config = m_service.getConfiguration(); 876 int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD; 877 int max_nb_buffers_xmit = MAX_XMIT_NB_BUFFERS; 878 int max_packetsize_xmit = MAX_XMIT_PACKET_SIZE; 879 int min_packetsize_xmit = MIN_XMIT_PACKET_SIZE; 880 if(config) { 881 config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period); 882 config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_xmit", max_nb_buffers_xmit); 883 config->getValueForSetting("ieee1394.isomanager.max_packetsize_xmit", max_packetsize_xmit); 884 config->getValueForSetting("ieee1394.isomanager.min_packetsize_xmit", min_packetsize_xmit); 885 } 886 794 887 // setup the optimal parameters for the raw1394 ISO buffering 795 // unsigned int packets_per_period = stream->getPacketsPerPeriod(); 796 unsigned int max_packet_size = stream->getMaxPacketSize(); 797 // unsigned int page_size = getpagesize(); 798 799 // Ensure we don't request a packet size bigger than the 800 // kernel-enforced maximum which is currently 1 page. 801 // if (max_packet_size > page_size) { 802 // debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size); 803 // return false; 804 // } 805 if (max_packet_size > MAX_XMIT_PACKET_SIZE) { 888 // reserve space for the 1394 header too (might not be necessary) 889 unsigned int max_packet_size = stream->getMaxPacketSize() + 8; 890 891 if (max_packet_size > (unsigned)max_packetsize_xmit) { 806 892 debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n", 807 max_packet_size, MAX_XMIT_PACKET_SIZE);893 max_packet_size, max_packetsize_xmit); 808 894 return false; 809 895 } 810 811 // the SP specifies how many packets to ISO-buffer812 int buffers = stream->getNbPacketsIsoXmitBuffer();813 if (buffers > MAX_XMIT_NB_BUFFERS) {814 debugOutput(DEBUG_LEVEL_VERBOSE,815 "nb buffers (%u) > MAX_XMIT_NB_BUFFERS (%u)\n", 816 buffers, MAX_XMIT_NB_BUFFERS);817 buffers = MAX_XMIT_NB_BUFFERS;818 } 819 unsigned int irq_interval = buffers / MINIMUM_INTERRUPTS_PER_PERIOD;896 if (max_packet_size < (unsigned)min_packetsize_xmit) { 897 debugError("min packet size (%u) < MIN_XMIT_PACKET_SIZE (%u), using min value\n", 898 max_packet_size, min_packetsize_xmit); 899 max_packet_size = min_packetsize_xmit; 900 } 901 902 int buffers = max_nb_buffers_xmit; 903 unsigned int packets_per_period = stream->getPacketsPerPeriod(); 904 905 int irq_interval = (packets_per_period-1) / min_interrupts_per_period; 820 906 if(irq_interval <= 0) irq_interval=1; 907 // ensure at least 2 hardware interrupts per ISO buffer wraparound 908 if(irq_interval > buffers/2) { 909 irq_interval = buffers/2; 910 } 821 911 822 912 debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");