Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | 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
*/
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