Subversion Repositories Kolibri OS

Rev

Rev 548 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
548 serge 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
*/
702 serge 156
#if defined(M_I86)
157
void _WCI86FAR __FInitRtns( unsigned limit ) {
158
    __InitRtns( limit );
159
}
160
#endif
548 serge 161
void __InitRtns( unsigned limit ) {
162
    __type_rtp local_limit;
163
    struct rt_init _WCI86NEAR *pnext;
164
    save_ds();
165
    save_es();
166
    __GETDS();
167
 
168
    local_limit = (__type_rtp)limit;
169
    for(;;) {
170
        {
171
            __type_rtp working_limit;
172
            struct rt_init _WCI86NEAR *pcur;
173
 
174
            pcur = (struct rt_init _WCI86NEAR*)&_Start_XI;
175
            #if defined(COMP_CFG_COFF)
176
                pcur++;
177
            #endif
178
            pnext = (struct rt_init _WCI86NEAR*)&_End_XI;
179
            working_limit = local_limit;
180
 
181
            // walk list of routines
702 serge 182
            while( pcur < (struct rt_init _WCI86NEAR*)&_End_XI ) {
548 serge 183
                // if this one hasn't been called
184
                if( pcur->rtn_type != PDONE ) {
185
                    // if the priority is better than best so far
702 serge 186
                    if( pcur->priority <= working_limit ) {
548 serge 187
                        // remember this one
188
                        pnext = pcur;
189
                        working_limit = pcur->priority;
190
                    }
191
                }
192
                // advance to next entry
193
                pcur++;
194
            }
195
            // check to see if all done, if we didn't find any
196
            // candidates then we can return
197
            if( pnext == (struct rt_init _WCI86NEAR*)&_End_XI ) {
198
                break;
199
            }
200
        }
201
#if defined(M_I86)
202
        if( pnext->rtn_type == PNEAR ) {
203
            callit_near( (npfn *)&pnext->rtn );
204
        } else {
205
            callit_far( (fpfn _WCI86NEAR *)&pnext->rtn );
206
        }
207
#else
208
        callit( &pnext->rtn );
209
#endif
210
        // mark entry as invoked
211
        pnext->rtn_type = PDONE;
212
    }
213
    restore_es();
214
    restore_ds();
215
}
216
 
217
/*
218
; - takes priority range parms in eax, edx, code will run fini routines whose
219
;       priority is >= eax (really al [0-255]) and <= edx (really dl [0-255])
220
;       eax==0,  edx=255 -> run all fini routines
221
;       eax==16, edx=255 -> run fini routines in range 16..255
222
;       eax==16, edx=40  -> run fini routines in range 16..40
223
*/
224
#if defined(M_I86)
225
void _WCI86FAR __FFiniRtns( unsigned min_limit, unsigned max_limit ) {
226
    __FiniRtns( min_limit, max_limit );
227
}
228
#endif
702 serge 229
void __FiniRtns( unsigned min_limit, unsigned max_limit ) {
548 serge 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