/*! initialize thread structures and create idle thread */ void k_threads_init () { extern kdevice_t *u_stdin, *u_stdout; kthread_t *kthr; int prio; list_init ( &all_threads ); /* queue for ready threads is empty */ init_ready_list (); /* setup programs */ pi.stdin = u_stdin; pi.stdout = u_stdout; pi.heap = kmalloc ( PROG_HEAP_SIZE ); pi.heap_size = PROG_HEAP_SIZE; prio = pi.prio; if ( !prio ) prio = THR_DEFAULT_PRIO; /* idle thread */ kthr = k_create_thread ( idle_thread, NULL, NULL, 0, NULL, 0, 1 ); /* first "user" thread */ k_create_thread (pi.init, NULL, pi.exit, prio, NULL, 0, 1 ); active_thread = NULL; k_schedule_threads (); }
/*! * End current thread (exit from it) * \param status Exit status number */ int sys__thread_exit ( void *p ) { int status; status = *( (int *) p ); active_thread->state = THR_STATE_PASSIVE; active_thread->ref_cnt--; active_thread->exit_status = status; #ifdef MESSAGES k_msgq_clean ( &active_thread->msg.msgq ); #endif /* release thread stack */ if ( active_thread->stack ) kfree ( active_thread->stack ); k_delete_thread_private_storage ( active_thread, active_thread->private_storage ); if ( !active_thread->ref_cnt ) { k_remove_thread_descriptor ( active_thread ); active_thread = NULL; } else { k_release_all_threads ( &active_thread->join_queue ); } k_schedule_threads (); return 0; }
/*! * 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 ); }
/*! * 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 ); }
/* Add alarm to alarm pool if its expiration time is defined If expiration time is in the past, alarm will be immediately activated! */ static void k_alarm_add ( kalarm_t *kalarm ) { int reschedule = 0; /* if exp_time is given (>0) add it into active alarms */ if ( kalarm->alarm.exp_time.sec + kalarm->alarm.exp_time.nsec > 0 ) { kalarm->active = 1; list_sort_add ( &kalarms, kalarm, &kalarm->list, alarm_cmp ); } else { kalarm->active = 0; } reschedule = k_schedule_alarms (); /* this or other alarm may expire */ SET_ERRNO ( SUCCESS ); /* block thread? */ if ( kalarm->active && ( kalarm->alarm.flags & IPC_WAIT ) ) { k_enqueue_thread ( NULL, &kalarm->queue ); reschedule = 1; } if ( reschedule ) k_schedule_threads (); }
/*! * Delete alarm * \param param Alarm * \returns status (0 for success) */ int k_alarm_remove ( void *id ) { kalarm_t *kalarm; int reschedule = 0; kalarm = id; ASSERT ( kalarm && kalarm->magic == ALARM_MAGIC ); /* remove from active alarms (if it was there) */ if ( kalarm->active ) list_remove ( &kalarms, FIRST, &kalarm->list ); #ifdef DEBUG kalarm->magic = 0; #endif SET_ERRNO ( SUCCESS ); /* release all waiting threads, if any */ reschedule = k_release_all_threads ( &kalarm->queue ); kfree ( kalarm ); reschedule += k_schedule_alarms (); if ( reschedule ) k_schedule_threads (); RETURN ( SUCCESS ); }
/*! * Create new thread (params on user stack!) * \param func Starting function * \param param Parameter for starting function * \param prio Priority for new thread * \param thr_desc User level thread descriptor * (parameters are on calling thread stack) */ int sys__create_thread ( void *p ) { void *func; void *param; int prio; thread_t *thr_desc; kthread_t *kthr; func = *( (void **) p ); p += sizeof (void *); param = *( (void **) p ); p += sizeof (void *); prio = *( (int *) p ); p += sizeof (int); kthr = k_create_thread (func, param, active_thread->proc->pi->exit, prio, NULL, 0, 1, active_thread->proc ); ASSERT_ERRNO_AND_EXIT ( kthr, E_NO_MEMORY ); thr_desc = *( (void **) p ); if ( thr_desc ) { thr_desc = U2K_GET_ADR ( thr_desc, active_thread->proc ); thr_desc->thread = kthr; thr_desc->thr_id = kthr->id; } SET_ERRNO ( SUCCESS ); k_schedule_threads (); RETURN ( SUCCESS ); }
/*! * 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 ); }
/*! * Create new thread * \param func Starting function * \param param Parameter for starting function * \param prio Priority for new thread * \param thr_desc User level thread descriptor * (parameters are on calling thread stack) */ int sys__create_thread ( void *p ) { void *func; void *param; int prio; thread_t *thr_desc; kthread_t *kthr; func = *( (void **) p ); p += sizeof (void *); param = *( (void **) p ); p += sizeof (void *); prio = *( (int *) p ); p += sizeof (int); kthr = k_create_thread ( func, param, pi.exit, prio, NULL, 0, 1 ); thr_desc = *( (void **) p ); if ( thr_desc ) { thr_desc->thread = kthr; thr_desc->thr_id = kthr->id; } SET_ERRNO ( SUCCESS ); k_schedule_threads (); RETURN ( SUCCESS ); }
/*! Unlock device */ int k_device_unlock ( kdevice_t *dev ) { if ( k_release_thread ( &dev->thrq ) ) k_schedule_threads (); else dev->locked = FALSE; return 0; }
/*! * Wait for thread termination * \param thread Thread descriptor (user level descriptor) * \param wait Wait if thread not finished (!=0) or not (0)? * \return 0 if thread already gone; -1 if not finished and 'wait' not set; * 'thread exit status' otherwise */ int sys__wait_for_thread ( void *p ) { thread_t *thread; int wait; kthread_t *kthr; int ret_value = 0; thread = U2K_GET_ADR ( *( (void **) p ), active_thread->proc ); p += sizeof (void *); wait = *( (int *) p ); ASSERT_ERRNO_AND_EXIT ( thread && thread->thread, E_INVALID_HANDLE ); kthr = thread->thread; if ( kthr->id != thread->thr_id ) /* at 'kthr' is now something else */ { ret_value = -SUCCESS; SET_ERRNO ( SUCCESS ); } else if ( kthr->state != THR_STATE_PASSIVE && !wait ) { ret_value = -E_NOT_FINISHED; SET_ERRNO ( E_NOT_FINISHED ); } else if ( kthr->state != THR_STATE_PASSIVE ) { kthr->ref_cnt++; ret_value = -E_RETRY; /* retry (collect thread status) */ SET_ERRNO ( E_RETRY ); k_enqueue_thread ( NULL, &kthr->join_queue ); k_schedule_threads (); } else { /* kthr->state == THR_STATE_PASSIVE, but thread descriptor still not freed - some thread still must collect its status */ SET_ERRNO ( SUCCESS ); ret_value = kthr->exit_status; kthr->ref_cnt--; if ( !kthr->ref_cnt ) k_remove_thread_descriptor ( kthr ); } return ret_value; }
/*! * End current thread (exit from it) * \param status Exit status number */ int sys__thread_exit ( void *p ) { int status; status = *( (int *) p ); active_thread->state = THR_STATE_PASSIVE; active_thread->ref_cnt--; active_thread->exit_status = status; active_thread->proc->thr_count--; #ifdef MESSAGES k_msgq_clean ( &active_thread->msg.msgq ); #endif /* release thread stack */ if ( active_thread->stack ) { if ( active_thread->proc->m.start ) /* user level thread */ ffs_free ( active_thread->proc->stack_pool, active_thread->stack ); else /* kernel level thread */ kfree ( active_thread->stack ); } k_delete_thread_private_storage ( active_thread, active_thread->private_storage ); if ( active_thread->proc->thr_count == 0 && active_thread->proc->pi ) { /* last (non-kernel) thread - remove process */ ASSERT ( list_remove ( &procs, FIRST, &active_thread->proc->all ) ); active_thread->proc->prog->started = FALSE; kfree ( active_thread->proc ); } if ( !active_thread->ref_cnt ) { k_remove_thread_descriptor ( active_thread ); active_thread = NULL; } else { k_release_all_threads ( &active_thread->join_queue ); } k_schedule_threads (); return 0; }
/*! Lock device */ int k_device_lock ( kdevice_t *dev, int wait ) { if ( !wait && dev->locked ) return -1; if ( dev->locked ) { k_enqueue_thread ( NULL, &dev->thrq ); k_schedule_threads (); } dev->locked = TRUE; return 0; }
/*! Release first or all threads from monitor queue (cond.var.) */ static int k_monitor_release ( monitor_q *queue, int broadcast ) { kmonitor_q *kqueue; kthread_t *kthr; kmonitor_t *kmonitor; int reschedule = 0; ASSERT_ERRNO_AND_EXIT ( queue && queue->ptr, E_INVALID_HANDLE ); disable_interrupts (); kqueue = queue->ptr; do { kthr = k_threadq_get ( &kqueue->queue ); /* first from queue */ if ( !kthr ) break; kmonitor = k_get_thread_qdata ( kthr ); if ( !kmonitor->lock ) /* monitor not locked? */ { /* unblocked thread becomes monitor owner */ kmonitor->lock = TRUE; kmonitor->owner = kthr; k_release_thread ( &kqueue->queue );/*to ready threads*/ reschedule++; } else { /* move thread from monitor queue (cond.var.) to monitor entrance queue */ kthr = k_threadq_remove ( &kqueue->queue, NULL ); k_enqueue_thread ( kthr, &kmonitor->queue ); } } while ( kthr && broadcast ); SET_ERRNO ( SUCCESS ); if ( reschedule ) k_schedule_threads (); enable_interrupts (); EXIT ( SUCCESS ); }
/*! * Destroy monitor (and unblock all threads blocked on it) */ int sys__monitor_queue_destroy ( monitor_q *queue ) { kmonitor_q *kqueue; ASSERT_ERRNO_AND_EXIT ( queue && queue->ptr, E_INVALID_HANDLE ); disable_interrupts (); kqueue = queue->ptr; if ( k_release_all_threads ( &kqueue->queue ) ) k_schedule_threads (); kfree ( kqueue ); queue->ptr = NULL; enable_interrupts (); EXIT ( SUCCESS ); }
/*! * Destroy monitor (and unblock all threads blocked on it) */ int sys__monitor_destroy ( monitor_t *monitor ) { kmonitor_t *kmonitor; ASSERT_ERRNO_AND_EXIT ( monitor && monitor->ptr, E_INVALID_HANDLE ); disable_interrupts (); kmonitor = monitor->ptr; if ( k_release_all_threads ( &kmonitor->queue ) ) k_schedule_threads (); kfree ( kmonitor ); monitor->ptr = NULL; enable_interrupts (); EXIT ( SUCCESS ); }
/*! initialize thread structures and create idle thread */ void k_threads_init () { kthread_t *kthr; list_init ( &all_threads ); list_init ( &procs ); /* queue for ready threads is empty */ init_ready_list (); /* initially create 'idle thread' */ kernel_proc.prog = NULL; kernel_proc.stack_pool = NULL; kernel_proc.m.start = NULL; kernel_proc.m.size = (size_t) 0xffffffff; kthr = k_create_thread ( idle_thread, NULL, NULL, 0, NULL, 0, 1, &kernel_proc ); active_thread = NULL; k_schedule_threads (); }
//int sys__wait_for_alarm ( void *alarm, int wait ) int sys__wait_for_alarm ( void *p ) { void *id; int wait; kalarm_t *kalarm; int retval; id = *( (void **) p ); ASSERT_ERRNO_AND_EXIT ( id, E_INVALID_HANDLE ); p += sizeof (void *); wait = *( (int *) p ); kalarm = id; ASSERT_ERRNO_AND_EXIT ( kalarm && kalarm->magic == ALARM_MAGIC, E_INVALID_HANDLE ); retval = 0; SET_ERRNO ( SUCCESS ); if ( kalarm->active ) { if ( wait & IPC_WAIT ) { k_enqueue_thread ( NULL, &kalarm->queue ); k_schedule_threads (); } else { SET_ERRNO ( E_NOT_EXPIRED ); retval = -E_NOT_EXPIRED; } } return retval; }
/*! 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 ); } }
/*! * Start program defined by 'prog' (loaded as module) as new process: * - initialize environment (stack area for threads, stdin, stdout) and start * it's first thread * \param prog_name Program name (as given with module) * \param param Command line arguments for starting thread (if not NULL) * \param prio Priority for starting thread * \return Pointer to descriptor of created process */ kthread_t *k_proc_start ( char *prog_name, void *param, int prio ) { extern kdevice_t *u_stdin, *u_stdout; extern list_t progs; kprog_t *prog; kprocess_t *proc; kthread_t *kthr; char **args = NULL, *arg, *karg, **kargs; size_t argsize; int i; prog = list_get ( &progs, FIRST ); while ( prog && strcmp ( prog->prog_name, prog_name ) ) prog = list_get_next ( &prog->all ); if ( !prog ) return NULL; if ( prog->started ) return NULL; /* create new process */ proc = kmalloc ( sizeof ( kprocess_t) ); ASSERT ( proc ); proc->prog = prog; proc->m.size = prog->m.size; proc->m.start = proc->pi = prog->pi; proc->pi->stdin = u_stdin; proc->pi->stdout = u_stdout; /* initialize memory pool for threads stacks */ proc->stack_pool = ffs_init ( U2K_GET_ADR ( proc->pi->stack, proc ), prog->pi->stack_size ); proc->thr_count = 0; if ( !prio ) prio = proc->pi->prio; if ( !prio ) prio = THR_DEFAULT_PRIO; if ( param ) /* have arguments? */ { /* copy command line arguments from kernel space to process; (use process stack space for arguments) */ kargs = param; for ( i = 0; kargs[i]; i++ ) ; argsize = ( (size_t) kargs[i-1] + strlen( kargs[i-1] ) + 1 ) - (size_t) param; if ( argsize > 0 ) { args = ffs_alloc ( proc->stack_pool, argsize ); arg = (void *) args + (i + 1) * sizeof (void *); kargs = param; i = 0; do { karg = kargs[i]; strcpy ( arg, karg ); args[i++] = K2U_GET_ADR ( arg, proc ); arg += strlen ( arg ) + 1; } while ( kargs[i] ); args[i] = NULL; args = K2U_GET_ADR ( args, proc ); } kfree ( param ); } kthr = k_create_thread ( proc->pi->init, args, NULL, prio, NULL, 0, 1, proc ); list_append ( &procs, proc, &proc->all ); prog->started = 1; k_schedule_threads (); return kthr; }
/*! * Called from interrupt handler when an alarm has expired */ static void k_timer_interrupt () { if ( k_schedule_alarms () ) k_schedule_threads (); }
/*! * Receive message from queue (global or from own thread message queue) */ int sys__msg_recv ( void *p ) { /* parameters on thread stack */ int src_type; /* MSG_QUEUE or MSG_THREAD */ void *src; /* (msg_q *) or (thread_t *) */ msg_t *msg; /* { type, size, data[0..size-1] } */ int type; /* message type (identifier) */ size_t size; /* size of 'data' member */ uint flags; /* local variables */ kthread_t *kthr; kthrmsg_qs *thrmsg; kgmsg_q *kgmsgq; kmsg_q *kmsgq; msg_q *msgq; kmsg_t *kmsg; src_type = *( (int *) p ); p += sizeof (int); src = *( (void **) p ); p += sizeof (void *); msg = *( (msg_t **) p ); p += sizeof (msg_t *); type = *( (int *) p ); p += sizeof (int); size = *( (size_t *) p ); p += sizeof (size_t); flags = *( (uint *) p ); ASSERT_ERRNO_AND_EXIT ( src && msg, E_INVALID_HANDLE ); src = U2K_GET_ADR ( src, k_get_active_process () ); msg = U2K_GET_ADR ( msg, k_get_active_process () ); ASSERT_ERRNO_AND_EXIT ( src_type == MSG_THREAD || src_type == MSG_QUEUE, E_INVALID_TYPE ); 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_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; 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 ); EXIT ( SUCCESS ); } else { /* queue empty! */ if ( !( flags & IPC_WAIT ) ) EXIT ( E_EMPTY ); SET_ERRNO ( E_RETRY ); /* block thread */ k_enqueue_thread ( NULL, &kmsgq->thrq ); k_schedule_threads (); RETURN ( E_RETRY ); } }
/*! * Send message to queue or signal to thread */ int sys__msg_post ( void *p ) { /* parameters on thread stack */ int dest_type; /* MSG_QUEUE, MSG_THREAD or MSG_SIGNAL */ void *dest; /* (msg_q *) or (thread_t *) */ msg_t *msg; /* { type, size, data[0..size-1] } */ uint flags; /* local variables */ 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; kprocess_t *proc; dest_type = *( (int *) p ); p += sizeof (int); dest = *( (void **) p ); p += sizeof (void *); msg = *( (msg_t **) p ); p += sizeof (msg_t *); flags = *( (uint *) p ); ASSERT_ERRNO_AND_EXIT ( dest && msg, E_INVALID_HANDLE ); dest = U2K_GET_ADR ( dest, k_get_active_process () ); msg = U2K_GET_ADR ( msg, k_get_active_process () ); if ( dest_type == MSG_THREAD || dest_type == MSG_SIGNAL ) { thr = dest; kthr = k_get_kthread ( thr ); ASSERT_ERRNO_AND_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_EXIT ( kgmsgq && kgmsgq->id == msgq->id, E_INVALID_HANDLE ); kmsgq = &kgmsgq->mq; } else { 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_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 (); EXIT ( SUCCESS ); } else { /* ignore message */ EXIT ( E_IGNORED ); } } /* must be MSG_SIGNAL */ if ( thrmsg->sig_prio <= msg->type ) { /* 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 ); proc = k_get_thread_process ( kthr ); new_kthr = k_create_thread ( thrmsg->signal_handler, K2U_GET_ADR ( cmsg, proc ), proc->pi->exit, k_get_thread_prio ( kthr ) + 1, NULL, 0, 1, proc ); ASSERT_ERRNO_AND_EXIT ( new_kthr, k_get_errno() ); k_set_thread_private_storage ( new_kthr, cmsg ); SET_ERRNO ( SUCCESS ); k_schedule_threads (); RETURN ( SUCCESS ); } else { /* ignore signal */ EXIT ( E_IGNORED ); } }
/*! 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 ); } }