/*! * Create new timer * \param clockid Clock used in timer * \param evp Timer expiration action * \param timerid Timer descriptor is returned in this variable * \return status 0 for success */ int sys__timer_create ( void *p ) { clockid_t clockid; sigevent_t *evp; timer_t *timerid; ktimer_t *ktimer; int retval = EXIT_SUCCESS; kobject_t *kobj; clockid = *( (clockid_t *) p ); p += sizeof (clockid_t); evp = *( (sigevent_t **) p ); p += sizeof (sigevent_t *); timerid = *( (timer_t **) p ); ASSERT_ERRNO_AND_EXIT ( clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC, EINVAL ); ASSERT_ERRNO_AND_EXIT ( evp && timerid, EINVAL ); retval = ktimer_create ( clockid, evp, &ktimer, kthread_get_active() ); if ( retval == EXIT_SUCCESS ) { kobj = kmalloc_kobject ( 0 ); kobj->kobject = ktimer; timerid->id = ktimer->id; timerid->ptr = kobj; } EXIT ( retval ); }
/*! * Lock mutex object * \param mutex Mutex descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_mutex_lock ( void *p ) { pthread_mutex_t *mutex; kpthread_mutex_t *kmutex; kobject_t *kobj; int retval = EXIT_SUCCESS; mutex = *( (pthread_mutex_t **) p ); ASSERT_ERRNO_AND_EXIT ( mutex, EINVAL ); kobj = mutex->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); kmutex = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( kmutex && kmutex->id == mutex->id, EINVAL ); retval = mutex_lock ( kmutex, kthread_get_active () ); if ( retval == 1 ) kthreads_schedule (); return retval != -1; }
/*! * Send signal to thread (from thread) * \param pid Thread descriptor (user level descriptor) * \param signo Signal number * \param sigval Parameter to send with signal * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__sigqueue ( void *p ) { pid_t pid; int signo; sigval_t sigval; pthread_t thread, sender; kthread_t *kthread; siginfo_t sig; pid = *( (pid_t *) p ); p += sizeof (pid_t); signo = *( (int *) p ); p += sizeof (int); sigval = *( (sigval_t *) p ); ASSERT_ERRNO_AND_EXIT ( signo > 0 && signo <= SIGMAX, EINVAL ); thread = (pthread_t) pid; /* pid_t should be pthread_t */ ASSERT_ERRNO_AND_EXIT ( thread.ptr, EINVAL ); kthread = thread.ptr; ASSERT_ERRNO_AND_EXIT ( kthread_get_id (kthread) == thread.id, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kthread_check_kthread ( kthread ), EINVAL ); sender.id = kthread_get_id (NULL); sender.ptr = kthread_get_active (); sig.si_signo = signo; sig.si_value = sigval; sig.si_pid = sender; sig.si_code = SI_USER; sig.si_errno = 0; EXIT ( ksignal_queue ( kthread, &sig ) ); }
/*! * Decrement (lock) semaphore value by 1 (if not 0 when thread is blocked) * \param sem Semaphore descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__sem_wait ( void *p ) { sem_t *sem; ksem_t *ksem; kobject_t *kobj; kthread_t *kthread; sem = *( (sem_t **) p ); ASSERT_ERRNO_AND_EXIT ( sem, EINVAL ); kthread = kthread_get_active (); kobj = sem->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); ksem = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( ksem && ksem->id == sem->id, EINVAL ); kthread_set_errno ( kthread, EXIT_SUCCESS ); if ( ksem->sem_value > 0 ) { ksem->sem_value--; ksem->last_lock = kthread; } else { kthread_enqueue ( kthread, &ksem->queue, 1, NULL, NULL ); kthreads_schedule (); } return EXIT_SUCCESS; }
/*! * Unlock mutex object * \param mutex Mutex descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_mutex_unlock ( void *p ) { pthread_mutex_t *mutex; kpthread_mutex_t *kmutex; kobject_t *kobj; mutex = *( (pthread_mutex_t **) p ); ASSERT_ERRNO_AND_EXIT ( mutex, EINVAL ); kobj = mutex->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); kmutex = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( kmutex && kmutex->id == mutex->id, EINVAL ); if ( kmutex->owner != kthread_get_active() ) { SET_ERRNO ( EPERM ); return EXIT_FAILURE; } SET_ERRNO ( EXIT_SUCCESS ); kmutex->owner = kthreadq_get ( &kmutex->queue ); if ( kmutex->owner ) { kthreadq_release ( &kmutex->queue ); kthreads_schedule (); } return EXIT_SUCCESS; }
/*! * Decrement (lock) semaphore value by 1 (if not 0 when thread is blocked) * \param sem Semaphore descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__sem_wait ( sem_t *sem ) { ksem_t *ksem; kobject_t *kobj; kthread_t *kthread; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( sem, EINVAL ); kthread = kthread_get_active (); kobj = sem->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); ksem = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( ksem && ksem->id == sem->id, EINVAL ); kthread_set_errno ( kthread, EXIT_SUCCESS ); kthread_set_syscall_retval ( kthread, EXIT_SUCCESS ); if ( ksem->sem_value > 0 ) { ksem->sem_value--; ksem->last_lock = kthread; } else { kthread_enqueue ( kthread, &ksem->queue ); kthreads_schedule (); } SYS_EXIT ( kthread_get_errno(NULL), kthread_get_syscall_retval(NULL) ); }
/*! * Lock mutex object * \param mutex Mutex descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_mutex_lock ( pthread_mutex_t *mutex ) { kpthread_mutex_t *kmutex; kobject_t *kobj; int retval = EXIT_SUCCESS; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( mutex, EINVAL ); kobj = mutex->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); kmutex = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( kmutex && kmutex->id == mutex->id, EINVAL ); retval = mutex_lock ( kmutex, kthread_get_active () ); if ( retval == 1 ) kthreads_schedule (); /* errno is already set */ if ( retval != -1 ) SYS_RETURN ( EXIT_SUCCESS ); else SYS_RETURN ( EXIT_FAILURE ); }
/*! * End current thread (exit from it) * \param retval Pointer to exit status */ int sys__pthread_exit ( void *p ) { void *retval; retval = *( (void **) p ); kthread_exit ( kthread_get_active(), retval, FALSE ); return 0; }
/*! * End current thread (exit from it) * \param retval Pointer to exit status */ int sys__pthread_exit ( void *retval ) { SYS_ENTRY(); kthread_exit ( kthread_get_active(), retval ); ASSERT ( FALSE ); /* should not return here! */ SYS_EXIT ( EXIT_FAILURE, EXIT_FAILURE ); }
/*! * Select ready thread with highest priority as active * - if different from current, move current into ready queue (id not NULL) and * move selected thread from ready queue to active queue */ void kthreads_schedule () { kthread_t *curr, *next = NULL; curr = kthread_get_active(); next = get_first_ready (); /* must exist an thread to return to, 'curr' or first from 'ready' */ ASSERT ( ( curr && kthread_is_active ( curr ) ) || next ); if ( !sys__feature ( FEATURE_SCHEDULER, FEATURE_GET, 0 ) && curr && kthread_is_active ( curr ) ) return;/*scheduler disabled, don't switch from current thread */ if ( !curr || !kthread_is_active ( curr ) || kthread_get_prio ( curr ) < kthread_get_prio ( next ) ) { if ( curr && !kthread_is_passive (curr) ) /* deactivate curr */ { /* move last active to ready queue, if still ready */ if ( kthread_is_active ( curr ) ) kthread_move_to_ready ( curr, LAST ); /* deactivation might change ready thread list */ next = get_first_ready (); ASSERT (next); } /* activate next */ next = kthread_remove_from_ready ( next ); ASSERT ( next ); kthread_set_active ( next ); } /* process pending signals (if any) */ ksignal_process_pending ( kthread_get_active() ); if ( curr != kthread_get_active() ) kthread_switch_to_thread ( curr, kthread_get_active() ); /* else => continue with current thread */ }
/*! * 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 ); }
/*! Return calling thread descriptor * \param thread Thread descriptor (user level descriptor) * \return 0 */ int sys__pthread_self ( pthread_t *thread ) { SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( thread, ESRCH ); thread->ptr = kthread_get_active (); thread->id = kthread_get_id (NULL); SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! * Simple Round-Robin scheduler: * - on timer tick move active into ready queue and pick next ready task */ static void ksched_rr_tick ( sigval_t sigval ) { if ( sys__feature ( FEATURE_SCHED_RR, FEATURE_GET, 0 ) == 0 ) return; kthread_t *active_thread = kthread_get_active(); if ( kthread_is_active ( active_thread ) ) { kthread_move_to_ready ( active_thread, LAST ); kthreads_schedule (); } }
/*! * 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 */ }
/*! Return calling thread descriptor * \param thread Thread descriptor (user level descriptor) * \return 0 */ int sys__pthread_self ( void *p ) { pthread_t *thread; thread = *( (void **) p ); ASSERT_ERRNO_AND_EXIT ( thread, ESRCH ); thread->ptr = kthread_get_active (); thread->id = kthread_get_id (NULL); EXIT ( EXIT_SUCCESS ); }
static int cond_release ( void *p, int release_all ) { pthread_cond_t *cond; kpthread_cond_t *kcond; kpthread_mutex_t *kmutex; kobject_t *kobj_cond, *kobj_mutex; kthread_t *kthread; int retval = 0; cond = *( (pthread_cond_t **) p ); ASSERT_ERRNO_AND_EXIT ( cond, EINVAL ); kobj_cond = cond->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_cond, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_cond->list ), EINVAL ); kcond = kobj_cond->kobject; ASSERT_ERRNO_AND_EXIT ( kcond && kcond->id == cond->id, EINVAL ); kthread_set_errno ( kthread_get_active (), EXIT_SUCCESS ); if ( (kthread = kthreadq_remove ( &kcond->queue, NULL )) ) { kobj_mutex = kthread_get_private_param ( kthread ); kmutex = kobj_mutex->kobject; retval = mutex_lock ( kmutex, kthread ); if ( retval == 0 ) kthread_move_to_ready ( kthread, LAST ); /* process other threads in queue */ while ( release_all && (kthread = kthreadq_remove ( &kcond->queue, NULL )) ) { kthread_set_errno ( kthread, EXIT_SUCCESS ); kobj_mutex = kthread_get_private_param ( kthread ); kmutex = kobj_mutex->kobject; kthread_enqueue(kthread, &kmutex->queue, 0, NULL, NULL); } } if ( retval > -1 ) kthreads_schedule (); return EXIT_SUCCESS; }
/*! * Modify thread signal mask * \param how How to modify current must * \param set Mask to use in modification * \param oset Where to store old mask * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_sigmask ( void *p ) { int how; sigset_t *set; sigset_t *oset; ksignal_handling_t *sh; int retval = EXIT_SUCCESS; how = *( (int *) p ); p += sizeof (int); set = *( (sigset_t **) p ); p += sizeof (sigset_t *); oset = *( (sigset_t **) p ); ASSERT_ERRNO_AND_EXIT ( set, EINVAL ); set = U2K_GET_ADR ( set, kthread_get_process (NULL) ); ASSERT_ERRNO_AND_EXIT ( set, EINVAL ); sh = kthread_get_sigparams ( NULL ); if (oset) oset = U2K_GET_ADR ( oset, kthread_get_process (NULL) ); if (oset) *oset = *sh->mask; switch ( how ) { case SIG_BLOCK: sigaddsets ( sh->mask, set ); break; case SIG_UNBLOCK: sigaddsets ( sh->mask, set ); break; case SIG_SETMASK: *sh->mask = *set; break; default: retval = EINVAL; } /* reevaluate pending signals with new mask */ if ( retval == EXIT_SUCCESS ) retval = ksignal_process_pending ( kthread_get_active () ); EXIT ( retval ); }
/*! Handle memory fault interrupt (and others undefined) */ void k_memory_fault () { LOG ( ERROR, "Undefined fault (exception)!!!"); if ( arch_prev_mode () == KERNEL_MODE ) { LOG ( ERROR, "PANIC: kernel caused GPF!"); halt (); } else { /* terminate active thread */ LOG ( ERROR, "Thread caused GPF, terminating!"); kthread_exit ( kthread_get_active(), NULL, TRUE ); } }
/*! * Wait on conditional variable * \param cond conditional variable descriptor (user level descriptor) * \param mutex Mutex descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_cond_wait ( void *p ) { pthread_cond_t *cond; pthread_mutex_t *mutex; kpthread_cond_t *kcond; kpthread_mutex_t *kmutex; kobject_t *kobj_cond, *kobj_mutex; int retval = EXIT_SUCCESS; cond = *( (pthread_cond_t **) p ); p += sizeof (pthread_cond_t *); mutex = *( (pthread_mutex_t **) p ); ASSERT_ERRNO_AND_EXIT ( cond && mutex, EINVAL ); kobj_cond = cond->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_cond, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_cond->list ), EINVAL ); kcond = kobj_cond->kobject; ASSERT_ERRNO_AND_EXIT ( kcond && kcond->id == cond->id, EINVAL ); kobj_mutex = mutex->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_mutex, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_mutex->list), EINVAL ); kmutex = kobj_mutex->kobject; ASSERT_ERRNO_AND_EXIT ( kmutex && kmutex->id == mutex->id, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kmutex->owner == kthread_get_active(), EPERM ); SET_ERRNO ( EXIT_SUCCESS ); /* move thread in conditional variable queue */ kthread_enqueue ( NULL, &kcond->queue, 0, NULL, NULL ); /* save reference to mutex object */ kthread_set_private_param ( NULL, kobj_mutex ); /* release mutex */ kmutex->owner = kthreadq_get ( &kmutex->queue ); if ( kmutex->owner ) kthreadq_release ( &kmutex->queue ); kthreads_schedule (); return retval; }
/*! * Modify thread signal mask * \param sig Signal number * \param act Signal handling behavior * \param oact Where to save old signal behavior * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__sigaction ( void *p ) { int sig; sigaction_t *act; sigaction_t *oact; ksignal_handling_t *sh; sig = *( (int *) p ); p += sizeof (int); act = *( (sigaction_t **) p ); p += sizeof (sigaction_t *); oact = *( (sigaction_t **) p ); ASSERT_ERRNO_AND_EXIT ( sig > 0 && sig <= SIGMAX, EINVAL ); if ( act ) act = U2K_GET_ADR ( act, kthread_get_process (NULL) ); if ( oact ) oact = U2K_GET_ADR ( oact, kthread_get_process (NULL) ); sh = kthread_get_sigparams ( NULL ); if ( oact ) *oact = sh->act[sig]; if ( act ) { if ( !( act->sa_flags & SA_SIGINFO ) ) EXIT ( ENOTSUP ); if ( act->sa_sigaction == SIG_ERR || act->sa_sigaction == SIG_DFL || act->sa_sigaction == SIG_IGN || act->sa_sigaction == SIG_HOLD ) { EXIT ( ENOTSUP ); } sh->act[sig] = *act; sigdelset ( sh->mask, sig ); /* accept sig */ /* reevaluate pending signals with changed behavior */ ksignal_process_pending ( kthread_get_active () ); } EXIT ( EXIT_SUCCESS ); }
/*! * Wait on conditional variable * \param cond conditional variable descriptor (user level descriptor) * \param mutex Mutex descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_cond_wait ( pthread_cond_t *cond, pthread_mutex_t *mutex ) { kpthread_cond_t *kcond; kpthread_mutex_t *kmutex; kobject_t *kobj_cond, *kobj_mutex; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( cond && mutex, EINVAL ); kobj_cond = cond->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_cond, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_cond->list ), EINVAL ); kcond = kobj_cond->kobject; ASSERT_ERRNO_AND_EXIT ( kcond && kcond->id == cond->id, EINVAL ); kobj_mutex = mutex->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_mutex, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_mutex->list), EINVAL ); kmutex = kobj_mutex->kobject; ASSERT_ERRNO_AND_EXIT ( kmutex && kmutex->id == mutex->id, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kmutex->owner == kthread_get_active(), EPERM ); kthread_set_errno ( NULL, EXIT_SUCCESS ); kthread_set_syscall_retval ( NULL, EXIT_SUCCESS ); /* move thread in conditional variable queue */ kthread_enqueue ( NULL, &kcond->queue ); /* save reference to mutex object */ kthread_set_private_param ( NULL, kobj_mutex ); /* release mutex */ kmutex->owner = kthreadq_get ( &kmutex->queue ); if ( kmutex->owner ) kthreadq_release ( &kmutex->queue ); kthreads_schedule (); SYS_EXIT ( kthread_get_errno(NULL), kthread_get_syscall_retval(NULL) ); }
/*! * Send a message to a message queue * \param mqdes Queue descriptor address (user level descriptor) * \param msg_ptr Message to be sent * \param msg_len Message size * \param msg_prio Message priority * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__mq_send ( void *p ) { kthread_t *kthread; int retval; kthread = kthread_get_active (); retval = kmq_send ( p, kthread ); if ( retval == EXIT_SUCCESS ) { kthread_set_errno ( kthread, EXIT_SUCCESS ); } else { kthread_set_errno ( kthread, retval ); retval = EXIT_FAILURE; } return retval; }
/*! * Wait for thread termination * \param thread Thread descriptor (user level descriptor) * \param retval Where to store exit status of joined thread * \return 0 if thread already gone; -1 if not finished and 'wait' not set; * 'thread exit status' otherwise */ int sys__pthread_join ( void *p ) { pthread_t *thread; void **retval; kthread_t *kthread; int ret_value = 0; thread = *( (pthread_t **) p ); p += sizeof (pthread_t *); retval = *( (void ***) p ); ASSERT_ERRNO_AND_EXIT ( thread, ESRCH ); kthread = thread->ptr; if ( kthread_get_id (kthread) != thread->id ) { /* at 'kthread' is now something else */ ret_value = EXIT_FAILURE; SET_ERRNO ( ESRCH ); } else if ( kthread_is_alive (kthread) ) { ret_value = EXIT_SUCCESS; SET_ERRNO ( EXIT_SUCCESS ); kthread_set_private_param ( kthread_get_active(), retval ); kthread_wait_thread ( NULL, kthread ); kthreads_schedule (); } else { /* target thread is passive, collect status and free descr. */ ret_value = EXIT_SUCCESS; SET_ERRNO ( EXIT_SUCCESS ); kthread_collect_status ( kthread, retval ); } return ret_value; }
/*! Timer interrupt for Round Robin */ static void rr_timer ( void *p ) { kthread_t *kthread = p; kthread_sched_data_t *tsched; if ( kthread_get_active () != kthread ) { /* bug or rr thread got canceled! Let asume second :) */ return; } tsched = kthread_get_sched_param ( kthread ); /* given time is elapsed, set remainder to zero */ tsched->params.rr.remainder.sec = tsched->params.rr.remainder.nsec = 0; /* move thread to ready queue - as last in coresponding queue */ kthread_move_to_ready ( kthread, LAST ); kthreads_schedule (); }
/*! * Increment (lock) semaphore value by 1 (or unblock one thread that is blocked) * \param sem Semaphore descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__sem_post ( void *p ) { sem_t *sem; ksem_t *ksem; kobject_t *kobj; kthread_t *kthread, *released; sem = *( (sem_t **) p ); ASSERT_ERRNO_AND_EXIT ( sem, EINVAL ); kthread = kthread_get_active (); kobj = sem->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); ksem = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( ksem && ksem->id == sem->id, EINVAL ); kthread_set_errno ( kthread, EXIT_SUCCESS ); released = kthreadq_get ( &ksem->queue ); /* first to release */ if ( !released || ksem->sem_value < 0 ) { /* if initial semaphore value (set by sem_init) was negative, * semaphore will not release threads until until its value * reaches zero (small extension of POSIX semaphore) */ ksem->sem_value++; } else { kthreadq_release ( &ksem->queue ); kthreads_schedule (); } return EXIT_SUCCESS; }
/*! * Wait for thread termination * \param thread Thread descriptor (user level descriptor) * \param retval Where to store exit status of joined thread * \return 0 if thread already gone; -1 if not finished and 'wait' not set; * 'thread exit status' otherwise */ int sys__pthread_join ( pthread_t *thread, void **retval ) { kthread_t *kthread; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( thread, ESRCH ); kthread = thread->ptr; if ( kthread_get_id (kthread) != thread->id ) { /* at 'kthread' is now something else */ SYS_EXIT ( ESRCH, EXIT_FAILURE ); } else if ( kthread_is_alive (kthread) ) { kthread_set_errno ( NULL, EXIT_SUCCESS ); kthread_set_syscall_retval ( NULL, EXIT_SUCCESS ); kthread_set_private_param ( kthread_get_active(), retval ); kthread_wait_thread ( NULL, kthread ); kthreads_schedule (); SYS_EXIT ( kthread_get_errno(NULL), kthread_get_syscall_retval(NULL) ); } else { /* target thread is passive, collect status and free descr. */ kthread_collect_status ( kthread, retval ); SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS ); } }