void AMXStackFramePrinter::PrintCallerName(const AMXStackFrame &frame) { if (IsMain(frame.amx(), frame.caller_address())) { stream_ << "main"; return; } if (debug_info_.IsLoaded()) { AMXDebugSymbol caller = debug_info_.GetExactFunction(frame.caller_address()); if (caller) { if (IsPublicFunction(frame.amx(), caller.GetCodeStart()) && !IsMain(frame.amx(), caller.GetCodeStart())) { stream_ << "public "; } PrintTag(caller); stream_ << caller.GetName(); return; } } const char *name = 0; if (frame.caller_address() != 0) { name = frame.amx().FindPublic(frame.caller_address()); } if (name != 0) { stream_ << "public " << name; } else { stream_ << "??"; } }
AM_ERR CQueue::SendMsg(const void *pMsg, AM_UINT msgSize) { AM_ASSERT(IsMain()); AUTO_LOCK(mpMutex); while (1) { if (mpMsgResult == NULL) { WriteData(mpSendBuffer, pMsg, msgSize); if (mnGet > 0) { mnGet --; mpCondGet->Signal(); } AM_ERR result; mpMsgResult = &result; mpCondReply->Wait(mpMutex); mpMsgResult = NULL; if (mnSendMsg > 0) { mnSendMsg --; mpCondSendMsg->Signal(); } return result; } mnSendMsg ++; mpCondSendMsg->Wait(mpMutex); } return ME_ERROR; }
AM_ERR CQueue::Construct(AM_UINT blockSize, AM_UINT nReservedSlots) { mBlockSize = ROUND_UP(blockSize, 4); // mpSendBuffer + list_node + list_node + ... + list_node mpReservedMemory = new AM_U8[NODE_SIZE * (nReservedSlots + 1)]; if (mpReservedMemory == NULL) { return ME_NO_MEMORY; } // for SendMsg() mpSendBuffer = (List*) mpReservedMemory; mpSendBuffer->pNext = NULL; mpSendBuffer->bAllocated = false; // reserved nodes, keep in free-list List *pNode = (List*) (mpReservedMemory + NODE_SIZE); for (; nReservedSlots > 0; nReservedSlots --) { pNode->bAllocated = false; pNode->pNext = mpFreeList; mpFreeList = pNode; pNode = (List*) ((AM_U8*) pNode + NODE_SIZE); } if (IsMain()) { if ((mpMutex = CMutex::Create(false)) == NULL) { return ME_OS_ERROR; } if ((mpCondGet = CCondition::Create()) == NULL) { return ME_OS_ERROR; } if ((mpCondReply = CCondition::Create()) == NULL) { return ME_OS_ERROR; } if ((mpCondSendMsg = CCondition::Create()) == NULL) { return ME_OS_ERROR; } } else { mpMutex = mpMainQ->mpMutex; mpCondGet = mpMainQ->mpCondGet; mpCondReply = mpMainQ->mpCondReply; mpCondSendMsg = mpMainQ->mpCondSendMsg; // attach to main-Q AUTO_LOCK(mpMainQ->mpMutex); mpPrevQ = mpMainQ->mpPrevQ; mpNextQ = mpMainQ; mpPrevQ->mpNextQ = this; mpNextQ->mpPrevQ = this; } return ME_OK; }
void CQueue::Reply(AM_ERR result) { AUTO_LOCK(mpMutex); AM_ASSERT(IsMain()); AM_ASSERT(mpMsgResult); *mpMsgResult = result; mpCondReply->Signal(); }
static void PrintHeader(const Proto* tf) { printf("\n%s " SOURCE_FMT " (%d instruction%s/%d bytes at %p)\n", IsMain(tf)?"main":"function",SOURCE, S(tf->ncode),tf->ncode*Sizeof(Instruction),tf); printf("%d%s param%s, %d stack%s, ", tf->numparams,tf->is_vararg?"+":"",SS(tf->numparams),S(tf->maxstacksize)); printf("%d local%s, %d string%s, %d number%s, %d function%s, %d line%s\n", S(tf->nlocvars),S(tf->nkstr),S(tf->nknum),S(tf->nkproto),S(tf->nlineinfo)); }
void PrintFunction(TFunc* tf) { if (IsMain(tf)) printf("\nmain of \"%s\" (%d bytes at %p)\n",tf->fileName,tf->size,tf); else printf("\nfunction \"%s\":%d (%d bytes at %p); used at main+%d\n", tf->fileName,tf->lineDefined,tf->size,tf,tf->marked); V=tf->locvars; PrintCode(tf->code,tf->code+tf->size); }
static void PrintHeader(const Proto* f) { printf("\n%s <%s:%d> (%d instruction%s, %d bytes at %p)\n", IsMain(f)?"main":"function",Source(f),f->lineDefined, S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); printf("%d%s param%s, %d stack%s, %d upvalue%s, ", f->numparams,f->is_vararg?"+":"",SS(f->numparams),S(f->maxstacksize), S(f->nups)); printf("%d local%s, %d constant%s, %d function%s\n", S(f->sizelocvars),S(f->sizek),S(f->sizep)); }
bool wxThread::SetConcurrency(size_t level) { wxASSERT_MSG( IsMain(), wxT("should only be called from the main thread") ); // ok only for the default one if ( level == 0 ) return 0; // Don't know how to realize this on OS/2. return level == 1; }
void AMXStackFramePrinter::PrintCallerName(const AMXStackFrame &frame, const AMXDebugSymbol &caller) { bool is_public = IsPublicFunction(frame.amx(), caller.GetCodeStart()); bool is_main = IsMain(frame.amx(), caller.GetCodeStart()); if (is_public && !is_main) { *stream_ << "public "; } PrintTag(caller); *stream_ << caller.GetName(); }
bool CQueue::PeekMsg(void *pMsg, AM_UINT msgSize) { AM_ASSERT(IsMain()); AUTO_LOCK(mpMutex); if (mnData > 0) { if (pMsg) ReadData(pMsg, msgSize); return true; } return false; }
void DumpFunction(TFunc* tf, FILE* D) { lastF=tf; ThreadCode(tf->code,tf->code+tf->size); fputc(ID_FUN,D); DumpSize(tf->size,D); DumpWord(tf->lineDefined,D); if (IsMain(tf)) DumpString(tf->fileName,D); else DumpWord(tf->marked,D); DumpBlock(tf->code,tf->size,D); DumpStrings(D); }
void AMXStackFramePrinter::PrintCallerName(const AMXStackFrame &frame) { if (IsMain(frame.amx(), frame.caller_address())) { *stream_ << "main"; } else { const char *name = 0; if (frame.caller_address() != 0) { name = frame.amx().FindPublic(frame.caller_address()); } if (name != 0) { *stream_ << "public " << name; } else { *stream_ << "??"; } } }
void CQueue::GetMsg(void *pMsg, AM_UINT msgSize) { AM_ASSERT(IsMain()); AUTO_LOCK(mpMutex); while (1) { if (mnData > 0) { ReadData(pMsg, msgSize); return; } mnGet ++; mpCondGet->Wait(mpMutex); } }
bool wxThread::SetConcurrency(size_t level) { wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") ); // ok only for the default one if ( level == 0 ) return 0; // how many CPUs have we got? if ( GetCPUCount() == 1 ) { // don't bother with all this complicated stuff - on a single // processor system it doesn't make much sense anyhow return level == 1; } return TRUE ; }
AM_ERR CQueue::PostMsg(const void *pMsg, AM_UINT msgSize) { AM_ASSERT(IsMain()); AUTO_LOCK(mpMutex); List *pNode = AllocNode(); if (pNode == NULL) { return ME_NO_MEMORY; } WriteData(pNode, pMsg, msgSize); if (mnGet > 0) { mnGet --; mpCondGet->Signal(); } return ME_OK; }
bool CQueue::GetMsgEx(void *pMsg, AM_UINT msgSize) { AM_ASSERT(IsMain()); AUTO_LOCK(mpMutex); while (1) { if (mbDisabled) return false; if (mnData > 0) { ReadData(pMsg, msgSize); return true; } mnGet ++; mpCondGet->Wait(mpMutex); } return false; }
// wait this main-Q and all its sub-Qs CQueue::QType CQueue::WaitDataMsg(void *pMsg, AM_UINT msgSize, WaitResult *pResult) { AM_ASSERT(IsMain()); AUTO_LOCK(mpMutex); while (1) { if (mnData > 0) { ReadData(pMsg, msgSize); return Q_MSG; } for (CQueue *q = mpNextQ; q != this; q = q->mpNextQ) { if (q->mnData > 0 && !q->mbDisabled) { pResult->pDataQ = q; pResult->pOwner = q->mpOwner; pResult->blockSize = q->mBlockSize; /* move the hit Q to the tail, semi Round Robin if (q != mpPrevQ) { // if q is not the tail q->mpPrevQ->mpNextQ = q->mpNextQ; q->mpNextQ->mpPrevQ = q->mpPrevQ; mpPrevQ->mpNextQ = q; q->mpPrevQ = mpPrevQ; mpPrevQ = q; q->mpNextQ = this; } */ return Q_DATA; } } mnGet ++; mpCondGet->Wait(mpMutex); } return Q_MSG; // Add this line to shut up code analysis warning }
//------------------------------------------------------------------------------------------------- void TextureMemory::Initialize() { // Todo: texture palette can probably have more slots, and other palette memory types can also expand. For now just 1 for testing texture palettes // Todo: If VRAM_E is mapped to texture or extended palette, it occupies more than 1 slot. Make this possible // Todo: Implement palette support. Only direct colored textures for now //PaletteMemory.Initialize(this); //PaletteMemory.AddSlot(BankE | BankF | BankG); if (IsMain()) { InitializeSlots(4); Slots[0]->AddSupportedMapping(BankA, VRAM_A_TEXTURE_SLOT0); Slots[0]->AddSupportedMapping(BankB, VRAM_B_TEXTURE_SLOT0); Slots[0]->AddSupportedMapping(BankC, VRAM_C_TEXTURE_SLOT0); Slots[0]->AddSupportedMapping(BankD, VRAM_D_TEXTURE_SLOT0); Slots[1]->AddSupportedMapping(BankA, VRAM_A_TEXTURE_SLOT1); Slots[1]->AddSupportedMapping(BankB, VRAM_B_TEXTURE_SLOT1); Slots[1]->AddSupportedMapping(BankC, VRAM_C_TEXTURE_SLOT1); Slots[1]->AddSupportedMapping(BankD, VRAM_D_TEXTURE_SLOT1); Slots[2]->AddSupportedMapping(BankA, VRAM_A_TEXTURE_SLOT2); Slots[2]->AddSupportedMapping(BankB, VRAM_B_TEXTURE_SLOT2); Slots[2]->AddSupportedMapping(BankC, VRAM_C_TEXTURE_SLOT2); Slots[2]->AddSupportedMapping(BankD, VRAM_D_TEXTURE_SLOT2); Slots[3]->AddSupportedMapping(BankA, VRAM_A_TEXTURE_SLOT3); Slots[3]->AddSupportedMapping(BankB, VRAM_B_TEXTURE_SLOT3); Slots[3]->AddSupportedMapping(BankC, VRAM_C_TEXTURE_SLOT3); Slots[3]->AddSupportedMapping(BankD, VRAM_D_TEXTURE_SLOT3); // Todo: hack, only works if BankA is mapped to TextureMemory nextAvailableAddress = VRAM_A; } }
CQueue::~CQueue() { if (mpMutex) { __LOCK(mpMutex); } AM_ASSERT(mnGet == 0); AM_ASSERT(mnSendMsg == 0); if (IsSub()) { // detach from main-Q mpPrevQ->mpNextQ = mpNextQ; mpNextQ->mpPrevQ = mpPrevQ; } else { // all sub-Qs should be removed AM_ASSERT(mpPrevQ == this); AM_ASSERT(mpNextQ == this); AM_ASSERT(mpMsgResult == NULL); } mpHead->Delete(); mpFreeList->Delete(); delete[] mpReservedMemory; if (mpMutex) { __UNLOCK(mpMutex); } if (IsMain()) { AM_DELETE(mpCondSendMsg); AM_DELETE(mpCondReply); AM_DELETE(mpCondGet); AM_DELETE(mpMutex); } }
wxThreadError wxThread::Delete(ExitCode *pRc) { ExitCode rc = 0; // Delete() is always safe to call, so consider all possible states // has the thread started to run? bool shouldResume = FALSE; { wxCriticalSectionLocker lock(m_critsect); if ( m_internal->GetState() == STATE_NEW ) { // WinThreadStart() will see it and terminate immediately m_internal->SetState(STATE_EXITED); shouldResume = TRUE; } } // is the thread paused? if ( shouldResume || IsPaused() ) Resume(); // does is still run? if ( IsRunning() ) { if ( IsMain() ) { // set flag for wxIsWaitingForThread() gs_waitingForThread = TRUE; #if wxUSE_GUI wxBeginBusyCursor(); #endif // wxUSE_GUI } // ask the thread to terminate { wxCriticalSectionLocker lock(m_critsect); m_internal->Cancel(); } #if wxUSE_GUI // simply wait for the thread to terminate while( TestDestroy() ) { ::YieldToAnyThread() ; } #else // !wxUSE_GUI // simply wait for the thread to terminate while( TestDestroy() ) { ::YieldToAnyThread() ; } #endif // wxUSE_GUI/!wxUSE_GUI if ( IsMain() ) { gs_waitingForThread = FALSE; #if wxUSE_GUI wxEndBusyCursor(); #endif // wxUSE_GUI } } if ( IsDetached() ) { // if the thread exits normally, this is done in WinThreadStart, but in // this case it would have been too early because // MsgWaitForMultipleObject() would fail if the therad handle was // closed while we were waiting on it, so we must do it here delete this; } if ( pRc ) *pRc = rc; return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR; }
wxThreadError wxThread::Delete(ExitCode *pRc) { ExitCode rc = 0; // Delete() is always safe to call, so consider all possible states // we might need to resume the thread, but we might also not need to cancel // it if it doesn't run yet bool shouldResume = false, shouldCancel = true, isRunning = false; // check if the thread already started to run { wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); if ( m_internal->GetState() == STATE_NEW ) { // WinThreadStart() will see it and terminate immediately, no need // to cancel the thread - but we still need to resume it to let it // run m_internal->SetState(STATE_EXITED); Resume(); // it knows about STATE_EXITED special case shouldCancel = false; isRunning = true; // shouldResume is correctly set to false here } else { shouldResume = IsPaused(); } } // resume the thread if it is paused if ( shouldResume ) Resume(); TID hThread = m_internal->GetHandle(); if ( isRunning || IsRunning()) { if (IsMain()) { // set flag for wxIsWaitingForThread() gs_bWaitingForThread = true; } // ask the thread to terminate if ( shouldCancel ) { wxCriticalSectionLocker lock(m_critsect); m_internal->Cancel(); } #if 0 // we can't just wait for the thread to terminate because it might be // calling some GUI functions and so it will never terminate before we // process the Windows messages that result from these functions DWORD result = 0; // suppress warnings from broken compilers do { if ( IsMain() ) { // give the thread we're waiting for chance to do the GUI call // it might be in if ( (gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread() ) { wxMutexGuiLeave(); } } result = ::DosWaitThread(&hThread, DCWW_NOWAIT); // FIXME: We ought to have a message processing loop here!! switch ( result ) { case ERROR_INTERRUPT: case ERROR_THREAD_NOT_TERMINATED: break; case ERROR_INVALID_THREADID: case NO_ERROR: // thread we're waiting for just terminated // or even does not exist any more. result = NO_ERROR; break; default: wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); } if ( IsMain() ) { // event processing - needed if we are the main thread // to give other threads a chance to do remaining GUI // processing and terminate cleanly. wxTheApp->HandleSockets(); if (wxTheApp->Pending()) if ( !wxTheApp->DoMessage() ) { // WM_QUIT received: kill the thread Kill(); return wxTHREAD_KILLED; } else wxUsleep(10); } else wxUsleep(10); } while ( result != NO_ERROR ); #else // !wxUSE_GUI // simply wait for the thread to terminate // // OTOH, even console apps create windows (in wxExecute, for WinSock // &c), so may be use MsgWaitForMultipleObject() too here? if ( ::DosWaitThread(&hThread, DCWW_WAIT) != NO_ERROR ) { wxFAIL_MSG(wxT("unexpected result of DosWaitThread")); } #endif // wxUSE_GUI/!wxUSE_GUI if ( IsMain() ) { gs_bWaitingForThread = false; } } #if 0 // although the thread might be already in the EXITED state it might not // have terminated yet and so we are not sure that it has actually // terminated if the "if" above hadn't been taken do { if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) ) { wxLogLastError(wxT("GetExitCodeThread")); rc = (ExitCode)-1; } } while ( (DWORD)rc == STILL_ACTIVE ); #endif if ( IsDetached() ) { // if the thread exits normally, this is done in WinThreadStart, but in // this case it would have been too early because // MsgWaitForMultipleObject() would fail if the thread handle was // closed while we were waiting on it, so we must do it here delete this; } if ( pRc ) *pRc = rc; return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR; }
//------------------------------------------------------------------------------------------------- int TextureMemory::Maximum() const { // Main engine can use 512kb (Bank A through D) for textures. Sub engine has no 3D, so no textures return (IsMain()) ? 0x80000 : 0; }