|
29 | 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30 | 30 | */
|
31 | 31 |
|
| 32 | +#include <jinue/shared/asm/errno.h> |
32 | 33 | #include <kernel/domain/alloc/page_alloc.h>
|
33 | 34 | #include <kernel/domain/entities/descriptor.h>
|
34 | 35 | #include <kernel/domain/entities/object.h>
|
@@ -270,6 +271,33 @@ static thread_t *reschedule(bool current_can_run) {
|
270 | 271 | return to;
|
271 | 272 | }
|
272 | 273 |
|
| 274 | +/** |
| 275 | + * Yield the current thread |
| 276 | + * |
| 277 | + * The current thread is added at the tail of the ready queue. It continues |
| 278 | + * running if no other thread is ready to run. |
| 279 | + */ |
| 280 | +void thread_yield_current(void) { |
| 281 | + thread_t *current = get_current_thread(); |
| 282 | + thread_t *to = reschedule(true); |
| 283 | + |
| 284 | + if(to == current) { |
| 285 | + return; |
| 286 | + } |
| 287 | + |
| 288 | + to->state = THREAD_STATE_RUNNING; |
| 289 | + |
| 290 | + if(current->process != to->process) { |
| 291 | + process_switch_to(to->process); |
| 292 | + } |
| 293 | + |
| 294 | + spin_lock(&ready_queue.lock); |
| 295 | + |
| 296 | + thread_ready_locked(current); |
| 297 | + |
| 298 | + machine_switch_thread_and_unlock(current, to, &ready_queue.lock); |
| 299 | +} |
| 300 | + |
273 | 301 | /**
|
274 | 302 | * Terminate the current thread
|
275 | 303 | *
|
@@ -388,30 +416,35 @@ void thread_block_current_and_unlock(spinlock_t *lock) {
|
388 | 416 | }
|
389 | 417 |
|
390 | 418 | /**
|
391 |
| - * Yield the current thread |
| 419 | + * Block until thread terminates |
392 | 420 | *
|
393 |
| - * The current thread is added at the tail of the ready queue. It continues |
394 |
| - * running if no other thread is ready to run. |
| 421 | + * @param thread awaited thread |
| 422 | + * @return zero on success, negated error code on failure |
| 423 | + * |
395 | 424 | */
|
396 |
| -void thread_yield_current(void) { |
397 |
| - thread_t *current = get_current_thread(); |
398 |
| - thread_t *to = reschedule(true); |
| 425 | +int thread_await(thread_t *thread) { |
| 426 | + thread_t *current = get_current_thread(); |
399 | 427 |
|
400 |
| - if(to == current) { |
401 |
| - return; |
| 428 | + if(thread == current) { |
| 429 | + return -JINUE_EDEADLK; |
402 | 430 | }
|
403 | 431 |
|
404 |
| - to->state = THREAD_STATE_RUNNING; |
| 432 | + spin_lock(&thread->await_lock); |
405 | 433 |
|
406 |
| - if(current->process != to->process) { |
407 |
| - process_switch_to(to->process); |
| 434 | + if(thread->state == THREAD_STATE_CREATED || thread->awaiter != NULL) { |
| 435 | + spin_unlock(&thread->await_lock); |
| 436 | + return -JINUE_ESRCH; |
408 | 437 | }
|
409 | 438 |
|
410 |
| - spin_lock(&ready_queue.lock); |
| 439 | + thread->awaiter = current; |
411 | 440 |
|
412 |
| - thread_ready_locked(current); |
| 441 | + if(thread->state == THREAD_STATE_ZOMBIE) { |
| 442 | + spin_unlock(&thread->await_lock); |
| 443 | + } else { |
| 444 | + thread_block_current_and_unlock(&thread->await_lock); |
| 445 | + } |
413 | 446 |
|
414 |
| - machine_switch_thread_and_unlock(current, to, &ready_queue.lock); |
| 447 | + return 0; |
415 | 448 | }
|
416 | 449 |
|
417 | 450 | /**
|
|
0 commit comments