1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
;
;
; Copyright (C) Microsoft Corporation, 1987
;
; This Module contains Proprietary Information of Microsoft
; Corporation and should be treated as Confidential.
;
subttl emthread.asm - Emulator multi-thread support for OS/2
page
thread1static=1 ; set DS = EMULATOR_DATA for thread 1
; dynamically allocate data areas for other threads
_DATA segment word public 'DATA'
_DATA ends
DGROUP group _DATA
_DATA segment word public 'DATA'
extrn __FPDSARRAY:WORD
ifdef i386
extrn __threadid:FWORD ; far pointer to ???? thread id
else
extrn __threadid:DWORD ; far pointer to WORD thread id
endif
_DATA ends
dataoffset equ offset DGROUP:
include os2dll.inc ; defines _SIGNAL_LOCK
; and other lock values;
; must be synchronized with
; \clib\include\86\os2dll.inc
; and \clib\include\os2dll.h
extrn __lockf:FAR
extrn __unlockf:FAR
LOAD_DS_EDI macro
local TIDOk, LoadDone
;
; loads ds:edi with far pointer to thread's DS selector
; (pointer into __FPDSARRAY)
;
; uses eax,edi,es,ds
;
; sets eax = 2 * (thread id)
;
mov ax,DGROUP
mov ds,ax ; set DS = DGROUP temporarily
assume ds:DGROUP
les edi,[__threadid] ; ES:eDI = far pointer to thread id
mov ax,es:[edi] ; AX = thread id (far ptr to WORD)
cmp ax, MAXTHREADID
jbe TIDOk
push ax
call LoadDS_EDI
pop ax
shl ax, 1 ; thread id times 2
jmp short LoadDone
TIDOk:
shl eax,1 ; thread id times 2
mov edi,dataoffset __FPDSARRAY
add edi,eax ; index into __FPDSARRAY
LoadDone:
endm
LOADthreadDS macro
;
; loads thread's DS from __FPDSARRAY indexed by thread id
; preserves all registers except DS and eAX
;
; __FPDSARRAY[0] = MAXTHREAD
; __FPDSARRAY[i] = emulator DS for thread i, 1<=i<=MAXTHREAD
;
push edi ; save eDI
push es ; save ES
LOAD_DS_EDI ; get pointer (ds:edi) to thread's DS
mov ds,ds:[edi] ; set up DS to thread's data area
assume ds:EMULATOR_DATA ; or dynamically allocated copy
pop es
pop edi ; restore DI
endm
ALLOCthreadDS macro
pub allocperthread
LOAD_DS_EDI ; get pointer into __FPDSARRAY
; eAX = 2 * (thread_id)
ifdef thread1static
;
; for thread 1, use EMULATOR_DATA segment
;
cmp eax,2 ; thread 1?
jnz allocds ; no - dynamically allocate DS
mov ax,EMULATOR_DATA ; yes - use static area
mov ds:[edi],ax ; store new DS into __FPDSARRAY
mov ds,ax
assume ds:EMULATOR_DATA ; or dynamically allocated copy
mov es,ax ; ES = DS = EMULATOR_DATA
jmp allocdone
else
jmp allocds
endif ;thread1static
pub allocerror
mov ax,-3 ; return allocation error
stc
ret
;
ifdef thread1static
; for threads other than thread 1, allocate new DS from the system
else
; for all threads, allocate new DS from the system
endif
;
pub allocds
assume ds:DGROUP
push offset __fptaskdata ; size of per-thread data area
push ds ; ds:di = addr of thread's DS
push edi
push 0 ; non-shared segment
os2call DOSALLOCSEG
or ax,ax ; allocation error?
jnz allocerror ; yes - cause thread init to fail
mov di,ds:[edi] ; set ES = DS = thread's data selector
mov ds,di
mov es,di
assume ds:EMULATOR_DATA ; or dynamically allocated copy
pub allocdone
;
; ES = DS = selector for emulator data area
;
mov edx,offset __fptaskdata ; dx = size of emulator data area
sub edx,offset EMULATOR_DATA; jwm
xor ax,ax ; prepare to zero out data segment
xor edi,edi ; start at offset zero
mov edi,offset EMULATOR_DATA; jwm : begin at the beginning
mov ecx,edx ; cx = size of segment (even)
shr ecx,1 ; halve it
rep stosw ; zero it!
endm
FREEthreadDS macro
pub freeperthread
assume ds:EMULATOR_DATA ; or dynamically allocated copy
ifdef thread1static
mov ax,ds
cmp ax,EMULATOR_DATA ; don't free thread 1's area
je nofreeseg
endif ;thread1static
push ds
os2call DOSFREESEG ; free per-thread emulator data area
nofreeseg:
LOAD_DS_EDI ; get pointer into __FPDSARRAY
mov word ptr ds:[edi],0 ; zero out __FPDSARRAY element
; for the current thread
assume ds:EMULATOR_DATA
endm
|