Rev 2436 | Rev 2446 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2436 | Rev 2440 | ||
|---|---|---|---|
| Line 155... | Line 155... | ||
| 155 | 155 | ||
| 156 | /* call the architecture-specific part of the constructor */ |
156 | /* call the architecture-specific part of the constructor */ |
| 157 | thr_constructor_arch(t); |
157 | thr_constructor_arch(t); |
| 158 | 158 | ||
| 159 | #ifdef ARCH_HAS_FPU |
159 | #ifdef ARCH_HAS_FPU |
| 160 | # ifdef CONFIG_FPU_LAZY |
160 | #ifdef CONFIG_FPU_LAZY |
| 161 | t->saved_fpu_context = NULL; |
161 | t->saved_fpu_context = NULL; |
| 162 | # else |
162 | #else |
| 163 | t->saved_fpu_context = slab_alloc(fpu_context_slab,kmflags); |
163 | t->saved_fpu_context = slab_alloc(fpu_context_slab, kmflags); |
| 164 | if (!t->saved_fpu_context) |
164 | if (!t->saved_fpu_context) |
| 165 | return -1; |
165 | return -1; |
| 166 | # endif |
166 | #endif |
| 167 | #endif |
167 | #endif |
| 168 | 168 | ||
| 169 | t->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags); |
169 | t->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags); |
| 170 | if (! t->kstack) { |
170 | if (!t->kstack) { |
| 171 | #ifdef ARCH_HAS_FPU |
171 | #ifdef ARCH_HAS_FPU |
| 172 | if (t->saved_fpu_context) |
172 | if (t->saved_fpu_context) |
| 173 | slab_free(fpu_context_slab,t->saved_fpu_context); |
173 | slab_free(fpu_context_slab, t->saved_fpu_context); |
| 174 | #endif |
174 | #endif |
| 175 | return -1; |
175 | return -1; |
| 176 | } |
176 | } |
| 177 | 177 | ||
| 178 | return 0; |
178 | return 0; |
| Line 187... | Line 187... | ||
| 187 | thr_destructor_arch(t); |
187 | thr_destructor_arch(t); |
| 188 | 188 | ||
| 189 | frame_free(KA2PA(t->kstack)); |
189 | frame_free(KA2PA(t->kstack)); |
| 190 | #ifdef ARCH_HAS_FPU |
190 | #ifdef ARCH_HAS_FPU |
| 191 | if (t->saved_fpu_context) |
191 | if (t->saved_fpu_context) |
| 192 | slab_free(fpu_context_slab,t->saved_fpu_context); |
192 | slab_free(fpu_context_slab, t->saved_fpu_context); |
| 193 | #endif |
193 | #endif |
| 194 | return 1; /* One page freed */ |
194 | return 1; /* One page freed */ |
| 195 | } |
195 | } |
| 196 | 196 | ||
| 197 | /** Initialize threads |
197 | /** Initialize threads |
| Line 230... | Line 230... | ||
| 230 | 230 | ||
| 231 | ipl = interrupts_disable(); |
231 | ipl = interrupts_disable(); |
| 232 | 232 | ||
| 233 | spinlock_lock(&t->lock); |
233 | spinlock_lock(&t->lock); |
| 234 | 234 | ||
| 235 | ASSERT(! (t->state == Ready)); |
235 | ASSERT(!(t->state == Ready)); |
| 236 | 236 | ||
| 237 | i = (t->priority < RQ_COUNT - 1) ? ++t->priority : t->priority; |
237 | i = (t->priority < RQ_COUNT - 1) ? ++t->priority : t->priority; |
| 238 | 238 | ||
| 239 | cpu = CPU; |
239 | cpu = CPU; |
| 240 | if (t->flags & THREAD_FLAG_WIRED) { |
240 | if (t->flags & THREAD_FLAG_WIRED) { |
| Line 258... | Line 258... | ||
| 258 | atomic_inc(&cpu->nrdy); |
258 | atomic_inc(&cpu->nrdy); |
| 259 | 259 | ||
| 260 | interrupts_restore(ipl); |
260 | interrupts_restore(ipl); |
| 261 | } |
261 | } |
| 262 | 262 | ||
| 263 | /** Destroy thread memory structure |
- | |
| 264 | * |
- | |
| 265 | * Detach thread from all queues, cpus etc. and destroy it. |
- | |
| 266 | * |
- | |
| 267 | * Assume thread->lock is held!! |
- | |
| 268 | */ |
- | |
| 269 | void thread_destroy(thread_t *t) |
- | |
| 270 | { |
- | |
| 271 | bool destroy_task = false; |
- | |
| 272 | - | ||
| 273 | ASSERT(t->state == Exiting || t->state == Undead); |
- | |
| 274 | ASSERT(t->task); |
- | |
| 275 | ASSERT(t->cpu); |
- | |
| 276 | - | ||
| 277 | spinlock_lock(&t->cpu->lock); |
- | |
| 278 | if(t->cpu->fpu_owner == t) |
- | |
| 279 | t->cpu->fpu_owner = NULL; |
- | |
| 280 | spinlock_unlock(&t->cpu->lock); |
- | |
| 281 | - | ||
| 282 | spinlock_unlock(&t->lock); |
- | |
| 283 | - | ||
| 284 | spinlock_lock(&threads_lock); |
- | |
| 285 | btree_remove(&threads_btree, (btree_key_t) ((uintptr_t ) t), NULL); |
- | |
| 286 | spinlock_unlock(&threads_lock); |
- | |
| 287 | - | ||
| 288 | /* |
- | |
| 289 | * Detach from the containing task. |
- | |
| 290 | */ |
- | |
| 291 | spinlock_lock(&t->task->lock); |
- | |
| 292 | list_remove(&t->th_link); |
- | |
| 293 | if (--t->task->refcount == 0) { |
- | |
| 294 | t->task->accept_new_threads = false; |
- | |
| 295 | destroy_task = true; |
- | |
| 296 | } |
- | |
| 297 | spinlock_unlock(&t->task->lock); |
- | |
| 298 | - | ||
| 299 | if (destroy_task) |
- | |
| 300 | task_destroy(t->task); |
- | |
| 301 | - | ||
| 302 | /* |
- | |
| 303 | * If the thread had a userspace context, free up its kernel_uarg |
- | |
| 304 | * structure. |
- | |
| 305 | */ |
- | |
| 306 | if (t->flags & THREAD_FLAG_USPACE) { |
- | |
| 307 | ASSERT(t->thread_arg); |
- | |
| 308 | free(t->thread_arg); |
- | |
| 309 | } |
- | |
| 310 | - | ||
| 311 | slab_free(thread_slab, t); |
- | |
| 312 | } |
- | |
| 313 | - | ||
| 314 | /** Create new thread |
263 | /** Create new thread |
| 315 | * |
264 | * |
| 316 | * Create a new thread. |
265 | * Create a new thread. |
| 317 | * |
266 | * |
| 318 | * @param func Thread's implementing function. |
267 | * @param func Thread's implementing function. |
| Line 390... | Line 339... | ||
| 390 | t->fpu_context_exists = 0; |
339 | t->fpu_context_exists = 0; |
| 391 | t->fpu_context_engaged = 0; |
340 | t->fpu_context_engaged = 0; |
| 392 | 341 | ||
| 393 | /* might depend on previous initialization */ |
342 | /* might depend on previous initialization */ |
| 394 | thread_create_arch(t); |
343 | thread_create_arch(t); |
| 395 | 344 | ||
| 396 | /* |
- | |
| 397 | * Attach to the containing task. |
- | |
| 398 | */ |
- | |
| 399 | ipl = interrupts_disable(); |
345 | ipl = interrupts_disable(); |
| 400 | spinlock_lock(&task->lock); |
346 | spinlock_lock(&task->lock); |
| 401 | if (!task->accept_new_threads) { |
347 | if (!task->accept_new_threads) { |
| 402 | spinlock_unlock(&task->lock); |
348 | spinlock_unlock(&task->lock); |
| 403 | slab_free(thread_slab, t); |
349 | slab_free(thread_slab, t); |
| 404 | interrupts_restore(ipl); |
350 | interrupts_restore(ipl); |
| 405 | return NULL; |
351 | return NULL; |
| - | 352 | } else { |
|
| - | 353 | /* |
|
| - | 354 | * Bump the reference count so that this task cannot be |
|
| - | 355 | * destroyed while the new thread is being attached to it. |
|
| - | 356 | */ |
|
| - | 357 | task->refcount++; |
|
| 406 | } |
358 | } |
| - | 359 | spinlock_unlock(&task->lock); |
|
| - | 360 | interrupts_restore(ipl); |
|
| - | 361 | ||
| - | 362 | if (!(flags & THREAD_FLAG_NOATTACH)) |
|
| - | 363 | thread_attach(t, task); |
|
| - | 364 | ||
| - | 365 | return t; |
|
| - | 366 | } |
|
| - | 367 | ||
| - | 368 | /** Destroy thread memory structure |
|
| - | 369 | * |
|
| - | 370 | * Detach thread from all queues, cpus etc. and destroy it. |
|
| - | 371 | * |
|
| - | 372 | * Assume thread->lock is held!! |
|
| - | 373 | */ |
|
| - | 374 | void thread_destroy(thread_t *t) |
|
| - | 375 | { |
|
| - | 376 | bool destroy_task = false; |
|
| - | 377 | ||
| - | 378 | ASSERT(t->state == Exiting || t->state == Undead); |
|
| - | 379 | ASSERT(t->task); |
|
| - | 380 | ASSERT(t->cpu); |
|
| - | 381 | ||
| - | 382 | spinlock_lock(&t->cpu->lock); |
|
| - | 383 | if (t->cpu->fpu_owner == t) |
|
| - | 384 | t->cpu->fpu_owner = NULL; |
|
| - | 385 | spinlock_unlock(&t->cpu->lock); |
|
| - | 386 | ||
| - | 387 | spinlock_unlock(&t->lock); |
|
| - | 388 | ||
| - | 389 | spinlock_lock(&threads_lock); |
|
| - | 390 | btree_remove(&threads_btree, (btree_key_t) ((uintptr_t ) t), NULL); |
|
| - | 391 | spinlock_unlock(&threads_lock); |
|
| - | 392 | ||
| - | 393 | /* |
|
| - | 394 | * Detach from the containing task. |
|
| - | 395 | */ |
|
| - | 396 | spinlock_lock(&t->task->lock); |
|
| - | 397 | list_remove(&t->th_link); |
|
| - | 398 | if (--t->task->refcount == 0) { |
|
| - | 399 | t->task->accept_new_threads = false; |
|
| - | 400 | destroy_task = true; |
|
| - | 401 | } |
|
| - | 402 | spinlock_unlock(&t->task->lock); |
|
| - | 403 | ||
| - | 404 | if (destroy_task) |
|
| - | 405 | task_destroy(t->task); |
|
| - | 406 | ||
| - | 407 | /* |
|
| - | 408 | * If the thread had a userspace context, free up its kernel_uarg |
|
| - | 409 | * structure. |
|
| - | 410 | */ |
|
| - | 411 | if (t->flags & THREAD_FLAG_USPACE) { |
|
| - | 412 | ASSERT(t->thread_arg); |
|
| - | 413 | free(t->thread_arg); |
|
| - | 414 | } |
|
| - | 415 | ||
| - | 416 | slab_free(thread_slab, t); |
|
| - | 417 | } |
|
| - | 418 | ||
| - | 419 | /** Make the thread visible to the system. |
|
| - | 420 | * |
|
| - | 421 | * Attach the thread structure to the current task and make it visible in the |
|
| - | 422 | * threads_btree. |
|
| - | 423 | * |
|
| - | 424 | * @param t Thread to be attached to the task. |
|
| - | 425 | * @param task Task to which the thread is to be attached. |
|
| - | 426 | */ |
|
| - | 427 | void thread_attach(thread_t *t, task_t *task) |
|
| - | 428 | { |
|
| - | 429 | ipl_t ipl; |
|
| - | 430 | ||
| - | 431 | /* |
|
| - | 432 | * Attach to the current task. |
|
| - | 433 | */ |
|
| - | 434 | ipl = interrupts_disable(); |
|
| - | 435 | spinlock_lock(&task->lock); |
|
| - | 436 | ASSERT(task->refcount); |
|
| 407 | list_append(&t->th_link, &task->th_head); |
437 | list_append(&t->th_link, &task->th_head); |
| 408 | if (task->refcount++ == 0) |
438 | if (task->refcount == 1) |
| 409 | task->main_thread = t; |
439 | task->main_thread = t; |
| 410 | spinlock_unlock(&task->lock); |
440 | spinlock_unlock(&task->lock); |
| 411 | 441 | ||
| 412 | /* |
442 | /* |
| 413 | * Register this thread in the system-wide list. |
443 | * Register this thread in the system-wide list. |
| Line 416... | Line 446... | ||
| 416 | btree_insert(&threads_btree, (btree_key_t) ((uintptr_t) t), (void *) t, |
446 | btree_insert(&threads_btree, (btree_key_t) ((uintptr_t) t), (void *) t, |
| 417 | NULL); |
447 | NULL); |
| 418 | spinlock_unlock(&threads_lock); |
448 | spinlock_unlock(&threads_lock); |
| 419 | 449 | ||
| 420 | interrupts_restore(ipl); |
450 | interrupts_restore(ipl); |
| 421 | - | ||
| 422 | return t; |
- | |
| 423 | } |
451 | } |
| 424 | 452 | ||
| 425 | /** Terminate thread. |
453 | /** Terminate thread. |
| 426 | * |
454 | * |
| 427 | * End current thread execution and switch it to the exiting state. All pending |
455 | * End current thread execution and switch it to the exiting state. All pending |
| Line 663... | Line 691... | ||
| 663 | if (rc != 0) { |
691 | if (rc != 0) { |
| 664 | free(kernel_uarg); |
692 | free(kernel_uarg); |
| 665 | return (unative_t) rc; |
693 | return (unative_t) rc; |
| 666 | } |
694 | } |
| 667 | 695 | ||
| 668 | t = thread_create(uinit, kernel_uarg, TASK, THREAD_FLAG_USPACE, namebuf, |
696 | t = thread_create(uinit, kernel_uarg, TASK, |
| 669 | false); |
697 | THREAD_FLAG_USPACE | THREAD_FLAG_NOATTACH, namebuf, false); |
| 670 | if (t) { |
698 | if (t) { |
| - | 699 | if (uspace_thread_id != NULL) { |
|
| - | 700 | int rc; |
|
| - | 701 | ||
| - | 702 | rc = copy_to_uspace(uspace_thread_id, &t->tid, |
|
| - | 703 | sizeof(t->tid)); |
|
| - | 704 | if (rc != 0) { |
|
| - | 705 | ipl_t ipl; |
|
| - | 706 | ||
| - | 707 | /* |
|
| - | 708 | * We have encountered a failure, but the thread |
|
| - | 709 | * has already been created. We need to undo its |
|
| - | 710 | * creation now. |
|
| - | 711 | */ |
|
| - | 712 | ||
| - | 713 | /* |
|
| - | 714 | * The new thread structure is initialized, |
|
| - | 715 | * but is still not visible to the system. |
|
| - | 716 | * We can safely deallocate it. |
|
| - | 717 | */ |
|
| - | 718 | slab_free(thread_slab, t); |
|
| - | 719 | free(kernel_uarg); |
|
| - | 720 | ||
| - | 721 | /* |
|
| - | 722 | * Now we need to decrement the task reference |
|
| - | 723 | * counter. Because we are running within the |
|
| - | 724 | * same task, thread t is not the last thread |
|
| - | 725 | * in the task, so it is safe to merely |
|
| - | 726 | * decrement the counter. |
|
| - | 727 | */ |
|
| - | 728 | ipl = interrupts_disable(); |
|
| - | 729 | spinlock_lock(&TASK->lock); |
|
| - | 730 | TASK->refcount--; |
|
| - | 731 | spinlock_unlock(&TASK->lock); |
|
| - | 732 | interrupts_restore(ipl); |
|
| - | 733 | ||
| - | 734 | return (unative_t) rc; |
|
| - | 735 | } |
|
| - | 736 | } |
|
| - | 737 | thread_attach(t, TASK); |
|
| 671 | thread_ready(t); |
738 | thread_ready(t); |
| 672 | if (uspace_thread_id != NULL) |
- | |
| 673 | return (unative_t) copy_to_uspace(uspace_thread_id, |
- | |
| 674 | &t->tid, sizeof(t->tid)); |
- | |
| 675 | else |
739 | |
| 676 | return 0; |
740 | return 0; |
| 677 | } else |
741 | } else |
| 678 | free(kernel_uarg); |
742 | free(kernel_uarg); |
| 679 | 743 | ||
| 680 | return (unative_t) ENOMEM; |
744 | return (unative_t) ENOMEM; |
| 681 | } |
745 | } |