• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /barrelfish-2018-10-04/lib/barrelfish/

Lines Matching defs:thread

42 /// Maximum number of threads in a domain, used to size VM region for thread structures
46 /// Static stack and storage for a bootstrap/cleanup thread
51 static struct thread staticthread __attribute__((aligned(THREAD_ALIGNMENT))) = {
57 /// Storage metadata for thread structures (and TLS data)
61 // XXX: mutex and spinlock protecting thread slabs in spanned domains
63 * inter-disp message handler thread, and if it blocks in a mutex, there is no
71 /// Base and size of the original ("pristine") thread-local storage init data
90 /// int counter for assigning initial thread ids
94 /// Debugging assertions on thread queues
95 static void check_queue(struct thread *queue)
100 struct thread *q = queue;
121 static inline void check_queue(struct thread *queue) {}
125 * \brief Enqueue a thread in the given queue
129 void thread_enqueue(struct thread *thread, struct thread **queue)
131 assert_disabled(thread != NULL);
135 *queue = thread->prev = thread->next = thread;
138 thread->prev = (*queue)->prev;
139 thread->next = *queue;
140 (*queue)->prev = thread;
141 assert_disabled(thread->prev != NULL);
142 thread->prev->next = thread;
149 * \brief Dequeue the first thread on the given queue
153 * \returns Pointer to thread that was dequeued
155 struct thread *thread_dequeue(struct thread **queue)
158 struct thread *thread = *queue;
159 assert_disabled(thread != NULL);
160 check_queue(thread);
161 if (thread->prev == thread) {
162 assert_disabled(thread->next == thread);
165 thread->prev->next = thread->next;
166 thread->next->prev = thread->prev;
167 *queue = thread->next;
171 thread->prev = thread->next = NULL;
173 return thread;
177 * \brief Remove a specific thread from a queue
179 * Does not check that the thread is in the given queue, which it must be.
182 void thread_remove_from_queue(struct thread **queue, struct thread *thread)
185 assert_disabled(thread != NULL);
187 if (thread->prev == thread) {
188 assert_disabled(thread->next == thread);
189 assert_disabled(*queue == thread);
192 thread->prev->next = thread->next;
193 thread->next->prev = thread->prev;
194 if (*queue == thread) {
195 *queue = thread->next;
200 thread->prev = thread->next = NULL;
204 /// Refill backing storage for thread region
213 size_t blocksize = sizeof(struct thread) + tls_block_total_len;
224 /// Initialise the state of a new thread structure
225 static void thread_init(dispatcher_handle_t disp, struct thread *newthread)
258 static bool thread_check_stack_bounds(struct thread *thread,
261 return sp > (lvaddr_t)thread->stack ||
262 sp <= (lvaddr_t)thread->stack_top;
266 * \brief Schedule and run the next active thread, or yield the dispatcher.
288 struct thread *next = disp_gen->current->next;
291 // save previous thread's state
297 // same thread as before
312 /** Free all heap/slab-allocated state associated with a thread */
313 static void free_thread(struct thread *thread)
316 assert(thread->thread_seg_selector != 0);
319 if (thread->thread_seg_selector == fs) {
320 assert(thread->disp == curdispatcher());
321 struct dispatcher_x86_64 *disp_priv = get_dispatcher_x86_64(thread->disp);
322 // we're freeing the current thread; make sure we reload a valid segment
328 ldt_free_segment(thread->thread_seg_selector);
331 free(thread->stack);
332 if (thread->tls_dtv != NULL) {
333 free(thread->tls_dtv);
338 slab_free(&thread_slabs, thread->slab); // frees thread itself
346 * \brief Creates a new thread that will not be runnable
348 * \param start_func Function to run on the new thread
354 struct thread *thread_create_unrunnable(thread_func_t start_func, void *arg,
380 struct thread *newthread = (void *)ALIGN_PTR((uintptr_t)space + tls_block_total_len, THREAD_ALIGNMENT);
382 // init thread
395 // create a TLS thread vector
409 DEBUG_ERR(err, "error allocating LDT segment for new thread");
424 // set thread's ID
436 * \brief Creates a new thread, and makes it runnable
438 * \param start_func Function to run on the new thread
444 struct thread *thread_create_varstack(thread_func_t start_func, void *arg,
447 struct thread *newthread = thread_create_unrunnable(start_func, arg, stacksize);
460 * \brief Creates a new thread, and makes it runnable
462 * \param start_func Function to run on the new thread
467 struct thread *thread_create(thread_func_t start_func, void *arg)
473 * \brief Wait for termination of another thread
475 * \param thread Pointer to thread to wait for
476 * \param retval Pointer to variable to hold return value of thread, or NULL
480 errval_t thread_join(struct thread *thread, int *retval)
482 assert(thread != NULL);
484 assert(thread->coreid == disp_get_core_id());
486 thread_mutex_lock(&thread->exit_lock);
487 if(thread->detached) {
489 thread_mutex_unlock(&thread->exit_lock);
493 if(thread->joining) {
495 thread_mutex_unlock(&thread->exit_lock);
499 thread->joining = true;
500 if(thread->state != THREAD_STATE_EXITED) { // Possibly wait for thread exit
501 thread_cond_wait(&thread->exit_condition, &thread->exit_lock);
505 *retval = thread->return_value;
508 thread_mutex_unlock(&thread->exit_lock); // Not really needed
509 free_thread(thread);
515 * \brief Detach a thread. Free its state when it terminates.
517 * \param thread Pointer to thread to detach
521 errval_t thread_detach(struct thread *thread)
523 assert(thread != NULL);
524 thread_mutex_lock(&thread->exit_lock);
526 if(thread->joining) {
528 thread_mutex_unlock(&thread->exit_lock);
532 if(!thread->detached) {
533 thread->detached = true;
536 thread_mutex_unlock(&thread->exit_lock);
540 if(thread->state == THREAD_STATE_EXITED) {
542 free_thread(thread);
546 thread_mutex_unlock(&thread->exit_lock);
551 * \brief Returns the thread pointer to the currently-running thread
553 struct thread *thread_self(void)
555 struct thread *me;
570 struct thread *thread_self_disabled(void)
582 uintptr_t thread_get_id(struct thread *t)
589 struct thread *me = thread_self();
595 struct thread *me = thread_self();
610 struct thread *me = thread_self();
623 struct thread *me = thread_self();
631 struct thread *me = thread_self();
632 // if thread's outgoing token is set, get it
641 struct thread *me = thread_self();
647 struct thread *me = thread_self();
704 struct thread *me = thread_self();
709 * \brief Yield the calling thread
711 * Switches to the next runnable thread in this dispatcher, or if none is
723 struct thread *me = disp_gen->current;
724 struct thread *next = me;
749 * \brief Yield both the calling thread, and the dispatcher to another domain
772 /// Function that runs on the static thread/stack to clean up a "real" (alloced) thread
775 struct thread *thread = arg;
777 // free old thread and its stack
778 if (thread != NULL) {
779 free_thread(thread);
782 // disable and release static thread
787 struct thread *me = disp_gen->current;
788 struct thread *ft =
792 // run the next thread, if any
793 struct thread *next = me->next;
808 * \brief Terminate the calling thread
812 struct thread *me = thread_self();
816 // if this is the static thread, we don't need to do anything but cleanup
819 // disable and release static thread
826 struct thread *ft =
830 // run the next thread, if any
831 struct thread *next = me->next;
844 // otherwise, we use a dispatcher-local thread to perform cleanup
876 struct thread *wakeup =
884 // run the next thread, if any
885 struct thread *next = me->next;
908 * This function is intended for use by multi-processor thread synchronisation
918 struct thread **queue,
924 struct thread *me = disp_gen->current;
925 struct thread *next = me->next;
957 * \brief Block the calling thread, while disabled
968 void *thread_block_disabled(dispatcher_handle_t disp, struct thread **queue)
974 * \brief Block the calling thread, while enabled
984 void *thread_block(struct thread **queue)
990 * \brief Unblock a single thread from a given queue, while disabled
992 * A single thread is removed from the queue of blocked threads, and awoken.
999 * \returns Pointer to thread to be woken on a foreign dispatcher
1001 struct thread *thread_unblock_one_disabled(dispatcher_handle_t handle,
1002 struct thread **queue,
1012 // Wakeup one waiting thread
1013 struct thread *wakeup = thread_dequeue(queue);
1018 /* enqueue on run queue if it's "our" thread, and not paused */
1031 * \brief Unblock a single thread from a given queue, while enabled
1033 * A single thread is removed from the queue of blocked threads, and awoken.
1039 * \returns Pointer to thread to be woken on a foreign dispatcher
1041 struct thread *thread_unblock_one(struct thread **queue, void *reason)
1043 struct thread *thread;
1046 thread = thread_unblock_one_disabled(handle, queue, reason);
1048 return thread;
1063 struct thread *thread_unblock_all_disabled(dispatcher_handle_t handle,
1064 struct thread **queue, void *reason)
1067 struct thread *wakeupq = NULL;
1071 struct thread *wakeup = thread_unblock_one_disabled(handle, queue, reason);
1104 printf("%s: error in creating a thread, NULL parameters given\n",
1123 size_t blocksize = sizeof(struct thread) + tls_block_total_len + THREAD_ALIGNMENT;
1126 USER_PANIC_ERR(err, "vspace_mmu_aware_init for thread region failed\n");
1131 // run main() on this thread, since we can't allocate
1137 // Start real thread to run main()
1138 struct thread *thread = thread_create(main_thread, params);
1139 assert(thread != NULL);
1146 * \brief Initialise thread system while still disabled
1148 * This function initialises the thread system while the dispatcher is still
1165 // Create the first thread manually
1166 struct thread *thread = &staticthread;
1170 thread->stack_top = (char *)thread->stack_top
1171 - (lvaddr_t)thread->stack_top % STACK_ALIGNMENT;
1173 // Initialise the first (static) thread
1174 thread_init(handle, thread);
1175 thread->detached = true;
1179 errval_t err = ldt_alloc_segment_disabled(handle, thread,
1180 &thread->thread_seg_selector);
1182 USER_PANIC_ERR(err, "error allocating LDT segment for first thread");
1189 registers_set_initial(&thread->regs, thread, (lvaddr_t)thread_entry,
1192 (lvaddr_t)thread->stack_top,
1196 thread->disp = handle;
1197 thread_enqueue(thread, &disp_gen->runq);
1198 disp_gen->current = thread;
1200 disp_resume(handle, &thread->regs);
1206 * Runs the provided thread after enqueuing it and enabling the dispatcher
1208 void thread_init_remote(dispatcher_handle_t handle, struct thread *thread)
1213 thread_enqueue(thread, &disp_gen->runq);
1214 disp_gen->current = thread;
1216 disp_resume(handle, &thread->regs);
1224 * for thread metadata in the slab allocator. It can go away once we sanely
1242 size_t blocksize = sizeof(struct thread) + tls_block_total_len;
1252 "thread slabs\n");
1264 * \brief Pause (suspend execution of) the given thread, and optionally capture its register state
1266 * The thread will not be run, until a subsequent call to thread_resume()
1268 void thread_pause_and_capture_state(struct thread *thread,
1271 assert(thread != NULL);
1274 if (thread->disp == dh) {
1275 if (!thread->paused) {
1276 thread->paused = true;
1277 if (thread == disp->current) { // doesn't make much sense...
1278 sys_print("Warning: pausing current thread!\n",100);
1279 assert_disabled(thread->state == THREAD_STATE_RUNNABLE);
1281 } else if (thread->state == THREAD_STATE_RUNNABLE) {
1282 thread_remove_from_queue(&disp->runq, thread);
1286 *ret_regs = &thread->regs;
1295 * \brief Pause (suspend execution of) the given thread
1297 * The thread will not be run, until a subsequent call to thread_resume()
1299 void thread_pause(struct thread *thread)
1301 thread_pause_and_capture_state(thread, NULL);
1305 * \brief Resume execution of a thread previously suspended by thread_pause()
1307 void thread_resume(struct thread *thread)
1309 assert(thread != NULL);
1312 if (thread->disp == dh) {
1313 if (thread->paused) {
1314 thread->paused = false;
1315 if (thread->state == THREAD_STATE_RUNNABLE) {
1316 thread_enqueue(thread, &disp->runq);
1326 * \brief Set old-style thread-local storage pointer.
1331 struct thread *me = thread_self();
1337 struct thread *me = thread_self();
1342 * \brief Return old-style thread-local storage pointer.
1347 struct thread *me = thread_self();
1353 struct thread *me = thread_self();
1358 * \brief Set the exception handler function for the current thread.
1373 struct thread *me = thread_self();
1400 struct thread *me = thread_self();
1425 void thread_debug_regs(struct thread *t);
1426 void thread_debug_regs(struct thread *t)
1440 * \brief Deliver an exception to the current thread, and resume.
1456 struct thread *thread = disp_gen->current;
1457 assert_disabled(thread != NULL);
1461 if (thread->exception_handler == NULL || thread->exception_stack_top == NULL
1462 || thread->in_exception) {
1463 if (thread->in_exception) {
1464 sys_print("Can't deliver exception to thread: already in handler\n",
1467 sys_print("Can't deliver exception to thread: handler not set\n",
1473 if (sp < (lvaddr_t)thread->stack ||
1474 sp > (lvaddr_t)thread->stack_top) {
1478 PRIxPTR "]\n", (lvaddr_t) sp, (lvaddr_t) thread->stack,
1479 (lvaddr_t) thread->stack_top);
1483 // TODO: actually delete the thread!
1485 thread_remove_from_queue(&disp_gen->runq, thread);
1489 thread->in_exception = true;
1491 lvaddr_t stack_top = (lvaddr_t)thread->exception_stack_top;
1493 // save thread's state at time of fault on top of exception stack
1502 assert_disabled(stack_top > (lvaddr_t)thread->exception_stack + 8192);
1507 registers_set_initial(&thread->regs, thread,
1512 disp_resume(handle, &thread->regs);