/*! * Create global message queue */ int sys__create_msg_queue ( void *p ) { /* parameters on thread stack */ msg_q *msgq; uint min_prio; /* local variables */ kgmsg_q *gmsgq; msgq = *( (msg_q **) p ); p += sizeof (msg_q *); min_prio = *( (uint *) p ); ASSERT_ERRNO_AND_EXIT ( msgq, E_INVALID_HANDLE ); msgq = U2K_GET_ADR ( msgq, k_get_active_process () ); gmsgq = kmalloc ( sizeof ( kgmsg_q ) ); ASSERT_ERRNO_AND_EXIT ( gmsgq, E_NO_MEMORY ); list_init ( &gmsgq->mq.msgs ); /* list for messages */ k_threadq_init ( &gmsgq->mq.thrq ); /* list for blocked threads */ gmsgq->mq.min_prio = min_prio; msgq->id = gmsgq->id = k_new_unique_id (); msgq->handle = gmsgq; list_append ( &kmsg_qs, gmsgq, &gmsgq->all ); /* all msg.q. list */ EXIT ( SUCCESS ); }
/*! * Delete global message queue */ int sys__delete_msg_queue ( void *p ) { /* parameter on thread stack */ msg_q *msgq; /* local variables */ kgmsg_q *gmsgq; msgq = *( (msg_q **) p ); ASSERT_ERRNO_AND_EXIT ( msgq, E_INVALID_HANDLE ); msgq = U2K_GET_ADR ( msgq, k_get_active_process () ); gmsgq = msgq->handle; ASSERT_ERRNO_AND_EXIT ( gmsgq->id == msgq->id, E_INVALID_HANDLE ); k_msgq_clean ( &gmsgq->mq ); k_release_all_threads ( &gmsgq->mq.thrq ); k_free_unique_id ( gmsgq->id ); kfree ( gmsgq ); msgq->id = 0; msgq->handle = NULL; 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) ); }
/*! * Initialize semaphore object * \param sem Semaphore descriptor (user level descriptor) * \param pshared Shall semaphore object be shared between processes * \param value Initial semaphore value * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__sem_init ( sem_t *sem, int pshared, int value ) { ksem_t *ksem; kobject_t *kobj; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( sem, EINVAL ); kobj = kmalloc_kobject ( sizeof (ksem_t) ); ASSERT_ERRNO_AND_EXIT ( kobj, ENOMEM ); ksem = kobj->kobject; ksem->id = k_new_id (); ksem->sem_value = value; ksem->last_lock = NULL; ksem->flags = 0; ksem->ref_cnt = 1; kthreadq_init ( &ksem->queue ); if ( pshared ) ksem->flags |= PTHREAD_PROCESS_SHARED; sem->ptr = kobj; sem->id = ksem->id; SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! * 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 ); }
/*! * 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 ) ); }
/*! * Change scheduling parameters * \param thread User level thread descriptor * \param policy Thread scheduling policy * \param param Additional scheduling parameters (when policy != SCHED_FIFO) * \return 0 */ int sys__pthread_setschedparam ( void *p ) { pthread_t *thread; int policy; sched_param_t *param; kthread_t *kthread; thread = *( (pthread_t **) p ); p += sizeof (pthread_t *); policy = *( (int *) p ); p += sizeof (int); param = *( (sched_param_t **) p ); kthread = thread->ptr; ASSERT_ERRNO_AND_EXIT ( kthread, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kthread_get_id (kthread) == thread->id, ESRCH ); ASSERT_ERRNO_AND_EXIT ( kthread_is_alive (kthread), ESRCH ); ASSERT_ERRNO_AND_EXIT ( policy >= 0 && policy < SCHED_NUM, EINVAL ); if ( param ) { ASSERT_ERRNO_AND_EXIT ( param->sched_priority >= THREAD_MIN_PRIO && param->sched_priority <= THREAD_MAX_PRIO, EINVAL ); } return kthread_setschedparam ( kthread, policy, param ); }
/*! * Block thread (on conditional variable) and release monitor */ int sys__monitor_wait ( monitor_t *monitor, monitor_q *queue ) { kmonitor_t *kmonitor; kmonitor_q *kqueue; ASSERT_ERRNO_AND_EXIT ( monitor && monitor->ptr, E_INVALID_HANDLE ); ASSERT_ERRNO_AND_EXIT ( queue && queue->ptr, E_INVALID_HANDLE ); kmonitor = monitor->ptr; kqueue = queue->ptr; ASSERT_ERRNO_AND_EXIT ( kmonitor->owner == k_get_active_thread (), E_NOT_OWNER ); disable_interrupts (); SET_ERRNO ( SUCCESS ); k_set_thread_qdata ( NULL, kmonitor ); k_enqueue_thread ( NULL, &kqueue->queue ); kmonitor->owner = k_threadq_get ( &kmonitor->queue ); if ( !k_release_thread ( &kmonitor->queue ) ) kmonitor->lock = FALSE; k_schedule_threads (); enable_interrupts (); EXIT ( SUCCESS ); }
/*! Change thread scheduling parameters ------------------------------------- */ int kthread_setschedparam (kthread_t *kthread, int policy, sched_param_t *param) { int sched_priority; ASSERT_ERRNO_AND_EXIT ( kthread, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kthread_is_alive (kthread), ESRCH ); ASSERT_ERRNO_AND_EXIT ( policy >= 0 && policy < SCHED_NUM, EINVAL ); if ( param ) { ASSERT_ERRNO_AND_EXIT ( param->sched_priority >= THREAD_MIN_PRIO && param->sched_priority <= THREAD_MAX_PRIO, EINVAL ); if ( param->sched_priority ) sched_priority = param->sched_priority; else sched_priority = kthread->sched_priority; } else { sched_priority = kthread->sched_priority; } /* change in priority? */ if ( kthread->sched_priority != sched_priority ) kthread_set_prio ( kthread, sched_priority ); 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; }
/*! * Change scheduling parameters * \param thread User level thread descriptor * \param policy Thread scheduling policy * \param param Additional scheduling parameters (when policy != SCHED_FIFO) * \return 0 */ int sys__pthread_setschedparam ( pthread_t *thread, int policy, sched_param_t *param ) { kthread_t *kthread; int retval; SYS_ENTRY(); kthread = thread->ptr; ASSERT_ERRNO_AND_EXIT ( kthread, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kthread_get_id (kthread) == thread->id, ESRCH ); ASSERT_ERRNO_AND_EXIT ( kthread_is_alive (kthread), ESRCH ); ASSERT_ERRNO_AND_EXIT ( policy == SCHED_FIFO, ENOTSUP ); if ( param ) { ASSERT_ERRNO_AND_EXIT ( param->sched_priority >= THREAD_MIN_PRIO && param->sched_priority <= THREAD_MAX_PRIO, EINVAL ); } retval = kthread_setschedparam ( kthread, policy, param ); if ( retval == EXIT_SUCCESS ) SYS_EXIT ( EXIT_SUCCESS, retval ); else SYS_EXIT ( retval, EXIT_FAILURE ); }
/*! * Destroy semaphore object * \param sem Semaphore descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__sem_destroy ( void *p ) { sem_t *sem; ksem_t *ksem; kobject_t *kobj; sem = *( (sem_t **) p ); ASSERT_ERRNO_AND_EXIT ( sem, EINVAL ); 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 ); ASSERT_ERRNO_AND_EXIT (kthreadq_get (&ksem->queue) == NULL, ENOTEMPTY); ksem->ref_cnt--; /* additional cleanup here (e.g. if semaphore is shared leave it) */ if ( ksem->ref_cnt ) EXIT2 ( EBUSY, EXIT_FAILURE ); kfree_kobject ( kobj ); sem->ptr = NULL; sem->id = 0; EXIT2 ( EXIT_SUCCESS, 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 ( 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; }
/*! * 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 ); }
/*! * Initialize semaphore object * \param sem Semaphore descriptor (user level descriptor) * \param pshared Shall semaphore object be shared between processes * \param value Initial semaphore value * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__sem_init ( void *p ) { sem_t *sem; int pshared; int value; ksem_t *ksem; kobject_t *kobj; sem = *( (sem_t **) p ); p += sizeof (sem_t *); pshared = *( (int *) p ); p += sizeof (int); value = *( (uint *) p ); ASSERT_ERRNO_AND_EXIT ( sem, EINVAL ); kobj = kmalloc_kobject ( sizeof (ksem_t) ); ASSERT_ERRNO_AND_EXIT ( kobj, ENOMEM ); ksem = kobj->kobject; ksem->id = k_new_id (); ksem->sem_value = value; ksem->last_lock = NULL; ksem->flags = 0; ksem->ref_cnt = 1; kthreadq_init ( &ksem->queue ); if ( pshared ) ksem->flags |= PTHREAD_PROCESS_SHARED; sem->ptr = kobj; sem->id = ksem->id; EXIT2 ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! * Destroy conditional variable object * \param cond conditional variable descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_cond_destroy ( void *p ) { pthread_cond_t *cond; kpthread_cond_t *kcond; kobject_t *kobj; cond = *( (pthread_cond_t **) p ); ASSERT_ERRNO_AND_EXIT ( cond, EINVAL ); kobj = cond->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); kcond = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( kcond && kcond->id == cond->id, EINVAL ); kcond->ref_cnt--; /* additional cleanup here (e.g. if cond.var. is shared leave it) */ if ( kcond->ref_cnt ) EXIT2 ( EBUSY, EXIT_FAILURE ); kfree_kobject ( kobj ); cond->ptr = NULL; cond->id = 0; EXIT2 ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! * 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; }
/*! * Initialize mutex object * \param mutex Mutex descriptor (user level descriptor) * \param mutexattr Mutex parameters * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_mutex_init ( void *p ) { pthread_mutex_t *mutex; /* pthread_mutexattr_t *mutexattr; not implemented */ kpthread_mutex_t *kmutex; kobject_t *kobj; mutex = *( (pthread_mutex_t **) p ); /* p += sizeof (pthread_mutex_t *); mutexattr = *( (pthread_mutexattr_t *) p ); */ ASSERT_ERRNO_AND_EXIT ( mutex, EINVAL ); kobj = kmalloc_kobject ( sizeof (kpthread_mutex_t) ); ASSERT_ERRNO_AND_EXIT ( kobj, ENOMEM ); kmutex = kobj->kobject; kmutex->id = k_new_id (); kmutex->owner = NULL; kmutex->flags = 0; kmutex->ref_cnt = 1; kthreadq_init ( &kmutex->queue ); mutex->ptr = kobj; mutex->id = kmutex->id; EXIT2 ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! * Initialize mutex object * \param mutex Mutex descriptor (user level descriptor) * \param mutexattr Mutex parameters * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_mutex_init ( pthread_mutex_t *mutex, pthread_mutexattr_t *mutexattr ) { kpthread_mutex_t *kmutex; kobject_t *kobj; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( mutex, EINVAL ); kobj = kmalloc_kobject ( sizeof (kpthread_mutex_t) ); ASSERT_ERRNO_AND_EXIT ( kobj, ENOMEM ); kmutex = kobj->kobject; kmutex->id = k_new_id (); kmutex->owner = NULL; kmutex->flags = 0; kmutex->ref_cnt = 1; kthreadq_init ( &kmutex->queue ); mutex->ptr = kobj; mutex->id = kmutex->id; SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! * Get timer expiration time * \param timerid Timer descriptor (user descriptor) * \param value Where to store time to next timer expiration (+period) * \return status 0 for success */ int sys__timer_gettime ( void *p ) { timer_t *timerid; itimerspec_t *value; ktimer_t *ktimer; int retval; kobject_t *kobj; timerid = *( (timer_t **) p ); p += sizeof (timer_t *); value = *( (itimerspec_t **) p ); ASSERT_ERRNO_AND_EXIT ( timerid, EINVAL ); kobj = timerid->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); ktimer = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( ktimer && ktimer->id == timerid->id, EINVAL ); retval = ktimer_gettime ( ktimer, value ); EXIT ( retval ); }
/*! * Delete timer * \param timerid Timer descriptor (user descriptor) * \return status 0 for success */ int sys__timer_delete ( void *p ) { timer_t *timerid; ktimer_t *ktimer; int retval; kobject_t *kobj; timerid = *( (timer_t **) p ); ASSERT_ERRNO_AND_EXIT ( timerid, EINVAL ); kobj = timerid->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EINVAL ); ktimer = kobj->kobject; ASSERT_ERRNO_AND_EXIT ( ktimer && ktimer->id == timerid->id, EINVAL ); retval = ktimer_delete ( ktimer ); kfree_kobject ( kobj ); EXIT ( retval ); }
/*! * Unlock monitor (or block trying) */ int sys__monitor_unlock ( monitor_t *monitor ) { kmonitor_t *kmonitor; ASSERT_ERRNO_AND_EXIT ( monitor && monitor->ptr, E_INVALID_HANDLE ); kmonitor = monitor->ptr; ASSERT_ERRNO_AND_EXIT ( kmonitor->owner == k_get_active_thread (), E_NOT_OWNER ); disable_interrupts (); SET_ERRNO ( SUCCESS ); kmonitor->owner = k_threadq_get ( &kmonitor->queue ); if ( !k_release_thread ( &kmonitor->queue ) ) kmonitor->lock = FALSE; else k_schedule_threads (); enable_interrupts (); EXIT ( SUCCESS ); }
/*! * Initialize conditional variable object * \param cond conditional variable descriptor (user level descriptor) * \param condattr conditional variable descriptor (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__pthread_cond_init ( void *p ) { pthread_cond_t *cond; /* pthread_condattr_t *condattr; not implemented */ kpthread_cond_t *kcond; kobject_t *kobj; cond = *( (pthread_cond_t **) p ); /* p += sizeof (pthread_cond_t *); condattr = *( (pthread_condattr_t *) p ); */ ASSERT_ERRNO_AND_EXIT ( cond, EINVAL ); kobj = kmalloc_kobject ( sizeof (kpthread_cond_t) ); ASSERT_ERRNO_AND_EXIT ( kobj, ENOMEM ); kcond = kobj->kobject; kcond->id = k_new_id (); kcond->flags = 0; kcond->ref_cnt = 1; kthreadq_init ( &kcond->queue ); cond->ptr = kobj; cond->id = kcond->id; EXIT2 ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! * Create new thread (params on user stack!) * \param thread User level thread descriptor * \param attr Thread attributes * \param start_routine Starting function for new thread * \param arg Parameter sent to starting function * (parameters are on calling thread stack) */ int sys__pthread_create ( void *p ) { pthread_t *thread; pthread_attr_t *attr; void *(*start_routine) (void *); void *arg; kthread_t *kthread; uint flags = 0; int sched_policy = SCHED_FIFO; int sched_priority = THREAD_DEF_PRIO; void *stackaddr = NULL; size_t stacksize = 0; thread = *( (pthread_t **) p ); p += sizeof (pthread_t *); attr = *( (pthread_attr_t **) p ); p += sizeof (pthread_attr_t *); start_routine = *( (void **) p ); p += sizeof (void *); arg = *( (void **) p ); if ( attr ) { flags = attr->flags; sched_policy = attr->sched_policy; sched_priority = attr->sched_params.sched_priority; stackaddr = attr->stackaddr; stacksize = attr->stacksize; ASSERT_ERRNO_AND_EXIT ( sched_policy >= 0 && sched_policy < SCHED_NUM, ENOTSUP ); ASSERT_ERRNO_AND_EXIT ( sched_priority >= THREAD_MIN_PRIO && sched_priority <= THREAD_MAX_PRIO, ENOMEM ); /* if ( flags & SOMETHING ) change attributes ... */ } kthread = kthread_create ( start_routine, arg, flags, sched_policy, sched_priority, stackaddr, stacksize ); ASSERT_ERRNO_AND_EXIT ( kthread, ENOMEM ); if ( thread ) { thread->ptr = kthread; thread->id = kthread_get_id (kthread); } SET_ERRNO ( EXIT_SUCCESS ); kthreads_schedule (); return EXIT_SUCCESS; }
/*! * Close a message queue * \param mqdes Queue descriptor address (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__mq_close ( void *p ) { mqd_t *mqdes; kmq_queue_t *kq_queue; kobject_t *kobj; kmq_msg_t *kmq_msg; kthread_t *kthread; mqdes = *( (mqd_t **) p ); ASSERT_ERRNO_AND_EXIT ( mqdes, EBADF ); kobj = mqdes->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EBADF ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EBADF ); kq_queue = kobj->kobject; kq_queue = list_find_and_remove ( &kmq_queue, &kq_queue->list ); if ( !kq_queue || kq_queue->id != mqdes->id ) EXIT2 ( EBADF, EXIT_FAILURE ); kq_queue->ref_cnt--; if ( !kq_queue->ref_cnt ) { /* remove messages */ while( (kmq_msg = list_remove(&kq_queue->msg_list,FIRST,NULL)) ) kfree (kmq_msg); /* remove blocked threads */ while ( (kthread = kthreadq_remove (&kq_queue->send_q, NULL)) ) { kthread_move_to_ready ( kthread, LAST ); kthread_set_errno ( kthread, EBADF ); kthread_set_syscall_retval ( kthread, EXIT_FAILURE ); } while ( (kthread = kthreadq_remove (&kq_queue->recv_q, NULL)) ) { kthread_move_to_ready ( kthread, LAST ); kthread_set_errno ( kthread, EBADF ); kthread_set_syscall_retval ( kthread, EXIT_FAILURE ); } list_remove ( &kmq_queue, 0, &kq_queue->list ); k_free_id ( kq_queue->id ); kfree ( kq_queue->name ); kfree ( kq_queue ); } /* remove kernel object descriptor */ kfree_kobject ( kobj ); EXIT2 ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! * 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 */ }
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 ); }
/*! * Retrieve parameters for existing alarm (get its values) * \param alarm Pointer where alarm parameters will be stored * \return status (0 for success) */ int sys__alarm_get ( void *id, alarm_t *alarm ) { kalarm_t *kalarm; ASSERT_ERRNO_AND_EXIT ( id && alarm, E_INVALID_HANDLE ); kalarm = id; ASSERT_ERRNO_AND_EXIT ( kalarm && kalarm->magic == ALARM_MAGIC, E_INVALID_HANDLE ); *alarm = kalarm->alarm; EXIT ( SUCCESS ); }
/*! * Lock monitor (or block trying) */ int sys__monitor_lock ( monitor_t *monitor ) { kmonitor_t *kmonitor; ASSERT_ERRNO_AND_EXIT ( monitor && monitor->ptr, E_INVALID_HANDLE ); disable_interrupts (); kmonitor = monitor->ptr; SET_ERRNO ( SUCCESS ); if ( !kmonitor->lock ) { kmonitor->lock = TRUE; kmonitor->owner = k_get_active_thread (); } else { k_enqueue_thread ( NULL, &kmonitor->queue ); k_schedule_threads (); } enable_interrupts (); EXIT ( SUCCESS ); }