static void thr_suspender(void *arg) { struct thread *td = (struct thread *) arg; int error; for (;;) { if (QUIT == 1) break; error = kthread_suspend(td, 10*hz); if (error != 0 && QUIT == 0) { if (error == EWOULDBLOCK) panic("Ooops: kthread deadlock\n"); else panic("kthread_suspend error: %d\n", error); break; } } mtx_lock(&test_global_lock); test_thrcnt--; wakeup(&global_condvar); mtx_unlock(&test_global_lock); kthread_exit(); }
/*! * Suspend thread until given time elapses * \param clockid Clock to use * \param flags Flags (TIMER_ABSTIME) * \param request Suspend duration * \param remain Remainder time if interrupted during suspension * \return status */ int sys__clock_nanosleep ( void *p ) { clockid_t clockid; int flags; timespec_t *request; timespec_t *remain; int retval = EXIT_SUCCESS; kthread_t *kthread = kthread_get_active (); ktimer_t *ktimer; sigevent_t evp; itimerspec_t itimer; clockid = *( (clockid_t *) p ); p += sizeof (clockid_t); flags = *( (int *) p ); p += sizeof (int); request = *( (timespec_t **) p ); p += sizeof (timespec_t *); remain = *( (timespec_t **) p ); ASSERT_ERRNO_AND_EXIT ( (clockid==CLOCK_REALTIME || clockid==CLOCK_MONOTONIC) && request && TIME_IS_SET(request), EINVAL ); /* Timers are used for "sleep" operations through steps 1-4 */ /* 1. create timer, but not arm it yet */ evp.sigev_notify = SIGEV_WAKE_THREAD; evp.sigev_value.sival_ptr = kthread; evp.sigev_notify_function = kclock_wake_thread; retval += ktimer_create ( clockid, &evp, &ktimer, kthread ); ASSERT ( retval == EXIT_SUCCESS ); /* save remainder location, if provided */ ktimer->param = remain; /* 2. suspend thread */ kthread_set_private_param ( kthread, ktimer ); retval += kthread_suspend ( kthread, kclock_interrupt_sleep, ktimer ); ASSERT ( retval == EXIT_SUCCESS ); /* 3. arm timer */ TIME_RESET ( &itimer.it_interval ); itimer.it_value = *request; retval += ktimer_settime ( ktimer, flags, &itimer, NULL ); ASSERT ( retval == EXIT_SUCCESS ); /* 4. pick other thread as active */ kthreads_schedule (); EXIT ( retval ); }
/*! * Wait for signal * \param set Signals thread is waiting for * \param info Where to save caught signal * \return signal number if signal is caught, * -1 otherwise and appropriate error number is set */ int sys__sigwaitinfo ( void *p ) { sigset_t *set; siginfo_t *info; kthread_t *kthread; ksignal_handling_t *sh; ksiginfo_t *ksig, *next; int retval; set = *( (sigset_t **) p ); p += sizeof (sigset_t *); info = *( (siginfo_t **) p ); ASSERT_ERRNO_AND_EXIT ( set, EINVAL ); set = U2K_GET_ADR ( set, kthread_get_process (NULL) ); ASSERT_ERRNO_AND_EXIT ( set, EINVAL ); if ( info ) info = U2K_GET_ADR ( info, kthread_get_process (NULL) ); kthread = kthread_get_active (); sh = kthread_get_sigparams ( kthread ); /* first, search for such signal in pending signals */ ksig = list_get ( &sh->pending_signals, FIRST ); while ( ksig ) { next = list_get_next ( &ksig->list ); if ( sigtestset ( set, ksig->siginfo.si_signo ) ) { retval = ksig->siginfo.si_signo; if ( info ) *info = ksig->siginfo; list_remove ( &sh->pending_signals, 0, &ksig->list ); kfree ( ksig ); EXIT2 ( EXIT_SUCCESS, retval ); } ksig = next; } /* * if no pending signal found that matches given mask * suspend thread until signal is received */ kthread_suspend ( kthread, ksignal_received_signal, NULL ); kthreads_schedule (); EXIT ( EINTR ); /* if other events wake thread */ }
void kthread_shutdown(void *arg, int howto) { struct thread *td; int error; if (panicstr) return; td = (struct thread *)arg; printf("Waiting (max %d seconds) for system thread `%s' to stop... ", kproc_shutdown_wait, td->td_name); error = kthread_suspend(td, kproc_shutdown_wait * hz); if (error == EWOULDBLOCK) printf("timed out\n"); else printf("done\n"); }