int main(int argc, char *argv[]) { void *status= 0; int t = 0; if(argc==2) t = atoi(argv[1]); //thread_start(&threads[0]); thread_run(&threads[0]); printf("\nDone-0\n"); //thread_start(&threads[1]); thread_run(&threads[1]); printf("\nDone-1\n"); //thread_start(&threads[2]); thread_run(&threads[2]); printf("\nDone-2\n"); //thread_start(&threads[3]); thread_run(&threads[3]); printf("\nDone-3\n"); //pthread_join(threads[2], &status); //pthread_join(threads[3], &status); //pthread_join(threads[1], &status); //pthread_join(threads[0], &status); printf("\nMain() exiting\n"); return 0; }
/* * 本地 server 节点的线程也需要启动,因为本地节点需要把其他的 kmod 节点数据转发 * 到共享这个 server 节点的其他 kmod 节点中 */ void node_list_run(struct node_list *node_list) { int idx; struct node *node; for(idx = 0; idx < node_list->node_num; idx++) { node = node_list->nodes[idx]; thread_run(node->data_worker); thread_run(node->meta_worker); } }
/* * Insert a new waitable thread for checking and processing. */ DWORD scheduler_insert_waitable( HANDLE waitable, LPVOID context, WaitableNotifyRoutine routine ) { DWORD result = ERROR_SUCCESS; THREAD * swt = NULL; WaitableEntry * entry = (WaitableEntry *)malloc( sizeof( WaitableEntry ) ); if( entry == NULL ) return ERROR_NOT_ENOUGH_MEMORY; dprintf( "[SCHEDULER] entering scheduler_insert_waitable( 0x%08X, 0x%08X, 0x%08X )", waitable, context, routine ); memset( entry, 0, sizeof( WaitableEntry ) ); entry->remote = schedulerRemote; entry->waitable = waitable; entry->context = context; entry->routine = routine; swt = thread_create( scheduler_waitable_thread, entry, NULL ); if( swt != NULL ) { dprintf( "[SCHEDULER] created scheduler_waitable_thread 0x%08X", swt ); thread_run( swt ); } else { free( entry ); result = ERROR_INVALID_HANDLE; } dprintf( "[SCHEDULER] leaving scheduler_insert_waitable" ); return result; }
process_id_t process_spawn(const char* executable) { TID_t thread; interrupt_status_t intr_status; process_id_t my_pid = process_get_current_process(); process_id_t pid = alloc_process_id(PROCESS_RUNNING); if (pid < 0) { /* Process table full */ return -1; } stringcopy(process_table[pid].executable, executable, PROCESS_NAME_MAX); process_table[pid].retval = 0; process_table[pid].first_zombie = -1; process_table[pid].prev_zombie = -1; process_table[pid].next_zombie = -1; process_table[pid].parent = my_pid; process_table[pid].children = 0; intr_status = _interrupt_disable(); spinlock_acquire(&process_table_slock); if (my_pid >= 0) { process_table[my_pid].children++; } spinlock_release(&process_table_slock); _interrupt_set_state(intr_status); thread = thread_create((void (*)(uint32_t))(&process_start), (uint32_t)pid); thread_run(thread); return pid; }
process_id_t process_spawn(const char *executable, const char **argv) { TID_t thread; process_id_t pid = alloc_process_id(); int ret; if (pid == PROCESS_MAX_PROCESSES) { return PROCESS_PTABLE_FULL; } spinlock_acquire(&process_table_slock); process_table[pid].parent = process_get_current_process(); thread = thread_create((void (*)(uint32_t))(&process_run), pid); ret = setup_new_process(thread, executable, argv, &process_table[pid].entry_point, &process_table[pid].stack_top); if (ret != 0) { process_table[pid].state = PROCESS_ZOMBIE; ret = -1; } else { ret = pid; } thread_run(thread); spinlock_release(&process_table_slock); return ret; }
int main(int argc, char * argv[]) { unsigned short port; char * host; struct rmi * rmi; int i; int cnt; struct rmi find_rmi; #ifndef _WIN32 pthread_t pid; struct sigaction act; act.sa_sigaction = SIG_IGN; act.sa_flags = SA_NOMASK; sigaction(SIGPIPE, &act, NULL); #else if (0 != socket_init()) { trace("socket init failed\n"); return -1; } #endif if (argc != 2) { printf("usage: %s port\n", argv[0]); return -1; } /*server_ip = argv[1];*/ server_port = atoi(argv[1]); RMI_INIT_SERVER(&find_rmi, find); rmi_set_broadcast(&find_rmi); /* rmi_set_keepalive_time(&find_rmi, 0xffffff);*/ rmi_set_recv_buf_size(&find_rmi, 1024*1024); rmi_server_start(&find_rmi, 8888); for(i = 0; i < CONNECT_NUM; i++) { /*int ret = pthread_create(&pid, NULL, test_proc, NULL);*/ int j; for (j = 0; j < 3; j++) { if (thread_run(test_proc, NULL)) { break; } else { msleep(10); } } if (3 == j) { trace("start test_proc thread failed\n"); } } getchar(); printf("successs cnt: %d\n", test_cnt); rmi_server_close(&find_rmi); return 0; }
int main(int argc, char *argv[]) { static char stack[10][1024]; int i; printf("Semaphore sample program\n"); /* * Initialize semaphore with initial count 3 */ sem_init(&sem, 3); /* * Boost the priority of this thread */ thread_setpri(thread_self(), 100); /* * Create 10 threads */ for (i = 0; i < 10; i++) thread_run(new_thread, stack[i]+1024); /* * Wait... */ thread_suspend(thread_self()); return 0; }
/* 初期スレッドの起動 */ void kz_start(kz_func_t func, char *name, int priority, int stacksize, int argc, char *argv[]) { /* 動的メモリの初期化 */ kzmem_init(); /* * 以降で呼び出すスレッド関連のライブラリ関数の内部で * current を見ている場合があるので、currentをNULLに初期化しておく */ current = NULL; memset(readyque, 0, sizeof(readyque)); memset(threads, 0, sizeof(threads)); memset(handlers, 0, sizeof(handlers)); memset(msgboxes, 0, sizeof(msgboxes)); setintr(SOFTVEC_TYPE_SYSCALL, syscall_intr); setintr(SOFTVEC_TYPE_SOFTERR, softerr_intr); /* * システムコール発行不可なので直接関数を呼び出してスレッド作成する */ current = (kz_thread *)thread_run(func, name, priority, stacksize, argc, argv); /* * 渡されたスタックポインタをもとに実行される=上で登録したcurrentが実行される */ dispatch(¤t->context); /* ここには返ってこない */ }
void kz_start(kz_func_t func, char *name, int priority, int stacksize, int argc, char *argv[]) { kzmem_init(); /* 動的メモリの初期化 */ /* * 以降で呼び出すスレッド関連のライブラリ関数の内部で current を * 見ている場合があるので,current を NULL に初期化しておく. */ current = NULL; memset(readyque, 0, sizeof(readyque)); memset(threads, 0, sizeof(threads)); memset(handlers, 0, sizeof(handlers)); memset(msgboxes, 0, sizeof(msgboxes)); /* 割込みハンドラの登録 */ thread_setintr(SOFTVEC_TYPE_SYSCALL, syscall_intr); /* システム・コール */ thread_setintr(SOFTVEC_TYPE_SOFTERR, softerr_intr); /* ダウン要因発生 */ /* システム・コール発行不可なので直接関数を呼び出してスレッド作成する */ current = (kz_thread *)thread_run(func, name, priority, stacksize, argc, argv); /* 最初のスレッドを起動 */ dispatch(¤t->context); /* ここには返ってこない */ }
static int run_traverser(int (*pred)(struct coopth_per_thread_t *), void (*post)(struct coopth_per_thread_t *)) { int i; int cnt = 0; for (i = 0; i < threads_active; i++) { int tid = active_tids[i]; struct coopth_t *thr = &coopthreads[tid]; struct coopth_per_thread_t *pth = current_thr(thr); /* only run detached threads here */ if (pth->data.attached) continue; if (pth->data.left) { if (!left_running) error("coopth: switching to left thread?\n"); continue; } if (pred && !pred(pth)) continue; thread_run(thr, pth); if (post) post(pth); cnt++; } return cnt; }
int main(int argc,char **argv) { HANDLE engine; uint32_t n; ip = argv[1]; port = atoi(argv[2]); signal(SIGPIPE,SIG_IGN); if(InitNetSystem() != 0) { printf("Init error\n"); return 0; } wpacket_allocator = (allocator_t)create_block_obj_allocator(0,sizeof(struct wpacket)); uint32_t i = 0; //getchar(); //init_wpacket_pool(100000); //init_rpacket_pool(50000); //buffer_init_maxbuffer_size(2000); //buffer_init_64(2000); init_clients(); engine = CreateEngine(); thread_run(_Listen,&engine); tick = GetSystemMs(); while(1) { EngineRun(engine,15); now = GetSystemMs(); if(now - tick > 1000) { printf("recv:%u,send:%u,s_req:%u\n",packet_recv,packet_send,send_request); tick = now; packet_recv = 0; packet_send = 0; send_request = 0; s_p = 0; iocp_count = 0; recv_count = 0; } /*if(now - last_send_tick > 50) { //心跳,每50ms集中发一次包 last_send_tick = now; for(i=0; i < MAX_CLIENT; ++i) { if(clients[i]) { //++send_request; connection_send(clients[i],0,0); } } }*/ } return 0; }
/** * Spawns a new process in a separate kernel thread, running * the given executable */ process_id_t process_spawn(const char *executable) { TID_t tid; process_id_t pid; pid = process_obtain_slot(executable); tid = thread_create(&process_start_wrapper, (uint32_t)pid); thread_run(tid); return pid; }
void coopth_run_tid(int tid) { struct coopth_t *thr = &coopthreads[tid]; struct coopth_per_thread_t *pth = current_thr(thr); assert(DETACHED_RUNNING >= 0); if (DETACHED_RUNNING) return; assert(!pth->data.attached && !pth->data.left); thread_run(thr, pth); }
/* システムコールの呼び出し */ static void call_functions(kz_syscall_type_t type, kz_syscall_param_t *p) { switch (type) { /* kz_run() */ case KZ_SYSCALL_TYPE_RUN: p->un.run.ret = thread_run(p->un.run.func, p->un.run.name, p->un.run.priority, p->un.run.stacksize, p->un.run.argc, p->un.run.argv); break; /* kz_exit() */ case KZ_SYSCALL_TYPE_EXIT: thread_exit(); break; /* kz_wait() */ case KZ_SYSCALL_TYPE_WAIT: p->un.wait.ret = thread_wait(); break; /* kz_sleep() */ case KZ_SYSCALL_TYPE_SLEEP: p->un.sleep.ret = thread_sleep(); break; /* kz_wakeup() */ case KZ_SYSCALL_TYPE_WAKEUP: p->un.wakeup.ret = thread_wakeup(p->un.wakeup.id); break; /* kz_getid() */ case KZ_SYSCALL_TYPE_GETID: p->un.getid.ret = thread_getid(); break; /* kz_chpri() */ case KZ_SYSCALL_TYPE_CHPRI: p->un.chpri.ret = thread_chpri(p->un.chpri.priority); break; /* kz_kmalloc() */ case KZ_SYSCALL_TYPE_KMALLOC: p->un.kmalloc.ret = thread_kmalloc(p->un.kmalloc.size); break; /* kz_kmfree() */ case KZ_SYSCALL_TYPE_KMFREE: p->un.kmfree.ret = thread_kmfree(p->un.kmfree.p); break; default: break; } }
/* * The servers main dispatch loop for incoming requests using SSL over TCP */ static DWORD server_dispatch( Remote * remote ) { LONG result = ERROR_SUCCESS; Packet * packet = NULL; THREAD * cpt = NULL; dprintf( "[DISPATCH] entering server_dispatch( 0x%08X )", remote ); // Bring up the scheduler subsystem. result = scheduler_initialize( remote ); if( result != ERROR_SUCCESS ) return result; while( TRUE ) { if( event_poll( serverThread->sigterm, 0 ) ) { dprintf( "[DISPATCH] server dispatch thread signaled to terminate..." ); break; } result = server_socket_poll( remote, 100 ); if( result > 0 ) { result = packet_receive( remote, &packet ); if( result != ERROR_SUCCESS ) { dprintf( "[DISPATCH] packet_receive returned %d, exiting dispatcher...", result ); break; } cpt = thread_create( command_process_thread, remote, packet ); if( cpt ) { dprintf( "[DISPATCH] created command_process_thread 0x%08X, handle=0x%08X", cpt, cpt->handle ); thread_run( cpt ); } } else if( result < 0 ) { dprintf( "[DISPATCH] server_socket_poll returned %d, exiting dispatcher...", result ); break; } } dprintf( "[DISPATCH] calling scheduler_destroy..." ); scheduler_destroy(); dprintf( "[DISPATCH] calling command_join_threads..." ); command_join_threads(); dprintf( "[DISPATCH] leaving server_dispatch." ); return result; }
void ControlledThread::run() { thread_init(); _running = true; _event.signal(); thread_run(); thread_deinit(); _running = false; _event.signal(); }
int main(int argc,char **argv) { HANDLE engine; uint32_t n; init_system_time(10); ip = argv[1]; port = atoi(argv[2]); signal(SIGPIPE,SIG_IGN); if(InitNetSystem() != 0) { printf("Init error\n"); return 0; } wpacket_allocator = (allocator_t)create_block_obj_allocator(SINGLE_THREAD,sizeof(struct wpacket)); uint32_t i = 0; init_clients(); engine = CreateEngine(); thread_run(_Listen,&engine); tick = GetSystemMs(); while(1) { EngineRun(engine,100); now = GetSystemMs(); if(now - tick > 1000) { printf("recv:%u,send:%u,s_req:%u,total_recv:%u\n",packet_recv,packet_send,send_request,total_bytes_recv/1024/1024); tick = now; packet_recv = 0; packet_send = 0; send_request = 0; iocp_count = 0; total_bytes_recv = 0; //printf("w:%d,r:%d,b:%d\n",wpacket_count,rpacket_count,buf_count); } /* if(now - last_send_tick > 10) { last_send_tick = now; for(i=0; i < MAX_CLIENT; ++i) { if(clients[i]) { connection_send(clients[i],NULL,NULL); } } }*/ } return 0; }
static void coopth_hlt(Bit16u offs, void *arg) { struct coopth_t *thr = (struct coopth_t *)arg + offs; struct coopth_per_thread_t *pth = current_thr(thr); if (!pth->data.attached) { /* someone used coopth_unsafe_detach()? */ error("HLT on detached thread\n"); leavedos(2); return; } thread_run(thr, pth); }
static void blocking_test(void) { thread_t th; int rc; for (int i = 0; i < BUF_SIZE; i++) write_buf[i] = i & 0x7F; syslog(LOG_INFO, "fifo blocking:\n wr_open..."); if ((wr_fd = open(fifo_name, O_WRONLY, 0)) < 0) err(1, "open(%s)", fifo_name); syslog(LOG_INFO, "write open ok\n write1..."); if ((rc = write(wr_fd, write_buf, WR1_SIZE)) != -1) errx(1, "write1 %d, expected %d", rc, 0); else if (errno != EPIPE) err(1, "write1 %d", WR1_SIZE); syslog(LOG_INFO, "write1 ok\n rd_open..."); if ((rd_fd = open(fifo_name, O_RDONLY, 0)) < 0) err(1, "open(%s)", fifo_name); syslog(LOG_INFO, "read open ok\n write1a..."); if ((rc = write(wr_fd, write_buf, WR1_SIZE)) < 0) err(1, "write1a %d", WR1_SIZE); else if (rc != WR1_SIZE) errx(1, "wrote1a %d, expected %d", rc, WR1_SIZE); syslog(LOG_INFO, "write1a ok\n thread_run..."); th = thread_run("read", read_thread, th_stack, sizeof(th_stack), 1); syslog(LOG_INFO, "thread_run ok\n write2..."); rc = write(wr_fd, write_buf + WR1_SIZE, WR2_SIZE); if (rc < 0) err(1, "write2 %d", WR2_SIZE); else if (rc != WR2_SIZE) errx(1, "wrote2 %d, expected %d", rc, WR2_SIZE); syslog(LOG_INFO, "write2 ok\n close..."); if (close(wr_fd) < 0) err(1, "close(%d)", wr_fd); syslog(LOG_INFO, "write close ok\n sleep..."); timer_sleep(1000/*ms*/, NULL); syslog(LOG_INFO, "sleep done\n data check..."); if (validate_write(0, BUF_SIZE) || validate_read(0, BUF_SIZE)) errx(1, "data corrupt"); syslog(LOG_INFO, "data check ok\nblocking test complete\n"); }
static void call_functions(kz_syscall_type_t type, kz_syscall_param_t *p) { /* システム・コールの実行中にcurrentが書き換わるので注意 */ switch (type) { case KZ_SYSCALL_TYPE_RUN: /* kz_run() */ p->un.run.ret = thread_run(p->un.run.func, p->un.run.name, p->un.run.priority, p->un.run.stacksize, p->un.run.argc, p->un.run.argv); break; case KZ_SYSCALL_TYPE_EXIT: /* kz_exit() */ /* TCBが消去されるので,戻り値を書き込んではいけない */ thread_exit(); break; case KZ_SYSCALL_TYPE_WAIT: /* kz_wait() */ p->un.wait.ret = thread_wait(); break; case KZ_SYSCALL_TYPE_SLEEP: /* kz_sleep() */ p->un.sleep.ret = thread_sleep(); break; case KZ_SYSCALL_TYPE_WAKEUP: /* kz_wakeup() */ p->un.wakeup.ret = thread_wakeup(p->un.wakeup.id); break; case KZ_SYSCALL_TYPE_GETID: /* kz_getid() */ p->un.getid.ret = thread_getid(); break; case KZ_SYSCALL_TYPE_CHPRI: /* kz_chpri() */ p->un.chpri.ret = thread_chpri(p->un.chpri.priority); break; case KZ_SYSCALL_TYPE_KMALLOC: /* kz_kmalloc() */ p->un.kmalloc.ret = thread_kmalloc(p->un.kmalloc.size); break; case KZ_SYSCALL_TYPE_KMFREE: /* kz_kmfree() */ p->un.kmfree.ret = thread_kmfree(p->un.kmfree.p); break; case KZ_SYSCALL_TYPE_SEND: /* kz_send() */ p->un.send.ret = thread_send(p->un.send.id, p->un.send.size, p->un.send.p); break; case KZ_SYSCALL_TYPE_RECV: /* kz_recv() */ p->un.recv.ret = thread_recv(p->un.recv.id, p->un.recv.sizep, p->un.recv.pp); break; case KZ_SYSCALL_TYPE_SETINTR: /* kz_setintr() */ p->un.setintr.ret = thread_setintr(p->un.setintr.type, p->un.setintr.handler); break; default: break; } }
int main(int argc, char *argv[]) { printf("Deadlock test program\n"); /* * Boost priority of this thread */ thread_setpri(thread_self(), 90); /* * Initialize mutexes. */ mutex_init(&mtx_A); mutex_init(&mtx_B); /* * Create new threads */ th_1 = thread_run(thread_1, stack[0]+1024); thread_setpri(th_1, 100); th_2 = thread_run(thread_2, stack[1]+1024); thread_setpri(th_2, 101); /* * Start thread 2 */ thread_resume(th_2); /* * Wait... */ thread_suspend(thread_self()); return 0; }
process_id_t process_spawn(const char *executable) { TID_t thread; process_id_t pid = alloc_process_id(); if (pid == PROCESS_MAX_PROCESSES) return PROCESS_PTABLE_FULL; /* Remember to copy the executable name for use in process_start */ stringcopy(process_table[pid].executable, executable, PROCESS_MAX_FILELENGTH); process_table[pid].parent = process_get_current_process(); thread = thread_create((void (*)(uint32_t))(&process_start), pid); thread_run(thread); return pid; }
process_id_t process_spawn(char const *executable) { TID_t newThread; int i = findFreeBlock(); if(i < 0) return PROCESS_PTABLE_FULL; process_table[i].exec = executable; process_table[i].parent_id = process_get_current_process(); process_table[i].state = RUNNING; newThread = thread_create((void*)process_start,(uint32_t)i); thread_run(newThread); // kprintf("PROCESS SPAWN ER STARTET\n"); return i; /* pid of new process */ }
void kz_start(kz_func_t func, char* name, int stacksize, int argc, char* argv[]) { current = NULL; readyque.head = readyque.tail = NULL; memset(threads, 0, sizeof(threads)); memset(handlers, 0, sizeof(handlers)); setintr(SOFTVEC_TYPE_SYSCALL, syscall_intr); setintr(SOFTVEC_TYPE_SOFTERR, softerr_intr); current = (kz_thread*)thread_run(func, name, stacksize, argc, argv); dispatch(¤t->context); }
int do_on_thread(function_with_result func, void *args, unsigned int stack_size) { return func(args); int r; struct thread_info info; info.func = func; info.args = args; thread_t t; r = thread_run(&t, __thread_wrapper, &info, 0, stack_size); printf("run: %d\n", r); if (r < 0) return -1; thread_join(&t); return info.result; }
int main(int argc, char *argv[]) { Module *m; Thread t; const char *file = argc > 1 ? argv[1] : "out.rmd"; loader_add_dir_from_file(file); loader_add_dirs_from_env(); heap_create(); m = module_load_obligatory(file); if(thread_init(&t, m, "main") < 0) return 1; thread_run(&t); return 0; }
static void call_functions(kz_syscall_type_t type, kz_syscall_param_t* p) { switch(type) { case KZ_SYSCALL_TYPE_RUN: p->un.run.ret = thread_run(p->un.run.func, p->un.run.name, p->un.run.stacksize, p->un.run.argc, p->un.run.argv); break; case KZ_SYSCALL_TYPE_EXIT: thread_exit(); break; default: break; } }
static void run_server(const char *addr) { ACL_VSTREAM *sstream = acl_vstream_listen(addr, 128); acl_pthread_pool_t *pool; CONN *conn; acl_pthread_t tid; acl_pthread_attr_t attr; ACL_VSTREAM *client; if (sstream == NULL) { acl_msg_error("listen %s error(%s)", addr, acl_last_serror()); return; } pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); printf("listening on %s ...\n", addr); pool = acl_thread_pool_create(10, 10); while (1) { acl_mem_slice_delay_destroy(); if (acl_read_wait(ACL_VSTREAM_SOCK(sstream), 5) == -1) continue; client = acl_vstream_accept(sstream, NULL, 0); if (client == NULL) { acl_msg_error("accept error(%s)", acl_last_serror()); break; } acl_tcp_set_nodelay(ACL_VSTREAM_SOCK(client)); conn = acl_mycalloc(1, sizeof(CONN)); conn->stream = client; if (0) thread_run(conn); else if (1) acl_pthread_create(&tid, &attr, thread_main, conn); else acl_pthread_pool_add(pool, thread_run, conn); } acl_vstream_close(sstream); }
process_id_t process_spawn(const char* executable) { TID_t thread; interrupt_status_t intr_status; process_id_t my_pid = process_get_current_process(); process_id_t pid = alloc_process_id(PROCESS_RUNNING); if (pid < 0) { /* Process table full */ return -1; } stringcopy(process_table[pid].executable, executable, PROCESS_NAME_MAX); process_table[pid].retval = 0; process_table[pid].first_zombie = -1; process_table[pid].prev_zombie = -1; process_table[pid].next_zombie = -1; process_table[pid].parent = my_pid; intr_status = _interrupt_disable(); spinlock_acquire(&process_table_slock); if (my_pid >= 0) { process_table[my_pid].children++; } spinlock_release(&process_table_slock); _interrupt_set_state(intr_status); process_table[pid].children = 0; process_table[pid].threads = 1; process_table[pid].stack_end = (USERLAND_STACK_TOP & PAGE_SIZE_MASK) - CONFIG_USERLAND_STACK_SIZE*PAGE_SIZE; process_table[pid].bot_free_stack = 0; for(int i = 0 ; i < MAX_OPEN_FILES ; i++) { process_table[pid].open_files[i] = -1; } thread = thread_create((void (*)(uint32_t))(&process_start), (uint32_t)pid); thread_run(thread); return pid; }
/*! * @brief Reset the given TCP connection. * @param transport Pointer to the TCP transport to reset. * @param shuttingDown Indication that the Metsrv instance is terminating completely. */ static void transport_reset_tcp(Transport* transport, BOOL shuttingDown) { if (transport && transport->type == METERPRETER_TRANSPORT_SSL) { TcpTransportContext* ctx = (TcpTransportContext*)transport->ctx; dprintf("[TCP] Resetting transport from %u", ctx->fd); if (ctx->fd) { if (shuttingDown) { dprintf("[TCP] Transport is shutting down"); // we can terminate right here, given that we're closing up closesocket(ctx->fd); } else { dprintf("[TCP] It should now be safe to close the socket."); THREAD* t = thread_create(cleanup_socket, (LPVOID)ctx->fd, NULL, NULL); thread_run(t); } } ctx->fd = 0; dprintf("[TCP] Transport 0x%p is now reset to %u", transport, ctx->fd); } }