📄 mdmac.c
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include <Types.h>#include <Timer.h>#include <Files.h>#include <Errors.h>#include <Folders.h>#include <Gestalt.h>#include <Events.h>#include <Processes.h>#include <TextUtils.h>#include <MixedMode.h>#include <LowMem.h>#include <fcntl.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <stat.h>#include <stdarg.h>#include <unix.h>#include "MacErrorHandling.h"#include "primpl.h"#include "prgc.h"#include "mactime.h"#include "mdmac.h"// undefine getenv, so that _MD_GetEnv can call the version in NSStdLib::nsEnvironment.cpp.#undef getenv//// Local routines//unsigned char GarbageCollectorCacheFlusher(PRUint32 size);extern PRThread *gPrimaryThread;extern ProcessSerialNumber gApplicationProcess; // in macthr.c//##############################################################################//###############################################################################pragma mark -#pragma mark CREATING MACINTOSH THREAD STACKSenum { uppExitToShellProcInfo = kPascalStackBased, uppStackSpaceProcInfo = kRegisterBased | RESULT_SIZE(SIZE_CODE(sizeof(long))) | REGISTER_RESULT_LOCATION(kRegisterD0) | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(UInt16)))};typedef CALLBACK_API( long , StackSpacePatchPtr )(UInt16 trapNo);typedef REGISTER_UPP_TYPE(StackSpacePatchPtr) StackSpacePatchUPP;StackSpacePatchUPP gStackSpacePatchUPP = NULL;UniversalProcPtr gStackSpacePatchCallThru = NULL;long (*gCallOSTrapUniversalProc)(UniversalProcPtr,ProcInfoType,...) = NULL;pascal long StackSpacePatch(UInt16 trapNo){ char tos; PRThread *thisThread; thisThread = PR_CurrentThread(); // If we are the primary thread, then call through to the // good ol' fashion stack space implementation. Otherwise, // compute it by hand. if ((thisThread == gPrimaryThread) || (&tos < thisThread->stack->stackBottom) || (&tos > thisThread->stack->stackTop)) { return gCallOSTrapUniversalProc(gStackSpacePatchCallThru, uppStackSpaceProcInfo, trapNo); } else { return &tos - thisThread->stack->stackBottom; }}static void InstallStackSpacePatch(void){ long systemVersion; OSErr err; CFragConnectionID connID; Str255 errMessage; Ptr interfaceLibAddr; CFragSymbolClass symClass; UniversalProcPtr (*getOSTrapAddressProc)(UInt16); void (*setOSTrapAddressProc)(StackSpacePatchUPP, UInt16); UniversalProcPtr (*newRoutineDescriptorProc)(ProcPtr,ProcInfoType,ISAType); err = Gestalt(gestaltSystemVersion,&systemVersion); if (systemVersion >= 0x00000A00) // we don't need to patch StackSpace() return; // open connection to "InterfaceLib" err = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kFindCFrag, &connID, &interfaceLibAddr, errMessage); PR_ASSERT(err == noErr); if (err != noErr) return; // get symbol GetOSTrapAddress err = FindSymbol(connID, "\pGetOSTrapAddress", &(Ptr)getOSTrapAddressProc, &symClass); if (err != noErr) return; // get symbol SetOSTrapAddress err = FindSymbol(connID, "\pSetOSTrapAddress", &(Ptr)setOSTrapAddressProc, &symClass); if (err != noErr) return; // get symbol NewRoutineDescriptor err = FindSymbol(connID, "\pNewRoutineDescriptor", &(Ptr)newRoutineDescriptorProc, &symClass); if (err != noErr) return; // get symbol CallOSTrapUniversalProc err = FindSymbol(connID, "\pCallOSTrapUniversalProc", &(Ptr)gCallOSTrapUniversalProc, &symClass); if (err != noErr) return; // get and set trap address for StackSpace (A065) gStackSpacePatchCallThru = getOSTrapAddressProc(0x0065); if (gStackSpacePatchCallThru) { gStackSpacePatchUPP = (StackSpacePatchUPP)newRoutineDescriptorProc((ProcPtr)(StackSpacePatch), uppStackSpaceProcInfo, GetCurrentArchitecture()); setOSTrapAddressProc(gStackSpacePatchUPP, 0x0065); }#if DEBUG StackSpace();#endif}//##############################################################################//###############################################################################pragma mark -#pragma mark ENVIRONMENT VARIABLEStypedef struct EnvVariable EnvVariable;struct EnvVariable { char *variable; char *value; EnvVariable *next;};EnvVariable *gEnvironmentVariables = NULL;char *_MD_GetEnv(const char *name){ EnvVariable *currentVariable = gEnvironmentVariables; while (currentVariable) { if (!strcmp(currentVariable->variable, name)) return currentVariable->value; currentVariable = currentVariable->next; } return getenv(name);}PR_IMPLEMENT(int) _MD_PutEnv(const char *string){ EnvVariable *currentVariable = gEnvironmentVariables; char *variableCopy, *value, *current; variableCopy = strdup(string); PR_ASSERT(variableCopy != NULL); current = variableCopy; while (*current != '=') current++; *current = 0; current++; value = current; while (currentVariable) { if (!strcmp(currentVariable->variable, variableCopy)) break; currentVariable = currentVariable->next; } if (currentVariable == NULL) { currentVariable = PR_NEW(EnvVariable); if (currentVariable == NULL) { PR_DELETE(variableCopy); return -1; } currentVariable->variable = strdup(variableCopy); currentVariable->value = strdup(value); currentVariable->next = gEnvironmentVariables; gEnvironmentVariables = currentVariable; } else { PR_DELETE(currentVariable->value); currentVariable->value = strdup(current); /* This is a temporary hack. Working on a real fix, remove this when done. */ /* OK, there are two ways to access the */ /* library path, getenv() and PR_GetLibraryPath(). Take a look at PR_GetLibraryPath(). */ /* You'll see that we keep the path in a global which is intialized at startup from */ /* a call to getenv(). From then on, they have nothing in common. */ /* We need to keep them in synch. */ if (strcmp(currentVariable->variable, "LD_LIBRARY_PATH") == 0) PR_SetLibraryPath(currentVariable->value); } PR_DELETE(variableCopy); return 0;}//##############################################################################//###############################################################################pragma mark -#pragma mark MISCELLANEOUSPRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np){ if (isCurrent) { (void) setjmp(t->md.jb); } *np = sizeof(t->md.jb) / sizeof(PRUint32); return (PRWord*) (t->md.jb);}void _MD_GetRegisters(PRUint32 *to){ (void) setjmp((void*) to);}void _MD_EarlyInit(){ Handle environmentVariables; GetCurrentProcess(&gApplicationProcess); INIT_CRITICAL_REGION(); InitIdleSemaphore();#if !defined(MAC_NSPR_STANDALONE) // MacintoshInitializeMemory(); Moved to mdmacmem.c: AllocateRawMemory(Size blockSize)#else MacintoshInitializeMemory();#endif MacintoshInitializeTime(); // Install resource-controlled environment variables. environmentVariables = GetResource('Envi', 128); if (environmentVariables != NULL) { Size resourceSize; char *currentPutEnvString = (char *)*environmentVariables, *currentScanChar = currentPutEnvString; resourceSize = GetHandleSize(environmentVariables); DetachResource(environmentVariables); HLock(environmentVariables); while (resourceSize--) { if ((*currentScanChar == '\n') || (*currentScanChar == '\r')) { *currentScanChar = 0; _MD_PutEnv (currentPutEnvString); currentPutEnvString = currentScanChar + 1; } currentScanChar++; } DisposeHandle(environmentVariables); }#ifdef PR_INTERNAL_LOGGING _MD_PutEnv ("NSPR_LOG_MODULES=clock:6,cmon:6,io:6,mon:6,linker:6,cvar:6,sched:6,thread:6");#endif InstallStackSpacePatch();}void _MD_FinalInit(){ _MD_InitNetAccess();}void PR_InitMemory(void) {#ifndef NSPR_AS_SHARED_LIB // Needed for Mac browsers without Java. We don't want them calling PR_INIT, since it // brings in all of the thread support. But we do need to allow them to initialize // the NSPR memory package. // This should go away when all clients of the NSPR want threads AND memory. MacintoshInitializeMemory();#endif}//##############################################################################//###############################################################################pragma mark -#pragma mark TERMINATION// THIS IS *** VERY *** IMPORTANT... our CFM Termination proc.// This allows us to deactivate our Time Mananger task even// if we are not totally gracefully exited. If this is not// done then we will randomly crash at later times when the// task is called after the app heap is gone.#if TARGET_CARBONextern OTClientContextPtr clientContext;#define CLOSE_OPEN_TRANSPORT() CloseOpenTransportInContext(clientContext)#else#define CLOSE_OPEN_TRANSPORT() CloseOpenTransport()#endif /* TARGET_CARBON */extern pascal void __NSTerminate(void);void CleanupTermProc(void){ _MD_StopInterrupts(); // deactive Time Manager task CLOSE_OPEN_TRANSPORT(); TermIdleSemaphore(); TERM_CRITICAL_REGION(); __NSTerminate();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -