/** * \b thread_shell * * Shell routine which is used to call all thread entry points. * * This routine is called whenever a new thread is starting, and * provides a simple wrapper around the thread entry point that * allows us to carry out any actions we want to do on thread's * first starting up, or returning after completion. * * We mainly just want to make sure interrupts are enabled when a * thread is run for the first time. This can be done via stack * restores when threads are first run, but it's handy to have this * wrapper anyway to run some common code if threads run to * completion. * * A thread shell is also handy for providing port users with a place * to do any other initialisation that must be done for each thread * (e.g. opening stdio files etc). * * @return None */ static void thread_shell (void) { ATOM_TCB *curr_tcb; /* Get the TCB of the thread being started */ curr_tcb = atomCurrentContext(); /** * Open a stdout file descriptor so that the thread has its own stdout. * In theory threads could open stdout to different output drivers * if syscalls.s supported different output write functions. */ stdout = fopen ("/debuguart", "w"); setvbuf (stdout, 0, _IONBF, 0); /** * Enable interrupts - these will not be enabled when a thread * is first restored. */ contextEnableInterrupts (); /* Call the thread entry point */ if (curr_tcb && curr_tcb->entry_point) { curr_tcb->entry_point(curr_tcb->entry_param); } /* Clean up after thread completion */ fclose (stdout); _reclaim_reent (&(curr_tcb->port_priv.reent)); /* Thread has run to completion: remove it from the ready list */ curr_tcb->terminated = TRUE; atomSched (FALSE); }
ThreadControlBlock::~ThreadControlBlock() { sequenceNumber_ = ~sequenceNumber_; const InterruptMaskingLock interruptMaskingLock; _reclaim_reent(&reent_); }
EXPORT_C void CloseSTDLIB() { struct _reent* p=(struct _reent*)Dll::Tls(); if (p==0) return; _reclaim_reent(p); // Reclaiming calls the atexit processing and generally tries to tidy up User::Free(p); // then we give back the struct _reent itself Dll::SetTls(0); // ... so we don't free it again when the DLL exits }
int __libc_delete_hook(lwp_cntrl *curr_thr, lwp_cntrl *delete_thr) { struct _reent *ptr; if(curr_thr==delete_thr) ptr = _REENT; else ptr = (struct _reent*)delete_thr->libc_reent; if(ptr && ptr!=&libc_globl_reent) { _wrapup_reent(ptr); _reclaim_reent(ptr); free(ptr); } delete_thr->libc_reent = 0; if(curr_thr==delete_thr) _REENT = 0; return 1; }
void libc_wrapup(void) { /* * In case RTEMS is already down, don't do this. It could be * dangerous. */ if (!_System_state_Is_up(_System_state_Get())) return; /* * This was already done if the user called exit() directly . _wrapup_reent(0); */ if (_REENT != _global_impure_ptr) { _wrapup_reent(_global_impure_ptr); #if 0 /* Don't reclaim this one, just in case we do printfs * on the way out to ROM. */ _reclaim_reent(&libc_global_reent); #endif _REENT = _global_impure_ptr; } /* * Try to drain output buffers. * * Should this be changed to do *all* file streams? * _fwalk (_REENT, fclose); */ fclose (stdin); fclose (stdout); fclose (stderr); }
ThreadControlBlock::~ThreadControlBlock() { architecture::InterruptMaskingLock interruptMaskingLock; _reclaim_reent(&reent_); }