/** * This function will initialize an object and add it to object system management. * * @param object the specified object to be initialized. * @param type the object type. * @param name the object name. In system, the object's name must be unique. */ void rt_object_init(struct rt_object *object, enum rt_object_class_type type, const char *name) { register rt_base_t temp; struct rt_object_information *information; #ifdef RT_USING_MODULE /* get module object information */ information = (rt_module_self() != RT_NULL) ? &rt_module_self()->module_object[type] : &rt_object_container[type]; #else /* get object information */ information = &rt_object_container[type]; #endif /* initialize object's parameters */ /* set object type to static */ object->type = type | RT_Object_Class_Static; /* copy name */ rt_strncpy(object->name, name, RT_NAME_MAX); RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object)); /* lock interrupt */ temp = rt_hw_interrupt_disable(); /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); /* unlock interrupt */ rt_hw_interrupt_enable(temp); }
/** * This function will delete a thread. The thread object will be removed from * thread queue and detached/deleted from system object management. * * @param thread the thread to be deleted * * @return the operation status, RT_EOK on OK, -RT_ERROR on error * */ rt_err_t rt_thread_delete(rt_thread_t thread) { rt_base_t lock; /* thread check */ RT_ASSERT(thread != RT_NULL); /* remove from schedule */ rt_schedule_remove_thread(thread); /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); /* change stat */ thread->stat = RT_THREAD_CLOSE; /* disable interrupt */ lock = rt_hw_interrupt_disable(); /* insert to defunct thread list */ rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); /* enable interrupt */ rt_hw_interrupt_enable(lock); return RT_EOK; }
/** * This function will allocate an object from object system * * @param type the type of object * @param name the object name. In system, the object's name must be unique. * * @return object */ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char* name) { struct rt_object* object; register rt_base_t temp; struct rt_object_information* information; RT_DEBUG_NOT_IN_INTERRUPT; #ifdef RT_USING_MODULE /* get module object information, module object should be managed by kernel object container */ information = (rt_module_self() != RT_NULL && (type != RT_Object_Class_Module)) ? &rt_module_self()->module_object[type] : &rt_object_container[type]; #else /* get object information */ information = &rt_object_container[type]; #endif object = (struct rt_object*)rt_malloc(information->object_size); if (object == RT_NULL) { /* no memory can be allocated */ return RT_NULL; } /* initialize object's parameters */ /* set object type */ object->type = type; /* set object flag */ object->flag = 0; #ifdef RT_USING_MODULE if(rt_module_self() != RT_NULL) { object->flag |= RT_OBJECT_FLAG_MODULE; } object->module_id = (void*)rt_module_self(); #endif /* copy name */ for (temp = 0; temp < RT_NAME_MAX; temp ++) { object->name[temp] = name[temp]; } RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object)); /* lock interrupt */ temp = rt_hw_interrupt_disable(); /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); /* unlock interrupt */ rt_hw_interrupt_enable(temp); /* return object */ return object; }
static void rt_thread_exit(void) { struct rt_thread *thread; register rt_base_t level; /* get current thread */ thread = rt_current_thread; /* disable interrupt */ level = rt_hw_interrupt_disable(); /* remove from schedule */ rt_schedule_remove_thread(thread); /* change stat */ thread->stat = RT_THREAD_CLOSE; /* remove it from timer list */ rt_list_remove(&(thread->thread_timer.list)); rt_object_detach((rt_object_t)&(thread->thread_timer)); if ((rt_object_is_systemobject((rt_object_t)thread) == RT_EOK) && thread->cleanup == RT_NULL) { rt_object_detach((rt_object_t)thread); } else { /* insert to defunct thread list */ rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); } /* enable interrupt */ rt_hw_interrupt_enable(level); /* switch to next task */ rt_schedule(); }
/** * This function will init an object and add it to object system management. * * @param object the specified object to be initialized. * @param type the object type. * @param name the object name. In system, the object's name must * be unique. */ void rt_object_init(struct rt_object* object, enum rt_object_class_type type, const char* name) { register rt_base_t temp; struct rt_object_information* information; /* get object information */ information = &rt_object_container[type]; /* init object's parameters */ /* set object type to static */ object->type = type | RT_Object_Class_Static; /* copy name */ for (temp = 0; temp < RT_NAME_MAX; temp ++) { object->name[temp] = name[temp]; } #ifdef RT_USING_HOOK if (rt_object_attach_hook != RT_NULL) { rt_object_attach_hook(object); } #endif /* lock interrupt */ temp = rt_hw_interrupt_disable(); /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); /* unlock interrupt */ rt_hw_interrupt_enable(temp); }
rt_err_t rt_mq_init(rt_mq_t mq, const char* name, void *msgpool, rt_size_t msg_size, rt_size_t pool_size, rt_uint8_t flag) { size_t index; struct rt_mq_message* head; /* parameter check */ RT_ASSERT(mq != RT_NULL); /* set parent flag */ mq->flag = flag; for (index = 0; index < RT_NAME_MAX; index ++) { mq->name[index] = name[index]; } /* append to mq list */ SDL_mutexP(_mq_list_mutex); rt_list_insert_after(&(_mq_list), &(mq->list)); SDL_mutexV(_mq_list_mutex); /* set message pool */ mq->msg_pool = msgpool; /* get correct message size */ mq->msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE); mq->max_msgs = pool_size / (mq->msg_size + sizeof(struct rt_mq_message)); /* init message list */ mq->msg_queue_head = RT_NULL; mq->msg_queue_tail = RT_NULL; /* init message empty list */ mq->msg_queue_free = RT_NULL; for (index = 0; index < mq->max_msgs; index ++) { head = (struct rt_mq_message*)((rt_uint8_t*)mq->msg_pool + index * (mq->msg_size + sizeof(struct rt_mq_message))); head->next = mq->msg_queue_free; mq->msg_queue_free = head; } /* the initial entry is zero */ mq->entry = 0; /* init mutex */ mq->host_mq = (void*) malloc(sizeof(struct host_mq)); hmq->mutex = SDL_CreateSemaphore(1); hmq->msg = SDL_CreateSemaphore(0); return RT_EOK; }
/** * This function will allocate an object from object system * * @param type the type of object * @param name the object name. In system, the object's name must be unique. * * @return object */ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char* name) { struct rt_object* object; register rt_base_t temp; struct rt_object_information* information; /* get object information */ information = &rt_object_container[type]; object = (struct rt_object*)rt_malloc(information->object_size); if (object == RT_NULL) { /* no memory can be allocated */ return RT_NULL; } /* init object's parameters */ /* set object type */ object->type = type; /* copy name */ for (temp = 0; temp < RT_NAME_MAX; temp ++) { object->name[temp] = name[temp]; } #ifdef RT_USING_HOOK if (rt_object_attach_hook != RT_NULL) rt_object_attach_hook(object); #endif /* lock interrupt */ temp = rt_hw_interrupt_disable(); /* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list)); /* unlock interrupt */ rt_hw_interrupt_enable(temp); /* return object */ return object; }
/** * This function will allocate a block from memory pool * * @param mp the memory pool object * @param time the waiting time * * @return the allocated memory block or RT_NULL on allocated failed */ void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time) { rt_uint8_t *block_ptr; register rt_base_t level; struct rt_thread *thread; /* disable interrupt */ level = rt_hw_interrupt_disable(); if (mp->block_free_count) { /* memory block is available. decrease the free block counter */ mp->block_free_count --; /* get block from block list */ block_ptr = mp->block_list; mp->block_list = *(rt_uint8_t **)block_ptr; /* point to memory pool */ *(rt_uint8_t **)block_ptr = (rt_uint8_t *)mp; } else { /* memory block is unavailable. */ if (time == 0) { /* enable interrupt */ rt_hw_interrupt_enable(level); return RT_NULL; } else { RT_DEBUG_NOT_IN_INTERRUPT; /* get current thread */ thread = rt_thread_self(); /* need suspend thread */ rt_thread_suspend(thread); rt_list_insert_after(&(mp->suspend_thread), &(thread->tlist)); mp->suspend_thread_count ++; if (time > 0) { /* init thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(level); /* do a schedule */ rt_schedule(); if (thread->error != RT_EOK) return RT_NULL; /* disable interrupt */ level = rt_hw_interrupt_disable(); /* decrease free block */ mp->block_free_count --; /* get block from block list */ block_ptr = mp->block_list; mp->block_list = *(rt_uint8_t **)block_ptr; /* point to memory pool */ *(rt_uint8_t **)block_ptr = (rt_uint8_t *)mp; } } /* enable interrupt */ rt_hw_interrupt_enable(level); RT_OBJECT_HOOK_CALL(rt_mp_alloc_hook, (mp, (rt_uint8_t *)(block_ptr + sizeof(rt_uint8_t *)))); return (rt_uint8_t *)(block_ptr + sizeof(rt_uint8_t *)); }
/** * This function will start the timer * * @param timer the timer to be started * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_timer_start(rt_timer_t timer) { int row_lvl; rt_list_t *timer_list; register rt_base_t level; rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL]; unsigned int tst_nr; static unsigned int random_nr; /* timer check */ RT_ASSERT(timer != RT_NULL); if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) return -RT_ERROR; RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent))); /* * get timeout tick, * the max timeout tick shall not great than RT_TICK_MAX/2 */ RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2); timer->timeout_tick = rt_tick_get() + timer->init_tick; /* disable interrupt */ level = rt_hw_interrupt_disable(); #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { /* insert timer to soft timer list */ timer_list = rt_soft_timer_list; } else #endif { /* insert timer to system timer list */ timer_list = rt_timer_list; } row_head[0] = &timer_list[0]; for (row_lvl = 0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL; row_lvl++) { for (;row_head[row_lvl] != timer_list[row_lvl].prev; row_head[row_lvl] = row_head[row_lvl]->next) { struct rt_timer *t; rt_list_t *p = row_head[row_lvl]->next; /* fix up the entry pointer */ t = rt_list_entry(p, struct rt_timer, row[row_lvl]); /* If we have two timers that timeout at the same time, it's * preferred that the timer inserted early get called early. * So insert the new timer to the end the the some-timeout timer * list. */ if ((t->timeout_tick - timer->timeout_tick) == 0) { continue; } else if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX / 2) { break; } } if (row_lvl != RT_TIMER_SKIP_LIST_LEVEL - 1) row_head[row_lvl+1] = row_head[row_lvl]+1; } /* Interestingly, this super simple timer insert counter works very very * well on distributing the list height uniformly. By means of "very very * well", I mean it beats the randomness of timer->timeout_tick very easily * (actually, the timeout_tick is not random and easy to be attacked). */ random_nr++; tst_nr = random_nr; rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL-1], &(timer->row[RT_TIMER_SKIP_LIST_LEVEL-1])); for (row_lvl = 2; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL; row_lvl++) { if (!(tst_nr & RT_TIMER_SKIP_LIST_MASK)) rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL - row_lvl], &(timer->row[RT_TIMER_SKIP_LIST_LEVEL - row_lvl])); else break; /* Shift over the bits we have tested. Works well with 1 bit and 2 * bits. */ tst_nr >>= (RT_TIMER_SKIP_LIST_MASK+1)>>1; } timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED; /* enable interrupt */ rt_hw_interrupt_enable(level); #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { /* check whether timer thread is ready */ if (timer_thread.stat != RT_THREAD_READY) { /* resume timer thread to check soft timer */ rt_thread_resume(&timer_thread); rt_schedule(); } } #endif return -RT_EOK; }
rt_mq_t rt_mq_create (const char* name, rt_size_t msg_size, rt_size_t max_msgs, rt_uint8_t flag) { size_t index; struct rt_messagequeue* mq; struct rt_mq_message* head; /* allocate object */ mq = (rt_mq_t) rt_malloc(sizeof(struct rt_messagequeue)); if (mq == RT_NULL) return mq; /* set flag */ mq->flag = flag; for (index = 0; index < RT_NAME_MAX; index ++) { mq->name[index] = name[index]; } /* append to mq list */ SDL_mutexP(_mq_list_mutex); rt_list_insert_after(&(_mq_list), &(mq->list)); SDL_mutexV(_mq_list_mutex); /* init message queue */ /* get correct message size */ mq->msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE); mq->max_msgs = max_msgs; /* allocate message pool */ mq->msg_pool = rt_malloc((mq->msg_size + sizeof(struct rt_mq_message))* mq->max_msgs); if (mq->msg_pool == RT_NULL) { rt_mq_delete(mq); return RT_NULL; } /* init message list */ mq->msg_queue_head = RT_NULL; mq->msg_queue_tail = RT_NULL; /* init message empty list */ mq->msg_queue_free = RT_NULL; for (index = 0; index < mq->max_msgs; index ++) { head = (struct rt_mq_message*)((rt_uint8_t*)mq->msg_pool + index * (mq->msg_size + sizeof(struct rt_mq_message))); head->next = mq->msg_queue_free; mq->msg_queue_free = head; } /* the initial entry is zero */ mq->entry = 0; /* init mutex */ mq->host_mq = (void*) malloc(sizeof(struct host_mq)); hmq->mutex = SDL_CreateSemaphore(1); hmq->msg = SDL_CreateSemaphore(0); return mq; }