Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2481 → Rev 2482

/trunk/uspace/lib/libc/generic/psthread.c
File deleted
/trunk/uspace/lib/libc/generic/thread.c
37,7 → 37,7
#include <stdlib.h>
#include <libarch/faddr.h>
#include <kernel/proc/uarg.h>
#include <psthread.h>
#include <fibril.h>
#include <string.h>
#include <async.h>
 
100,10 → 100,10
*/
void __thread_main(uspace_arg_t *uarg)
{
psthread_data_t *pt;
fibril_t *f;
 
pt = psthread_setup();
__tcb_set(pt->tcb);
f = fibril_setup();
__tcb_set(f->tcb);
uarg->uspace_thread_function(uarg->uspace_thread_arg);
/* XXX: we cannot free the userspace stack while running on it */
112,7 → 112,7
 
/* If there is a manager, destroy it */
async_destroy_manager();
psthread_teardown(pt);
fibril_teardown(f);
 
thread_exit(0);
}
/trunk/uspace/lib/libc/generic/fibril.c
0,0 → 1,374
/*
* Copyright (c) 2006 Ondrej Palkovsky
* Copyright (c) 2007 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <libadt/list.h>
#include <fibril.h>
#include <malloc.h>
#include <unistd.h>
#include <thread.h>
#include <stdio.h>
#include <libarch/faddr.h>
#include <futex.h>
#include <assert.h>
#include <async.h>
 
#ifndef FIBRIL_INITIAL_STACK_PAGES_NO
#define FIBRIL_INITIAL_STACK_PAGES_NO 1
#endif
 
static LIST_INITIALIZE(ready_list);
static LIST_INITIALIZE(serialized_list);
static LIST_INITIALIZE(manager_list);
 
static void fibril_main(void);
 
static atomic_t fibril_futex = FUTEX_INITIALIZER;
/** Number of threads that are in async_serialized mode */
static int serialized_threads; /* Protected by async_futex */
/** Thread-local count of serialization. If >0, we must not preempt */
static __thread int serialization_count;
/** Counter for fibrils residing in async_manager */
static int fibrils_in_manager;
 
/** Setup fibril information into TCB structure */
fibril_t *fibril_setup(void)
{
fibril_t *f;
tcb_t *tcb;
 
tcb = __make_tls();
if (!tcb)
return NULL;
 
f = malloc(sizeof(*f));
if (!f) {
__free_tls(tcb);
return NULL;
}
 
tcb->fibril_data = f;
f->tcb = tcb;
 
return f;
}
 
void fibril_teardown(fibril_t *f)
{
__free_tls(f->tcb);
free(f);
}
 
/** Function that spans the whole life-cycle of a fibril.
*
* Each fibril begins execution in this function. Then the function
* implementing the fibril logic is called. After its return, the return value
* is saved for a potentional joiner. If the joiner exists, it is woken up. The
* fibril then switches to another fibril, which cleans up after it.
*/
void fibril_main(void)
{
fibril_t *f = __tcb_get()->fibril_data;
 
f->retval = f->func(f->arg);
 
/*
* If there is a joiner, wake it up and save our return value.
*/
if (f->joiner) {
list_append(&f->joiner->link, &ready_list);
f->joiner->joinee_retval = f->retval;
}
 
fibril_schedule_next_adv(FIBRIL_FROM_DEAD);
/* not reached */
}
 
/** Schedule next fibril.
*
* If calling with FIBRIL_TO_MANAGER parameter, the async_futex should be
* held.
*
* @param stype One of FIBRIL_SLEEP, FIBRIL_PREEMPT, FIBRIL_TO_MANAGER,
* FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter
* describes the circumstances of the switch.
* @return Return 0 if there is no ready fibril,
* return 1 otherwise.
*/
int fibril_schedule_next_adv(fibril_switch_type_t stype)
{
fibril_t *srcf, *dstf;
int retval = 0;
futex_down(&fibril_futex);
 
if (stype == FIBRIL_PREEMPT && list_empty(&ready_list))
goto ret_0;
if (stype == FIBRIL_SLEEP) {
if (list_empty(&ready_list) && list_empty(&serialized_list))
goto ret_0;
}
 
if (stype == FIBRIL_FROM_MANAGER) {
if (list_empty(&ready_list) && list_empty(&serialized_list))
goto ret_0;
/*
* Do not preempt if there is not sufficient count of thread
* managers.
*/
if (list_empty(&serialized_list) && fibrils_in_manager <=
serialized_threads) {
goto ret_0;
}
}
/* If we are going to manager and none exists, create it */
if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
while (list_empty(&manager_list)) {
futex_up(&fibril_futex);
async_create_manager();
futex_down(&fibril_futex);
}
}
srcf = __tcb_get()->fibril_data;
if (stype != FIBRIL_FROM_DEAD) {
/* Save current state */
if (!context_save(&srcf->ctx)) {
if (serialization_count)
srcf->flags &= ~FIBRIL_SERIALIZED;
if (srcf->clean_after_me) {
/*
* Cleanup after the dead fibril from which we
* restored context here.
*/
free(srcf->clean_after_me->stack);
fibril_teardown(srcf->clean_after_me);
srcf->clean_after_me = NULL;
}
return 1; /* futex_up already done here */
}
 
/* Save myself to the correct run list */
if (stype == FIBRIL_PREEMPT)
list_append(&srcf->link, &ready_list);
else if (stype == FIBRIL_FROM_MANAGER) {
list_append(&srcf->link, &manager_list);
fibrils_in_manager--;
} else {
/*
* If stype == FIBRIL_TO_MANAGER, don't put ourselves to
* any list, we should already be somewhere, or we will
* be lost.
*
* The stype == FIBRIL_SLEEP case is similar. The fibril
* has an external refernce which can be used to wake it
* up once that time has come.
*/
}
}
 
/* Choose a new fibril to run */
if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
dstf = list_get_instance(manager_list.next, fibril_t, link);
if (serialization_count && stype == FIBRIL_TO_MANAGER) {
serialized_threads++;
srcf->flags |= FIBRIL_SERIALIZED;
}
fibrils_in_manager++;
 
if (stype == FIBRIL_FROM_DEAD)
dstf->clean_after_me = srcf;
} else {
if (!list_empty(&serialized_list)) {
dstf = list_get_instance(serialized_list.next, fibril_t,
link);
serialized_threads--;
} else {
dstf = list_get_instance(ready_list.next, fibril_t,
link);
}
}
list_remove(&dstf->link);
 
futex_up(&fibril_futex);
context_restore(&dstf->ctx);
/* not reached */
 
ret_0:
futex_up(&fibril_futex);
return retval;
}
 
/** Wait for fibril to finish.
*
* Each fibril can be only joined by one other fibril. Moreover, the joiner must
* be from the same thread as the joinee.
*
* @param fid Fibril to join.
*
* @return Value returned by the completed fibril.
*/
int fibril_join(fid_t fid)
{
fibril_t *f;
fibril_t *cur;
 
/* Handle fid = Kernel address -> it is wait for call */
f = (fibril_t *) fid;
 
/*
* The joiner is running so the joinee isn't.
*/
cur = __tcb_get()->fibril_data;
f->joiner = cur;
fibril_schedule_next_adv(FIBRIL_SLEEP);
 
/*
* The joinee fills in the return value.
*/
return cur->joinee_retval;
}
 
/** Create a new fibril.
*
* @param func Implementing function of the new fibril.
* @param arg Argument to pass to func.
*
* @return Return 0 on failure or TLS of the new fibril.
*/
fid_t fibril_create(int (*func)(void *), void *arg)
{
fibril_t *f;
 
f = fibril_setup();
if (!f)
return 0;
f->stack = (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO *
getpagesize());
 
if (!f->stack) {
fibril_teardown(f);
return 0;
}
 
f->arg = arg;
f->func = func;
f->clean_after_me = NULL;
f->joiner = NULL;
f->joinee_retval = 0;
f->retval = 0;
f->flags = 0;
 
context_save(&f->ctx);
context_set(&f->ctx, FADDR(fibril_main), f->stack,
FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), f->tcb);
 
return (fid_t) f;
}
 
/** Add a fibril to the ready list.
*
* @param fid Pinter to the fibril structure of the fibril to be added.
*/
void fibril_add_ready(fid_t fid)
{
fibril_t *f;
 
f = (fibril_t *) fid;
futex_down(&fibril_futex);
if ((f->flags & FIBRIL_SERIALIZED))
list_append(&f->link, &serialized_list);
else
list_append(&f->link, &ready_list);
futex_up(&fibril_futex);
}
 
/** Add a fibril to the manager list.
*
* @param fid Pinter to the fibril structure of the fibril to be added.
*/
void fibril_add_manager(fid_t fid)
{
fibril_t *f;
 
f = (fibril_t *) fid;
 
futex_down(&fibril_futex);
list_append(&f->link, &manager_list);
futex_up(&fibril_futex);
}
 
/** Remove one manager from the manager list. */
void fibril_remove_manager(void)
{
futex_down(&fibril_futex);
if (list_empty(&manager_list)) {
futex_up(&fibril_futex);
return;
}
list_remove(manager_list.next);
futex_up(&fibril_futex);
}
 
/** Return fibril id of the currently running fibril.
*
* @return Fibril ID of the currently running pseudo thread.
*/
fid_t fibril_get_id(void)
{
return (fid_t) __tcb_get()->fibril_data;
}
 
/** Disable preemption
*
* If the fibril wants to send several message in a row and does not want to be
* preempted, it should start async_serialize_start() in the beginning of
* communication and async_serialize_end() in the end. If it is a true
* multithreaded application, it should protect the communication channel by a
* futex as well. Interrupt messages can still be preempted.
*/
void fibril_inc_sercount(void)
{
serialization_count++;
}
 
/** Restore the preemption counter to the previous state. */
void fibril_dec_sercount(void)
{
serialization_count--;
}
 
/** @}
*/
 
/trunk/uspace/lib/libc/generic/libc.c
42,7 → 42,7
#include <unistd.h>
#include <thread.h>
#include <malloc.h>
#include <psthread.h>
#include <fibril.h>
#include <io/stream.h>
#include <ipc/ipc.h>
#include <async.h>
57,12 → 57,12
 
void __main(void)
{
psthread_data_t *pt;
fibril_t *f;
 
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ);
_async_init();
pt = psthread_setup();
__tcb_set(pt->tcb);
f = fibril_setup();
__tcb_set(f->tcb);
}
 
void __io_init(void)
74,7 → 74,7
 
void __exit(void)
{
psthread_teardown(__tcb_get()->pst_data);
fibril_teardown(__tcb_get()->fibril_data);
_exit(0);
}
 
/trunk/uspace/lib/libc/generic/ipc.c
49,7 → 49,7
#include <futex.h>
#include <kernel/synch/synch.h>
#include <async.h>
#include <psthread.h>
#include <fibril.h>
 
/** Structure used for keeping track of sent asynchronous calls and queing
* unsent calls.
66,7 → 66,7
int phoneid;
} msg;
} u;
pstid_t ptid; /**< Pseudothread waiting for sending this call. */
fid_t fid; /**< Fibril waiting for sending this call. */
} async_call_t;
 
LIST_INITIALIZE(dispatched_calls);
216,11 → 216,11
list_append(&call->list, &queued_calls);
 
if (can_preempt) {
call->ptid = psthread_get_id();
psthread_schedule_next_adv(PS_TO_MANAGER);
call->fid = fibril_get_id();
fibril_schedule_next_adv(FIBRIL_TO_MANAGER);
/* Async futex unlocked by previous call */
} else {
call->ptid = 0;
call->fid = 0;
futex_up(&async_futex);
}
return;
383,8 → 383,8
list_remove(&call->list);
 
futex_up(&async_futex);
if (call->ptid)
psthread_add_ready(call->ptid);
if (call->fid)
fibril_add_ready(call->fid);
if (callid == IPC_CALLRET_FATAL) {
if (call->callback)
/trunk/uspace/lib/libc/generic/async.c
85,11 → 85,10
* ....
* }
*
* TODO: Detaching/joining dead psthreads?
*/
#include <futex.h>
#include <async.h>
#include <psthread.h>
#include <fibril.h>
#include <stdio.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
104,13 → 103,18
static LIST_INITIALIZE(timeout_list);
 
typedef struct {
struct timeval expires; /**< Expiration time for waiting thread */
int inlist; /**< If true, this struct is in timeout list */
/** Expiration time for waiting fibril. */
struct timeval expires;
/** If true, this struct is in the timeout list. */
int inlist;
link_t link;
 
pstid_t ptid; /**< Thread waiting for this message */
int active; /**< If this thread is currently active */
int timedout; /**< If true, we timed out */
/** Fibril waiting for this message. */
fid_t fid;
/** If this fibril is currently active. */
int active;
/** If true, we timed out. */
int timedout;
} awaiter_t;
 
typedef struct {
118,7 → 122,7
 
int done; /**< If reply was received */
ipc_call_t *dataptr; /**< Pointer where the answer data
* is stored */
* is stored */
ipcarg_t retval;
} amsg_t;
 
131,18 → 135,19
typedef struct {
awaiter_t wdata;
 
link_t link; /**< Hash table link */
link_t link; /**< Hash table link. */
ipcarg_t in_phone_hash; /**< Incoming phone hash. */
link_t msg_queue; /**< Messages that should be delivered to this thread */
link_t msg_queue; /**< Messages that should be delivered
* to this fibril. */
/* Structures for connection opening packet */
ipc_callid_t callid;
ipc_call_t call;
ipc_callid_t close_callid; /* Identification of closing packet */
void (*cthread)(ipc_callid_t,ipc_call_t *);
ipc_callid_t close_callid; /* Identification of closing packet. */
void (*cfibril)(ipc_callid_t, ipc_call_t *);
} connection_t;
 
/** Identifier of incoming connection handled by current thread */
__thread connection_t *PS_connection;
/** Identifier of the incoming connection handled by the current fibril. */
__thread connection_t *FIBRIL_connection;
/** If true, it is forbidden to use async_req functions and
* all preemption is disabled */
__thread int in_interrupt_handler;
285,7 → 290,7
list_remove(&conn->wdata.link);
}
conn->wdata.active = 1;
psthread_add_ready(conn->wdata.ptid);
fibril_add_ready(conn->wdata.fid);
}
 
futex_up(&async_futex);
300,13 → 305,13
ipc_callid_t callid;
connection_t *conn;
assert(PS_connection);
/* GCC 4.1.0 coughs on PS_connection-> dereference,
assert(FIBRIL_connection);
/* GCC 4.1.0 coughs on FIBRIL_connection-> dereference,
* GCC 4.1.1 happilly puts the rdhwr instruction in delay slot.
* I would never expect to find so many errors in
* compiler *($&$(*&$
*/
conn = PS_connection;
conn = FIBRIL_connection;
 
futex_down(&async_futex);
 
322,11 → 327,11
insert_timeout(&conn->wdata);
 
conn->wdata.active = 0;
psthread_schedule_next_adv(PS_TO_MANAGER);
fibril_schedule_next_adv(FIBRIL_TO_MANAGER);
/* Futex is up after getting back from async_manager
* get it again */
futex_down(&async_futex);
if (usecs && conn->wdata.timedout && \
if (usecs && conn->wdata.timedout &&
list_empty(&conn->msg_queue)) {
/* If we timed out-> exit */
futex_up(&async_futex);
364,7 → 369,7
*
* @param arg Connection structure pointer
*/
static int connection_thread(void *arg)
static int connection_fibril(void *arg)
{
unsigned long key;
msg_t *msg;
371,26 → 376,28
int close_answered = 0;
 
/* Setup thread local connection pointer */
PS_connection = (connection_t *)arg;
PS_connection->cthread(PS_connection->callid, &PS_connection->call);
FIBRIL_connection = (connection_t *) arg;
FIBRIL_connection->cfibril(FIBRIL_connection->callid,
&FIBRIL_connection->call);
/* Remove myself from connection hash table */
futex_down(&async_futex);
key = PS_connection->in_phone_hash;
key = FIBRIL_connection->in_phone_hash;
hash_table_remove(&conn_hash_table, &key, 1);
futex_up(&async_futex);
/* Answer all remaining messages with ehangup */
while (!list_empty(&PS_connection->msg_queue)) {
msg = list_get_instance(PS_connection->msg_queue.next, msg_t, link);
while (!list_empty(&FIBRIL_connection->msg_queue)) {
msg = list_get_instance(FIBRIL_connection->msg_queue.next,
msg_t, link);
list_remove(&msg->link);
if (msg->callid == PS_connection->close_callid)
if (msg->callid == FIBRIL_connection->close_callid)
close_answered = 1;
ipc_answer_fast(msg->callid, EHANGUP, 0, 0);
free(msg);
}
if (PS_connection->close_callid)
ipc_answer_fast(PS_connection->close_callid, 0, 0, 0);
if (FIBRIL_connection->close_callid)
ipc_answer_fast(FIBRIL_connection->close_callid, 0, 0, 0);
return 0;
}
405,11 → 412,12
* @param in_phone_hash Identification of the incoming connection
* @param callid Callid of the IPC_M_CONNECT_ME_TO packet
* @param call Call data of the opening packet
* @param cthread Thread function that should be called upon
* @param cfibril Fibril function that should be called upon
* opening the connection
* @return New thread id
* @return New fibril id.
*/
pstid_t async_new_connection(ipcarg_t in_phone_hash,ipc_callid_t callid, ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *))
fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *))
{
connection_t *conn;
unsigned long key;
426,10 → 434,10
if (call)
conn->call = *call;
conn->wdata.active = 1; /* We will activate it asap */
conn->cthread = cthread;
conn->cfibril = cfibril;
 
conn->wdata.ptid = psthread_create(connection_thread, conn);
if (!conn->wdata.ptid) {
conn->wdata.fid = fibril_create(connection_fibril, conn);
if (!conn->wdata.fid) {
free(conn);
ipc_answer_fast(callid, ENOMEM, 0, 0);
return NULL;
440,9 → 448,9
hash_table_insert(&conn_hash_table, &key, &conn->link);
futex_up(&async_futex);
 
psthread_add_ready(conn->wdata.ptid);
fibril_add_ready(conn->wdata.fid);
 
return conn->wdata.ptid;
return conn->wdata.fid;
}
 
/** Handle call that was received */
459,7 → 467,8
switch (IPC_GET_METHOD(*call)) {
case IPC_M_CONNECT_ME_TO:
/* Open new connection with thread etc. */
async_new_connection(IPC_GET_ARG3(*call), callid, call, client_connection);
async_new_connection(IPC_GET_ARG3(*call), callid, call,
client_connection);
return;
}
 
485,7 → 494,7
 
cur = timeout_list.next;
while (cur != &timeout_list) {
waiter = list_get_instance(cur,awaiter_t,link);
waiter = list_get_instance(cur, awaiter_t, link);
if (tv_gt(&waiter->expires, &tv))
break;
cur = cur->next;
497,7 → 506,7
*/
if (!waiter->active) {
waiter->active = 1;
psthread_add_ready(waiter->ptid);
fibril_add_ready(waiter->fid);
}
}
 
514,7 → 523,7
struct timeval tv;
 
while (1) {
if (psthread_schedule_next_adv(PS_FROM_MANAGER)) {
if (fibril_schedule_next_adv(FIBRIL_FROM_MANAGER)) {
futex_up(&async_futex);
/* async_futex is always held
* when entering manager thread
523,8 → 532,9
}
futex_down(&async_futex);
if (!list_empty(&timeout_list)) {
waiter = list_get_instance(timeout_list.next,awaiter_t,link);
gettimeofday(&tv,NULL);
waiter = list_get_instance(timeout_list.next, awaiter_t,
link);
gettimeofday(&tv, NULL);
if (tv_gteq(&tv, &waiter->expires)) {
futex_up(&async_futex);
handle_expired_timeouts();
572,22 → 582,23
/** Add one manager to manager list */
void async_create_manager(void)
{
pstid_t ptid;
fid_t fid;
 
ptid = psthread_create(async_manager_thread, NULL);
psthread_add_manager(ptid);
fid = fibril_create(async_manager_thread, NULL);
fibril_add_manager(fid);
}
 
/** Remove one manager from manager list */
void async_destroy_manager(void)
{
psthread_remove_manager();
fibril_remove_manager();
}
 
/** Initialize internal structures needed for async manager */
int _async_init(void)
{
if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, &conn_hash_table_ops)) {
if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1,
&conn_hash_table_ops)) {
printf("%s: cannot create hash table\n", "async");
return ENOMEM;
}
597,7 → 608,7
 
/** IPC handler for messages in async framework
*
* Notify thread that is waiting for this message, that it arrived
* Notify the fibril which is waiting for this message, that it arrived
*/
static void reply_received(void *private, int retval,
ipc_call_t *data)
620,7 → 631,7
msg->done = 1;
if (! msg->wdata.active) {
msg->wdata.active = 1;
psthread_add_ready(msg->wdata.ptid);
fibril_add_ready(msg->wdata.fid);
}
futex_up(&async_futex);
}
636,7 → 647,8
amsg_t *msg;
 
if (in_interrupt_handler) {
printf("Cannot send asynchronous request in interrupt handler.\n");
printf("Cannot send asynchronous request in interrupt "
"handler.\n");
_exit(1);
}
 
646,7 → 658,7
 
msg->wdata.active = 1; /* We may sleep in next method, but it
* will use it's own mechanism */
ipc_call_async_2(phoneid,method,arg1,arg2,msg,reply_received,1);
ipc_call_async_2(phoneid, method, arg1, arg2, msg, reply_received, 1);
 
return (aid_t) msg;
}
672,7 → 684,8
 
msg->wdata.active = 1; /* We may sleep in next method, but it
* will use it's own mechanism */
ipc_call_async_3(phoneid,method,arg1,arg2,arg3, msg,reply_received,1);
ipc_call_async_3(phoneid, method, arg1, arg2, arg3, msg, reply_received,
1);
 
return (aid_t) msg;
}
694,12 → 707,12
goto done;
}
 
msg->wdata.ptid = psthread_get_id();
msg->wdata.fid = fibril_get_id();
msg->wdata.active = 0;
msg->wdata.inlist = 0;
/* Leave locked async_futex when entering this function */
psthread_schedule_next_adv(PS_TO_MANAGER);
/* futex is up automatically after psthread_schedule_next...*/
fibril_schedule_next_adv(FIBRIL_TO_MANAGER);
/* futex is up automatically after fibril_schedule_next...*/
done:
if (retval)
*retval = msg->retval;
732,13 → 745,13
gettimeofday(&msg->wdata.expires, NULL);
tv_add(&msg->wdata.expires, timeout);
 
msg->wdata.ptid = psthread_get_id();
msg->wdata.fid = fibril_get_id();
msg->wdata.active = 0;
insert_timeout(&msg->wdata);
 
/* Leave locked async_futex when entering this function */
psthread_schedule_next_adv(PS_TO_MANAGER);
/* futex is up automatically after psthread_schedule_next...*/
fibril_schedule_next_adv(FIBRIL_TO_MANAGER);
/* futex is up automatically after fibril_schedule_next...*/
 
if (!msg->done)
return ETIMEOUT;
768,7 → 781,7
if (!msg)
return;
 
msg->wdata.ptid = psthread_get_id();
msg->wdata.fid = fibril_get_id();
msg->wdata.active = 0;
 
gettimeofday(&msg->wdata.expires, NULL);
777,8 → 790,8
futex_down(&async_futex);
insert_timeout(&msg->wdata);
/* Leave locked async_futex when entering this function */
psthread_schedule_next_adv(PS_TO_MANAGER);
/* futex is up automatically after psthread_schedule_next...*/
fibril_schedule_next_adv(FIBRIL_TO_MANAGER);
/* futex is up automatically after fibril_schedule_next...*/
free(msg);
}
 
799,12 → 812,14
void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t arg2, ipcarg_t arg3)
{
ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, !in_interrupt_handler);
ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL,
!in_interrupt_handler);
}
 
void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2)
{
ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, !in_interrupt_handler);
ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL,
!in_interrupt_handler);
}
 
/** @}