summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow16/win87em/emthread.asm
blob: 8fa5a51dc6d6e8644335b4ce89cd76a62ce299f7 (plain) (blame)
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