; ; ; 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