Changeset 132ab5d1 in mainline for uspace/lib/c/generic/async.c


Ignore:
Timestamp:
2018-01-30T03:20:45Z (7 years ago)
Author:
Jenda <jenda.jzqk73@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5a6cc679
Parents:
8bfb163 (diff), 6a5d05b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge commit '6a5d05bd2551e64111bea4f9332dd7448c26ce84' into forwardport

Separate return value from error code in gen_irq_code*().

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/async.c

    r8bfb163 r132ab5d1  
    7777 *   }
    7878 *
    79  *   port_handler(icallid, *icall)
     79 *   port_handler(ichandle, *icall)
    8080 *   {
    8181 *     if (want_refuse) {
    82  *       async_answer_0(icallid, ELIMIT);
     82 *       async_answer_0(ichandle, ELIMIT);
    8383 *       return;
    8484 *     }
    85  *     async_answer_0(icallid, EOK);
    86  *
    87  *     callid = async_get_call(&call);
    88  *     somehow_handle_the_call(callid, call);
    89  *     async_answer_2(callid, 1, 2, 3);
    90  *
    91  *     callid = async_get_call(&call);
     85 *     async_answer_0(ichandle, EOK);
     86 *
     87 *     chandle = async_get_call(&call);
     88 *     somehow_handle_the_call(chandle, call);
     89 *     async_answer_2(chandle, 1, 2, 3);
     90 *
     91 *     chandle = async_get_call(&call);
    9292 *     ...
    9393 *   }
     
    113113#include <libarch/barrier.h>
    114114#include <stdbool.h>
    115 #include <malloc.h>
     115#include <stdlib.h>
    116116#include <mem.h>
    117117#include <stdlib.h>
     
    185185        link_t link;
    186186       
    187         ipc_callid_t callid;
     187        cap_handle_t chandle;
    188188        ipc_call_t call;
    189189} msg_t;
     
    205205        ipc_call_t *dataptr;
    206206       
    207         sysarg_t retval;
     207        int retval;
    208208} amsg_t;
    209209
     
    237237       
    238238        /** Identification of the opening call. */
    239         ipc_callid_t callid;
     239        cap_handle_t chandle;
    240240       
    241241        /** Call data of the opening call. */
     
    243243       
    244244        /** Identification of the closing call. */
    245         ipc_callid_t close_callid;
     245        cap_handle_t close_chandle;
    246246       
    247247        /** Fibril function that will be used to handle the connection. */
     
    332332                msg->destroyed = false;
    333333                msg->dataptr = NULL;
    334                 msg->retval = (sysarg_t) EINVAL;
     334                msg->retval = EINVAL;
    335335                awaiter_initialize(&msg->wdata);
    336336        }
     
    374374/** Default fallback fibril function.
    375375 *
    376  * This fallback fibril function gets called on incomming
    377  * connections that do not have a specific handler defined.
    378  *
    379  * @param callid Hash of the incoming call.
    380  * @param call   Data of the incoming call.
    381  * @param arg    Local argument
    382  *
    383  */
    384 static void default_fallback_port_handler(ipc_callid_t callid, ipc_call_t *call,
    385     void *arg)
    386 {
    387         ipc_answer_0(callid, ENOENT);
     376 * This fallback fibril function gets called on incomming connections that do
     377 * not have a specific handler defined.
     378 *
     379 * @param chandle  Handle of the incoming call.
     380 * @param call     Data of the incoming call.
     381 * @param arg      Local argument
     382 *
     383 */
     384static void default_fallback_port_handler(cap_handle_t chandle,
     385    ipc_call_t *call, void *arg)
     386{
     387        ipc_answer_0(chandle, ENOENT);
    388388}
    389389
     
    715715        client_t *client = async_client_get(fibril_connection->in_task_id, true);
    716716        if (!client) {
    717                 ipc_answer_0(fibril_connection->callid, ENOMEM);
     717                ipc_answer_0(fibril_connection->chandle, ENOMEM);
    718718                return 0;
    719719        }
     
    724724         * Call the connection handler function.
    725725         */
    726         fibril_connection->handler(fibril_connection->callid,
     726        fibril_connection->handler(fibril_connection->chandle,
    727727            &fibril_connection->call, fibril_connection->data);
    728728       
     
    751751               
    752752                list_remove(&msg->link);
    753                 ipc_answer_0(msg->callid, EHANGUP);
     753                ipc_answer_0(msg->chandle, EHANGUP);
    754754                free(msg);
    755755        }
     
    759759         * i.e. IPC_M_PHONE_HUNGUP.
    760760         */
    761         if (fibril_connection->close_callid)
    762                 ipc_answer_0(fibril_connection->close_callid, EOK);
     761        if (fibril_connection->close_chandle)
     762                ipc_answer_0(fibril_connection->close_chandle, EOK);
    763763       
    764764        free(fibril_connection);
    765         return 0;
     765        return EOK;
    766766}
    767767
    768768/** Create a new fibril for a new connection.
    769769 *
    770  * Create new fibril for connection, fill in connection structures
    771  * and insert it into the hash table, so that later we can easily
    772  * do routing of messages to particular fibrils.
    773  *
    774  * @param in_task_id    Identification of the incoming connection.
    775  * @param in_phone_hash Identification of the incoming connection.
    776  * @param callid        Hash of the opening IPC_M_CONNECT_ME_TO call.
    777  *                      If callid is zero, the connection was opened by
    778  *                      accepting the IPC_M_CONNECT_TO_ME call and this
    779  *                      function is called directly by the server.
    780  * @param call          Call data of the opening call.
    781  * @param handler       Connection handler.
    782  * @param data          Client argument to pass to the connection handler.
    783  *
    784  * @return New fibril id or NULL on failure.
     770 * Create new fibril for connection, fill in connection structures and insert it
     771 * into the hash table, so that later we can easily do routing of messages to
     772 * particular fibrils.
     773 *
     774 * @param in_task_id     Identification of the incoming connection.
     775 * @param in_phone_hash  Identification of the incoming connection.
     776 * @param chandle        Handle of the opening IPC_M_CONNECT_ME_TO call.
     777 *                       If chandle is CAP_NIL, the connection was opened by
     778 *                       accepting the IPC_M_CONNECT_TO_ME call and this
     779 *                       function is called directly by the server.
     780 * @param call           Call data of the opening call.
     781 * @param handler        Connection handler.
     782 * @param data           Client argument to pass to the connection handler.
     783 *
     784 * @return  New fibril id or NULL on failure.
    785785 *
    786786 */
    787787static fid_t async_new_connection(task_id_t in_task_id, sysarg_t in_phone_hash,
    788     ipc_callid_t callid, ipc_call_t *call, async_port_handler_t handler,
     788    cap_handle_t chandle, ipc_call_t *call, async_port_handler_t handler,
    789789    void *data)
    790790{
    791791        connection_t *conn = malloc(sizeof(*conn));
    792792        if (!conn) {
    793                 if (callid)
    794                         ipc_answer_0(callid, ENOMEM);
     793                if (chandle != CAP_NIL)
     794                        ipc_answer_0(chandle, ENOMEM);
    795795               
    796796                return (uintptr_t) NULL;
     
    800800        conn->in_phone_hash = in_phone_hash;
    801801        list_initialize(&conn->msg_queue);
    802         conn->callid = callid;
    803         conn->close_callid = 0;
     802        conn->chandle = chandle;
     803        conn->close_chandle = CAP_NIL;
    804804        conn->handler = handler;
    805805        conn->data = data;
     
    815815                free(conn);
    816816               
    817                 if (callid)
    818                         ipc_answer_0(callid, ENOMEM);
     817                if (chandle != CAP_NIL)
     818                        ipc_answer_0(chandle, ENOMEM);
    819819               
    820820                return (uintptr_t) NULL;
     
    844844 * @param port_id ID of the newly created port.
    845845 *
    846  * @return Zero on success or a negative error code.
     846 * @return Zero on success or an error code.
    847847 *
    848848 */
     
    860860            &answer);
    861861       
    862         sysarg_t ret;
     862        int ret;
    863863        async_wait_for(req, &ret);
    864864        if (ret != EOK)
     
    892892       
    893893        fid_t fid = async_new_connection(answer.in_task_id, phone_hash,
    894             0, NULL, handler, data);
     894            CAP_NIL, NULL, handler, data);
    895895        if (fid == (uintptr_t) NULL)
    896896                return ENOMEM;
     
    961961 * timeouts are unregistered.
    962962 *
    963  * @param callid Hash of the incoming call.
    964  * @param call   Data of the incoming call.
     963 * @param chandle  Handle of the incoming call.
     964 * @param call     Data of the incoming call.
    965965 *
    966966 * @return False if the call doesn't match any connection.
     
    968968 *
    969969 */
    970 static bool route_call(ipc_callid_t callid, ipc_call_t *call)
     970static bool route_call(cap_handle_t chandle, ipc_call_t *call)
    971971{
    972972        assert(call);
     
    991991        }
    992992       
    993         msg->callid = callid;
     993        msg->chandle = chandle;
    994994        msg->call = *call;
    995995        list_append(&msg->link, &conn->msg_queue);
    996996       
    997997        if (IPC_GET_IMETHOD(*call) == IPC_M_PHONE_HUNGUP)
    998                 conn->close_callid = callid;
     998                conn->close_chandle = chandle;
    999999       
    10001000        /* If the connection fibril is waiting for an event, activate it */
     
    10171017/** Process notification.
    10181018 *
    1019  * @param callid Hash of the incoming call.
    10201019 * @param call   Data of the incoming call.
    10211020 *
    10221021 */
    1023 static void process_notification(ipc_callid_t callid, ipc_call_t *call)
     1022static void process_notification(ipc_call_t *call)
    10241023{
    10251024        async_notification_handler_t handler = NULL;
     
    10421041       
    10431042        if (handler)
    1044                 handler(callid, call, data);
     1043                handler(call, data);
    10451044}
    10461045
     
    10521051 * @param ucode   Top-half pseudocode handler.
    10531052 *
    1054  * @return IRQ capability handle on success.
    1055  * @return Negative error code.
     1053 * @param[out] handle  IRQ capability handle on success.
     1054 *
     1055 * @return An error code.
    10561056 *
    10571057 */
    10581058int async_irq_subscribe(int inr, async_notification_handler_t handler,
    1059     void *data, const irq_code_t *ucode)
     1059    void *data, const irq_code_t *ucode, cap_handle_t *handle)
    10601060{
    10611061        notification_t *notification =
     
    10771077        futex_up(&async_futex);
    10781078       
    1079         return ipc_irq_subscribe(inr, imethod, ucode);
     1079        cap_handle_t cap;
     1080        int rc = ipc_irq_subscribe(inr, imethod, ucode, &cap);
     1081        if (rc == EOK && handle != NULL) {
     1082                *handle = cap;
     1083        }
     1084        return rc;
    10801085}
    10811086
     
    10841089 * @param cap     IRQ capability handle.
    10851090 *
    1086  * @return Zero on success or a negative error code.
     1091 * @return Zero on success or an error code.
    10871092 *
    10881093 */
     
    11011106 * @param data    Notification handler client data.
    11021107 *
    1103  * @return Zero on success or a negative error code.
     1108 * @return Zero on success or an error code.
    11041109 *
    11051110 */
     
    11341139 * @param data    Notification handler client data.
    11351140 *
    1136  * @return Zero on success or a negative error code.
     1141 * @return Zero on success or an error code.
    11371142 *
    11381143 */
     
    11871192/** Return new incoming message for the current (fibril-local) connection.
    11881193 *
    1189  * @param call  Storage where the incoming call data will be stored.
    1190  * @param usecs Timeout in microseconds. Zero denotes no timeout.
    1191  *
    1192  * @return If no timeout was specified, then a hash of the
    1193  *         incoming call is returned. If a timeout is specified,
    1194  *         then a hash of the incoming call is returned unless
    1195  *         the timeout expires prior to receiving a message. In
    1196  *         that case zero is returned.
    1197  *
    1198  */
    1199 ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
     1194 * @param call   Storage where the incoming call data will be stored.
     1195 * @param usecs  Timeout in microseconds. Zero denotes no timeout.
     1196 *
     1197 * @return  If no timeout was specified, then a handle of the incoming call is
     1198 *          returned. If a timeout is specified, then a handle of the incoming
     1199 *          call is returned unless the timeout expires prior to receiving a
     1200 *          message. In that case zero CAP_NIL is returned.
     1201 */
     1202cap_handle_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
    12001203{
    12011204        assert(call);
     
    12201223        /* If nothing in queue, wait until something arrives */
    12211224        while (list_empty(&conn->msg_queue)) {
    1222                 if (conn->close_callid) {
     1225                if (conn->close_chandle) {
    12231226                        /*
    12241227                         * Handle the case when the connection was already
     
    12311234                        IPC_SET_IMETHOD(*call, IPC_M_PHONE_HUNGUP);
    12321235                        futex_up(&async_futex);
    1233                         return conn->close_callid;
     1236                        return conn->close_chandle;
    12341237                }
    12351238               
     
    12561259                        /* If we timed out -> exit */
    12571260                        futex_up(&async_futex);
    1258                         return 0;
     1261                        return CAP_NIL;
    12591262                }
    12601263        }
     
    12641267        list_remove(&msg->link);
    12651268       
    1266         ipc_callid_t callid = msg->callid;
     1269        cap_handle_t chandle = msg->chandle;
    12671270        *call = msg->call;
    12681271        free(msg);
    12691272       
    12701273        futex_up(&async_futex);
    1271         return callid;
     1274        return chandle;
    12721275}
    12731276
     
    13321335 * Otherwise the call is routed to its connection fibril.
    13331336 *
    1334  * @param callid Hash of the incoming call.
    1335  * @param call   Data of the incoming call.
    1336  *
    1337  */
    1338 static void handle_call(ipc_callid_t callid, ipc_call_t *call)
     1337 * @param chandle  Handle of the incoming call.
     1338 * @param call     Data of the incoming call.
     1339 *
     1340 */
     1341static void handle_call(cap_handle_t chandle, ipc_call_t *call)
    13391342{
    13401343        assert(call);
    13411344       
    13421345        /* Kernel notification */
    1343         if ((callid & IPC_CALLID_NOTIFICATION)) {
     1346        if ((chandle == CAP_NIL) && (call->flags & IPC_CALL_NOTIF)) {
    13441347                fibril_t *fibril = (fibril_t *) __tcb_get()->fibril_data;
    13451348                unsigned oldsw = fibril->switches;
    13461349               
    1347                 process_notification(callid, call);
     1350                process_notification(call);
    13481351               
    13491352                if (oldsw != fibril->switches) {
     
    13711374                sysarg_t in_phone_hash = IPC_GET_ARG5(*call);
    13721375               
    1373                 async_notification_handler_t handler = fallback_port_handler;
     1376                async_port_handler_t handler = fallback_port_handler;
    13741377                void *data = fallback_port_data;
    13751378               
     
    13811384                }
    13821385               
    1383                 async_new_connection(call->in_task_id, in_phone_hash, callid,
     1386                async_new_connection(call->in_task_id, in_phone_hash, chandle,
    13841387                    call, handler, data);
    13851388                return;
     
    13871390       
    13881391        /* Try to route the call through the connection hash table */
    1389         if (route_call(callid, call))
     1392        if (route_call(chandle, call))
    13901393                return;
    13911394       
    13921395        /* Unknown call from unknown phone - hang it up */
    1393         ipc_answer_0(callid, EHANGUP);
     1396        ipc_answer_0(chandle, EHANGUP);
    13941397}
    13951398
     
    14861489               
    14871490                ipc_call_t call;
    1488                 ipc_callid_t callid = ipc_wait_cycle(&call, timeout, flags);
     1491                int rc = ipc_wait_cycle(&call, timeout, flags);
    14891492               
    14901493                atomic_dec(&threads_in_ipc_wait);
    14911494               
    1492                 if (!callid) {
    1493                         handle_expired_timeouts();
     1495                assert(rc == EOK);
     1496
     1497                if (call.cap_handle == CAP_NIL) {
     1498                        if ((call.flags &
     1499                            (IPC_CALL_NOTIF | IPC_CALL_ANSWERED)) == 0) {
     1500                                /* Neither a notification nor an answer. */
     1501                                handle_expired_timeouts();
     1502                                continue;
     1503                        }
     1504                }
     1505
     1506                if (call.flags & IPC_CALL_ANSWERED)
    14941507                        continue;
    1495                 }
    1496                
    1497                 if (callid & IPC_CALLID_ANSWERED)
    1498                         continue;
    1499                
    1500                 handle_call(callid, &call);
    1501         }
    1502        
     1508
     1509                handle_call(call.cap_handle, &call);
     1510        }
     1511
    15031512        return 0;
    15041513}
     
    16311640 * @param arg3    Service-defined payload argument.
    16321641 * @param arg4    Service-defined payload argument.
    1633  * @param dataptr If non-NULL, storage where the reply data will be
    1634  *                stored.
     1642 * @param dataptr If non-NULL, storage where the reply data will be stored.
    16351643 *
    16361644 * @return Hash of the sent message or 0 on error.
     
    17011709 *
    17021710 */
    1703 void async_wait_for(aid_t amsgid, sysarg_t *retval)
     1711void async_wait_for(aid_t amsgid, int *retval)
    17041712{
    17051713        assert(amsgid);
     
    17471755 *
    17481756 */
    1749 int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout)
     1757int async_wait_timeout(aid_t amsgid, int *retval, suseconds_t timeout)
    17501758{
    17511759        assert(amsgid);
     
    18481856void async_usleep(suseconds_t timeout)
    18491857{
    1850         amsg_t *msg = amsg_create();
    1851         if (!msg)
    1852                 return;
    1853        
    1854         msg->wdata.fid = fibril_get_id();
    1855        
    1856         getuptime(&msg->wdata.to_event.expires);
    1857         tv_add_diff(&msg->wdata.to_event.expires, timeout);
     1858        awaiter_t awaiter;
     1859        awaiter_initialize(&awaiter);
     1860       
     1861        awaiter.fid = fibril_get_id();
     1862       
     1863        getuptime(&awaiter.to_event.expires);
     1864        tv_add_diff(&awaiter.to_event.expires, timeout);
    18581865       
    18591866        futex_down(&async_futex);
    18601867       
    1861         async_insert_timeout(&msg->wdata);
     1868        async_insert_timeout(&awaiter);
    18621869       
    18631870        /* Leave the async_futex locked when entering this function */
     
    18651872       
    18661873        /* Futex is up automatically after fibril_switch() */
    1867        
    1868         amsg_destroy(msg);
     1874}
     1875
     1876/** Delay execution for the specified number of seconds
     1877 *
     1878 * @param sec Number of seconds to sleep
     1879 */
     1880void async_sleep(unsigned int sec)
     1881{
     1882        /*
     1883         * Sleep in 1000 second steps to support
     1884         * full argument range
     1885         */
     1886
     1887        while (sec > 0) {
     1888                unsigned int period = (sec > 1000) ? 1000 : sec;
     1889
     1890                async_usleep(period * 1000000);
     1891                sec -= period;
     1892        }
    18691893}
    18701894
     
    18881912 * @param r5      If non-NULL, storage for the 5th reply argument.
    18891913 *
    1890  * @return Return code of the reply or a negative error code.
    1891  *
    1892  */
    1893 sysarg_t async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1914 * @return Return code of the reply or an error code.
     1915 *
     1916 */
     1917int async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    18941918    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
    18951919    sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
     
    19021926            &result);
    19031927       
    1904         sysarg_t rc;
     1928        int rc;
    19051929        async_wait_for(aid, &rc);
    19061930       
     
    19401964 * @param r5      If non-NULL, storage for the 5th reply argument.
    19411965 *
    1942  * @return Return code of the reply or a negative error code.
    1943  *
    1944  */
    1945 sysarg_t async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     1966 * @return Return code of the reply or an error code.
     1967 *
     1968 */
     1969int async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
    19461970    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
    19471971    sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
     
    19541978            &result);
    19551979       
    1956         sysarg_t rc;
     1980        int rc;
    19571981        async_wait_for(aid, &rc);
    19581982       
     
    20182042}
    20192043
    2020 sysarg_t async_answer_0(ipc_callid_t callid, sysarg_t retval)
    2021 {
    2022         return ipc_answer_0(callid, retval);
    2023 }
    2024 
    2025 sysarg_t async_answer_1(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1)
    2026 {
    2027         return ipc_answer_1(callid, retval, arg1);
    2028 }
    2029 
    2030 sysarg_t async_answer_2(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     2044int async_answer_0(cap_handle_t chandle, int retval)
     2045{
     2046        return ipc_answer_0(chandle, retval);
     2047}
     2048
     2049int async_answer_1(cap_handle_t chandle, int retval, sysarg_t arg1)
     2050{
     2051        return ipc_answer_1(chandle, retval, arg1);
     2052}
     2053
     2054int async_answer_2(cap_handle_t chandle, int retval, sysarg_t arg1,
    20312055    sysarg_t arg2)
    20322056{
    2033         return ipc_answer_2(callid, retval, arg1, arg2);
    2034 }
    2035 
    2036 sysarg_t async_answer_3(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     2057        return ipc_answer_2(chandle, retval, arg1, arg2);
     2058}
     2059
     2060int async_answer_3(cap_handle_t chandle, int retval, sysarg_t arg1,
    20372061    sysarg_t arg2, sysarg_t arg3)
    20382062{
    2039         return ipc_answer_3(callid, retval, arg1, arg2, arg3);
    2040 }
    2041 
    2042 sysarg_t async_answer_4(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     2063        return ipc_answer_3(chandle, retval, arg1, arg2, arg3);
     2064}
     2065
     2066int async_answer_4(cap_handle_t chandle, int retval, sysarg_t arg1,
    20432067    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
    20442068{
    2045         return ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4);
    2046 }
    2047 
    2048 sysarg_t async_answer_5(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     2069        return ipc_answer_4(chandle, retval, arg1, arg2, arg3, arg4);
     2070}
     2071
     2072int async_answer_5(cap_handle_t chandle, int retval, sysarg_t arg1,
    20492073    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
    20502074{
    2051         return ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5);
    2052 }
    2053 
    2054 int async_forward_fast(ipc_callid_t callid, async_exch_t *exch,
     2075        return ipc_answer_5(chandle, retval, arg1, arg2, arg3, arg4, arg5);
     2076}
     2077
     2078int async_forward_fast(cap_handle_t chandle, async_exch_t *exch,
    20552079    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
    20562080{
     
    20582082                return ENOENT;
    20592083       
    2060         return ipc_forward_fast(callid, exch->phone, imethod, arg1, arg2, mode);
    2061 }
    2062 
    2063 int async_forward_slow(ipc_callid_t callid, async_exch_t *exch,
     2084        return ipc_forward_fast(chandle, exch->phone, imethod, arg1, arg2, mode);
     2085}
     2086
     2087int async_forward_slow(cap_handle_t chandle, async_exch_t *exch,
    20642088    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
    20652089    sysarg_t arg4, sysarg_t arg5, unsigned int mode)
     
    20682092                return ENOENT;
    20692093       
    2070         return ipc_forward_slow(callid, exch->phone, imethod, arg1, arg2, arg3,
     2094        return ipc_forward_slow(chandle, exch->phone, imethod, arg1, arg2, arg3,
    20712095            arg4, arg5, mode);
    20722096}
     
    20812105 * @param arg3            User defined argument.
    20822106 *
    2083  * @return Zero on success or a negative error code.
     2107 * @return Zero on success or an error code.
    20842108 *
    20852109 */
     
    20942118            &answer);
    20952119       
    2096         sysarg_t rc;
     2120        int rc;
    20972121        async_wait_for(req, &rc);
    20982122        if (rc != EOK)
     
    21032127
    21042128static int async_connect_me_to_internal(int phone, sysarg_t arg1, sysarg_t arg2,
    2105     sysarg_t arg3, sysarg_t arg4)
     2129    sysarg_t arg3, sysarg_t arg4, int *out_phone)
    21062130{
    21072131        ipc_call_t result;
     2132       
     2133        // XXX: Workaround for GCC's inability to infer association between
     2134        // rc == EOK and *out_phone being assigned.
     2135        *out_phone = -1;
    21082136       
    21092137        amsg_t *msg = amsg_create();
     
    21172145            msg, reply_received);
    21182146       
    2119         sysarg_t rc;
     2147        int rc;
    21202148        async_wait_for((aid_t) msg, &rc);
    21212149       
     
    21232151                return rc;
    21242152       
    2125         return (int) IPC_GET_ARG5(result);
     2153        *out_phone = (int) IPC_GET_ARG5(result);
     2154        return EOK;
    21262155}
    21272156
     
    21532182        }
    21542183       
    2155         int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
    2156             0);
    2157         if (phone < 0) {
    2158                 errno = phone;
     2184        int phone;
     2185        int rc = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
     2186            0, &phone);
     2187        if (rc != EOK) {
     2188                errno = rc;
    21592189                free(sess);
    21602190                return NULL;
     
    22052235        }
    22062236       
    2207         int phone = async_connect_me_to_internal(exch->phone, iface, arg2,
    2208             arg3, 0);
    2209         if (phone < 0) {
    2210                 errno = phone;
     2237        int phone;
     2238        int rc = async_connect_me_to_internal(exch->phone, iface, arg2,
     2239            arg3, 0, &phone);
     2240        if (rc != EOK) {
     2241                errno = rc;
    22112242                free(sess);
    22122243                return NULL;
     
    22752306        }
    22762307       
    2277         int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
    2278             IPC_FLAG_BLOCKING);
    2279        
    2280         if (phone < 0) {
    2281                 errno = phone;
     2308        int phone;
     2309        int rc = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
     2310            IPC_FLAG_BLOCKING, &phone);
     2311       
     2312        if (rc != EOK) {
     2313                errno = rc;
    22822314                free(sess);
    22832315                return NULL;
     
    23282360        }
    23292361       
    2330         int phone = async_connect_me_to_internal(exch->phone, iface, arg2,
    2331             arg3, IPC_FLAG_BLOCKING);
    2332         if (phone < 0) {
    2333                 errno = phone;
     2362        int phone;
     2363        int rc = async_connect_me_to_internal(exch->phone, iface, arg2,
     2364            arg3, IPC_FLAG_BLOCKING, &phone);
     2365        if (rc != EOK) {
     2366                errno = rc;
    23342367                free(sess);
    23352368                return NULL;
     
    23632396        }
    23642397       
    2365         int phone = ipc_connect_kbox(id);
    2366         if (phone < 0) {
    2367                 errno = phone;
     2398        cap_handle_t phone;
     2399        int rc = ipc_connect_kbox(id, &phone);
     2400        if (rc != EOK) {
     2401                errno = rc;
    23682402                free(sess);
    23692403                return NULL;
     
    23962430 * @param sess Session to hung up.
    23972431 *
    2398  * @return Zero on success or a negative error code.
     2432 * @return Zero on success or an error code.
    23992433 *
    24002434 */
     
    24822516                } else if (mgmt == EXCHANGE_PARALLEL) {
    24832517                        int phone;
     2518                        int rc;
    24842519                       
    24852520                retry:
     
    24872522                         * Make a one-time attempt to connect a new data phone.
    24882523                         */
    2489                         phone = async_connect_me_to_internal(sess->phone, sess->arg1,
    2490                             sess->arg2, sess->arg3, 0);
    2491                         if (phone >= 0) {
     2524                        rc = async_connect_me_to_internal(sess->phone, sess->arg1,
     2525                            sess->arg2, sess->arg3, 0, &phone);
     2526                        if (rc == EOK) {
    24922527                                exch = (async_exch_t *) malloc(sizeof(async_exch_t));
    24932528                                if (exch != NULL) {
     
    25752610 *              base address. Cannot be NULL.
    25762611 *
    2577  * @return Zero on success or a negative error code from errno.h.
     2612 * @return Zero on success or an error code from errno.h.
    25782613 *
    25792614 */
     
    26042639 * So far, this wrapper is to be used from within a connection fibril.
    26052640 *
    2606  * @param callid Storage for the hash of the IPC_M_SHARE_IN call.
    2607  * @param size   Destination address space area size.
     2641 * @param chandle  Storage for the handle of the IPC_M_SHARE_IN call.
     2642 * @param size     Destination address space area size.
    26082643 *
    26092644 * @return True on success, false on failure.
    26102645 *
    26112646 */
    2612 bool async_share_in_receive(ipc_callid_t *callid, size_t *size)
    2613 {
    2614         assert(callid);
     2647bool async_share_in_receive(cap_handle_t *chandle, size_t *size)
     2648{
     2649        assert(chandle);
    26152650        assert(size);
    26162651       
    26172652        ipc_call_t data;
    2618         *callid = async_get_call(&data);
     2653        *chandle = async_get_call(&data);
    26192654       
    26202655        if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_IN)
     
    26312666 * argument.
    26322667 *
    2633  * @param callid Hash of the IPC_M_DATA_READ call to answer.
    2634  * @param src    Source address space base.
    2635  * @param flags  Flags to be used for sharing. Bits can be only cleared.
     2668 * @param chandle  Handle of the IPC_M_DATA_READ call to answer.
     2669 * @param src      Source address space base.
     2670 * @param flags    Flags to be used for sharing. Bits can be only cleared.
    26362671 *
    26372672 * @return Zero on success or a value from @ref errno.h on failure.
    26382673 *
    26392674 */
    2640 int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
    2641 {
    2642         return ipc_answer_3(callid, EOK, (sysarg_t) src, (sysarg_t) flags,
     2675int async_share_in_finalize(cap_handle_t chandle, void *src, unsigned int flags)
     2676{
     2677        return ipc_answer_3(chandle, EOK, (sysarg_t) src, (sysarg_t) flags,
    26432678            (sysarg_t) __entry);
    26442679}
     
    26502685 * @param flags Flags to be used for sharing. Bits can be only cleared.
    26512686 *
    2652  * @return Zero on success or a negative error code from errno.h.
     2687 * @return Zero on success or an error code from errno.h.
    26532688 *
    26542689 */
     
    26702705 * So far, this wrapper is to be used from within a connection fibril.
    26712706 *
    2672  * @param callid Storage for the hash of the IPC_M_SHARE_OUT call.
    2673  * @param size   Storage for the source address space area size.
    2674  * @param flags  Storage for the sharing flags.
     2707 * @param chandle Storage for the hash of the IPC_M_SHARE_OUT call.
     2708 * @param size     Storage for the source address space area size.
     2709 * @param flags    Storage for the sharing flags.
    26752710 *
    26762711 * @return True on success, false on failure.
    26772712 *
    26782713 */
    2679 bool async_share_out_receive(ipc_callid_t *callid, size_t *size, unsigned int *flags)
    2680 {
    2681         assert(callid);
     2714bool async_share_out_receive(cap_handle_t *chandle, size_t *size,
     2715    unsigned int *flags)
     2716{
     2717        assert(chandle);
    26822718        assert(size);
    26832719        assert(flags);
    26842720       
    26852721        ipc_call_t data;
    2686         *callid = async_get_call(&data);
     2722        *chandle = async_get_call(&data);
    26872723       
    26882724        if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_OUT)
     
    27002736 * argument.
    27012737 *
    2702  * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
    2703  * @param dst    Address of the storage for the destination address space area
    2704  *               base address.
    2705  *
    2706  * @return Zero on success or a value from @ref errno.h on failure.
    2707  *
    2708  */
    2709 int async_share_out_finalize(ipc_callid_t callid, void **dst)
    2710 {
    2711         return ipc_answer_2(callid, EOK, (sysarg_t) __entry, (sysarg_t) dst);
     2738 * @param chandle  Handle of the IPC_M_DATA_WRITE call to answer.
     2739 * @param dst      Address of the storage for the destination address space area
     2740 *                 base address.
     2741 *
     2742 * @return  Zero on success or a value from @ref errno.h on failure.
     2743 *
     2744 */
     2745int async_share_out_finalize(cap_handle_t chandle, void **dst)
     2746{
     2747        return ipc_answer_2(chandle, EOK, (sysarg_t) __entry, (sysarg_t) dst);
    27122748}
    27132749
     
    27352771 * @param size Size of the destination buffer.
    27362772 *
    2737  * @return Zero on success or a negative error code from errno.h.
     2773 * @return Zero on success or an error code from errno.h.
    27382774 *
    27392775 */
     
    27552791 * So far, this wrapper is to be used from within a connection fibril.
    27562792 *
    2757  * @param callid Storage for the hash of the IPC_M_DATA_READ.
    2758  * @param size   Storage for the maximum size. Can be NULL.
     2793 * @param chandle  Storage for the handle of the IPC_M_DATA_READ.
     2794 * @param size     Storage for the maximum size. Can be NULL.
    27592795 *
    27602796 * @return True on success, false on failure.
    27612797 *
    27622798 */
    2763 bool async_data_read_receive(ipc_callid_t *callid, size_t *size)
     2799bool async_data_read_receive(cap_handle_t *chandle, size_t *size)
    27642800{
    27652801        ipc_call_t data;
    2766         return async_data_read_receive_call(callid, &data, size);
     2802        return async_data_read_receive_call(chandle, &data, size);
    27672803}
    27682804
     
    27752811 * So far, this wrapper is to be used from within a connection fibril.
    27762812 *
    2777  * @param callid Storage for the hash of the IPC_M_DATA_READ.
    2778  * @param size   Storage for the maximum size. Can be NULL.
     2813 * @param chandle  Storage for the handle of the IPC_M_DATA_READ.
     2814 * @param size     Storage for the maximum size. Can be NULL.
    27792815 *
    27802816 * @return True on success, false on failure.
    27812817 *
    27822818 */
    2783 bool async_data_read_receive_call(ipc_callid_t *callid, ipc_call_t *data,
     2819bool async_data_read_receive_call(cap_handle_t *chandle, ipc_call_t *data,
    27842820    size_t *size)
    27852821{
    2786         assert(callid);
     2822        assert(chandle);
    27872823        assert(data);
    27882824       
    2789         *callid = async_get_call(data);
     2825        *chandle = async_get_call(data);
    27902826       
    27912827        if (IPC_GET_IMETHOD(*data) != IPC_M_DATA_READ)
     
    28042840 * argument.
    28052841 *
    2806  * @param callid Hash of the IPC_M_DATA_READ call to answer.
    2807  * @param src    Source address for the IPC_M_DATA_READ call.
    2808  * @param size   Size for the IPC_M_DATA_READ call. Can be smaller than
    2809  *               the maximum size announced by the sender.
    2810  *
    2811  * @return Zero on success or a value from @ref errno.h on failure.
    2812  *
    2813  */
    2814 int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
    2815 {
    2816         return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) size);
     2842 * @param chandle  Handle of the IPC_M_DATA_READ call to answer.
     2843 * @param src      Source address for the IPC_M_DATA_READ call.
     2844 * @param size     Size for the IPC_M_DATA_READ call. Can be smaller than
     2845 *                 the maximum size announced by the sender.
     2846 *
     2847 * @return  Zero on success or a value from @ref errno.h on failure.
     2848 *
     2849 */
     2850int async_data_read_finalize(cap_handle_t chandle, const void *src, size_t size)
     2851{
     2852        return ipc_answer_2(chandle, EOK, (sysarg_t) src, (sysarg_t) size);
    28172853}
    28182854
     
    28272863                return ENOENT;
    28282864       
    2829         ipc_callid_t callid;
    2830         if (!async_data_read_receive(&callid, NULL)) {
    2831                 ipc_answer_0(callid, EINVAL);
     2865        cap_handle_t chandle;
     2866        if (!async_data_read_receive(&chandle, NULL)) {
     2867                ipc_answer_0(chandle, EINVAL);
    28322868                return EINVAL;
    28332869        }
     
    28362872            dataptr);
    28372873        if (msg == 0) {
    2838                 ipc_answer_0(callid, EINVAL);
     2874                ipc_answer_0(chandle, EINVAL);
    28392875                return EINVAL;
    28402876        }
    28412877       
    2842         int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
     2878        int retval = ipc_forward_fast(chandle, exch->phone, 0, 0, 0,
    28432879            IPC_FF_ROUTE_FROM_ME);
    28442880        if (retval != EOK) {
    28452881                async_forget(msg);
    2846                 ipc_answer_0(callid, retval);
     2882                ipc_answer_0(chandle, retval);
    28472883                return retval;
    28482884        }
    28492885       
    2850         sysarg_t rc;
     2886        int rc;
    28512887        async_wait_for(msg, &rc);
    28522888       
     
    28602896 * @param size Size of the source buffer.
    28612897 *
    2862  * @return Zero on success or a negative error code from errno.h.
     2898 * @return Zero on success or an error code from errno.h.
    28632899 *
    28642900 */
     
    28802916 * So far, this wrapper is to be used from within a connection fibril.
    28812917 *
    2882  * @param callid Storage for the hash of the IPC_M_DATA_WRITE.
    2883  * @param size   Storage for the suggested size. May be NULL.
    2884  *
    2885  * @return True on success, false on failure.
    2886  *
    2887  */
    2888 bool async_data_write_receive(ipc_callid_t *callid, size_t *size)
     2918 * @param chandle  Storage for the handle of the IPC_M_DATA_WRITE.
     2919 * @param size     Storage for the suggested size. May be NULL.
     2920 *
     2921 * @return  True on success, false on failure.
     2922 *
     2923 */
     2924bool async_data_write_receive(cap_handle_t *chandle, size_t *size)
    28892925{
    28902926        ipc_call_t data;
    2891         return async_data_write_receive_call(callid, &data, size);
     2927        return async_data_write_receive_call(chandle, &data, size);
    28922928}
    28932929
     
    29002936 * So far, this wrapper is to be used from within a connection fibril.
    29012937 *
    2902  * @param callid Storage for the hash of the IPC_M_DATA_WRITE.
    2903  * @param data   Storage for the ipc call data.
    2904  * @param size   Storage for the suggested size. May be NULL.
     2938 * @param chandle  Storage for the handle of the IPC_M_DATA_WRITE.
     2939 * @param data     Storage for the ipc call data.
     2940 * @param size     Storage for the suggested size. May be NULL.
    29052941 *
    29062942 * @return True on success, false on failure.
    29072943 *
    29082944 */
    2909 bool async_data_write_receive_call(ipc_callid_t *callid, ipc_call_t *data,
     2945bool async_data_write_receive_call(cap_handle_t *chandle, ipc_call_t *data,
    29102946    size_t *size)
    29112947{
    2912         assert(callid);
     2948        assert(chandle);
    29132949        assert(data);
    29142950       
    2915         *callid = async_get_call(data);
     2951        *chandle = async_get_call(data);
    29162952       
    29172953        if (IPC_GET_IMETHOD(*data) != IPC_M_DATA_WRITE)
     
    29302966 * argument.
    29312967 *
    2932  * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
    2933  * @param dst    Final destination address for the IPC_M_DATA_WRITE call.
    2934  * @param size   Final size for the IPC_M_DATA_WRITE call.
    2935  *
    2936  * @return Zero on success or a value from @ref errno.h on failure.
    2937  *
    2938  */
    2939 int async_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
    2940 {
    2941         return ipc_answer_2(callid, EOK, (sysarg_t) dst, (sysarg_t) size);
     2968 * @param chandle  Handle of the IPC_M_DATA_WRITE call to answer.
     2969 * @param dst      Final destination address for the IPC_M_DATA_WRITE call.
     2970 * @param size     Final size for the IPC_M_DATA_WRITE call.
     2971 *
     2972 * @return  Zero on success or a value from @ref errno.h on failure.
     2973 *
     2974 */
     2975int async_data_write_finalize(cap_handle_t chandle, void *dst, size_t size)
     2976{
     2977        return ipc_answer_2(chandle, EOK, (sysarg_t) dst, (sysarg_t) size);
    29422978}
    29432979
     
    29693005        assert(data);
    29703006       
    2971         ipc_callid_t callid;
     3007        cap_handle_t chandle;
    29723008        size_t size;
    2973         if (!async_data_write_receive(&callid, &size)) {
    2974                 ipc_answer_0(callid, EINVAL);
     3009        if (!async_data_write_receive(&chandle, &size)) {
     3010                ipc_answer_0(chandle, EINVAL);
    29753011                return EINVAL;
    29763012        }
    29773013       
    29783014        if (size < min_size) {
    2979                 ipc_answer_0(callid, EINVAL);
     3015                ipc_answer_0(chandle, EINVAL);
    29803016                return EINVAL;
    29813017        }
    29823018       
    29833019        if ((max_size > 0) && (size > max_size)) {
    2984                 ipc_answer_0(callid, EINVAL);
     3020                ipc_answer_0(chandle, EINVAL);
    29853021                return EINVAL;
    29863022        }
    29873023       
    29883024        if ((granularity > 0) && ((size % granularity) != 0)) {
    2989                 ipc_answer_0(callid, EINVAL);
     3025                ipc_answer_0(chandle, EINVAL);
    29903026                return EINVAL;
    29913027        }
     
    29993035       
    30003036        if (arg_data == NULL) {
    3001                 ipc_answer_0(callid, ENOMEM);
     3037                ipc_answer_0(chandle, ENOMEM);
    30023038                return ENOMEM;
    30033039        }
    30043040       
    3005         int rc = async_data_write_finalize(callid, arg_data, size);
     3041        int rc = async_data_write_finalize(chandle, arg_data, size);
    30063042        if (rc != EOK) {
    30073043                free(arg_data);
     
    30263062 *
    30273063 */
    3028 void async_data_write_void(sysarg_t retval)
    3029 {
    3030         ipc_callid_t callid;
    3031         async_data_write_receive(&callid, NULL);
    3032         ipc_answer_0(callid, retval);
     3064void async_data_write_void(int retval)
     3065{
     3066        cap_handle_t chandle;
     3067        async_data_write_receive(&chandle, NULL);
     3068        ipc_answer_0(chandle, retval);
    30333069}
    30343070
     
    30433079                return ENOENT;
    30443080       
    3045         ipc_callid_t callid;
    3046         if (!async_data_write_receive(&callid, NULL)) {
    3047                 ipc_answer_0(callid, EINVAL);
     3081        cap_handle_t chandle;
     3082        if (!async_data_write_receive(&chandle, NULL)) {
     3083                ipc_answer_0(chandle, EINVAL);
    30483084                return EINVAL;
    30493085        }
     
    30523088            dataptr);
    30533089        if (msg == 0) {
    3054                 ipc_answer_0(callid, EINVAL);
     3090                ipc_answer_0(chandle, EINVAL);
    30553091                return EINVAL;
    30563092        }
    30573093       
    3058         int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
     3094        int retval = ipc_forward_fast(chandle, exch->phone, 0, 0, 0,
    30593095            IPC_FF_ROUTE_FROM_ME);
    30603096        if (retval != EOK) {
    30613097                async_forget(msg);
    3062                 ipc_answer_0(callid, retval);
     3098                ipc_answer_0(chandle, retval);
    30633099                return retval;
    30643100        }
    30653101       
    3066         sysarg_t rc;
     3102        int rc;
    30673103        async_wait_for(msg, &rc);
    30683104       
     
    30853121        /* Accept the phone */
    30863122        ipc_call_t call;
    3087         ipc_callid_t callid = async_get_call(&call);
    3088         int phone = (int) IPC_GET_ARG5(call);
    3089        
    3090         if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) ||
    3091             (phone < 0)) {
    3092                 async_answer_0(callid, EINVAL);
     3123        cap_handle_t chandle = async_get_call(&call);
     3124        cap_handle_t phandle = (cap_handle_t) IPC_GET_ARG5(call);
     3125       
     3126        if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) || (phandle < 0)) {
     3127                async_answer_0(chandle, EINVAL);
    30933128                return NULL;
    30943129        }
     
    30963131        async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
    30973132        if (sess == NULL) {
    3098                 async_answer_0(callid, ENOMEM);
     3133                async_answer_0(chandle, ENOMEM);
    30993134                return NULL;
    31003135        }
     
    31023137        sess->iface = 0;
    31033138        sess->mgmt = mgmt;
    3104         sess->phone = phone;
     3139        sess->phone = phandle;
    31053140        sess->arg1 = 0;
    31063141        sess->arg2 = 0;
     
    31153150       
    31163151        /* Acknowledge the connected phone */
    3117         async_answer_0(callid, EOK);
     3152        async_answer_0(chandle, EOK);
    31183153       
    31193154        return sess;
     
    31363171async_sess_t *async_callback_receive_start(exch_mgmt_t mgmt, ipc_call_t *call)
    31373172{
    3138         int phone = (int) IPC_GET_ARG5(*call);
    3139        
    3140         if ((IPC_GET_IMETHOD(*call) != IPC_M_CONNECT_TO_ME) ||
    3141             (phone < 0))
     3173        cap_handle_t phandle = (cap_handle_t) IPC_GET_ARG5(*call);
     3174       
     3175        if ((IPC_GET_IMETHOD(*call) != IPC_M_CONNECT_TO_ME) || (phandle < 0))
    31423176                return NULL;
    31433177       
     
    31483182        sess->iface = 0;
    31493183        sess->mgmt = mgmt;
    3150         sess->phone = phone;
     3184        sess->phone = phandle;
    31513185        sess->arg1 = 0;
    31523186        sess->arg2 = 0;
     
    31703204}
    31713205
    3172 bool async_state_change_receive(ipc_callid_t *callid, sysarg_t *arg1,
     3206bool async_state_change_receive(cap_handle_t *chandle, sysarg_t *arg1,
    31733207    sysarg_t *arg2, sysarg_t *arg3)
    31743208{
    3175         assert(callid);
     3209        assert(chandle);
    31763210       
    31773211        ipc_call_t call;
    3178         *callid = async_get_call(&call);
     3212        *chandle = async_get_call(&call);
    31793213       
    31803214        if (IPC_GET_IMETHOD(call) != IPC_M_STATE_CHANGE_AUTHORIZE)
     
    31913225}
    31923226
    3193 int async_state_change_finalize(ipc_callid_t callid, async_exch_t *other_exch)
    3194 {
    3195         return ipc_answer_1(callid, EOK, other_exch->phone);
     3227int async_state_change_finalize(cap_handle_t chandle, async_exch_t *other_exch)
     3228{
     3229        return ipc_answer_1(chandle, EOK, other_exch->phone);
    31963230}
    31973231
Note: See TracChangeset for help on using the changeset viewer.