30 |
#include <pthread.h> |
#include <pthread.h> |
31 |
|
|
32 |
#include <l4.h> |
#include <l4.h> |
33 |
|
#include <compiler.h> |
34 |
|
|
35 |
#include "cap-server-intern.h" |
#include "cap-server-intern.h" |
36 |
|
|
119 |
} |
} |
120 |
|
|
121 |
|
|
122 |
/* Process the message MSG from thread FROM in worker thread WORKER of |
/* Process the message CTX->MSG from thread CTX->FROM in worker thread |
123 |
bucket BUCKET. Return ECAP_NOREPLY if no reply should be sent. Any |
CTX->WORKER of bucket CTX->BUCKET. Return ECAP_NOREPLY if no reply |
124 |
other error will be replied to the user. If 0 is returned, MSG |
should be sent. Any other error will be replied to the user. If 0 |
125 |
must contain the reply message. */ |
is returned, CTX->MSG must contain the reply message. */ |
126 |
static error_t |
static error_t |
127 |
__attribute__((always_inline)) |
__attribute__((always_inline)) |
128 |
manage_demuxer (hurd_cap_rpc_context_t ctx, _hurd_cap_list_item_t worker) |
manage_demuxer (hurd_cap_rpc_context_t ctx, _hurd_cap_list_item_t worker) |
365 |
worker->next = NULL; |
worker->next = NULL; |
366 |
worker->prevp = NULL; |
worker->prevp = NULL; |
367 |
|
|
368 |
if (__builtin_expect (async, 0)) |
if (EXPECT_FALSE (async)) |
369 |
{ |
{ |
370 |
/* We have to add ourselves to the free list and inform the |
/* We have to add ourselves to the free list and inform the |
371 |
worker_alloc_async thread. */ |
worker_alloc_async thread. */ |
402 |
|
|
403 |
while (1) |
while (1) |
404 |
{ |
{ |
405 |
if (__builtin_expect (l4_ipc_failed (msg_tag), 0)) |
if (EXPECT_FALSE (l4_ipc_failed (msg_tag))) |
406 |
{ |
{ |
407 |
/* Slow path. */ |
/* Slow path. */ |
408 |
|
|
458 |
assert (l4_thread_is_equal (l4_actual_sender (), manager)); |
assert (l4_thread_is_equal (l4_actual_sender (), manager)); |
459 |
|
|
460 |
pthread_mutex_lock (&bucket->lock); |
pthread_mutex_lock (&bucket->lock); |
461 |
/* We process cancellation messages irregardless of the |
/* We process cancellation messages regardless of the |
462 |
bucket state. */ |
bucket state. */ |
463 |
if (l4_msg_label (ctx.msg) == HURD_CAP_MSG_LABEL_CANCEL) |
if (EXPECT_FALSE (l4_msg_label (ctx.msg) |
464 |
|
== HURD_CAP_MSG_LABEL_CANCEL)) |
465 |
{ |
{ |
466 |
if (l4_untyped_words (l4_msg_msg_tag (ctx.msg)) == 1) |
if (l4_untyped_words (l4_msg_msg_tag (ctx.msg)) == 1) |
467 |
{ |
{ |
496 |
else |
else |
497 |
{ |
{ |
498 |
/* Normal RPCs. */ |
/* Normal RPCs. */ |
499 |
if (bucket->state == _HURD_CAP_STATE_BLACK) |
if (EXPECT_FALSE (bucket->state == _HURD_CAP_STATE_BLACK)) |
500 |
{ |
{ |
501 |
/* The bucket operations have been ended, and the |
/* The bucket operations have been ended, and the |
502 |
manager has already been canceled. We know that |
manager has already been canceled. We know that |
512 |
} |
} |
513 |
else |
else |
514 |
{ |
{ |
515 |
if (bucket->state != _HURD_CAP_STATE_GREEN) |
if (EXPECT_FALSE (bucket->state != _HURD_CAP_STATE_GREEN)) |
516 |
{ |
{ |
517 |
/* If we are inhibited, we will have to wait |
/* If we are inhibited, we will have to wait |
518 |
until we are uninhibited. */ |
until we are uninhibited. */ |
521 |
|
|
522 |
/* FIXME: This is inefficient. ihash should support |
/* FIXME: This is inefficient. ihash should support |
523 |
an "add if not there" function. */ |
an "add if not there" function. */ |
524 |
if (hurd_ihash_find (&bucket->senders, from)) |
if (EXPECT_FALSE (hurd_ihash_find (&bucket->senders, from))) |
525 |
err = EBUSY; |
err = EBUSY; |
526 |
else |
else |
527 |
{ |
{ |
532 |
} |
} |
533 |
} |
} |
534 |
|
|
535 |
if (err) |
if (EXPECT_FALSE (err)) |
536 |
{ |
{ |
537 |
pthread_mutex_unlock (&bucket->lock); |
pthread_mutex_unlock (&bucket->lock); |
538 |
|
|
570 |
that we are not the current worker thread |
that we are not the current worker thread |
571 |
anymore. */ |
anymore. */ |
572 |
|
|
573 |
if (inhibited) |
if (EXPECT_FALSE (inhibited)) |
574 |
{ |
{ |
575 |
pthread_mutex_lock (&bucket->lock); |
pthread_mutex_lock (&bucket->lock); |
576 |
while (!err && bucket->state != _HURD_CAP_STATE_GREEN |
while (!err && bucket->state != _HURD_CAP_STATE_GREEN |
592 |
pthread_mutex_unlock (&bucket->lock); |
pthread_mutex_unlock (&bucket->lock); |
593 |
} |
} |
594 |
|
|
595 |
if (!err) |
if (EXPECT_TRUE (!err)) |
596 |
{ |
{ |
597 |
/* Process the message. */ |
/* Process the message. */ |
598 |
ctx.sender = hurd_task_id_from_thread_id (from); |
ctx.sender = hurd_task_id_from_thread_id (from); |
616 |
immediately follows up with a new message of course |
immediately follows up with a new message of course |
617 |
can expect that to work properly. */ |
can expect that to work properly. */ |
618 |
|
|
619 |
if (bucket->is_manager_waiting && !bucket->free_worker) |
if (EXPECT_FALSE (bucket->is_manager_waiting |
620 |
|
&& !bucket->free_worker)) |
621 |
{ |
{ |
622 |
/* The manager is starving for worker threads. */ |
/* The manager is starving for worker threads. */ |
623 |
pthread_cond_broadcast (&bucket->cond); |
pthread_cond_broadcast (&bucket->cond); |
626 |
/* Remove from pending_rpcs (or waiting_rpcs) list. */ |
/* Remove from pending_rpcs (or waiting_rpcs) list. */ |
627 |
_hurd_cap_list_item_remove (worker); |
_hurd_cap_list_item_remove (worker); |
628 |
/* The last waiting RPC may have to signal the manager. */ |
/* The last waiting RPC may have to signal the manager. */ |
629 |
if (inhibited && bucket->state == _HURD_CAP_STATE_BLACK |
if (EXPECT_FALSE (inhibited |
630 |
&& !bucket->waiting_rpcs) |
&& bucket->state == _HURD_CAP_STATE_BLACK |
631 |
|
&& !bucket->waiting_rpcs)) |
632 |
pthread_cond_broadcast (&bucket->cond); |
pthread_cond_broadcast (&bucket->cond); |
633 |
_hurd_cap_list_item_add (&bucket->free_worker, worker); |
_hurd_cap_list_item_add (&bucket->free_worker, worker); |
634 |
|
|
647 |
pthread_mutex_unlock (&bucket->lock); |
pthread_mutex_unlock (&bucket->lock); |
648 |
|
|
649 |
/* Finally, return the reply message, if appropriate. */ |
/* Finally, return the reply message, if appropriate. */ |
650 |
if (__builtin_expect (err != ECAP_NOREPLY, 1)) |
if (EXPECT_TRUE (err != ECAP_NOREPLY)) |
651 |
{ |
{ |
652 |
if (__builtin_expect (err, 0)) |
if (EXPECT_FALSE (err)) |
653 |
reply_err (from, err); |
reply_err (from, err); |
654 |
else |
else |
655 |
{ |
{ |
669 |
from = manager; |
from = manager; |
670 |
msg_tag = l4_xreceive_timeout (manager, timeout, &from); |
msg_tag = l4_xreceive_timeout (manager, timeout, &from); |
671 |
|
|
672 |
/* From here, we will loop all over to the beginning of |
/* From here, we will loop to the beginning of the |
673 |
the while(1) block. */ |
while(1) block. */ |
674 |
} |
} |
675 |
} |
} |
676 |
} |
} |
733 |
|
|
734 |
pthread_mutex_lock (&bucket->lock); |
pthread_mutex_lock (&bucket->lock); |
735 |
|
|
736 |
if (__builtin_expect (bucket->free_worker == NULL, 0)) |
if (EXPECT_FALSE (bucket->free_worker == NULL)) |
737 |
{ |
{ |
738 |
/* Slow path. Create a new thread and use that. */ |
/* Slow path. Create a new thread and use that. */ |
739 |
error_t err; |
error_t err; |
962 |
be true for most of the IPC operations in this file. */ |
be true for most of the IPC operations in this file. */ |
963 |
msg_tag = l4_wait_timeout (global_timeout, &from); |
msg_tag = l4_wait_timeout (global_timeout, &from); |
964 |
|
|
965 |
if (__builtin_expect (l4_ipc_failed (msg_tag), 0)) |
if (EXPECT_FALSE (l4_ipc_failed (msg_tag))) |
966 |
{ |
{ |
967 |
l4_word_t err_code = l4_error_code (); |
l4_word_t err_code = l4_error_code (); |
968 |
|
|
1013 |
msg_tag = l4_lcall (worker); |
msg_tag = l4_lcall (worker); |
1014 |
assert (l4_ipc_succeeded (msg_tag)); |
assert (l4_ipc_succeeded (msg_tag)); |
1015 |
|
|
1016 |
if (__builtin_expect |
if (EXPECT_TRUE (l4_label (msg_tag) |
1017 |
(l4_label (msg_tag) == _HURD_CAP_MSG_WORKER_ACCEPTED, 1)) |
== _HURD_CAP_MSG_WORKER_ACCEPTED)) |
1018 |
{ |
{ |
1019 |
worker = manage_mt_get_next_worker (&info, &worker_thread); |
worker = manage_mt_get_next_worker (&info, &worker_thread); |
1020 |
if (worker == l4_nilthread) |
if (worker == l4_nilthread) |