static void iothread_instance_finalize(Object *obj) { IOThread *iothread = IOTHREAD(obj); iothread_stop(iothread); /* * Before glib2 2.33.10, there is a glib2 bug that GSource context * pointer may not be cleared even if the context has already been * destroyed (while it should). Here let's free the AIO context * earlier to bypass that glib bug. * * We can remove this comment after the minimum supported glib2 * version boosts to 2.33.10. Before that, let's free the * GSources first before destroying any GMainContext. */ if (iothread->ctx) { aio_context_unref(iothread->ctx); iothread->ctx = NULL; } if (iothread->worker_context) { g_main_context_unref(iothread->worker_context); iothread->worker_context = NULL; } qemu_cond_destroy(&iothread->init_done_cond); qemu_mutex_destroy(&iothread->init_done_lock); }
int32_t iothread_start( struct iothread * self, uint8_t index, iothreads_t parent ) { self->index = index; self->parent = parent; self->sets = evsets_create(); if ( self->sets == NULL ) { iothread_stop(self); return -1; } self->cmdevent = event_create(); self->queue = msgqueue_create( MSGQUEUE_DEFAULT_SIZE ); if ( self->queue == NULL || self->cmdevent == NULL ) { iothread_stop(self); return -2; } // 初始化命令事件 event_set( self->cmdevent, msgqueue_popfd(self->queue), EV_READ|EV_PERSIST ); event_set_callback( self->cmdevent, iothread_on_command, self ); evsets_add( self->sets, self->cmdevent, 0 ); // 启动线程 pthread_attr_t attr; pthread_attr_init( &attr ); // assert( pthread_attr_setstacksize( &attr, THREAD_DEFAULT_STACK_SIZE ) ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); int32_t rc = pthread_create(&(self->id), &attr, iothread_main, self); pthread_attr_destroy( &attr ); if ( rc != 0 ) { iothread_stop(self); return -3; } return 0; }
static int iothread_stop_iter(Object *object, void *opaque) { IOThread *iothread; iothread = (IOThread *)object_dynamic_cast(object, TYPE_IOTHREAD); if (!iothread) { return 0; } iothread_stop(iothread); return 0; }
static void iothread_instance_finalize(Object *obj) { IOThread *iothread = IOTHREAD(obj); iothread_stop(obj, NULL); qemu_cond_destroy(&iothread->init_done_cond); qemu_mutex_destroy(&iothread->init_done_lock); if (!iothread->ctx) { return; } aio_context_unref(iothread->ctx); }
void iothreads_stop( iothreads_t self ) { uint8_t i = 0; struct iothreads * iothreads = (struct iothreads *)(self); // 向所有线程发送停止命令 iothreads->runflags = 0; for ( i = 0; i < iothreads->nthreads; ++i ) { iothread_post( iothreads->threadgroup+i, eTaskType_Null, 0, NULL, 0 ); } // 等待线程退出 pthread_mutex_lock( &iothreads->lock ); while ( iothreads->nrunthreads > 0 ) { pthread_cond_wait( &iothreads->cond, &iothreads->lock ); } pthread_mutex_unlock( &iothreads->lock ); // 销毁所有网络线程 for ( i = 0; i < iothreads->nthreads; ++i ) { iothread_stop( iothreads->threadgroup + i ); } pthread_cond_destroy( &iothreads->cond ); pthread_mutex_destroy( &iothreads->lock ); if ( iothreads->threadgroup ) { free( iothreads->threadgroup ); iothreads->threadgroup = NULL; } free ( iothreads ); return; }