Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /****************************************************************************
  2. *
  3. *                            Open Watcom Project
  4. *
  5. *    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
  6. *
  7. *  ========================================================================
  8. *
  9. *    This file contains Original Code and/or Modifications of Original
  10. *    Code as defined in and that are subject to the Sybase Open Watcom
  11. *    Public License version 1.0 (the 'License'). You may not use this file
  12. *    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
  13. *    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
  14. *    provided with the Original Code and Modifications, and is also
  15. *    available at www.sybase.com/developer/opensource.
  16. *
  17. *    The Original Code and all software distributed under the License are
  18. *    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  19. *    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
  20. *    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
  21. *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
  22. *    NON-INFRINGEMENT. Please see the License for the specific language
  23. *    governing rights and limitations under the License.
  24. *
  25. *  ========================================================================
  26. *
  27. * Description:  Initialization and termination of clib.
  28. *
  29. ****************************************************************************/
  30.  
  31.  
  32. #include "variety.h"
  33. #include "initfini.h"
  34. #include "rtinit.h"
  35.  
  36. #define PNEAR ((__type_rtp)0)
  37. #define PFAR  ((__type_rtp)1)
  38. #define PDONE ((__type_rtp)2)
  39.  
  40. #if ( COMP_CFG_COFF == 1 ) || defined(__AXP__) || defined(__PPC__) || defined(__MIPS__)
  41.     // following is an attempt to drop the need for an assembler
  42.     // segment definitions file
  43.     // unfortunately, the use of XIB,XIE,YIB,YIE doesn't get the
  44.     // right sort of segments by default
  45.     #pragma data_seg( ".rtl$xib", "DATA" );
  46.     YIXI( TS_SEG_XIB, _Start_XI, 0, 0 )
  47.     #pragma data_seg( ".rtl$xie", "DATA" );
  48.     YIXI( TS_SEG_XIE, _End_XI, 0, 0 )
  49.     #pragma data_seg( ".rtl$yib", "DATA" );
  50.     YIXI( TS_SEG_YIB, _Start_YI, 0, 0 )
  51.     #pragma data_seg( ".rtl$yie", "DATA" );
  52.     YIXI( TS_SEG_YIE, _End_YI, 0, 0 )
  53.     #pragma data_seg( ".data", "DATA" );
  54. #elif defined(_M_IX86)
  55.     extern struct rt_init _Start_XI;
  56.     extern struct rt_init _End_XI;
  57.  
  58.     extern struct rt_init _Start_YI;
  59.     extern struct rt_init _End_YI;
  60. #else
  61.     #error unsupported platform
  62. #endif
  63.  
  64. typedef void (*pfn)(void);
  65. typedef void (_WCI86FAR * _WCI86FAR fpfn)(void);
  66. typedef void (_WCI86NEAR * _WCI86NEAR npfn)(void);
  67.  
  68. #if defined(__AXP__) || defined(__PPC__) || defined(__MIPS__)
  69.     #define __GETDS()
  70.     #define save_ds()
  71.     #define restore_ds()
  72.     #define save_es()
  73.     #define restore_es()
  74.     #define setup_es()
  75. #elif defined(__WINDOWS_386__)
  76.     #define __GETDS()
  77.     #define save_ds()
  78.     #define restore_ds()
  79.     #define save_es()
  80.     #define restore_es()
  81.     #define setup_es()
  82. #elif defined(__386__)
  83.     #define __GETDS()
  84.     #define save_ds()
  85.     #define restore_ds()
  86. #if defined(__FLAT__)
  87.     #define save_es()
  88.     #define restore_es()
  89.     #define setup_es()
  90. #else
  91.     extern void save_es( void );
  92.     #pragma aux save_es = modify exact [es];
  93.     extern void restore_es( void );
  94.     #pragma aux restore_es = modify exact [es];
  95.     extern void setup_es( void );
  96.     #pragma aux setup_es = \
  97.                 "push ds" \
  98.                 "pop es" \
  99.                 modify exact [es];
  100. #endif
  101. #elif defined(M_I86)
  102.     extern void save_dx( void );
  103.     #pragma aux save_dx = modify exact [dx];
  104.     extern void _WCI86NEAR __GETDS( void );
  105.     #pragma aux __GETDS "__GETDS";
  106.     extern void save_ds( void );
  107.     #pragma aux save_ds = "push ds" modify exact [sp];
  108.     extern void restore_ds( void );
  109.     #pragma aux restore_ds = "pop ds" modify exact [sp];
  110.     #define save_es()
  111.     #define restore_es()
  112. #else
  113.     #error unsupported platform
  114. #endif
  115.  
  116. #if defined(M_I86)
  117. static void callit_near( npfn *f ) {
  118.     // don't call a null pointer
  119.     if( *f ) {
  120.         save_dx();
  121.         save_ds();
  122.         // call function
  123.         (void)(**f)();
  124.         restore_ds();
  125.     }
  126. }
  127.  
  128. static void callit_far( fpfn _WCI86NEAR *f ) {
  129.     // don't call a null pointer
  130.     if( *f ) {
  131.         save_ds();
  132.         // call function
  133.         (void)(**f)();
  134.         restore_ds();
  135.     }
  136. }
  137. #else
  138. static void callit( pfn *f ) {
  139.     // don't call a null pointer
  140.     if( *f ) {
  141.         // QNX needs es==ds
  142.         setup_es();
  143.         // call function
  144.         (void)(**f)();
  145.     }
  146. }
  147. #endif
  148.  
  149. /*
  150. ; - takes priority limit parm in eax, code will run init routines whose
  151. ;       priority is < eax (really al [0-255])
  152. ;       eax==255 -> run all init routines
  153. ;       eax==15  -> run init routines whose priority is <= 15
  154. ;
  155. */
  156.  
  157. void __InitRtns( unsigned limit ) {
  158.     __type_rtp local_limit;
  159.     struct rt_init _WCI86NEAR *pnext;
  160.     save_ds();
  161.     save_es();
  162.     __GETDS();
  163.  
  164.     local_limit = (__type_rtp)limit;
  165.     for(;;) {
  166.         {
  167.             __type_rtp working_limit;
  168.             struct rt_init _WCI86NEAR *pcur;
  169.  
  170.             pcur = (struct rt_init _WCI86NEAR*)&_Start_XI;
  171.             #if defined(COMP_CFG_COFF)
  172.                 pcur++;
  173.             #endif
  174.             pnext = (struct rt_init _WCI86NEAR*)&_End_XI;
  175.             working_limit = local_limit;
  176.  
  177.             // walk list of routines
  178.             while( pcur < (struct rt_init _WCI86NEAR*)&_End_XI )
  179.             {
  180.                 // if this one hasn't been called
  181.                 if( pcur->rtn_type != PDONE ) {
  182.                     // if the priority is better than best so far
  183.                     if( pcur->priority <= working_limit )
  184.                     {
  185.                         // remember this one
  186.                         pnext = pcur;
  187.                         working_limit = pcur->priority;
  188.                     }
  189.                 }
  190.                 // advance to next entry
  191.                 pcur++;
  192.             }
  193.             // check to see if all done, if we didn't find any
  194.             // candidates then we can return
  195.             if( pnext == (struct rt_init _WCI86NEAR*)&_End_XI ) {
  196.                 break;
  197.             }
  198.         }
  199. #if defined(M_I86)
  200.         if( pnext->rtn_type == PNEAR ) {
  201.             callit_near( (npfn *)&pnext->rtn );
  202.         } else {
  203.             callit_far( (fpfn _WCI86NEAR *)&pnext->rtn );
  204.         }
  205. #else
  206.         callit( &pnext->rtn );
  207. #endif
  208.         // mark entry as invoked
  209.         pnext->rtn_type = PDONE;
  210.     }
  211.     restore_es();
  212.     restore_ds();
  213. }
  214.  
  215. /*
  216. ; - takes priority range parms in eax, edx, code will run fini routines whose
  217. ;       priority is >= eax (really al [0-255]) and <= edx (really dl [0-255])
  218. ;       eax==0,  edx=255 -> run all fini routines
  219. ;       eax==16, edx=255 -> run fini routines in range 16..255
  220. ;       eax==16, edx=40  -> run fini routines in range 16..40
  221. */
  222. #if defined(M_I86)
  223. void _WCI86FAR __FFiniRtns( unsigned min_limit, unsigned max_limit ) {
  224.     __FiniRtns( min_limit, max_limit );
  225. }
  226. #endif
  227.  
  228. void __FiniRtns( unsigned min_limit, unsigned max_limit )
  229. {
  230.     __type_rtp local_min_limit;
  231.     __type_rtp local_max_limit;
  232.     struct rt_init _WCI86NEAR *pnext;
  233.     save_ds();
  234.     save_es();
  235.     __GETDS();
  236.  
  237.     local_min_limit = (__type_rtp)min_limit;
  238.     local_max_limit = (__type_rtp)max_limit;
  239.     for(;;) {
  240.         {
  241.             __type_rtp working_limit;
  242.             struct rt_init _WCI86NEAR *pcur;
  243.  
  244.             pcur = (struct rt_init _WCI86NEAR*)&_Start_YI;
  245.             #if defined(COMP_CFG_COFF)
  246.                 pcur++;
  247.             #endif
  248.             pnext = (struct rt_init _WCI86NEAR*)&_End_YI;
  249.             working_limit = local_min_limit;
  250.  
  251.             // walk list of routines
  252.             while( pcur < (struct rt_init _WCI86NEAR*)&_End_YI )
  253.             {
  254.                 // if this one hasn't been called
  255.                 if( pcur->rtn_type != PDONE ) {
  256.                     // if the priority is better than best so far
  257.                     if( pcur->priority >= working_limit )
  258.                     {
  259.                         // remember this one
  260.                         pnext = pcur;
  261.                         working_limit = pcur->priority;
  262.                     }
  263.                 }
  264.                 // advance to next entry
  265.                 pcur++;
  266.             }
  267.             // check to see if all done, if we didn't find any
  268.             // candidates then we can return
  269.             if( pnext == (struct rt_init _WCI86NEAR*)&_End_YI ) {
  270.                 break;
  271.             }
  272.         }
  273.         if( pnext->priority <= local_max_limit ) {
  274. #if defined(M_I86)
  275.             if( pnext->rtn_type == PNEAR ) {
  276.                 callit_near( (npfn *)&pnext->rtn );
  277.             } else {
  278.                 callit_far( (fpfn _WCI86NEAR *)&pnext->rtn );
  279.             }
  280. #else
  281.             callit( &pnext->rtn );
  282. #endif
  283.         }
  284.         // mark entry as invoked even if we don't call it
  285.         // if we didn't call it, it is because we don't want to
  286.         // call finirtns with priority > max_limit, in that case
  287.         // marking the function as called, won't hurt anything
  288.         pnext->rtn_type = PDONE;
  289.     }
  290.     restore_es();
  291.     restore_ds();
  292. }
  293.  
  294.