ssize_t LPC2000Serial::writeBlock(const void *buffer, size_t size, off_t where) { Lock<FastMutex> l(txMutex); FastInterruptDisableLock dLock; size_t len=size; const char *buf=reinterpret_cast<const char*>(buffer); while(len>0) { //If no data in software and hardware queue if((serial->LSR & (1<<5)) && (txQueue.isEmpty())) { //Fill hardware queue first for(int i=0;i<hwTxQueueLen;i++) { serial->THR=*buf++; len--; if(len==0) break; } } else { if(txQueue.IRQput(*buf)==true) { buf++; len--; } else { FastInterruptEnableLock eLock(dLock); txQueue.waitUntilNotFull(); } } } return size; }
/** * \internal * Read a single block of 512 bytes from an SD/MMC card. * Card must be selected prior to caling this function. * \param buffer, a buffer whose size is >=512 bytes * \param lba logical block address of the block to read. */ static bool singleBlockRead(unsigned char *buffer, unsigned int lba) { if(cardType!=SDHC) lba*=512; // Convert to byte address if not SDHC if(waitForCardReady()==false) return false; // Single block read unsigned int* newBuf=BufferConverter::toWordAlignedWithoutCopy(buffer); CmdResult cr; DataResult dr; bool failed=true; for(;;) { // Since we read with polling, a context switch or interrupt here // would cause a fifo overrun, so we disable interrupts. FastInterruptDisableLock dLock; SDIO->DTIMER=1048576; SDIO->DLEN=512; //Block size 512 bytes, block data xfer, from card to controller SDIO->DCTRL=(9<<4) | SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN; cr=Command::IRQsend(Command::CMD17,lba); if(cr.IRQvalidateR1Response()) { dr=IRQreceiveDataBlock(newBuf,512/sizeof(unsigned int)); SDIO->DCTRL=0; //Disable data path state machine //If failed because too slow check if it is possible to reduce speed if(dr.getError()==DataResult::RXOverrun) { if(ClockController::IRQreduceClockSpeed()) { //Disabling interrupts for too long is bad FastInterruptEnableLock eLock(dLock); //After an error during data xfer the card might be a little //confused. So send STOP_TRANSMISSION command to reassure it cr=Command::send(Command::CMD12,0); if(cr.validateR1Response()) continue; } } if(dr.getError()==DataResult::Ok) failed=false; } break; } if(failed) { cr.validateR1Response(); dr.validateError(); //After an error during data xfer the card might be a little //confused. So send STOP_TRANSMISSION command to reassure it cr=Command::send(Command::CMD12,0); cr.validateR1Response(); return false; } BufferConverter::toOriginalBuffer(); return true; }
bool Thread::join(void** result) { { FastInterruptDisableLock dLock; if(this==Thread::IRQgetCurrentThread()) return false; if(Thread::IRQexists(this)==false) return false; if(this->flags.isDetached()) return false; if(this->flags.isDeletedJoin()==false) { //Another thread already called join on toJoin if(this->joinData.waitingForJoin!=NULL) return false; this->joinData.waitingForJoin=Thread::IRQgetCurrentThread(); for(;;) { //Wait Thread::IRQgetCurrentThread()->flags.IRQsetJoinWait(true); { FastInterruptEnableLock eLock(dLock); Thread::yield(); } if(Thread::IRQexists(this)==false) return false; if(this->flags.isDetached()) return false; if(this->flags.isDeletedJoin()) break; } } //Thread deleted, complete join procedure //Setting detached flag will make isDeleted() return true, //so its memory can be deallocated this->flags.IRQsetDetached(); if(result!=NULL) *result=this->joinData.result; } { PauseKernelLock lock; //Since there is surely one dead thread, deallocate it immediately //to free its memory as soon as possible Scheduler::PKremoveDeadThreads(); } return true; }
/** * Used to initialize static objects only once, in a threadsafe way * \param g guard struct * \return 0 if object already initialized, 1 if this thread has to initialize * it, or lock if another thread has already started initializing it */ extern "C" int __cxa_guard_acquire(__guard *g) { miosix::InterruptDisableLock dLock; volatile MiosixGuard *guard=reinterpret_cast<volatile MiosixGuard*>(g); for(;;) { if(guard->flag==1) return 0; //Object already initialized, good if(guard->flag==0) { //Object uninitialized, and no other thread trying to initialize it guard->owner=miosix::Thread::IRQgetCurrentThread(); //guard->owner serves the double task of being the thread id of //the thread initializing the object, and being the flag to signal //that the object is initialized or not. If bit #0 of guard->owner //is @ 1 the object is initialized. All this works on the assumption //that Thread* pointers never have bit #0 @ 1, and this assetion //checks that this condition really holds if(guard->flag & 1) miosix::errorHandler(miosix::UNEXPECTED); return 1; } //If we get here, the object is being initialized by another thread if(guard->owner==miosix::Thread::IRQgetCurrentThread()) { //Wait, the other thread initializing the object is this thread?!? //We have a recursive initialization error. Not throwing an //exception to avoid pulling in exceptions even with -fno-exception IRQerrorLog("Recursive initialization\r\n"); _exit(1); } { miosix::InterruptEnableLock eLock(dLock); miosix::Thread::yield(); //Sort of a spinlock, a "yieldlock"... } } }