/** @brief The workhorse thread of the test. * * This thread recursively spawns two copies of itself decrementing n_voidstar * so long as n_voidstar is positive. Each thread repeats this process n_throws * times, after joining on the threads it created. * * @param The level we are at (to keep us from infinitly recursively spawning. */ void *juggle(void * n_voidstar) { int sub1, sub2; int throws; int substat; int ret; int n = (int)n_voidstar; inc_count(); print_count(n); if (n > 0) { for (throws = 0; throws < n_throws; throws++) { // Toss up two balls sub1 = thr_create(juggle, (void *)(n - 1)); if (sub1 < 0) { lprintf("Lev %d failed to create first thread w/ err %d\n", n, sub1); } sub2 = thr_create(juggle, (void *)(n - 1)); if (sub2 < 0) { lprintf("Lev %d failed to create second thread w/ err %d\n", n, sub2); } // Try to catch them if ((ret = thr_join(sub1, (void*)&substat)) != 0 || substat != (n - 1)) { lprintf("Lev %d failed to join first thread correctly:\n\t", n); lprintf("join(%d), ret = %d, %d ?= %d\n", sub1, ret, (n - 1), substat); } if ((ret = thr_join(sub2, (void*)&substat)) != 0 || substat != (n - 1)) { lprintf("Lev %d failed to join second thread correctly:\n\t", n); lprintf("join(%d), ret = %d, %d ?= %d\n", sub2, ret, (n - 1), substat); } } } #ifdef PRINT // Tell that we were successfull. putchar((char)n + '0'); #endif print_count(n); // Hang in the air for some amount of time sleep(genrand() % SLEEP_MAX); return (void *)n; }
void thread_work() { int i; #ifdef UNBOUND #ifdef SOLARIS if (thr_setconcurrency(nthreads) != 0) { perror("Oops, thr_setconcurrency failed"); exit(1); } #endif #endif /* create nthreads threads, having each start at do_work */ for (i = 0; i < nthreads; i++) { int retval; #ifdef SOLARIS #ifdef BOUND retval = thr_create(0, 0, do_work, 0, THR_BOUND, &(tid[i])); #endif #ifdef UNBOUND retval = thr_create(0, 0, do_work, 0, 0, &(tid[i])); #endif #endif #ifdef POSIX #ifdef BOUND retval = pthread_create(&(tid[i]), &attr, do_work, 0); #endif #ifdef UNBOUND retval = pthread_create(&(tid[i]), 0, do_work, 0); #endif #endif if(retval != 0) { perror("Oops, thr_create failed"); exit(1); } } /* wait for all threads to complete their work and join */ for (i = 0; i < nthreads; i++) { #ifdef SOLARIS thr_join(tid[i], 0, 0); #endif #ifdef POSIX pthread_join(tid[i], 0); #endif } }
/**************************************************************************** * Main function ****************************************************************************/ int main() { thread_t *producers; thread_t *consumers; thread_t tid; int *prod_ids; int *cons_ids; SPC *status; int x; signal(SIGALRM, SIG_IGN); producers = (thread_t*)malloc(sizeof(thread_t) * NUMBER_PRODUCERS); consumers = (thread_t*)malloc(sizeof(thread_t) * NUMBER_CONSUMERS); prod_ids = (int*)malloc(sizeof(int) * NUMBER_PRODUCERS); cons_ids = (int*)malloc(sizeof(int) * NUMBER_CONSUMERS); buffer = (int*)malloc(sizeof(int) * BUFFER_SIZE); /* Create the producer threads */ for(x = 0; x < NUMBER_PRODUCERS; x++) { prod_ids[x] = x + 1; thr_create(NULL, NULL, Producer, &prod_ids[x], 0, &producers[x]); } /* Create the consumer threads */ for(x = 0; x < NUMBER_CONSUMERS; x++) { cons_ids[x] = x + 1; thr_create(NULL, NULL, Consumer, &cons_ids[x], 0, &consumers[x]); } /* Wait for the threads to finish */ for(x = 0; x < NUMBER_PRODUCERS + NUMBER_CONSUMERS; x++) { thr_join(0, &tid, (void**)&status); if(status->type == PRODUCER) { printf("main(): PRODUCER-%d joined. %d widgets created.\n", status->id, status->num); } else { printf("main(): CONSUMER-%d joined. %d widgets consumed.\n", status->id, status->num); } } free(producers); free(consumers); free(prod_ids); free(cons_ids); free(buffer); return 0; }
main (int argc, char *argv[]) { int ncorr, t1arg, t0arg, orig_ncorr; thread_t tid1, tid0; float rate; if (argc != 6) { printf ("usage: %s t0_bound t0_new_lwp t1_bound t1_new_lwp ncorr\n", argv[0]); exit (1); } t0arg = THR_DETACHED; if (atoi (argv[1])) t0arg |= THR_BOUND; if (atoi (argv[2])) t0arg |= THR_NEW_LWP; t1arg = THR_DETACHED; if (atoi (argv[3])) t1arg |= THR_BOUND; if (atoi (argv[4])) t1arg |= THR_NEW_LWP; ncorr = atoi (argv[5]); if (thr_create (0, 0, work, 0, t0arg, &tid0) != 0) perror ("couldn't create thread 0"); if (thr_create (0, 0, work, (void *) 1, t1arg, &tid1) != 0) perror ("couldn't create thread 1"); orig_ncorr = thr_getconcurrency (); if (ncorr) thr_setconcurrency (ncorr); sleep (NSLEEP); rate = (count[0] + count[1]) / ((float) NSLEEP); printf ("\n------------------------------------------------------------------------\n"); printf ("t0arg 0x%x (%s, %s, %s)\nt1arg 0x%x (%s, %s, %s)\ncount[0] %d count[1] %d\n\ ncorr_orig %d ncorr_set %d ncorr_end %d rate %.3f per_cxt %.2f usec\n", t0arg, (t0arg & THR_DETACHED) ? "THR_DETACHED" : "Not Detached", (t0arg & THR_BOUND) ? "THR_BOUND" : "Not Bound", (t0arg & THR_NEW_LWP) ? "THR_NEW_LWP" : "No New_LWP", t1arg, (t1arg & THR_DETACHED) ? "THR_DETACHED" : "Not Detached", (t1arg & THR_BOUND) ? "THR_BOUND" : "Not Bound", (t1arg & THR_NEW_LWP) ? "THR_NEW_LWP" : "No New_LWP", count[0], count[1], orig_ncorr, ncorr, thr_getconcurrency (), rate, 1.0e6 / rate); }
int main( int argc, char *argv[] ) { int i, err; switch(argc) { case 6: i = atoi(argv[5]); if(i >= 0) bad_sleep = i; case 5: i = atoi(argv[4]); if(i >= 0) pause = i; case 4: i = atoi(argv[3]); if(i > 0) sems = i; case 3: i = atoi(argv[2]); if(i <= 26 && i > 0) run = i; case 2: i = atoi(argv[1]); if(i > 1 || i <= 24) threads = i; default: break; } expect(thr_init(STACK_SIZE)); expect(mutex_init(&lock_print)); expect(mutex_init(&lock_running)); expect(sem_init(&sem, sems)); for(i=0; i<80; i++) empty[i] = ' '; empty[80] = '\0'; expect(thr_create(bad, (void*)i) >= 0); for(i=0; i<threads; i++) expect(thr_create(race, (void*)i) >= 0); getchar(); expect(set_cursor_pos(24,0)); task_vanish(0); }
/** @brief spawns a new thread in the thread group * * @param tg, an initialized thread group to spawn the new thread in * @param func, function to run in the new thread * @param arg, argument to pass the function to func * @return 0 on success, nonzero otherwise */ int thrgrp_create(thrgrp_group_t *tg, void *(*func)(void *),void *arg){ int tid; thrgrp_data_t * data; /* setup a hunk of data this is used both to get the arguments into the other thread, and then as the memory to go on the zombie queue, this way we only malloc once */ data = malloc(sizeof(thrgrp_data_t)); if(data == NULL) return -1; data->tmp.func = func; data->tmp.arg = arg; data->tmp.tg = tg; /* spawn the thread */ tid = thr_create(thrgrp_bottom, data); /* tid<0 indicates error */ if(tid < 0) return tid; /* we don't return the tid, because your not supposed to join on it must be joined with thrgrp_join(), not thr_join() */ return 0; }
void start_register_monitor(const char *name, volatile U32 *addr, int x, int y, unsigned width, unsigned height, Window root, GC labelgc, GC boxgc, int bgPixel, int dgPixel) { thread_t monitor_thread; struct regmon_args *regmon_args; if ((regmon_args = (struct regmon_args *)malloc(sizeof(struct regmon_args)))) { regmon_args->label = name; regmon_args->addr = addr; regmon_args->x = x; regmon_args->y = y; regmon_args->width = width; regmon_args->height = height; regmon_args->root = root; regmon_args->labelgc = labelgc; regmon_args->boxgc = boxgc; regmon_args->backgroundPixel = bgPixel; regmon_args->shadowPixel = dgPixel; thr_create(NULL, 0, register_monitor_main, (void *)regmon_args, THR_DETACHED | THR_DAEMON, &monitor_thread); } }
void main(int argc, char** argv) { if (argc != 3 ) { cerr <<"Usage " << argv[0]<< "<BUF_SIZE> < # of THREAD>"<<endl; return; } long flag = THR_DETACHED|THR_NEW_LWP; MemRegisterTask(); new int; MemInitDefaultPool(); MEM_POOL_INFO info; MemPoolInfo(MemDefaultPool, NULL, &info); printf("def pool pageSize: %d;" "blockSizeFS: %hd\n", info.pageSize, info.blockSizeFS); long long buf_size = atoll(argv[1]); int no_of_threads = atoi(argv[2]); thread_t t1; for(int i=0;i<no_of_threads;i++) { thr_create(NULL,0,thr_RUN,(void*)&buf_size,flag, &t1); } while (thr_join(NULL, NULL, NULL)==0); return; }
/* create listen thread */ static boolean_t create_listen_thread(vntsd_group_t *groupp) { char err_msg[VNTSD_LINE_LEN]; int rv; assert(groupp); (void) mutex_lock(&groupp->lock); assert(groupp->num_cons); D1(stderr, "t@%d create_listen:%lld\n", thr_self(), groupp->tcp_port); if ((rv = thr_create(NULL, 0, (thr_func_t)vntsd_listen_thread, (void *)groupp, THR_DETACHED, &groupp->listen_tid)) != 0) { (void) (void) snprintf(err_msg, sizeof (err_msg), "Can not create listen thread for" "group %s tcp %llx\n", groupp->group_name, groupp->tcp_port); vntsd_log(VNTSD_ERR_CREATE_LISTEN_THR, err_msg); /* clean up group queue */ vntsd_free_que(&groupp->conspq, (clean_func_t)free_cons); groupp->listen_tid = (thread_t)-1; } (void) mutex_unlock(&groupp->lock); return (rv != 0); }
int umem_create_update_thread(void) { #ifndef _WIN32 sigset_t sigmask, oldmask; #endif ASSERT(MUTEX_HELD(&umem_update_lock)); ASSERT(umem_update_thr == 0); #ifndef _WIN32 /* * The update thread handles no signals */ (void) sigfillset(&sigmask); (void) thr_sigsetmask(SIG_BLOCK, &sigmask, &oldmask); #endif if (thr_create(NULL, 0, umem_update_thread, NULL, THR_BOUND | THR_DAEMON | THR_DETACHED, &umem_update_thr) == 0) { #ifndef _WIN32 (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); #endif return (1); } umem_update_thr = 0; #ifndef _WIN32 (void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL); #endif return (0); }
/* * Fire off a detached thread for each host in the list, if the thread * create fails simply run synchronously. */ static void doit(char *hostname) { thread_t tid; char *thread_hostname; (void) mutex_lock(&thr_mtx); while (thread_count >= MAX_THREADS) { (void) mutex_unlock(&thr_mtx); (void) sleep(PATIENCE/2); (void) mutex_lock(&thr_mtx); } thread_count++; (void) mutex_unlock(&thr_mtx); thread_hostname = strdup(hostname); if (thread_hostname == (char *)NULL) { (void) mutex_lock(&tty); (void) fprintf(stderr, "Ran out of memory\n"); (void) mutex_unlock(&tty); exit(1); } if (thr_create(NULL, 0, do_one, thread_hostname, THR_DETACHED, &tid) != 0) { (void) do_one(thread_hostname); } }
/* * MPIU_Thread_create() */ void MPIU_Thread_create(MPIU_Thread_func_t func, void * data, MPIU_Thread_id_t * idp, int * errp) { struct MPEI_Thread_info * thread_info; int err = MPIU_THREAD_SUCCESS; /* FIXME: faster allocation, or avoid it all together? */ thread_info = (struct MPEI_Thread_info *) MPIU_Malloc(sizeof(struct MPEI_Thread_info)); if (thread_info != NULL) { thread_info->func = func; thread_info->data = data; err = thr_create(NULL, 0, MPEI_Thread_start, thread_info, THR_DETACHED, idp); /* FIXME: convert error to an MPIU_THREAD_ERR value */ } else { err = 1000000000; } if (errp != NULL) { *errp = err; } }
/****************************************************************** * KpThreadCreate (Solaris Version) * * Description * * This function creates a new thread which starts execution at the * function specified by startFunc. The function startFunc receives * one 32 bit argument specified by arg. The new thread has its own * stack starting at the location specified by stackBase and continuing * for stackSize bytes. If stackBase is NULL, a new stack is created. If * stackSize is zero then the default stack size is used. The * KpThreadFlags structure pointed to by flags is used to specify the * security attributes and creation flags for the thread. If flags is NULL * then the default security attributes and creation flags are used. * * Author * mjb * * Created * July 5, 1994 *****************************************************************************/ KpThread_t KpThreadCreate (KpThrStartFunc startFunc, KpGenericPtr_t arg, KpGenericPtr_t stackBase, KpInt32_t stackSize, KpThreadFlags_p flags) { KpThread_t thread; KpInt32_t lclFlags; int retVal; /* Create the thread */ if (NULL == flags) { lclFlags = 0; } else { lclFlags = flags->CreationFlags; } retVal = thr_create (stackBase, stackSize, startFunc, arg, lclFlags, &thread); if (0 != retVal) { return (NULL); } return (thread); } /* KpThreadCreate */
void * sub_c(void *arg) { void *status; int i; thread_t main_thr, ret_thr; main_thr = (thread_t)arg; printf("C: In thread C...\n"); if (thr_create(NULL, 0, sub_f, (void *)0, THR_BOUND|THR_DAEMON, NULL)) fprintf(stderr, "Can't create thr_f\n"), exit(1); printf("C: Join main thread\n"); if (thr_join(main_thr,(thread_t *)&ret_thr, &status)) fprintf(stderr, "thr_join Error\n"), exit(1); printf("C: Main thread (%d) returned thread (%d) w/status %d\n", main_thr, ret_thr, (int) status); /* process */ for (i=0;i<1000000*(int)thr_self();i++); printf("C: Thread exiting...\n"); thr_exit((void *)88); }
// Create and start the frame thread int HAE_CreateFrameThread(void* context, HAE_FrameThreadProc proc) { if (proc) { long error; theFrameProc = proc; error = thr_create(NULL, NULL, PV_NativeFrameThreadProc, NULL, THR_BOUND | THR_NEW_LWP, &theFrameThread); if (error == 0) { error = thr_setprio(theFrameThread, 127); if (error == 0) { return 0; } else { DEBUG_STR("Failure to set priority of Solaris thread\n"); } } else { DEBUG_STR("Failure to create Solaris thread\n"); } theFrameProc = NULL; } return -1; }
void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx) { SSL_CTX *ssl_ctx[2]; thread_t thread_ctx[MAX_THREAD_NUMBER]; int i; ssl_ctx[0]=s_ctx; ssl_ctx[1]=c_ctx; thr_setconcurrency(thread_number); for (i=0; i<thread_number; i++) { thr_create(NULL, THREAD_STACK_SIZE, (void *(*)())ndoit, (void *)ssl_ctx, 0L, &(thread_ctx[i])); } printf("reaping\n"); for (i=0; i<thread_number; i++) { thr_join(thread_ctx[i],NULL,NULL); } printf("solaris threads done (%d,%d)\n", s_ctx->references,c_ctx->references); }
static nscd_rc_t _nscd_init_getent_ctx_monitor() { int errnum; char *me = "_nscd_init_getent_ctx_monitor"; _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) (me, "initializing the getent context monitor\n"); /* * the forker nscd does not process getent requests * so no need to monitor orphan getent contexts */ if (_whoami == NSCD_FORKER) return (NSCD_SUCCESS); /* * start a thread to reclaim unused getent contexts */ if (thr_create(NULL, NULL, reclaim_getent_ctx, NULL, THR_DETACHED, NULL) != 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR) (me, "thr_create: %s\n", strerror(errnum)); return (NSCD_THREAD_CREATE_ERROR); } return (NSCD_SUCCESS); }
void * sub_d(void *arg) { thread_t thr_b = (thread_t) arg; int i; thread_t thr_e, ret_thr; void *status; printf("D: In thread D...\n"); if (thr_create(NULL, 0, sub_e, NULL, THR_NEW_LWP, &thr_e)) fprintf(stderr,"Can't create thr_e\n"), exit(1); printf("D: Created thread E:%d\n", thr_e); printf("D: Continue B thread = %d\n", thr_b); thr_continue(thr_b); printf("D: Join E thread\n"); if(thr_join(thr_e,(thread_t *)&ret_thr, &status)) fprintf(stderr,"thr_join Error\n"), exit(1); printf("D: E thread (%d) returned thread (%d) w/status %d\n", thr_e, ret_thr, (int) status); /* process */ for (i=0;i<1000000*(int)thr_self();i++); printf("D: Thread exiting...\n"); thr_exit((void *)55); }
Window::Window(long left, long top, long right, long bottom) : fShowLevel(0), fCanvasList(0) { int windowServerPort; windowServerPort = namer_find ("window_server", 0); if (windowServerPort <= 0) { printf("couldn't connect to window server\n"); return; } int localReplyPort = port_create(0, "client_syncport"); fEventPort = port_create(0, "client_eventport"); fConnection = new Connection(windowServerPort, localReplyPort); fConnection->WriteInt8(OP_CREATE_WINDOW); fConnection->WriteInt32(0); // Child of root window fConnection->WriteInt32(left); fConnection->WriteInt32(top); fConnection->WriteInt32(right); fConnection->WriteInt32(bottom); fConnection->WriteInt32(fEventPort); fConnection->Flush(); fID = fConnection->ReadInt32(); fLock = qsem_create(1); thr_create((void*) EventLoop, this, "win_thread"); }
int start_register_dump(struct m_registers *regs) { thread_t register_thread; return(thr_create(NULL, 0, register_dump_main, (void *)regs, THR_DETACHED | THR_DAEMON, ®ister_thread)); }
void create_log_thread(zlog_t *logp, zoneid_t id) { int res; zlog_mode_t mode; shutting_down = 0; zlogp = logp; mode = get_logger_mode(); if (mode == ZLOG_NONE) return; if (init_zfd_devs(zlogp, mode) == -1) { zerror(zlogp, B_FALSE, "zfd setup: device initialization failed"); return; } res = thr_create(NULL, 0, (void * (*)(void *))srvr, (void *)mode, 0, &logger_tid); if (res != 0) { zerror(zlogp, B_FALSE, "error %d creating logger thread", res); logger_tid = 0; } }
/*ARGSUSED*/ taskq_t * taskq_create(const char *name, int nthreads, pri_t pri, int minalloc, int maxalloc, uint_t flags) { taskq_t *tq = kmem_zalloc(sizeof (taskq_t), KM_SLEEP); int t; rw_init(&tq->tq_threadlock, NULL, RW_DEFAULT, NULL); tq->tq_flags = flags | TASKQ_ACTIVE; tq->tq_active = nthreads; tq->tq_nthreads = nthreads; tq->tq_minalloc = minalloc; tq->tq_maxalloc = maxalloc; tq->tq_task.task_next = &tq->tq_task; tq->tq_task.task_prev = &tq->tq_task; tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP); if (flags & TASKQ_PREPOPULATE) { mutex_enter(&tq->tq_lock); while (minalloc-- > 0) task_free(tq, task_alloc(tq, KM_SLEEP)); mutex_exit(&tq->tq_lock); } for (t = 0; t < nthreads; t++) (void) thr_create(0, 0, taskq_thread, tq, THR_BOUND, &tq->tq_threadlist[t]); return (tq); }
int _nscd_setup_child_server(int did) { int errnum; int fd; nscd_rc_t rc; char *me = "_nscd_setup_child_server"; /* Re-establish our own server thread pool */ (void) door_server_create(server_create); if (thr_keycreate(&server_key, server_destroy) != 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) (me, "thr_keycreate failed: %s", strerror(errnum)); return (-1); } /* * Create a new door. * Keep DOOR_REFUSE_DESC (self-cred nscds don't fork) */ (void) close(did); if ((fd = door_create(switcher, NAME_SERVICE_DOOR_COOKIE, DOOR_REFUSE_DESC|DOOR_UNREF|DOOR_NO_CANCEL)) < 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) (me, "door_create failed: %s", strerror(errnum)); return (-1); } /* * kick off routing socket monitor thread */ if (thr_create(NULL, NULL, (void *(*)(void *))rts_mon, 0, 0, NULL) != 0) { errnum = errno; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "thr_create (routing socket monitor): %s\n", strerror(errnum)); (void) door_revoke(fd); return (-1); } /* * start monitoring the states of the name service clients */ rc = _nscd_init_smf_monitor(); if (rc != NSCD_SUCCESS) { _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR) (me, "unable to start the SMF monitor (rc = %d)\n", rc); (void) door_revoke(fd); return (-1); } return (fd); }
int ldap_pvt_thread_create( ldap_pvt_thread_t * thread, int detach, void *(*start_routine)( void *), void *arg) { return( thr_create( NULL, LDAP_PVT_THREAD_STACK_SIZE, start_routine, arg, detach ? THR_DETACHED : 0, thread ) ); }
void prodcons(int num_producers, int num_consumers) { int port = port_create(0, "prodcons"); printf("%d producers, %d consumers\n", num_producers, num_consumers); for (int i = 0; i < num_producers; i++) { cl_info *scinfo = new cl_info; snprintf(scinfo->name, 32, "producer %d", i + 1); scinfo->port = port; thr_create(producer, scinfo, scinfo->name); } for (int i = 0; i < num_consumers; i++) { cl_info *scinfo = new cl_info; snprintf(scinfo->name, 32, "consumer %d", i + 1); scinfo->port = port; thr_create(consumer, scinfo, scinfo->name); } }
int Thread::start() { // create a Sun-specific LPW thread int thread_status = thr_create( NULL, 0, thread_run, (void *) this, THR_BOUND, &m_tid ); if (thread_status != 0) { printf("unable to allocate a thread. (errcode=%d)\n", thread_status); } return (thread_status); }
/* ARGSUSED */ int PGPThreadCreate( PGPThread_t *tid, PGPThreadAttr_t *attr, VFP func, void *arg ) { return( thr_create( NULL, 0, func, arg, *attr, tid ) ); }
void malloc_test(void) { printf("starting malloc tests\n"); #if LOOK_ITS_A_RACE malloc_sem = sem_create(1,"malloc lock"); #endif for (int i = 0; i < 5; i++) thr_create(malloc_thread, 0, "malloc_thread"); }
/*ARGSUSED*/ kthread_t * zk_thread_create(void (*func)(), void *arg) { thread_t tid; VERIFY(thr_create(0, 0, (void *(*)(void *))func, arg, THR_DETACHED, &tid) == 0); return ((void *)(uintptr_t)tid); }
main() { int i; struct sigaction act; act.sa_handler = ExitHandler; (void) sigemptyset(&act.sa_mask); (void) sigaction(SIGTERM, &act, NULL); mutex_init(&first_mutex, 0 , 0); mutex_init(&second_mutex, 0 , 0); main_thread = thr_self(); thr_create(NULL,0,first_thread,0,THR_NEW_LWP,&one_tid); thr_create(NULL,0,second_thread,0,THR_NEW_LWP,&two_tid); for (i = 0; i < 10; i++){ fprintf(stderr, "main loop: %d\n", i); if (i == 5) { thr_kill(one_tid, SIGTERM); } sleep(3); } thr_kill(two_tid, SIGTERM); sleep(5); fprintf(stderr, "main exit\n"); }