Mercurial > flash_v2
comparison packages/kernel/current/src/common/clock.cxx @ 64:c38311975d4f ecos-sw-2000-01-28
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
| author | jlarmour |
|---|---|
| date | Fri, 28 Jan 2000 04:59:39 +0000 |
| parents | 29bc183297e1 |
| children | bf00f99aec69 |
comparison
equal
deleted
inserted
replaced
| 63:119e6e57c342 | 64:c38311975d4f |
|---|---|
| 4 // | 4 // |
| 5 // Clock class implementations | 5 // Clock class implementations |
| 6 // | 6 // |
| 7 //========================================================================== | 7 //========================================================================== |
| 8 //####COPYRIGHTBEGIN#### | 8 //####COPYRIGHTBEGIN#### |
| 9 // | 9 // |
| 10 // ------------------------------------------- | 10 // ------------------------------------------- |
| 11 // The contents of this file are subject to the Cygnus eCos Public License | 11 // The contents of this file are subject to the Red Hat eCos Public License |
| 12 // Version 1.0 (the "License"); you may not use this file except in | 12 // Version 1.0 (the "License"); you may not use this file except in |
| 13 // compliance with the License. You may obtain a copy of the License at | 13 // compliance with the License. You may obtain a copy of the License at |
| 14 // http://sourceware.cygnus.com/ecos | 14 // http://sourceware.cygnus.com/ecos |
| 15 // | 15 // |
| 16 // Software distributed under the License is distributed on an "AS IS" | 16 // Software distributed under the License is distributed on an |
| 17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the | 17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
| 18 // License for the specific language governing rights and limitations under | 18 // License for the specific language governing rights and limitations under |
| 19 // the License. | 19 // the License. |
| 20 // | 20 // |
| 21 // The Original Code is eCos - Embedded Cygnus Operating System, released | 21 // The Original Code is eCos - Embedded Configurable Operating System, |
| 22 // September 30, 1998. | 22 // released September 30, 1998. |
| 23 // | 23 // |
| 24 // The Initial Developer of the Original Code is Cygnus. Portions created | 24 // The Initial Developer of the Original Code is Red Hat. |
| 25 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. | 25 // Portions created by Red Hat are |
| 26 // ------------------------------------------- | 26 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. |
| 27 // | 27 // All Rights Reserved. |
| 28 // ------------------------------------------- | |
| 29 // | |
| 28 //####COPYRIGHTEND#### | 30 //####COPYRIGHTEND#### |
| 29 //========================================================================== | 31 //========================================================================== |
| 30 //#####DESCRIPTIONBEGIN#### | 32 //#####DESCRIPTIONBEGIN#### |
| 31 // | 33 // |
| 32 // Author(s): nickg | 34 // Author(s): nickg |
| 483 return true; | 485 return true; |
| 484 } | 486 } |
| 485 | 487 |
| 486 #endif | 488 #endif |
| 487 | 489 |
| 490 // ------------------------------------------------------------------------- | |
| 491 // | |
| 492 // Clock Converters: split a rational into 4 factors to try to prevent | |
| 493 // overflow whilst retaining reasonable accuracy. | |
| 494 // | |
| 495 // typically we get numbers like 1,000,000 for ns_per and | |
| 496 // 100 and 1,000,000,000 for the dividend and divisor. | |
| 497 // So we want answers like 1/10 and 10/1 out of these routines. | |
| 498 | |
| 499 static void construct_converter( Cyg_Clock::converter *pcc, | |
| 500 cyg_uint64 m1, cyg_uint64 d1, | |
| 501 cyg_uint64 m2, cyg_uint64 d2 ) | |
| 502 { | |
| 503 cyg_uint64 upper, lower; | |
| 504 unsigned int i; | |
| 505 static cyg_uint16 primes[] = { | |
| 506 3,5,7,11,13,17,19,23,29,31,37,41,43,47, | |
| 507 53,59,61,67,71,73,79,83,89,97, | |
| 508 101,103,107,109,113,127,131,137,139,149, | |
| 509 151,157,163,167,173,179,181,191,193,197,199, | |
| 510 239, // for 1,111,111 | |
| 511 541, // for 10,101,011 | |
| 512 1667, // for 8,333,333 | |
| 513 }; | |
| 514 | |
| 515 int rounding = 0; | |
| 516 | |
| 517 // Here we assume that our workings will fit in a 64; the point is to | |
| 518 // allow calculations with a number of ticks that may be large. | |
| 519 upper = m1 * m2; | |
| 520 lower = d1 * d2; | |
| 521 #ifdef CYGDBG_USE_ASSERTS | |
| 522 cyg_uint64 save_upper = upper; | |
| 523 cyg_uint64 save_lower = lower; | |
| 524 #endif | |
| 525 | |
| 526 retry_rounding: | |
| 527 // First strip out common powers of 2 | |
| 528 while ( (0 == (1 & upper)) && ( 0 == (1 & lower)) ) { | |
| 529 upper >>= 1; | |
| 530 lower >>= 1; | |
| 531 } | |
| 532 | |
| 533 // then common factors - use lazy table above | |
| 534 for ( i = 0 ; i < (sizeof( primes )/sizeof( primes[0] )); i++ ) { | |
| 535 cyg_uint64 j, k, p = (cyg_uint64)(primes[i]); | |
| 536 j = upper / p; | |
| 537 while ( j * p == upper ) { | |
| 538 k = lower / p; | |
| 539 if ( k * p != lower ) | |
| 540 break; | |
| 541 upper = j; | |
| 542 lower = k; | |
| 543 j = upper / p; | |
| 544 } | |
| 545 } | |
| 546 | |
| 547 m1 = upper; | |
| 548 d1 = lower; | |
| 549 m2 = 1; | |
| 550 d2 = 1; | |
| 551 | |
| 552 if ( m1 > 0x10000 ) { | |
| 553 // only bother if there are more than 16 bits consumed here | |
| 554 | |
| 555 // now move powers of 2 from d1 to d2 | |
| 556 // keeping them the same order of magnitude | |
| 557 while ( (0 == (1 & d1)) && (d2 < d1) ) { | |
| 558 d1 >>= 1; | |
| 559 d2 <<= 1; | |
| 560 } | |
| 561 | |
| 562 // and factors from the table - go too far, if anything | |
| 563 int cont = (d2 < d1); | |
| 564 for ( i = 0 ; cont && (i < (sizeof( primes )/sizeof( primes[0] ))); i++ ) { | |
| 565 cyg_uint64 k, p = (cyg_uint64)(primes[i]); | |
| 566 k = d1 / p; | |
| 567 while ( cont && ((k * p) == d1) ) { | |
| 568 // we can extract a prime | |
| 569 d1 = k; | |
| 570 d2 *= p; | |
| 571 k = d1 / p; | |
| 572 cont = (d2 < d1); | |
| 573 } | |
| 574 } | |
| 575 | |
| 576 // move powers of 2 from m1 to m2 so long as we do not go less than d1 | |
| 577 while ( (0 == (1 & m1)) && (m2 < m1) && (m1 > (d1 << 5)) ) { | |
| 578 m1 >>= 1; | |
| 579 m2 <<= 1; | |
| 580 if ( m1 < 0x10000 ) | |
| 581 break; | |
| 582 } | |
| 583 | |
| 584 // and factors from the table - ensure m1 stays well larger than d1 | |
| 585 cont = ((m2 < m1) && (m1 > (d1 << 4)) && (m1 > 0x10000)); | |
| 586 for ( i = 0 ; cont && (i < (sizeof( primes )/sizeof( primes[0] ))); i++ ) { | |
| 587 cyg_uint64 k, p = (cyg_uint64)(primes[i]); | |
| 588 k = m1 / p; | |
| 589 cont = cont && (k > (d1 << 4) && (k > 0x10000)); | |
| 590 while ( cont && ((k * p) == m1) ) { | |
| 591 // we can extract a prime | |
| 592 m1 = k; | |
| 593 m2 *= p; | |
| 594 k = m1 / p; // examine k for getting too small | |
| 595 cont = ((m2 < m1) && (k > (d1 << 4)) && (k > 0x10000)); | |
| 596 } | |
| 597 } | |
| 598 | |
| 599 // if, after all that, m1 odd and unchanged, and too large, | |
| 600 // decrement it just the once and try again: then try it | |
| 601 // incremented once. | |
| 602 if ( (m1 & 1) && (m1 == upper) && (m1 > 0x10000) && (rounding < 2) ) { | |
| 603 CYG_ASSERT( 1 == m2, "m2 should be 1 to try rounding" ); | |
| 604 m1--; | |
| 605 upper = m1; | |
| 606 rounding++; | |
| 607 goto retry_rounding; | |
| 608 } | |
| 609 // likewise for d1 - each of the pair can be odd only once each | |
| 610 if ( (d1 & 1) && (d1 == lower) && (d1 > 0x10000) && (rounding < 2) ) { | |
| 611 CYG_ASSERT( 1 == d2, "d2 should be 1 to try rounding" ); | |
| 612 d1--; | |
| 613 lower = d1; | |
| 614 rounding++; | |
| 615 goto retry_rounding; | |
| 616 } | |
| 617 } | |
| 618 | |
| 619 CYG_ASSERT( 0 != m1, "m1 zero" ); | |
| 620 CYG_ASSERT( 0 != m2, "m2 zero" ); | |
| 621 CYG_ASSERT( 0 != d1, "d1 zero" ); | |
| 622 CYG_ASSERT( 0 != d2, "d2 zero" ); | |
| 623 CYG_ASSERT( rounding || save_upper/save_lower == (m1 * m2)/(d1 * d2), | |
| 624 "Unequal in forwards direction" ); | |
| 625 CYG_ASSERT( rounding || save_lower/save_upper == (d1 * d2)/(m1 * m2), | |
| 626 "Unequal in reverse direction" ); | |
| 627 | |
| 628 pcc->mul1 = m1; | |
| 629 pcc->div1 = d1; | |
| 630 pcc->mul2 = m2; | |
| 631 pcc->div2 = d2; | |
| 632 } | |
| 633 | |
| 634 // other to clocks is (other * ns_per * dividend / divisor) | |
| 635 void Cyg_Clock::get_other_to_clock_converter( | |
| 636 cyg_uint64 ns_per_other_tick, | |
| 637 struct converter *pcc ) | |
| 638 { | |
| 639 construct_converter( pcc, | |
| 640 ns_per_other_tick, 1, | |
| 641 resolution.divisor, resolution.dividend ); | |
| 642 } | |
| 643 | |
| 644 // clocks to other is (ticks * divisor / dividend / ns_per) | |
| 645 void Cyg_Clock::get_clock_to_other_converter( | |
| 646 cyg_uint64 ns_per_other_tick, | |
| 647 struct converter *pcc ) | |
| 648 { | |
| 649 construct_converter( pcc, | |
| 650 1, ns_per_other_tick, | |
| 651 resolution.dividend, resolution.divisor ); | |
| 652 } | |
| 653 | |
| 654 | |
| 488 //========================================================================== | 655 //========================================================================== |
| 489 // Constructor for alarm object | 656 // Constructor for alarm object |
| 490 | 657 |
| 491 Cyg_Alarm::Cyg_Alarm( | 658 Cyg_Alarm::Cyg_Alarm( |
| 492 Cyg_Counter *c, // Attached to this counter | 659 Cyg_Counter *c, // Attached to this counter |
