/*! * 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 ( pthread_mutex_t *mutex ) { kpthread_mutex_t *kmutex; kobject_t *kobj; 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 ); 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 (); } SYS_EXIT ( EXIT_SUCCESS, 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 ); }
/*! * 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 ); }
/*! * 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 ); }
/*! * 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 ( sem_t *sem ) { ksem_t *ksem; kobject_t *kobj; SYS_ENTRY(); 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 ) SYS_EXIT ( EBUSY, EXIT_FAILURE ); kfree_kobject ( kobj ); sem->ptr = NULL; sem->id = 0; SYS_EXIT ( 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 ( 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) ); }
/*! * 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 ( pthread_cond_t *cond ) { kpthread_cond_t *kcond; kobject_t *kobj; SYS_ENTRY(); 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 ) SYS_EXIT ( EBUSY, EXIT_FAILURE ); kfree_kobject ( kobj ); cond->ptr = NULL; cond->id = 0; SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! * 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 ); }
/*! Set and get current thread error status */ int sys__set_errno ( int errno ) { SYS_ENTRY(); kthread_set_errno ( NULL, errno ); SYS_RETURN ( EXIT_SUCCESS ); }
/*! * 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 ); }
/*! 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 ); }
int sys__get_errno_ptr ( int **errno ) { SYS_ENTRY(); if ( errno ) { *errno = kthread_get_errno_ptr (NULL); SYS_RETURN ( EXIT_SUCCESS ); } else { SYS_RETURN ( EXIT_FAILURE ); } }
int sys__set_signal_handler (int sig_prio, void *sig_handler) { kthread_t *kthr; kthrmsg_qs *thrmsg; SYS_ENTRY(); kthr = k_get_active_thread(); thrmsg = k_get_thrmsg ( kthr ); thrmsg->signal_handler[sig_prio] = sig_handler; SYS_EXIT( SUCCESS ); }
/*! * Set current time * \param clockid Clock to use * \param time Time to set * \return status */ int sys__clock_settime ( clockid_t clockid, timespec_t *time ) { int retval; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( time && (clockid==CLOCK_REALTIME || clockid==CLOCK_MONOTONIC), EINVAL ); retval = kclock_settime ( clockid, time ); SYS_EXIT ( retval, retval ); }
static int cond_release ( pthread_cond_t *cond, int release_all ) { kpthread_cond_t *kcond; kpthread_mutex_t *kmutex; kobject_t *kobj_cond, *kobj_mutex; kthread_t *kthread; int retval = 0; SYS_ENTRY(); 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 ); } } if ( retval > -1 ) kthreads_schedule (); SYS_EXIT ( 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 ( 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; SYS_ENTRY(); 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 == SCHED_FIFO, 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); } kthreads_schedule (); SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! printf (or return) system information (and details) */ int sys__sysinfo ( char *buffer, size_t buf_size ) { /* only basic info defined in kernel/startup.c */ extern char system_info[]; SYS_ENTRY(); ASSERT_ERRNO_AND_EXIT ( buffer, EINVAL ); if ( strlen ( system_info ) > buf_size ) SYS_EXIT ( ENOMEM, EXIT_FAILURE ); strcpy ( buffer, system_info ); k_memory_info (); SYS_EXIT ( EXIT_SUCCESS, 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) ); }
/*! Create global message queue */ int sys__create_msg_queue ( msg_q *msgq, uint min_prio ) { kgmsg_q *gmsgq; SYS_ENTRY(); ASSERT_ERRNO_AND_SYS_EXIT ( msgq, E_INVALID_HANDLE ); gmsgq = kmalloc ( sizeof ( kgmsg_q ) ); ASSERT_ERRNO_AND_SYS_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 */ SYS_EXIT ( SUCCESS ); }
/*! * 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 ( sem_t *sem ) { ksem_t *ksem; kobject_t *kobj; kthread_t *kthread, *released; 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 ); 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 its value * reaches zero (small extension of POSIX semaphore) */ ksem->sem_value++; } else { kthreadq_release ( &ksem->queue ); kthreads_schedule (); } SYS_EXIT ( kthread_get_errno(NULL), kthread_get_syscall_retval(NULL) ); }
/*! * 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 (pthread_cond_t *cond, pthread_condattr_t *condattr) { kpthread_cond_t *kcond; kobject_t *kobj; SYS_ENTRY(); 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; SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! Define thread behavior towards messages and signals */ int sys__thread_msg_set (uint min_msg_prio, int min_sig_prio) { /* local variables */ kthread_t *kthr; kthrmsg_qs *thrmsg; SYS_ENTRY(); kthr = k_get_active_thread (); thrmsg = k_get_thrmsg ( kthr ); thrmsg->msgq.min_prio = min_msg_prio; thrmsg->sig_prio = min_sig_prio; //dodano int index; for (index = 0; index < HANDLER_NUM; index++) { thrmsg->signal_handler[index] = NULL; } //kraj dodavanja SYS_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 ); } }
/*! * Destroy 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_destroy ( pthread_mutex_t *mutex ) { kpthread_mutex_t *kmutex; kobject_t *kobj; 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 ); ASSERT_ERRNO_AND_EXIT ( kmutex->owner == NULL /* mutex locked! */ && kthreadq_get ( &kmutex->queue ) == NULL, ENOTEMPTY ); kmutex->ref_cnt--; /* additional cleanup here (e.g. if mutex is shared leave it) */ if ( kmutex->ref_cnt ) SYS_EXIT ( EBUSY, EXIT_FAILURE ); kfree_kobject ( kobj ); mutex->ptr = NULL; mutex->id = 0; SYS_EXIT ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! Delete global message queue */ int sys__delete_msg_queue ( msg_q *msgq ) { kgmsg_q *gmsgq; SYS_ENTRY(); ASSERT_ERRNO_AND_SYS_EXIT ( msgq, E_INVALID_HANDLE ); gmsgq = msgq->handle; ASSERT_ERRNO_AND_SYS_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; SYS_EXIT ( SUCCESS ); }
int sys__get_errno () { SYS_ENTRY(); SYS_RETURN ( kthread_get_errno (NULL) ); }
/*! Receive message from queue (global or from own thread message queue) */ int sys__msg_recv ( int src_type, void *src, msg_t *msg, int type, size_t size, uint flags ) { kthread_t *kthr; kthrmsg_qs *thrmsg; kgmsg_q *kgmsgq; kmsg_q *kmsgq; msg_q *msgq; kmsg_t *kmsg; SYS_ENTRY(); ASSERT_ERRNO_AND_SYS_EXIT ( src_type == MSG_THREAD || ( src_type == MSG_QUEUE && src ), E_INVALID_TYPE ); ASSERT_ERRNO_AND_SYS_EXIT ( msg && size > 0, E_INVALID_HANDLE ); if ( src_type == MSG_THREAD ) { kthr = k_get_active_thread (); thrmsg = k_get_thrmsg ( kthr ); kmsgq = &thrmsg->msgq; } else { /* src_type == MSG_QUEUE */ msgq = src; kgmsgq = msgq->handle; ASSERT_ERRNO_AND_SYS_EXIT ( kgmsgq && kgmsgq->id == msgq->id, E_INVALID_HANDLE ); kmsgq = &kgmsgq->mq; } /* get first message from queue */ kmsg = list_get ( &kmsgq->msgs, FIRST ); if ( type != 0 ) /* type != 0 => search for first message 'type' */ while ( kmsg && kmsg->msg.type != type ) kmsg = list_get_next ( &kmsg->list ); if ( kmsg ) /* have message */ { if ( size < kmsg->msg.size ) { msg->size = 0; SYS_EXIT ( E_TOO_BIG ); } msg->type = kmsg->msg.type; msg->size = kmsg->msg.size; memcpy ( msg->data, kmsg->msg.data, msg->size ); kmsg = list_remove ( &kmsgq->msgs, FIRST, &kmsg->list ); ASSERT ( kmsg ); kfree ( kmsg ); SYS_EXIT ( SUCCESS ); } else { /* queue empty! */ if ( !( flags & IPC_WAIT ) ) SYS_EXIT ( E_EMPTY ); //SET_ERRNO ( E_RETRY ); /* block thread */ k_enqueue_thread ( NULL, &kmsgq->thrq ); k_schedule_threads (); SYS_EXIT ( E_RETRY ); } }
/*! Send message to queue or signal to thread */ int sys__msg_post ( int dest_type, void *dest, msg_t *msg, uint flags ) { thread_t *thr; kthread_t *kthr, *new_kthr; kthrmsg_qs *thrmsg; kgmsg_q *kgmsgq; kmsg_q *kmsgq; msg_q *msgq; kmsg_t *kmsg; msg_t *cmsg; SYS_ENTRY(); ASSERT_ERRNO_AND_SYS_EXIT ( dest && msg, E_INVALID_HANDLE ); if ( dest_type == MSG_THREAD || dest_type == MSG_SIGNAL ) { thr = dest; kthr = k_get_kthread ( thr ); ASSERT_ERRNO_AND_SYS_EXIT ( kthr, E_DONT_EXIST ); thrmsg = k_get_thrmsg ( kthr ); kmsgq = &thrmsg->msgq; } else if ( dest_type == MSG_QUEUE ) { msgq = dest; kgmsgq = msgq->handle; ASSERT_ERRNO_AND_SYS_EXIT ( kgmsgq && kgmsgq->id == msgq->id, E_INVALID_HANDLE ); kmsgq = &kgmsgq->mq; } else { SYS_EXIT ( E_INVALID_TYPE ); } if ( dest_type == MSG_THREAD || dest_type == MSG_QUEUE ) { /* send message to queue */ if ( kmsgq->min_prio <= msg->type ) /* msg has required prio. */ { kmsg = kmalloc ( sizeof (kmsg_t) + msg->size ); ASSERT_ERRNO_AND_SYS_EXIT ( kmsg, E_NO_MEMORY ); kmsg->msg.type = msg->type; kmsg->msg.size = msg->size; memcpy ( kmsg->msg.data, msg->data, msg->size ); list_append ( &kmsgq->msgs, kmsg, &kmsg->list ); /* is thread waiting for message? */ if ( k_release_thread ( &kmsgq->thrq ) ) k_schedule_threads (); SYS_EXIT ( SUCCESS ); } else { /* ignore message */ SYS_EXIT ( E_IGNORED ); } } /* must be MSG_SIGNAL */ //promijenjen uvijet //ako je signal_handler postavljen, tada šalji signal if ( thrmsg->sig_prio <= msg->type && thrmsg->signal_handler[msg->type] != NULL ) { /* create thread that will service this signal */ cmsg = k_create_thread_private_storage ( kthr, sizeof (msg_t) + msg->size ); cmsg->type = msg->type; cmsg->size = msg->size; memcpy ( cmsg->data, msg->data, msg->size ); new_kthr = k_create_thread ( //koji handler??? thrmsg->signal_handler[msg->type], cmsg, pi.exit, k_get_thread_prio ( kthr ) + 1, NULL, 0, 1 ); ASSERT_ERRNO_AND_SYS_EXIT ( new_kthr, k_get_errno() ); k_set_thread_private_storage ( new_kthr, cmsg ); //SET_ERRNO ( SUCCESS ); k_schedule_threads (); SYS_EXIT ( SUCCESS ); } else { /* ignore signal */ SYS_EXIT ( E_IGNORED ); } }