Huint _destroy_thread( Huint id ) { // Deallocate the thread ID from the thread manager _clear_thread( id ); // Give the architecture dependent code a chance to destroy the thread _arch_destroy_thread( id, &threads[id], id ); // Deallocate the stack that the thread is using if( threads[id].stack != NULL ) { //free( threads[ id ].stack ); // Static allocation doesn't require free } // The stack pointer now points at nothing threads[ id ].stack = NULL; return SUCCESS; }
Huint _destroy_thread( Huint id ) { hthread_thread_t * global_context_ptr =(hthread_thread_t *) _vhwti_context_ptr_field(); hthread_thread_t * threads = (hthread_thread_t *)global_context_ptr; // Deallocate the thread ID from the thread manager _clear_thread( id ); // Give the architecture dependent code a change to destroy the thread //_arch_destroy_thread( id, &threads[id], id ); // Deallocate the stack that the thread is using if( threads[id].stack != NULL ) { //free( threads[ id ].stack ); // No need to free statically allocated objects } // The stack pointer now points at nothing threads[ id ].stack = NULL; return SUCCESS; }
/** \internal * \brief The system call which implements the hthread_create functionality. * * \author Wesley Peck <*****@*****.**> * * This function is the system call routine which implements the * hthread_create functionality for hthreads. The user space function * hthread_create invokes this function to create a new thread. * * \param th If the thread was created successfully then the new * thread will be stored in the location pointed to * by this argument. * \param attr The attributes to apply to the newly created thread. * See the documentation for hthread_attr_t for more on * the allowable attributes. * \param start A function pointer which is used as the beginning of * the new threads execution. If this function ever returns * then the new thread will be terminated. * \param arg An arbitrary pointer which is used as the first and * only argument to the start routine. * \return The return value is one of the following: * - EAGAIN : There was an error when attempting to create * the new thread. Trying the attempt again might * have a different result. * - ENOMEM : Not enough memory is available to satisfy the * request. Attempting again after more memory * is free might have different results. * - EINVAL : One of the parameters used when calling this * function is invalid. * - FAILURE : A generic failure occurred in the hardware * when attempting to setup the thread. * - SUCCESS : The thread was created successfully */ Hint _syscall_create( hthread_t *th, hthread_attr_t *attr, hthread_start_t start, void *arg ) { Huint threadStatus; Huint threadID; Huint addStatus; Huint setupStatus; Huint schedStatus; // Print out a trace message about this system call TRACE_PRINTF( TRACE_FINE, TRACE_SYSCALL, "SYSCALL: (OP=CREATE) (THR=0x%8.8x) (ATTR=0x%8.8x) (STRT=0x%8.8x) (ARG=0x%8.8x)\n", (Huint)th, (Huint)attr, (Huint)start, (Huint)arg ); // Ask the thread manager to create a new thread for us. If it // is successful then the thread id will be encoded into the return // value. if( attr->detached ) threadStatus = _create_detached(); else threadStatus = _create_joinable(); TRACE_PRINTF( TRACE_FINE, TRACE_SYSCALL, "SYSCALL: (OP=CREATE) (DET = 0x%8.8x)\n",(Huint)attr->detached ); // Check if there was an error while creating the new thread. If // there was then it means that all of the available threads are // being used, so we return an error. if( has_error(threadStatus) ) { TRACE_PRINTF( TRACE_DBG, TRACE_SYSCALL, "SYSCALL: (OP=CREATE) (STA=0x%8.8x) (ERR=CREATE)\n", threadStatus ); return EAGAIN; } // If there was no error then we need to get the new thread's id // out of the return status. threadID = extract_id( threadStatus ); TRACE_PRINTF( TRACE_DBG, TRACE_SYSCALL, "SYSCALL: (OP=CREATE) (TID=0x%8.8x)\n", threadID ); // Initialize the software structures used to keep track of the thread. setupStatus = _setup_thread( threadID, attr, start, arg ); if( setupStatus != SUCCESS ) { TRACE_PRINTF( TRACE_DBG, TRACE_SYSCALL, "SYSCALL: (OP=CREATE) (STA=0x%8.8x) (ERR=SETUP)\n", setupStatus ); return setupStatus; } // Set the scheduling parameter for the thread. if( attr->hardware != Htrue ) { TRACE_PRINTF( TRACE_DBG, TRACE_SYSCALL, "SYSCALL: (OP=CREATE) (Software Thread Sched. Param = 0x%8.8x)\n",attr->sched_param); schedStatus = _set_schedparam( threadID, attr->sched_param ); } else { TRACE_PRINTF( TRACE_DBG, TRACE_SYSCALL, "SYSCALL: (OP=CREATE) (Hardware Thread Sched. Param = 0x%8.8x)\n",attr->hardware_addr); schedStatus = _set_schedparam( threadID, attr->hardware_addr ); } if( schedStatus != SUCCESS ) { TRACE_PRINTF( TRACE_DBG, TRACE_SYSCALL, "SYSCALL: (OP=CREATE) (STA=0x%8.8x) (ERR=SCHED)\n", schedStatus ); return schedStatus; } // Now that we have the new thread setup so that it can run we // can add the thread in the ready-to-run queue. addStatus = _add_thread( threadID ); // Check if there was an error when adding the thread into the // ready-to-run queue. If there was then we need to clean up the // new thread and return an error condition. if( has_error(addStatus) ) { TRACE_PRINTF( TRACE_DBG, TRACE_SYSCALL, "SYSCALL: (OP=CREATE) (STA=0x%8.8x) (ERR=ADD)\n", addStatus ); addStatus = _read_sched_status(threadID); _decode_sched_status(addStatus); // Clean up the software structures used by the thread. _destroy_thread( threadID ); // Remove the thread. _clear_thread( threadID ); // Return an error condition. return EAGAIN; } // Return the thread ID to the caller. At this point the thread has // been successfully created and added to the queue so that we know // a valid thread ID will be returned to the user. *th = threadID; // Print out a trace message about this system call TRACE_PRINTF( TRACE_FINE, TRACE_SYSCALL, "SYSCALL DONE: (OP=CREATE) (THR=0x%8.8x) (ATTR=0x%8.8x) (STRT=0x%8.8x) (ARG=0x%8.8x)\n", (Huint)th, (Huint)attr, (Huint)start, (Huint)arg ); // The thread was created and added to the ready-to-run queue // successfully. Return the success code. return SUCCESS; }