2 * Copyright (c) 2010 Jakub Jermar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /** @addtogroup genericproc
35 * @brief Thread management functions.
39 #include <proc/scheduler.h>
40 #include <proc/thread.h>
41 #include <proc/task.h>
45 #include <arch/cycle.h>
47 #include <synch/spinlock.h>
48 #include <synch/waitq.h>
49 #include <synch/workqueue.h>
50 #include <synch/rcu.h>
56 #include <time/clock.h>
57 #include <time/timeout.h>
58 #include <time/delay.h>
60 #include <arch/interrupt.h>
62 #include <arch/faddr.h>
67 #include <main/uinit.h>
68 #include <syscall/copy.h>
72 const char *thread_states
[] = {
83 thread_id_t thread_id
;
87 /** Lock protecting the threads_tree AVL tree.
89 * For locking rules, see declaration thereof.
92 IRQ_SPINLOCK_INITIALIZE(threads_lock
);
94 /** AVL tree of all threads.
96 * When a thread is found in the threads_tree AVL tree, it is guaranteed to
97 * exist as long as the threads_lock is held.
100 avltree_t threads_tree
;
102 IRQ_SPINLOCK_STATIC_INITIALIZE(tidlock
);
103 static thread_id_t last_tid
= 0;
105 static slab_cache_t
*thread_cache
;
108 slab_cache_t
*fpu_context_cache
;
113 * This wrapper is provided to ensure that every thread makes a call to
114 * thread_exit() when its implementing function returns.
116 * interrupts_disable() is assumed.
119 static void cushion(void)
121 void (*f
)(void *) = THREAD
->thread_code
;
122 void *arg
= THREAD
->thread_arg
;
123 THREAD
->last_cycle
= get_cycle();
125 /* This is where each thread wakes up after its creation */
126 irq_spinlock_unlock(&THREAD
->lock
, false);
131 /* Accumulate accounting to the task */
132 irq_spinlock_lock(&THREAD
->lock
, true);
133 if (!THREAD
->uncounted
) {
134 thread_update_accounting(true);
135 uint64_t ucycles
= THREAD
->ucycles
;
137 uint64_t kcycles
= THREAD
->kcycles
;
140 irq_spinlock_pass(&THREAD
->lock
, &TASK
->lock
);
141 TASK
->ucycles
+= ucycles
;
142 TASK
->kcycles
+= kcycles
;
143 irq_spinlock_unlock(&TASK
->lock
, true);
145 irq_spinlock_unlock(&THREAD
->lock
, true);
152 /** Initialization and allocation for thread_t structure
155 static errno_t
thr_constructor(void *obj
, unsigned int kmflags
)
157 thread_t
*thread
= (thread_t
*) obj
;
159 irq_spinlock_initialize(&thread
->lock
, "thread_t_lock");
160 link_initialize(&thread
->rq_link
);
161 link_initialize(&thread
->wq_link
);
162 link_initialize(&thread
->th_link
);
164 /* call the architecture-specific part of the constructor */
165 thr_constructor_arch(thread
);
168 #ifdef CONFIG_FPU_LAZY
169 thread
->saved_fpu_context
= NULL
;
170 #else /* CONFIG_FPU_LAZY */
171 thread
->saved_fpu_context
= slab_alloc(fpu_context_cache
, kmflags
);
172 if (!thread
->saved_fpu_context
)
174 #endif /* CONFIG_FPU_LAZY */
175 #endif /* CONFIG_FPU */
178 * Allocate the kernel stack from the low-memory to prevent an infinite
179 * nesting of TLB-misses when accessing the stack from the part of the
180 * TLB-miss handler written in C.
182 * Note that low-memory is safe to be used for the stack as it will be
183 * covered by the kernel identity mapping, which guarantees not to
184 * nest TLB-misses infinitely (either via some hardware mechanism or
185 * by the construciton of the assembly-language part of the TLB-miss
188 * This restriction can be lifted once each architecture provides
189 * a similar guarantee, for example by locking the kernel stack
190 * in the TLB whenever it is allocated from the high-memory and the
191 * thread is being scheduled to run.
193 kmflags
|= FRAME_LOWMEM
;
194 kmflags
&= ~FRAME_HIGHMEM
;
196 uintptr_t stack_phys
=
197 frame_alloc(STACK_FRAMES
, kmflags
, STACK_SIZE
- 1);
200 if (thread
->saved_fpu_context
)
201 slab_free(fpu_context_cache
, thread
->saved_fpu_context
);
206 thread
->kstack
= (uint8_t *) PA2KA(stack_phys
);
209 mutex_initialize(&thread
->udebug
.lock
, MUTEX_PASSIVE
);
215 /** Destruction of thread_t object */
216 static size_t thr_destructor(void *obj
)
218 thread_t
*thread
= (thread_t
*) obj
;
220 /* call the architecture-specific part of the destructor */
221 thr_destructor_arch(thread
);
223 frame_free(KA2PA(thread
->kstack
), STACK_FRAMES
);
226 if (thread
->saved_fpu_context
)
227 slab_free(fpu_context_cache
, thread
->saved_fpu_context
);
230 return STACK_FRAMES
; /* number of frames freed */
233 /** Initialize threads
235 * Initialize kernel threads support.
238 void thread_init(void)
242 atomic_set(&nrdy
, 0);
243 thread_cache
= slab_cache_create("thread_t", sizeof(thread_t
), 0,
244 thr_constructor
, thr_destructor
, 0);
247 fpu_context_cache
= slab_cache_create("fpu_context_t",
248 sizeof(fpu_context_t
), FPU_CONTEXT_ALIGN
, NULL
, NULL
, 0);
251 avltree_create(&threads_tree
);
254 /** Wire thread to the given CPU
256 * @param cpu CPU to wire the thread to.
259 void thread_wire(thread_t
*thread
, cpu_t
*cpu
)
261 irq_spinlock_lock(&thread
->lock
, true);
263 thread
->wired
= true;
264 irq_spinlock_unlock(&thread
->lock
, true);
267 /** Invoked right before thread_ready() readies the thread. thread is locked. */
268 static void before_thread_is_ready(thread_t
*thread
)
270 assert(irq_spinlock_locked(&thread
->lock
));
271 workq_before_thread_is_ready(thread
);
274 /** Make thread ready
276 * Switch thread to the ready state.
278 * @param thread Thread to make ready.
281 void thread_ready(thread_t
*thread
)
283 irq_spinlock_lock(&thread
->lock
, true);
285 assert(thread
->state
!= Ready
);
287 before_thread_is_ready(thread
);
289 int i
= (thread
->priority
< RQ_COUNT
- 1) ?
290 ++thread
->priority
: thread
->priority
;
293 if (thread
->wired
|| thread
->nomigrate
|| thread
->fpu_context_engaged
) {
294 /* Cannot ready to another CPU */
295 assert(thread
->cpu
!= NULL
);
297 } else if (thread
->stolen
) {
298 /* Ready to the stealing CPU */
300 } else if (thread
->cpu
) {
301 /* Prefer the CPU on which the thread ran last */
302 assert(thread
->cpu
!= NULL
);
308 thread
->state
= Ready
;
310 irq_spinlock_pass(&thread
->lock
, &(cpu
->rq
[i
].lock
));
313 * Append thread to respective ready queue
314 * on respective processor.
317 list_append(&thread
->rq_link
, &cpu
->rq
[i
].rq
);
319 irq_spinlock_unlock(&(cpu
->rq
[i
].lock
), true);
322 atomic_inc(&cpu
->nrdy
);
325 /** Create new thread
327 * Create a new thread.
329 * @param func Thread's implementing function.
330 * @param arg Thread's implementing function argument.
331 * @param task Task to which the thread belongs. The caller must
332 * guarantee that the task won't cease to exist during the
333 * call. The task's lock may not be held.
334 * @param flags Thread flags.
335 * @param name Symbolic name (a copy is made).
337 * @return New thread's structure on success, NULL on failure.
340 thread_t
*thread_create(void (*func
)(void *), void *arg
, task_t
*task
,
341 thread_flags_t flags
, const char *name
)
343 thread_t
*thread
= (thread_t
*) slab_alloc(thread_cache
, 0);
347 /* Not needed, but good for debugging */
348 memsetb(thread
->kstack
, STACK_SIZE
, 0);
350 irq_spinlock_lock(&tidlock
, true);
351 thread
->tid
= ++last_tid
;
352 irq_spinlock_unlock(&tidlock
, true);
354 context_save(&thread
->saved_context
);
355 context_set(&thread
->saved_context
, FADDR(cushion
),
356 (uintptr_t) thread
->kstack
, STACK_SIZE
);
358 the_initialize((the_t
*) thread
->kstack
);
360 ipl_t ipl
= interrupts_disable();
361 thread
->saved_context
.ipl
= interrupts_read();
362 interrupts_restore(ipl
);
364 str_cpy(thread
->name
, THREAD_NAME_BUFLEN
, name
);
366 thread
->thread_code
= func
;
367 thread
->thread_arg
= arg
;
372 ((flags
& THREAD_FLAG_UNCOUNTED
) == THREAD_FLAG_UNCOUNTED
);
373 thread
->priority
= -1; /* Start in rq[0] */
375 thread
->wired
= false;
376 thread
->stolen
= false;
378 ((flags
& THREAD_FLAG_USPACE
) == THREAD_FLAG_USPACE
);
380 thread
->nomigrate
= 0;
381 thread
->state
= Entering
;
383 timeout_initialize(&thread
->sleep_timeout
);
384 thread
->sleep_interruptible
= false;
385 thread
->sleep_queue
= NULL
;
386 thread
->timeout_pending
= false;
388 thread
->in_copy_from_uspace
= false;
389 thread
->in_copy_to_uspace
= false;
391 thread
->interrupted
= false;
392 thread
->detached
= false;
393 waitq_initialize(&thread
->join_wq
);
397 thread
->workq
= NULL
;
399 thread
->fpu_context_exists
= false;
400 thread
->fpu_context_engaged
= false;
402 avltree_node_initialize(&thread
->threads_tree_node
);
403 thread
->threads_tree_node
.key
= (uintptr_t) thread
;
406 /* Initialize debugging stuff */
407 thread
->btrace
= false;
408 udebug_thread_initialize(&thread
->udebug
);
411 /* Might depend on previous initialization */
412 thread_create_arch(thread
);
414 rcu_thread_init(thread
);
416 if ((flags
& THREAD_FLAG_NOATTACH
) != THREAD_FLAG_NOATTACH
)
417 thread_attach(thread
, task
);
422 /** Destroy thread memory structure
424 * Detach thread from all queues, cpus etc. and destroy it.
426 * @param thread Thread to be destroyed.
427 * @param irq_res Indicate whether it should unlock thread->lock
428 * in interrupts-restore mode.
431 void thread_destroy(thread_t
*thread
, bool irq_res
)
433 assert(irq_spinlock_locked(&thread
->lock
));
434 assert((thread
->state
== Exiting
) || (thread
->state
== Lingering
));
435 assert(thread
->task
);
438 irq_spinlock_lock(&thread
->cpu
->lock
, false);
439 if (thread
->cpu
->fpu_owner
== thread
)
440 thread
->cpu
->fpu_owner
= NULL
;
441 irq_spinlock_unlock(&thread
->cpu
->lock
, false);
443 irq_spinlock_pass(&thread
->lock
, &threads_lock
);
445 avltree_delete(&threads_tree
, &thread
->threads_tree_node
);
447 irq_spinlock_pass(&threads_lock
, &thread
->task
->lock
);
450 * Detach from the containing task.
452 list_remove(&thread
->th_link
);
453 irq_spinlock_unlock(&thread
->task
->lock
, irq_res
);
456 * Drop the reference to the containing task.
458 task_release(thread
->task
);
459 slab_free(thread_cache
, thread
);
462 /** Make the thread visible to the system.
464 * Attach the thread structure to the current task and make it visible in the
467 * @param t Thread to be attached to the task.
468 * @param task Task to which the thread is to be attached.
471 void thread_attach(thread_t
*thread
, task_t
*task
)
474 * Attach to the specified task.
476 irq_spinlock_lock(&task
->lock
, true);
478 /* Hold a reference to the task. */
481 /* Must not count kbox thread into lifecount */
483 atomic_inc(&task
->lifecount
);
485 list_append(&thread
->th_link
, &task
->threads
);
487 irq_spinlock_pass(&task
->lock
, &threads_lock
);
490 * Register this thread in the system-wide list.
492 avltree_insert(&threads_tree
, &thread
->threads_tree_node
);
493 irq_spinlock_unlock(&threads_lock
, true);
496 /** Terminate thread.
498 * End current thread execution and switch it to the exiting state.
499 * All pending timeouts are executed.
502 void thread_exit(void)
504 if (THREAD
->uspace
) {
506 /* Generate udebug THREAD_E event */
507 udebug_thread_e_event();
510 * This thread will not execute any code or system calls from
513 udebug_stoppable_begin();
515 if (atomic_predec(&TASK
->lifecount
) == 0) {
517 * We are the last userspace thread in the task that
518 * still has not exited. With the exception of the
519 * moment the task was created, new userspace threads
520 * can only be created by threads of the same task.
521 * We are safe to perform cleanup.
525 futex_task_cleanup();
526 LOG("Cleanup of task %" PRIu64
" completed.", TASK
->taskid
);
531 irq_spinlock_lock(&THREAD
->lock
, true);
532 if (THREAD
->timeout_pending
) {
533 /* Busy waiting for timeouts in progress */
534 irq_spinlock_unlock(&THREAD
->lock
, true);
538 THREAD
->state
= Exiting
;
539 irq_spinlock_unlock(&THREAD
->lock
, true);
548 /** Interrupts an existing thread so that it may exit as soon as possible.
550 * Threads that are blocked waiting for a synchronization primitive
551 * are woken up with a return code of EINTR if the
552 * blocking call was interruptable. See waitq_sleep_timeout().
554 * The caller must guarantee the thread object is valid during the entire
555 * function, eg by holding the threads_lock lock.
557 * Interrupted threads automatically exit when returning back to user space.
559 * @param thread A valid thread object. The caller must guarantee it
560 * will remain valid until thread_interrupt() exits.
562 void thread_interrupt(thread_t
*thread
)
564 assert(thread
!= NULL
);
566 irq_spinlock_lock(&thread
->lock
, true);
568 thread
->interrupted
= true;
569 bool sleeping
= (thread
->state
== Sleeping
);
571 irq_spinlock_unlock(&thread
->lock
, true);
574 waitq_interrupt_sleep(thread
);
577 /** Returns true if the thread was interrupted.
579 * @param thread A valid thread object. User must guarantee it will
580 * be alive during the entire call.
581 * @return true if the thread was already interrupted via thread_interrupt().
583 bool thread_interrupted(thread_t
*thread
)
585 assert(thread
!= NULL
);
589 irq_spinlock_lock(&thread
->lock
, true);
590 interrupted
= thread
->interrupted
;
591 irq_spinlock_unlock(&thread
->lock
, true);
596 /** Prevent the current thread from being migrated to another processor. */
597 void thread_migration_disable(void)
604 /** Allow the current thread to be migrated to another processor. */
605 void thread_migration_enable(void)
608 assert(THREAD
->nomigrate
> 0);
610 if (THREAD
->nomigrate
> 0)
616 * Suspend execution of the current thread.
618 * @param sec Number of seconds to sleep.
621 void thread_sleep(uint32_t sec
)
623 /* Sleep in 1000 second steps to support
624 full argument range */
626 uint32_t period
= (sec
> 1000) ? 1000 : sec
;
628 thread_usleep(period
* 1000000);
633 /** Wait for another thread to exit.
635 * @param thread Thread to join on exit.
636 * @param usec Timeout in microseconds.
637 * @param flags Mode of operation.
639 * @return An error code from errno.h or an error code from synch.h.
642 errno_t
thread_join_timeout(thread_t
*thread
, uint32_t usec
, unsigned int flags
)
644 if (thread
== THREAD
)
648 * Since thread join can only be called once on an undetached thread,
649 * the thread pointer is guaranteed to be still valid.
652 irq_spinlock_lock(&thread
->lock
, true);
653 assert(!thread
->detached
);
654 irq_spinlock_unlock(&thread
->lock
, true);
656 return waitq_sleep_timeout(&thread
->join_wq
, usec
, flags
, NULL
);
661 * Mark the thread as detached. If the thread is already
662 * in the Lingering state, deallocate its resources.
664 * @param thread Thread to be detached.
667 void thread_detach(thread_t
*thread
)
670 * Since the thread is expected not to be already detached,
671 * pointer to it must be still valid.
673 irq_spinlock_lock(&thread
->lock
, true);
674 assert(!thread
->detached
);
676 if (thread
->state
== Lingering
) {
678 * Unlock &thread->lock and restore
679 * interrupts in thread_destroy().
681 thread_destroy(thread
, true);
684 thread
->detached
= true;
687 irq_spinlock_unlock(&thread
->lock
, true);
692 * Suspend execution of the current thread.
694 * @param usec Number of microseconds to sleep.
697 void thread_usleep(uint32_t usec
)
701 waitq_initialize(&wq
);
703 (void) waitq_sleep_timeout(&wq
, usec
, SYNCH_FLAGS_NON_BLOCKING
, NULL
);
706 static bool thread_walker(avltree_node_t
*node
, void *arg
)
708 bool *additional
= (bool *) arg
;
709 thread_t
*thread
= avltree_get_instance(node
, thread_t
, threads_tree_node
);
711 uint64_t ucycles
, kcycles
;
712 char usuffix
, ksuffix
;
713 order_suffix(thread
->ucycles
, &ucycles
, &usuffix
);
714 order_suffix(thread
->kcycles
, &kcycles
, &ksuffix
);
717 if (str_cmp(thread
->name
, "uinit") == 0)
718 name
= thread
->task
->name
;
724 printf("%-8" PRIu64
" %10p %10p %9" PRIu64
"%c %9" PRIu64
"%c ",
725 thread
->tid
, thread
->thread_code
, thread
->kstack
,
726 ucycles
, usuffix
, kcycles
, ksuffix
);
728 printf("%-8" PRIu64
" %-14s %10p %-8s %10p %-5" PRIu32
"\n",
729 thread
->tid
, name
, thread
, thread_states
[thread
->state
],
730 thread
->task
, thread
->task
->container
);
735 printf("%-8" PRIu64
" %18p %18p\n"
736 " %9" PRIu64
"%c %9" PRIu64
"%c ",
737 thread
->tid
, thread
->thread_code
, thread
->kstack
,
738 ucycles
, usuffix
, kcycles
, ksuffix
);
740 printf("%-8" PRIu64
" %-14s %18p %-8s %18p %-5" PRIu32
"\n",
741 thread
->tid
, name
, thread
, thread_states
[thread
->state
],
742 thread
->task
, thread
->task
->container
);
747 printf("%-5u", thread
->cpu
->id
);
751 if (thread
->state
== Sleeping
) {
753 printf(" %10p", thread
->sleep_queue
);
757 printf(" %18p", thread
->sleep_queue
);
767 /** Print list of threads debug info
769 * @param additional Print additional information.
772 void thread_print_list(bool additional
)
774 /* Messing with thread structures, avoid deadlock */
775 irq_spinlock_lock(&threads_lock
, true);
779 printf("[id ] [code ] [stack ] [ucycles ] [kcycles ]"
780 " [cpu] [waitqueue]\n");
782 printf("[id ] [name ] [address ] [state ] [task ]"
788 printf("[id ] [code ] [stack ]\n"
789 " [ucycles ] [kcycles ] [cpu] [waitqueue ]\n");
791 printf("[id ] [name ] [address ] [state ]"
795 avltree_walk(&threads_tree
, thread_walker
, &additional
);
797 irq_spinlock_unlock(&threads_lock
, true);
800 /** Check whether thread exists.
802 * Note that threads_lock must be already held and
803 * interrupts must be already disabled.
805 * @param thread Pointer to thread.
807 * @return True if thread t is known to the system, false otherwise.
810 bool thread_exists(thread_t
*thread
)
812 assert(interrupts_disabled());
813 assert(irq_spinlock_locked(&threads_lock
));
815 avltree_node_t
*node
=
816 avltree_search(&threads_tree
, (avltree_key_t
) ((uintptr_t) thread
));
821 /** Update accounting of current thread.
823 * Note that thread_lock on THREAD must be already held and
824 * interrupts must be already disabled.
826 * @param user True to update user accounting, false for kernel.
829 void thread_update_accounting(bool user
)
831 uint64_t time
= get_cycle();
833 assert(interrupts_disabled());
834 assert(irq_spinlock_locked(&THREAD
->lock
));
837 THREAD
->ucycles
+= time
- THREAD
->last_cycle
;
839 THREAD
->kcycles
+= time
- THREAD
->last_cycle
;
841 THREAD
->last_cycle
= time
;
844 static bool thread_search_walker(avltree_node_t
*node
, void *arg
)
847 (thread_t
*) avltree_get_instance(node
, thread_t
, threads_tree_node
);
848 thread_iterator_t
*iterator
= (thread_iterator_t
*) arg
;
850 if (thread
->tid
== iterator
->thread_id
) {
851 iterator
->thread
= thread
;
858 /** Find thread structure corresponding to thread ID.
860 * The threads_lock must be already held by the caller of this function and
861 * interrupts must be disabled.
863 * @param id Thread ID.
865 * @return Thread structure address or NULL if there is no such thread ID.
868 thread_t
*thread_find_by_id(thread_id_t thread_id
)
870 assert(interrupts_disabled());
871 assert(irq_spinlock_locked(&threads_lock
));
873 thread_iterator_t iterator
;
875 iterator
.thread_id
= thread_id
;
876 iterator
.thread
= NULL
;
878 avltree_walk(&threads_tree
, thread_search_walker
, (void *) &iterator
);
880 return iterator
.thread
;
885 void thread_stack_trace(thread_id_t thread_id
)
887 irq_spinlock_lock(&threads_lock
, true);
889 thread_t
*thread
= thread_find_by_id(thread_id
);
890 if (thread
== NULL
) {
891 printf("No such thread.\n");
892 irq_spinlock_unlock(&threads_lock
, true);
896 irq_spinlock_lock(&thread
->lock
, false);
899 * Schedule a stack trace to be printed
900 * just before the thread is scheduled next.
902 * If the thread is sleeping then try to interrupt
903 * the sleep. Any request for printing an uspace stack
904 * trace from within the kernel should be always
905 * considered a last resort debugging means, therefore
906 * forcing the thread's sleep to be interrupted
907 * is probably justifiable.
910 bool sleeping
= false;
911 istate_t
*istate
= thread
->udebug
.uspace_state
;
912 if (istate
!= NULL
) {
913 printf("Scheduling thread stack trace.\n");
914 thread
->btrace
= true;
915 if (thread
->state
== Sleeping
)
918 printf("Thread interrupt state not available.\n");
920 irq_spinlock_unlock(&thread
->lock
, false);
923 waitq_interrupt_sleep(thread
);
925 irq_spinlock_unlock(&threads_lock
, true);
928 #endif /* CONFIG_UDEBUG */
930 /** Process syscall to create new thread.
933 sys_errno_t
sys_thread_create(uspace_arg_t
*uspace_uarg
, char *uspace_name
,
934 size_t name_len
, thread_id_t
*uspace_thread_id
)
936 if (name_len
> THREAD_NAME_BUFLEN
- 1)
937 name_len
= THREAD_NAME_BUFLEN
- 1;
939 char namebuf
[THREAD_NAME_BUFLEN
];
940 errno_t rc
= copy_from_uspace(namebuf
, uspace_name
, name_len
);
942 return (sys_errno_t
) rc
;
944 namebuf
[name_len
] = 0;
947 * In case of failure, kernel_uarg will be deallocated in this function.
948 * In case of success, kernel_uarg will be freed in uinit().
950 uspace_arg_t
*kernel_uarg
=
951 (uspace_arg_t
*) malloc(sizeof(uspace_arg_t
), FRAME_ATOMIC
);
953 return (sys_errno_t
) ENOMEM
;
955 rc
= copy_from_uspace(kernel_uarg
, uspace_uarg
, sizeof(uspace_arg_t
));
958 return (sys_errno_t
) rc
;
961 thread_t
*thread
= thread_create(uinit
, kernel_uarg
, TASK
,
962 THREAD_FLAG_USPACE
| THREAD_FLAG_NOATTACH
, namebuf
);
964 if (uspace_thread_id
!= NULL
) {
965 rc
= copy_to_uspace(uspace_thread_id
, &thread
->tid
,
966 sizeof(thread
->tid
));
969 * We have encountered a failure, but the thread
970 * has already been created. We need to undo its
975 * The new thread structure is initialized, but
976 * is still not visible to the system.
977 * We can safely deallocate it.
979 slab_free(thread_cache
, thread
);
982 return (sys_errno_t
) rc
;
988 * Generate udebug THREAD_B event and attach the thread.
989 * This must be done atomically (with the debug locks held),
990 * otherwise we would either miss some thread or receive
991 * THREAD_B events for threads that already existed
992 * and could be detected with THREAD_READ before.
994 udebug_thread_b_event_attach(thread
, TASK
);
996 thread_attach(thread
, TASK
);
998 thread_ready(thread
);
1004 return (sys_errno_t
) ENOMEM
;
1007 /** Process syscall to terminate thread.
1010 sys_errno_t
sys_thread_exit(int uspace_status
)
1015 /** Syscall for getting TID.
1017 * @param uspace_thread_id Userspace address of 8-byte buffer where to store
1018 * current thread ID.
1020 * @return 0 on success or an error code from @ref errno.h.
1023 sys_errno_t
sys_thread_get_id(thread_id_t
*uspace_thread_id
)
1026 * No need to acquire lock on THREAD because tid
1027 * remains constant for the lifespan of the thread.
1030 return (sys_errno_t
) copy_to_uspace(uspace_thread_id
, &THREAD
->tid
,
1031 sizeof(THREAD
->tid
));
1034 /** Syscall wrapper for sleeping. */
1035 sys_errno_t
sys_thread_usleep(uint32_t usec
)
1037 thread_usleep(usec
);
1041 sys_errno_t
sys_thread_udelay(uint32_t usec
)