/*! * 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 ); }
/*! * 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 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 ); }
/*! * 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 ); }
/*! * 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 ); }
/*! * Create new thread * \param start_routine Starting function for new thread * \param arg Parameter sent to starting function * \param sched_policy Thread scheduling policy * \param sched_priority Thread priority * \param stackaddr Address of thread stack (if not NULL) * \param stacksize Stack size * \param proc Process descriptor thread belongs to * \return Pointer to descriptor of created kernel thread */ kthread_t *kthread_create ( void *start_routine, void *arg, uint flags, int sched_policy, int sched_priority, sched_supp_t *sched_param, void *stackaddr, size_t stacksize, kprocess_t *proc ) { ASSERT ( proc ); kthread_t *kthread; /* thread descriptor */ kthread = kmalloc ( sizeof (kthread_t) ); ASSERT ( kthread ); /* initialize thread descriptor */ kthread->id = k_new_id (); kthread->proc = proc; kthread->proc->thread_count++; kthread->queue = NULL; kthreadq_init ( &kthread->join_queue ); kthread_create_new_state ( kthread, start_routine, arg, stackaddr, stacksize, FALSE ); kthread->state.flags = flags; list_init ( &kthread->states ); /* connect signal mask in descriptor with state */ kthread->sig_handling.mask = &kthread->state.sigmask; ksignal_thread_init ( kthread ); list_append ( &all_threads, kthread, &kthread->all ); kthread->sched_policy = sched_policy; if ( sched_priority < 0 ) sched_priority = 0; if ( sched_priority >= PRIO_LEVELS ) sched_priority = PRIO_LEVELS - 1; kthread->sched_priority = sched_priority; kthread->ref_cnt = 1; kthread_move_to_ready ( kthread, LAST ); ksched2_thread_add (kthread, sched_policy, sched_priority, sched_param); return kthread; }
/*! * Create new timer * \param clockid Clock used in timer * \param evp Timer expiration action * \param ktimer Timer descriptor address is returned here * \param owner Timer owner: thread descriptor or NULL if kernel timer * \return status 0 for success */ int ktimer_create ( clockid_t clockid, sigevent_t *evp, ktimer_t **_ktimer, void *owner ) { ktimer_t *ktimer; ASSERT ( clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC ); ASSERT ( evp && _ktimer ); /* add other checks on evp if required */ ktimer = kmalloc ( sizeof (ktimer_t) ); ASSERT ( ktimer ); ktimer->id = k_new_id (); ktimer->clockid = clockid; ktimer->evp = *evp; ktimer->owner = owner; TIMER_DISARM ( ktimer ); ktimer->param = NULL; *_ktimer = ktimer; return 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 (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 ); }
/*! * Open a message queue * \param name Queue name * \param oflag Opening flags * \param mode Permissions on created queue (only when O_CREAT is set) * \param attr Message queue attributes (only when O_CREAT is set) * \param mqdes Return queue descriptor address (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__mq_open ( void *p ) { char *name; int oflag; /* mode_t mode; not used in this implementation */ mq_attr_t *attr; mqd_t *mqdes; kmq_queue_t *kq_queue; kobject_t *kobj; name = *( (char **) p ); p += sizeof (char *); oflag = *( (int *) p ); p += sizeof (int); /* mode = *( (mode_t *) p ); */ p += sizeof (mode_t); attr = *( (mq_attr_t **) p ); p += sizeof (mq_attr_t*); mqdes = *( (mqd_t **) p ); ASSERT_ERRNO_AND_EXIT ( name && mqdes, EBADF ); ASSERT_ERRNO_AND_EXIT ( strlen (name) < NAME_MAX, EBADF ); kq_queue = list_get ( &kmq_queue, FIRST ); while ( kq_queue && strcmp ( name, kq_queue->name ) ) kq_queue = list_get_next ( &kq_queue->list ); if ( ( kq_queue && ( (oflag & O_CREAT) || (oflag & O_EXCL) ) ) || ( !kq_queue && !(oflag & O_CREAT ) ) ) { mqdes->ptr = (void *) -1; mqdes->id = -1; EXIT2 ( EEXIST, EXIT_FAILURE ); } if ( !kq_queue && (oflag & O_CREAT) ) { kq_queue = kmalloc ( sizeof (kmq_queue_t) ); if ( attr ) kq_queue->attr = *attr; kq_queue->id = k_new_id (); kq_queue->attr.mq_curmsgs = 0; kq_queue->name = kmalloc ( strlen (name) + 1 ); strcpy ( kq_queue->name, name ); kq_queue->ref_cnt = 0; list_init ( &kq_queue->msg_list ); kthreadq_init ( &kq_queue->recv_q ); kthreadq_init ( &kq_queue->send_q ); list_append ( &kmq_queue, kq_queue, &kq_queue->list ); } kq_queue->ref_cnt++; kobj = kmalloc_kobject ( 0 ); kobj->kobject = kq_queue; kobj->flags = oflag; mqdes->ptr = kobj; mqdes->id = kq_queue->id; EXIT2 ( EXIT_SUCCESS, EXIT_SUCCESS ); }