diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/dll/ppc | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/dll/ppc')
-rw-r--r-- | private/ntos/dll/ppc/critsect.s | 381 | ||||
-rw-r--r-- | private/ntos/dll/ppc/currteb.s | 35 | ||||
-rw-r--r-- | private/ntos/dll/ppc/ldrthunk.s | 108 | ||||
-rw-r--r-- | private/ntos/dll/ppc/sources | 6 |
4 files changed, 530 insertions, 0 deletions
diff --git a/private/ntos/dll/ppc/critsect.s b/private/ntos/dll/ppc/critsect.s new file mode 100644 index 000000000..232b69fb4 --- /dev/null +++ b/private/ntos/dll/ppc/critsect.s @@ -0,0 +1,381 @@ +// TITLE("Eenter and Leave Critical Section") +//++ +// +// Copyright (c) 1993 IBM Corporation +// +// Module Name: +// +// critsect.s +// +// Abstract: +// +// This module implements functions to support user mode critical sections. +// +// Author: +// +// Chuck Bauman 12-Aug-1993 +// +// Environment: +// +// Any mode. +// +// Revision History: +// +// Port NT product1 source to PowerPC +// +//-- + +#include "ksppc.h" + +// SBTTL("Enter Critical Section") +//++ +// +// NTSTATUS +// RtlEnterCriticalSection( +// IN PRTL_CRITICAL_SECTION CriticalSection +// ) +// +// Routine Description: +// +// This function enters a critical section. +// +// N.B. This function is duplicated in the runtime library. +// +// Arguments: +// +// CriticalSection (r.3) - Supplies a pointer to a critical section. +// +// Return Value: +// +// STATUS_SUCCESS is returned as the function value. +// +//-- +.extern ..RtlpWaitForCriticalSection +.extern ..RtlpNotOwnerCriticalSection +.extern ..RtlpUnWaitCriticalSection +.extern ..DbgBreakPoint + + .struct 0 + .space StackFrameHeaderLength +EcAddr: .space 4 // saved critical section address +EcClient: .space 4 // saved ClientId + .space 4 // room for LR save + .align 3 // ensure 8 byte alignment +EcFrameLength: // frame length + +// +// RtlEnterCriticalSection has been performance optimized for the fast path +// making it a leaf entry. When the slow path must be performed to acquire +// a critical section a branch to a NESTED_ENTRY for unwinding purposes is +// performed. +// +#if DBG + NESTED_ENTRY(RtlEnterCriticalSection,EcFrameLength,0,0) + PROLOGUE_END(RtlEnterCriticalSection) +#else + LEAF_ENTRY(RtlEnterCriticalSection) +#endif + +// +// Attempt to enter the critical section. +// + li r.10,CsLockCount // Constant for lwarx/stwcx. pairs + +res1failed: + lwarx r.8,r.10,r.3 // get addend value + addi r.8,r.8,1 // increment addend value + // copy updated value + stwcx. r.8,r.10,r.3 // store conditionally + bne- res1failed // if eq, store failed + +// +// If the critical section is not already owned, then initialize the owner +// thread id, initialize the recursion count, and return a success status. +// + + cmpwi cr.5,r.8,0 + lwz r.4,TeClientId + 4(r.13)// get current thread unique id + +#if DBG + bne- cr.5,RtlpEnterCriticalSection.body // if ne, lock already owned + // NOTE: RtlEnterCriticalSection will + // NOT appear in a stack trace + + lwz r.9,CsOwningThread(r.3) // get current owning thread + cmpwi cr.5,r.9,0 + beq cr.5,thdidok // if eq, thread id is correct + bl ..DbgBreakPoint // break into debugger + // NOTE: RtlEnterCriticalSection will + // NOT appear in a stack trace +thdidok: + +#else + bne- cr.5,..RtlpEnterCriticalSection // if ne, lock already owned + // NOTE: RtlEnterCriticalSection will + // NOT appear in a stack trace +#endif + + stw r.4,CsOwningThread(r.3) // set critical section owner + li r.3,STATUS_SUCCESS // set return status + +#if DBG + NESTED_EXIT(RtlEnterCriticalSection,EcFrameLength,0,0) +#else + LEAF_EXIT(RtlEnterCriticalSection) +#endif + +// +// r.3 - Pointer to the critical section +// r.4 - Current thread unique ID +// + NESTED_ENTRY(RtlpEnterCriticalSection,EcFrameLength,0,0) + PROLOGUE_END(RtlpEnterCriticalSection) +// +// The critical section is owned. If the current thread is the owner, then +// increment the recursion count, and return a success status. Otherwise, +// wait for critical section ownership. +// + + lwz r.5,CsOwningThread(r.3) // get unique id of owner thread + cmpw r.5,r.4 + bne waitforlock // if ne, current thread not owner + + lwz r.5,CsRecursionCount(r.3)// increment the recursion count + addi r.5,r.5,1 // + stw r.5,CsRecursionCount(r.3) + li r.3,STATUS_SUCCESS // set return status + addi r.sp, r.sp, EcFrameLength + blr + +// +// The critical section is owned by a thread other than the current thread. +// Wait for ownership of the critical section. + +waitforlock: + stw r.4, EcClient(r.sp) // Save the client id + stw r.3, EcAddr(r.sp) // Save critical section address + bl ..RtlpWaitForCriticalSection + lwz r.4, EcClient(r.sp) // Restore client id + lwz r.5, EcAddr(r.sp) // Restore the critical section address + li r.3,STATUS_SUCCESS // set return status + stw r.4, CsOwningThread(r.5) // set critical section owner + + NESTED_EXIT(RtlpEnterCriticalSection,EcFrameLength,0,0) + + +// SBTTL("Leave Critical Section") +//++ +// +// NTSTATUS +// RtlLeaveCriticalSection( +// IN PRTL_CRITICAL_SECTION CriticalSection +// ) +// +// Routine Description: +// +// This function leaves a critical section. +// +// N.B. This function is duplicated in the runtime library. +// +// Arguments: +// +// CriticalSection (r.3) - Supplies a pointer to a critical section. +// +// Return Value: +// +// STATUS_SUCCESS is returned as the function value. +// +//-- + +// +// RtlLeaveCriticalSection has been performance optimized for the fast path +// making it a leaf entry. When the slow path must be performed to acquire +// a critical section a branch to a NESTED_ENTRY for unwinding purposes is +// performed. +// +#if DBG + NESTED_ENTRY(RtlLeaveCriticalSection,EcFrameLength,0,0) + PROLOGUE_END(RtlLeaveCriticalSection) +#else + LEAF_ENTRY(RtlLeaveCriticalSection) +#endif + + li r.10,CsLockCount // Constant for lwarx/stwcx. pairs + li r.9,0 +// +// If the current thread is not the owner of the critical section, then +// raise an exception. +// + +#if DBG + + lwz r.6,CsOwningThread(r.3) // get owning thread unique id + lwz r.4,TeClientId + 4(r.13) // get current thread unique id + cmpw r.4,r.6 + beq+ owner // if eq, current thread is owner + + bl ..RtlpNotOwnerCriticalSection // call RtlpNotOwnerCriticalSection + LWI(r.3,STATUS_INVALID_OWNER) // STATUS_INVALID_OWNER = 0xc000005a + b RtlLeaveCriticalSection.epi // return error code + +owner: + +#endif + +// +// Decrement the recursion count. If the result is zero, then the lock +// is no longer onwed. +// + + lwz r.5,CsRecursionCount(r.3) // decrement recursion count + subic. r.5,r.5,1 // + bge- stillowned // if gez, lock still owned + // predict branch not taken + stw r.9,CsOwningThread(r.3) // clear owner thread id + +// +// Decrement the lock count and check if a waiter should be continued. +// + + +res2failed: + lwarx r.8,r.10,r.3 // get addend value + subi r.8,r.8,1 // decrement addend value + stwcx. r.8,r.10,r.3 // store conditionally + bne- res2failed // if eq, store failed + + cmpwi cr.0,r.8,0 + +#if DBG + blt+ nowaits // if ltz, no waiter present + // predict branch taken + bl ..RtlpUnWaitCriticalSection + b nowaits +#else + bge- ..RtlpLeaveCriticalSection + // predict branch not taken + // NOTE: RtlLeaveCriticalSection will + // NOT appear in a stack trace + li r.3,STATUS_SUCCESS // set completion status + blr // return +#endif + +// +// Decrement the lock count and return a success status since the lock +// is still owned. +// + +stillowned: + stw r.5,CsRecursionCount(r.3) + +res3failed: + lwarx r.8,r.10,r.3 // get addend value + subi r.8,r.8,1 // decrement addend value + stwcx. r.8,r.10,r.3 // store conditionally + bne- res3failed // if eq, store failed + +nowaits: + li r.3,STATUS_SUCCESS // set completion status + +#if DBG + NESTED_EXIT(RtlLeaveCriticalSection,EcFrameLength,0,0) +#else + LEAF_EXIT(RtlLeaveCriticalSection) + +// +// r.3 - Pointer to the critical section +// + NESTED_ENTRY(RtlpLeaveCriticalSection,EcFrameLength,0,0) + PROLOGUE_END(RtlpLeaveCriticalSection) + + bl ..RtlpUnWaitCriticalSection + li r.3,STATUS_SUCCESS // set completion status + + NESTED_EXIT(RtlpLeaveCriticalSection,EcFrameLength,0,0) +#endif + + +// SBTTL("Try to Enter Critical Section") +//++ +// +// BOOL +// RtlTryEnterCriticalSection( +// IN PRTL_CRITICAL_SECTION CriticalSection +// ) +// +// Routine Description: +// +// This function attempts to enter a critical section without blocking. +// +// Arguments: +// +// CriticalSection (r3) - Supplies a pointer to a critical section. +// +// Return Value: +// +// If the critical section was successfully entered, then a value of TRUE +// is returned as the function value. Otherwise, a value of FALSE is returned. +// +//-- + + LEAF_ENTRY(RtlTryEnterCriticalSection) + + li r6, CsLockCount // offset into critical section + lwz r5, TeClientId+4(r13) // get current thread unique id +// +// Attempt to enter the critical section. +// + +tecs10: + lwarx r7, r6, r3 // get addend value - locked + addic. r8, r7, 1 // increment addend value + bne- tecs20 // jump if critical section owned + stwcx. r8, r6, r3 // store conditionally + bne- tecs10 // loop if store failed + +// +// The critical section is now owned by this thread. Initialize the owner +// thread id and return a successful status. +// + stw r5, CsOwningThread(r3) // set critical section owner + li r3, TRUE // set success status + blr // return + +tecs20: + +// +// The critical section is already owned. If it is owned by another thread, +// return FALSE immediately. If it is owned by this thread, we must increment +// the lock count here. +// + lwz r7, CsOwningThread(r3) // get current owner + cmpw r7, r5 // same thread? + beq tecs30 // if eq, this thread is already the owner + + li r3, FALSE // set failure status + blr // return + +tecs30: + + lwz r4, CsRecursionCount(r3) + +// +// This thread is already the owner of the critical section. Perform an atomic +// increment of the LockCount and a normal increment of the RecursionCount and +// return success. +// + +tecs40: + lwarx r7, r6, r3 // get addend value - locked + addi r8, r7, 1 // increment addend value + stwcx. r8, r6, r3 // store conditionally + bne- tecs40 // loop if store failed + +// +// Increment the recursion count +// + addi r5, r4, 1 + stw r5, CsRecursionCount(r3) + + li r3, TRUE // set success status + LEAF_EXIT(RtlTryEnterCriticalSection) // return diff --git a/private/ntos/dll/ppc/currteb.s b/private/ntos/dll/ppc/currteb.s new file mode 100644 index 000000000..96b628039 --- /dev/null +++ b/private/ntos/dll/ppc/currteb.s @@ -0,0 +1,35 @@ +// TITLE("LdrInitializeThunk") +//++ +// +// Copyright (c) 1993 IBM Corporation +// +// Module Name: +// +// currteb.s +// +// Abstract: +// +// This module creates the function descriptor for the fast path +// service call to get the current TEB address. This is isolated +// because only positive service numbers go in the service table +// and NtCurrentTeb uses a negative service number for system +// call optimization. +// +// +// Author: +// +// Chuck Bauman 29-Sep-1993 +// +// Environment: +// +// User mode. +// +// Revision History: +// +//-- + +#include "ksppc.h" + + LEAF_ENTRY(NtCurrentTeb) + mr r.3, r.13 // Return the TEB which should be in r.13 + LEAF_EXIT(NtCurrentTeb) diff --git a/private/ntos/dll/ppc/ldrthunk.s b/private/ntos/dll/ppc/ldrthunk.s new file mode 100644 index 000000000..0d214620c --- /dev/null +++ b/private/ntos/dll/ppc/ldrthunk.s @@ -0,0 +1,108 @@ +// TITLE("LdrInitializeThunk") +//++ +// +// Copyright (c) 1989 Microsoft Corporation +// +// Module Name: +// +// ldrthunk.s +// +// Abstract: +// +// This module implements the thunk for the LdrpInitialize APC routine. +// +// Author: +// +// Chuck Bauman 20-Mar-1993 +// +// Environment: +// +// Any mode. +// +// Revision History: +// +// Port NT product1 source to PowerPC 12-Aug-1993 +// Changed to nested function and added conversion of function +// descriptor. Peter Johnston (plj@vnet.ibm.com) 18-Aug-1994 +// +//-- + +#include "ksppc.h" + + +//++ +// +// VOID +// LdrInitializeThunk( +// IN PVOID NormalContext, +// IN PVOID SystemArgument1, +// IN PVOID SystemArgument2 +// ) +// +// Routine Description: +// +// This routine is called via APC and is the first code executed in +// user mode for every user mode thread. +// +// On entry to this routine, the current stack frame is immediately +// preceeded by a context record containing the initial state of the +// new thread. +// +// This function computes a pointer to the context record on the stack +// and calls LdrpInitialize with that pointer as its parameter. +// +// On return from LdrpInitialize, we convert the function descriptor +// whose address is in the Context record Iar field from a pointer to +// a function descriptor to the actual TOC and entry point values for +// the thread. +// +// Arguments: +// +// NormalContext (r.3) - User Mode APC context parameter (ignored). +// +// SystemArgument1 (r.4) - User Mode APC system argument 1 (ignored). +// +// SystemArgument2 (r.5) - User Mode APC system argument 2 (ignored). +// +// Return Value: +// +// None. +// +//-- + + .extern ..LdrpInitialize + + .struct 0 + .space STK_MIN_FRAME +LitLr: .space 4 + .align 3 +LitFr1: .space STK_MIN_FRAME +LitCx: .space ContextFrameLength + .align 3 +LitFrameLen: + + SPECIAL_ENTRY(LdrInitializeThunk) + mflr r.0 + stwu r.sp, -LitFr1(r.sp) // buy stack frame + addi r.3, r.sp, LitCx // compute context record addr + stw r.0, LitLr(r.sp) // save return address + PROLOGUE_END(LdrInitializeThunk) + + bl ..LdrpInitialize // Jump to LdrpInitialize + lwz r.11, LitCx + CxGpr2(r.sp) // TOC set + cmpwi r.11, 0 // jif true context passed + // (e.g: fork) + lwz r.11, LitCx + CxIar(r.sp) // read fn descr from Cr Iar + lwz r.0, LitLr(r.sp) // get return address + bne truectx + lwz r.12, 4(r.11) // get toc + lwz r.11, 0(r.11) // get fn entry + stw r.12, LitCx + CxGpr2(r.sp) // set initial toc + stw r.11, LitCx + CxIar(r.sp) // set entry point + +truectx: + mtlr r.0 // restore return address + + addi r.sp, r.sp, LitFr1 // free out stack frame + SPECIAL_EXIT(LdrInitializeThunk) + diff --git a/private/ntos/dll/ppc/sources b/private/ntos/dll/ppc/sources new file mode 100644 index 000000000..2f9b87b04 --- /dev/null +++ b/private/ntos/dll/ppc/sources @@ -0,0 +1,6 @@ +PPC_DLLLIBOBJECTS=..\..\rtl\user\obj\ppc\chkstk.obj + +PPC_SOURCES=..\ppc\critsect.s \ + ..\ppc\currteb.s \ + ppc\usrstubs.s \ + ..\ppc\ldrthunk.s |