Changes in uspace/lib/c/generic/ipc.c [10477601:63f8966] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/ipc.c
r10477601 r63f8966 38 38 */ 39 39 /** @file 40 */ 40 */ 41 41 42 42 #include <ipc/ipc.h> … … 45 45 #include <errno.h> 46 46 #include <adt/list.h> 47 #include <stdio.h> 48 #include <unistd.h> 47 49 #include <futex.h> 50 #include <kernel/synch/synch.h> 51 #include <async.h> 48 52 #include <fibril.h> 53 #include <assert.h> 49 54 50 55 /** 51 * Structures of this type are used for keeping track 52 * of sent asynchronous callsand queing unsent calls.56 * Structures of this type are used for keeping track of sent asynchronous calls 57 * and queing unsent calls. 53 58 */ 54 59 typedef struct { 55 60 link_t list; 56 61 57 62 ipc_async_callback_t callback; 58 63 void *private; 59 60 64 union { 61 65 ipc_callid_t callid; … … 65 69 } msg; 66 70 } u; 71 fid_t fid; /**< Fibril waiting for sending this call. */ 72 } async_call_t; 73 74 LIST_INITIALIZE(dispatched_calls); 75 76 /** List of asynchronous calls that were not accepted by kernel. 77 * 78 * It is protected by async_futex, because if the call cannot be sent into the 79 * kernel, the async framework is used automatically. 80 */ 81 LIST_INITIALIZE(queued_calls); 82 83 static atomic_t ipc_futex = FUTEX_INITIALIZER; 84 85 /** Make a fast synchronous call. 86 * 87 * Only three payload arguments can be passed using this function. However, this 88 * function is faster than the generic ipc_call_sync_slow() because the payload 89 * is passed directly in registers. 90 * 91 * @param phoneid Phone handle for the call. 92 * @param method Requested method. 93 * @param arg1 Service-defined payload argument. 94 * @param arg2 Service-defined payload argument. 95 * @param arg3 Service-defined payload argument. 96 * @param result1 If non-NULL, the return ARG1 will be stored there. 97 * @param result2 If non-NULL, the return ARG2 will be stored there. 98 * @param result3 If non-NULL, the return ARG3 will be stored there. 99 * @param result4 If non-NULL, the return ARG4 will be stored there. 100 * @param result5 If non-NULL, the return ARG5 will be stored there. 101 * 102 * @return Negative values represent errors returned by IPC. 103 * Otherwise the RETVAL of the answer is returned. 104 */ 105 int 106 ipc_call_sync_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, 107 ipcarg_t arg3, ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3, 108 ipcarg_t *result4, ipcarg_t *result5) 109 { 110 ipc_call_t resdata; 111 int callres; 67 112 68 /** Fibril waiting for sending this call. */ 69 fid_t fid; 70 } async_call_t; 71 72 LIST_INITIALIZE(dispatched_calls); 73 74 /** List of asynchronous calls that were not accepted by kernel. 75 * 76 * Protected by async_futex, because if the call is not accepted 77 * by the kernel, the async framework is used automatically. 78 * 79 */ 80 LIST_INITIALIZE(queued_calls); 81 82 static atomic_t ipc_futex = FUTEX_INITIALIZER; 83 84 /** Fast synchronous call. 85 * 86 * Only three payload arguments can be passed using this function. However, 87 * this function is faster than the generic ipc_call_sync_slow() because 88 * the payload is passed directly in registers. 89 * 90 * @param phoneid Phone handle for the call. 91 * @param method Requested method. 92 * @param arg1 Service-defined payload argument. 93 * @param arg2 Service-defined payload argument. 94 * @param arg3 Service-defined payload argument. 95 * @param result1 If non-NULL, the return ARG1 will be stored there. 96 * @param result2 If non-NULL, the return ARG2 will be stored there. 97 * @param result3 If non-NULL, the return ARG3 will be stored there. 98 * @param result4 If non-NULL, the return ARG4 will be stored there. 99 * @param result5 If non-NULL, the return ARG5 will be stored there. 100 * 101 * @return Negative values representing IPC errors. 102 * @return Otherwise the RETVAL of the answer. 103 * 104 */ 105 int ipc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1, 106 sysarg_t arg2, sysarg_t arg3, sysarg_t *result1, sysarg_t *result2, 107 sysarg_t *result3, sysarg_t *result4, sysarg_t *result5) 108 { 109 ipc_call_t resdata; 110 int callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1, 113 callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1, 111 114 arg2, arg3, (sysarg_t) &resdata); 112 115 if (callres) 113 116 return callres; 114 115 117 if (result1) 116 118 *result1 = IPC_GET_ARG1(resdata); … … 123 125 if (result5) 124 126 *result5 = IPC_GET_ARG5(resdata); 125 127 126 128 return IPC_GET_RETVAL(resdata); 127 129 } 128 130 129 /** Synchronous call transmitting 5 arguments of payload. 130 * 131 * @param phoneid Phone handle for the call. 132 * @param imethod Requested interface and method. 133 * @param arg1 Service-defined payload argument. 134 * @param arg2 Service-defined payload argument. 135 * @param arg3 Service-defined payload argument. 136 * @param arg4 Service-defined payload argument. 137 * @param arg5 Service-defined payload argument. 138 * @param result1 If non-NULL, storage for the first return argument. 139 * @param result2 If non-NULL, storage for the second return argument. 140 * @param result3 If non-NULL, storage for the third return argument. 141 * @param result4 If non-NULL, storage for the fourth return argument. 142 * @param result5 If non-NULL, storage for the fifth return argument. 143 * 144 * @return Negative values representing IPC errors. 145 * @return Otherwise the RETVAL of the answer. 146 * 147 */ 148 int ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, 149 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 150 sysarg_t *result1, sysarg_t *result2, sysarg_t *result3, sysarg_t *result4, 151 sysarg_t *result5) 131 /** Make a synchronous call transmitting 5 arguments of payload. 132 * 133 * @param phoneid Phone handle for the call. 134 * @param method Requested method. 135 * @param arg1 Service-defined payload argument. 136 * @param arg2 Service-defined payload argument. 137 * @param arg3 Service-defined payload argument. 138 * @param arg4 Service-defined payload argument. 139 * @param arg5 Service-defined payload argument. 140 * @param result1 If non-NULL, storage for the first return argument. 141 * @param result2 If non-NULL, storage for the second return argument. 142 * @param result3 If non-NULL, storage for the third return argument. 143 * @param result4 If non-NULL, storage for the fourth return argument. 144 * @param result5 If non-NULL, storage for the fifth return argument. 145 * 146 * @return Negative value means IPC error. 147 * Otherwise the RETVAL of the answer. 148 */ 149 int 150 ipc_call_sync_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, 151 ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, ipcarg_t *result1, 152 ipcarg_t *result2, ipcarg_t *result3, ipcarg_t *result4, ipcarg_t *result5) 152 153 { 153 154 ipc_call_t data; 154 155 IPC_SET_IMETHOD(data, imethod); 155 int callres; 156 157 IPC_SET_METHOD(data, method); 156 158 IPC_SET_ARG1(data, arg1); 157 159 IPC_SET_ARG2(data, arg2); … … 159 161 IPC_SET_ARG4(data, arg4); 160 162 IPC_SET_ARG5(data, arg5); 161 162 int callres = __SYSCALL3(SYS_IPC_CALL_SYNC_SLOW, phoneid,163 (sysarg_t) &data , (sysarg_t) &data);163 164 callres = __SYSCALL3(SYS_IPC_CALL_SYNC_SLOW, phoneid, (sysarg_t) &data, 165 (sysarg_t) &data); 164 166 if (callres) 165 167 return callres; 166 168 167 169 if (result1) 168 170 *result1 = IPC_GET_ARG1(data); … … 175 177 if (result5) 176 178 *result5 = IPC_GET_ARG5(data); 177 179 178 180 return IPC_GET_RETVAL(data); 179 181 } 180 182 181 /** Send asynchronous message via syscall. 182 * 183 * @param phoneid Phone handle for the call. 184 * @param data Call data with the request. 185 * 186 * @return Hash of the call or an error code. 187 * 188 */ 189 static ipc_callid_t ipc_call_async_internal(int phoneid, ipc_call_t *data) 183 /** Syscall to send asynchronous message. 184 * 185 * @param phoneid Phone handle for the call. 186 * @param data Call data with the request. 187 * 188 * @return Hash of the call or an error code. 189 */ 190 static ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data) 190 191 { 191 192 return __SYSCALL2(SYS_IPC_CALL_ASYNC_SLOW, phoneid, (sysarg_t) data); 192 193 } 193 194 194 /** Prolog for ipc_call_async_*() functions. 195 * 196 * @param private Argument for the answer/error callback. 197 * @param callback Answer/error callback. 198 * 199 * @return New, partially initialized async_call structure or NULL. 200 * 195 /** Prolog to ipc_call_async_*() functions. 196 * 197 * @param private Argument for the answer/error callback. 198 * @param callback Answer/error callback. 199 * 200 * @return New, partially initialized async_call structure or NULL. 201 201 */ 202 202 static inline async_call_t *ipc_prepare_async(void *private, 203 203 ipc_async_callback_t callback) 204 204 { 205 async_call_t *call = 206 (async_call_t *) malloc(sizeof(async_call_t)); 205 async_call_t *call; 206 207 call = malloc(sizeof(*call)); 207 208 if (!call) { 208 209 if (callback) 209 210 callback(private, ENOMEM, NULL); 210 211 211 return NULL; 212 212 } 213 214 213 call->callback = callback; 215 214 call->private = private; 216 215 217 216 return call; 218 217 } 219 218 220 /** Epilog for ipc_call_async_*() functions. 221 * 222 * @param callid Value returned by the SYS_IPC_CALL_ASYNC_* syscall. 223 * @param phoneid Phone handle through which the call was made. 224 * @param call Structure returned by ipc_prepare_async(). 225 * @param can_preempt If true, the current fibril can be preempted 226 * in this call. 227 * 219 /** Epilogue of ipc_call_async_*() functions. 220 * 221 * @param callid Value returned by the SYS_IPC_CALL_ASYNC_* syscall. 222 * @param phoneid Phone handle through which the call was made. 223 * @param call async_call structure returned by ipc_prepare_async(). 224 * @param can_preempt If non-zero, the current fibril can be preempted in this 225 * call. 228 226 */ 229 227 static inline void ipc_finish_async(ipc_callid_t callid, int phoneid, 230 async_call_t *call, bool can_preempt) 231 { 232 if (!call) { 233 /* Nothing to do regardless if failed or not */ 228 async_call_t *call, int can_preempt) 229 { 230 if (!call) { /* Nothing to do regardless if failed or not */ 234 231 futex_up(&ipc_futex); 235 232 return; 236 233 } 237 234 238 235 if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) { 239 236 futex_up(&ipc_futex); 240 241 237 /* Call asynchronous handler with error code */ 242 238 if (call->callback) 243 239 call->callback(call->private, ENOENT, NULL); 244 245 240 free(call); 246 241 return; 247 242 } 248 243 249 244 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { 250 245 futex_up(&ipc_futex); 251 246 252 247 call->u.msg.phoneid = phoneid; 253 248 254 249 futex_down(&async_futex); 255 250 list_append(&call->list, &queued_calls); 256 251 257 252 if (can_preempt) { 258 253 call->fid = fibril_get_id(); … … 263 258 futex_up(&async_futex); 264 259 } 265 266 260 return; 267 261 } 268 269 262 call->u.callid = callid; 270 271 263 /* Add call to the list of dispatched calls */ 272 264 list_append(&call->list, &dispatched_calls); 273 265 futex_up(&ipc_futex); 274 } 275 276 /** Fast asynchronous call. 266 267 } 268 269 /** Make a fast asynchronous call. 277 270 * 278 271 * This function can only handle four arguments of payload. It is, however, … … 280 273 * 281 274 * Note that this function is a void function. 282 * 283 * During normal operation, answering this call will trigger the callback. 284 * In case of fatal error, the callback handler is called with the proper 285 * error code. If the call cannot be temporarily made, it is queued. 286 * 287 * @param phoneid Phone handle for the call. 288 * @param imethod Requested interface and method. 289 * @param arg1 Service-defined payload argument. 290 * @param arg2 Service-defined payload argument. 291 * @param arg3 Service-defined payload argument. 292 * @param arg4 Service-defined payload argument. 293 * @param private Argument to be passed to the answer/error callback. 294 * @param callback Answer or error callback. 295 * @param can_preempt If true, the current fibril will be preempted in 296 * case the kernel temporarily refuses to accept more 297 * asynchronous calls. 298 * 299 */ 300 void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1, 301 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private, 302 ipc_async_callback_t callback, bool can_preempt) 275 * During normal opertation, answering this call will trigger the callback. 276 * In case of fatal error, call the callback handler with the proper error code. 277 * If the call cannot be temporarily made, queue it. 278 * 279 * @param phoneid Phone handle for the call. 280 * @param method Requested method. 281 * @param arg1 Service-defined payload argument. 282 * @param arg2 Service-defined payload argument. 283 * @param arg3 Service-defined payload argument. 284 * @param arg4 Service-defined payload argument. 285 * @param private Argument to be passed to the answer/error callback. 286 * @param callback Answer or error callback. 287 * @param can_preempt If non-zero, the current fibril will be preempted in 288 * case the kernel temporarily refuses to accept more 289 * asynchronous calls. 290 */ 291 void ipc_call_async_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, 292 ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, void *private, 293 ipc_async_callback_t callback, int can_preempt) 303 294 { 304 295 async_call_t *call = NULL; 305 296 ipc_callid_t callid; 297 306 298 if (callback) { 307 299 call = ipc_prepare_async(private, callback); … … 309 301 return; 310 302 } 311 303 312 304 /* 313 * We need to make sure that we get callid 314 * before another threadaccesses the queue again.305 * We need to make sure that we get callid before another thread 306 * accesses the queue again. 315 307 */ 316 317 308 futex_down(&ipc_futex); 318 ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid,319 imethod, arg1,arg2, arg3, arg4);320 309 callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, 310 arg2, arg3, arg4); 311 321 312 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { 322 313 if (!call) { … … 325 316 return; 326 317 } 327 328 IPC_SET_IMETHOD(call->u.msg.data, imethod); 318 IPC_SET_METHOD(call->u.msg.data, method); 329 319 IPC_SET_ARG1(call->u.msg.data, arg1); 330 320 IPC_SET_ARG2(call->u.msg.data, arg2); 331 321 IPC_SET_ARG3(call->u.msg.data, arg3); 332 322 IPC_SET_ARG4(call->u.msg.data, arg4); 333 334 323 /* 335 324 * To achieve deterministic behavior, we always zero out the 336 325 * arguments that are beyond the limits of the fast version. 337 326 */ 338 339 327 IPC_SET_ARG5(call->u.msg.data, 0); 340 328 } 341 342 329 ipc_finish_async(callid, phoneid, call, can_preempt); 343 330 } 344 331 345 /** Asynchronous call transmitting the entire payload.332 /** Make an asynchronous call transmitting the entire payload. 346 333 * 347 334 * Note that this function is a void function. 348 * 349 * During normal operation, answering this call will trigger the callback. 350 * In case of fatal error, the callback handler is called with the proper 351 * error code. If the call cannot be temporarily made, it is queued. 352 * 353 * @param phoneid Phone handle for the call. 354 * @param imethod Requested interface and method. 355 * @param arg1 Service-defined payload argument. 356 * @param arg2 Service-defined payload argument. 357 * @param arg3 Service-defined payload argument. 358 * @param arg4 Service-defined payload argument. 359 * @param arg5 Service-defined payload argument. 360 * @param private Argument to be passed to the answer/error callback. 361 * @param callback Answer or error callback. 362 * @param can_preempt If true, the current fibril will be preempted in 363 * case the kernel temporarily refuses to accept more 364 * asynchronous calls. 365 * 366 */ 367 void ipc_call_async_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, 368 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, void *private, 369 ipc_async_callback_t callback, bool can_preempt) 370 { 371 async_call_t *call = ipc_prepare_async(private, callback); 335 * During normal opertation, answering this call will trigger the callback. 336 * In case of fatal error, call the callback handler with the proper error code. 337 * If the call cannot be temporarily made, queue it. 338 * 339 * @param phoneid Phone handle for the call. 340 * @param method Requested method. 341 * @param arg1 Service-defined payload argument. 342 * @param arg2 Service-defined payload argument. 343 * @param arg3 Service-defined payload argument. 344 * @param arg4 Service-defined payload argument. 345 * @param arg5 Service-defined payload argument. 346 * @param private Argument to be passed to the answer/error callback. 347 * @param callback Answer or error callback. 348 * @param can_preempt If non-zero, the current fibril will be preempted in 349 * case the kernel temporarily refuses to accept more 350 * asynchronous calls. 351 * 352 */ 353 void ipc_call_async_slow(int phoneid, ipcarg_t method, ipcarg_t arg1, 354 ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, void *private, 355 ipc_async_callback_t callback, int can_preempt) 356 { 357 async_call_t *call; 358 ipc_callid_t callid; 359 360 call = ipc_prepare_async(private, callback); 372 361 if (!call) 373 362 return; 374 375 IPC_SET_ IMETHOD(call->u.msg.data, imethod);363 364 IPC_SET_METHOD(call->u.msg.data, method); 376 365 IPC_SET_ARG1(call->u.msg.data, arg1); 377 366 IPC_SET_ARG2(call->u.msg.data, arg2); … … 379 368 IPC_SET_ARG4(call->u.msg.data, arg4); 380 369 IPC_SET_ARG5(call->u.msg.data, arg5); 381 382 370 /* 383 * We need to make sure that we get callid 384 * before another threadaccesses the queue again.371 * We need to make sure that we get callid before another thread 372 * accesses the queue again. 385 373 */ 386 387 374 futex_down(&ipc_futex); 388 ipc_callid_t callid = 389 ipc_call_async_internal(phoneid, &call->u.msg.data); 390 375 callid = _ipc_call_async(phoneid, &call->u.msg.data); 376 391 377 ipc_finish_async(callid, phoneid, call, can_preempt); 392 378 } 393 379 394 /** Answer received call (fast version). 380 381 /** Answer a received call - fast version. 395 382 * 396 383 * The fast answer makes use of passing retval and first four arguments in 397 384 * registers. If you need to return more, use the ipc_answer_slow() instead. 398 385 * 399 * @param callid Hash of the call being answered. 400 * @param retval Return value. 401 * @param arg1 First return argument. 402 * @param arg2 Second return argument. 403 * @param arg3 Third return argument. 404 * @param arg4 Fourth return argument. 405 * 406 * @return Zero on success. 407 * @return Value from @ref errno.h on failure. 408 * 409 */ 410 sysarg_t ipc_answer_fast(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 411 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4) 386 * @param callid Hash of the call being answered. 387 * @param retval Return value. 388 * @param arg1 First return argument. 389 * @param arg2 Second return argument. 390 * @param arg3 Third return argument. 391 * @param arg4 Fourth return argument. 392 * 393 * @return Zero on success or a value from @ref errno.h on failure. 394 */ 395 ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1, 396 ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4) 412 397 { 413 398 return __SYSCALL6(SYS_IPC_ANSWER_FAST, callid, retval, arg1, arg2, arg3, … … 415 400 } 416 401 417 /** Answer received call (entire payload). 418 * 419 * @param callid Hash of the call being answered. 420 * @param retval Return value. 421 * @param arg1 First return argument. 422 * @param arg2 Second return argument. 423 * @param arg3 Third return argument. 424 * @param arg4 Fourth return argument. 425 * @param arg5 Fifth return argument. 426 * 427 * @return Zero on success. 428 * @return Value from @ref errno.h on failure. 429 * 430 */ 431 sysarg_t ipc_answer_slow(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 432 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 402 /** Answer a received call - slow full version. 403 * 404 * @param callid Hash of the call being answered. 405 * @param retval Return value. 406 * @param arg1 First return argument. 407 * @param arg2 Second return argument. 408 * @param arg3 Third return argument. 409 * @param arg4 Fourth return argument. 410 * @param arg5 Fifth return argument. 411 * 412 * @return Zero on success or a value from @ref errno.h on failure. 413 */ 414 ipcarg_t ipc_answer_slow(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1, 415 ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5) 433 416 { 434 417 ipc_call_t data; 435 418 436 419 IPC_SET_RETVAL(data, retval); 437 420 IPC_SET_ARG1(data, arg1); … … 440 423 IPC_SET_ARG4(data, arg4); 441 424 IPC_SET_ARG5(data, arg5); 442 425 443 426 return __SYSCALL2(SYS_IPC_ANSWER_SLOW, callid, (sysarg_t) &data); 444 427 } 445 428 446 /** Try to dispatch queued calls from the async queue. 447 * 448 */ 449 static void dispatch_queued_calls(void) 450 { 429 430 /** Try to dispatch queued calls from the async queue. */ 431 static void try_dispatch_queued_calls(void) 432 { 433 async_call_t *call; 434 ipc_callid_t callid; 435 451 436 /** @todo 452 * Integrate intelligently ipc_futex so that it is locked during453 * ipc_call_async_*() until it is added to dispatched_calls.437 * Integrate intelligently ipc_futex, so that it is locked during 438 * ipc_call_async_*(), until it is added to dispatched_calls. 454 439 */ 455 456 440 futex_down(&async_futex); 457 458 441 while (!list_empty(&queued_calls)) { 459 async_call_t *call = 460 list_get_instance(queued_calls.next, async_call_t, list); 461 ipc_callid_t callid = 462 ipc_call_async_internal(call->u.msg.phoneid, &call->u.msg.data); 463 464 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) 442 call = list_get_instance(queued_calls.next, async_call_t, list); 443 callid = _ipc_call_async(call->u.msg.phoneid, 444 &call->u.msg.data); 445 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { 465 446 break; 466 447 } 467 448 list_remove(&call->list); 468 449 469 450 futex_up(&async_futex); 470 471 451 if (call->fid) 472 452 fibril_add_ready(call->fid); … … 475 455 if (call->callback) 476 456 call->callback(call->private, ENOENT, NULL); 477 478 457 free(call); 479 458 } else { 480 459 call->u.callid = callid; 481 482 460 futex_down(&ipc_futex); 483 461 list_append(&call->list, &dispatched_calls); 484 462 futex_up(&ipc_futex); 485 463 } 486 487 464 futex_down(&async_futex); 488 465 } 489 490 466 futex_up(&async_futex); 491 467 } 492 468 493 /** Handle received answer.469 /** Handle a received answer. 494 470 * 495 471 * Find the hash of the answer and call the answer callback. 496 472 * 497 * The answer has the same hash as the request OR'ed with 498 * the IPC_CALLID_ANSWERED bit. 499 * 500 * @todo Use hash table. 501 * 502 * @param callid Hash of the received answer. 503 * @param data Call data of the answer. 504 * 473 * @todo Make it use hash table. 474 * 475 * @param callid Hash of the received answer. 476 * The answer has the same hash as the request OR'ed with 477 * the IPC_CALLID_ANSWERED bit. 478 * @param data Call data of the answer. 505 479 */ 506 480 static void handle_answer(ipc_callid_t callid, ipc_call_t *data) 507 481 { 482 link_t *item; 483 async_call_t *call; 484 508 485 callid &= ~IPC_CALLID_ANSWERED; 509 486 510 487 futex_down(&ipc_futex); 511 512 link_t *item;513 488 for (item = dispatched_calls.next; item != &dispatched_calls; 514 489 item = item->next) { 515 async_call_t *call = 516 list_get_instance(item, async_call_t, list); 517 490 call = list_get_instance(item, async_call_t, list); 518 491 if (call->u.callid == callid) { 519 492 list_remove(&call->list); 520 521 493 futex_up(&ipc_futex); 522 523 494 if (call->callback) 524 call->callback(call->private, 495 call->callback(call->private, 525 496 IPC_GET_RETVAL(*data), data); 526 527 497 free(call); 528 498 return; 529 499 } 530 500 } 531 532 501 futex_up(&ipc_futex); 533 502 } 534 503 535 /** Wait for first IPC call to come. 536 * 537 * @param call Incoming call storage.538 * @param usec Timeout in microseconds539 * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking).540 * 541 * @return Hash of the call. Note that certain bits have special542 * meaning: IPC_CALLID_ANSWERED is set in an answer543 * and IPC_CALLID_NOTIFICATION is used for notifications.544 * 545 * /546 ipc_callid_t ipc_wait_cycle(ipc_call_t *call, sysarg_t usec, 547 unsignedint flags)548 { 549 ipc_callid_t callid =550 __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags); 551 504 505 /** Wait for a first call to come. 506 * 507 * @param call Storage where the incoming call data will be stored. 508 * @param usec Timeout in microseconds 509 * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking). 510 * 511 * @return Hash of the call. Note that certain bits have special 512 * meaning. IPC_CALLID_ANSWERED will be set in an answer 513 * and IPC_CALLID_NOTIFICATION is used for notifications. 514 * 515 */ 516 ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags) 517 { 518 ipc_callid_t callid; 519 520 callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags); 552 521 /* Handle received answers */ 553 522 if (callid & IPC_CALLID_ANSWERED) { 554 523 handle_answer(callid, call); 555 dispatch_queued_calls();524 try_dispatch_queued_calls(); 556 525 } 557 526 558 527 return callid; 559 528 } 560 529 561 /** Interrupt one thread of this task from waiting for IPC. 562 * 563 */ 564 void ipc_poke(void) 565 { 566 __SYSCALL0(SYS_IPC_POKE); 567 } 568 569 /** Wait for first IPC call to come. 570 * 571 * Only requests are returned, answers are processed internally. 572 * 573 * @param call Incoming call storage. 574 * @param usec Timeout in microseconds 575 * 576 * @return Hash of the call. 577 * 578 */ 579 ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, sysarg_t usec) 530 /** Wait some time for an IPC call. 531 * 532 * The call will return after an answer is received. 533 * 534 * @param call Storage where the incoming call data will be stored. 535 * @param usec Timeout in microseconds. 536 * 537 * @return Hash of the answer. 538 */ 539 ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec) 580 540 { 581 541 ipc_callid_t callid; 582 542 583 543 do { 584 544 callid = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE); 585 545 } while (callid & IPC_CALLID_ANSWERED); 586 546 587 547 return callid; 588 548 } … … 590 550 /** Check if there is an IPC call waiting to be picked up. 591 551 * 592 * Only requests are returned, answers are processed internally. 593 * 594 * @param call Incoming call storage. 595 * 596 * @return Hash of the call. 597 * 552 * @param call Storage where the incoming call will be stored. 553 * @return Hash of the answer. 598 554 */ 599 555 ipc_callid_t ipc_trywait_for_call(ipc_call_t *call) 600 556 { 601 557 ipc_callid_t callid; 602 558 603 559 do { 604 560 callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, 605 561 SYNCH_FLAGS_NON_BLOCKING); 606 562 } while (callid & IPC_CALLID_ANSWERED); 607 563 608 564 return callid; 609 565 } 610 566 611 /** Request callback connection. 612 * 613 * The @a taskhash and @a phonehash identifiers returned 614 * by the kernel can be used for connection tracking. 615 * 616 * @param phoneid Phone handle used for contacting the other side. 617 * @param arg1 User defined argument. 618 * @param arg2 User defined argument. 619 * @param arg3 User defined argument. 620 * @param taskhash Opaque identifier of the client task. 621 * @param phonehash Opaque identifier of the phone that will 622 * be used for incoming calls. 623 * 624 * @return Zero on success or a negative error code. 625 * 626 */ 627 int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, 628 sysarg_t *taskhash, sysarg_t *phonehash) 567 /** Interrupt one thread of this task from waiting for IPC. */ 568 void ipc_poke(void) 569 { 570 __SYSCALL0(SYS_IPC_POKE); 571 } 572 573 /** Ask destination to do a callback connection. 574 * 575 * @param phoneid Phone handle used for contacting the other side. 576 * @param arg1 Service-defined argument. 577 * @param arg2 Service-defined argument. 578 * @param arg3 Service-defined argument. 579 * @param phonehash Storage where the library will store an opaque 580 * identifier of the phone that will be used for incoming 581 * calls. This identifier can be used for connection 582 * tracking. 583 * 584 * @return Zero on success or a negative error code. 585 */ 586 int ipc_connect_to_me(int phoneid, int arg1, int arg2, int arg3, 587 ipcarg_t *phonehash) 629 588 { 630 589 return ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2, 631 arg3, NULL, NULL, NULL, taskhash, phonehash); 632 } 633 634 /** Request new connection. 635 * 636 * @param phoneid Phone handle used for contacting the other side. 637 * @param arg1 User defined argument. 638 * @param arg2 User defined argument. 639 * @param arg3 User defined argument. 640 * 641 * @return New phone handle on success or a negative error code. 642 * 643 */ 644 int ipc_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 645 { 646 sysarg_t newphid; 647 int res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 590 arg3, NULL, NULL, NULL, NULL, phonehash); 591 } 592 593 /** Ask through phone for a new connection to some service. 594 * 595 * @param phoneid Phone handle used for contacting the other side. 596 * @param arg1 User defined argument. 597 * @param arg2 User defined argument. 598 * @param arg3 User defined argument. 599 * 600 * @return New phone handle on success or a negative error code. 601 */ 602 int ipc_connect_me_to(int phoneid, int arg1, int arg2, int arg3) 603 { 604 ipcarg_t newphid; 605 int res; 606 607 res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 648 608 NULL, NULL, NULL, NULL, &newphid); 649 609 if (res) 650 610 return res; 651 652 611 return newphid; 653 612 } 654 613 655 /** Request new connection (blocking)614 /** Ask through phone for a new connection to some service. 656 615 * 657 616 * If the connection is not available at the moment, the 658 * call should block. This has to be, however, implemented 659 * on the server side. 660 * 661 * @param phoneid Phone handle used for contacting the other side. 662 * @param arg1 User defined argument. 663 * @param arg2 User defined argument. 664 * @param arg3 User defined argument. 665 * 666 * @return New phone handle on success or a negative error code. 667 * 668 */ 669 int ipc_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2, 670 sysarg_t arg3) 671 { 672 sysarg_t newphid; 673 int res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 617 * call will block. 618 * 619 * @param phoneid Phone handle used for contacting the other side. 620 * @param arg1 User defined argument. 621 * @param arg2 User defined argument. 622 * @param arg3 User defined argument. 623 * 624 * @return New phone handle on success or a negative error code. 625 */ 626 int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3) 627 { 628 ipcarg_t newphid; 629 int res; 630 631 res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 674 632 IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); 675 633 if (res) 676 634 return res; 677 678 635 return newphid; 679 636 } … … 681 638 /** Hang up a phone. 682 639 * 683 * @param phoneid Handle of the phone to be hung up. 684 * 685 * @return Zero on success or a negative error code. 686 * 640 * @param phoneid Handle of the phone to be hung up. 641 * 642 * @return Zero on success or a negative error code. 687 643 */ 688 644 int ipc_hangup(int phoneid) … … 691 647 } 692 648 649 /** Register IRQ notification. 650 * 651 * @param inr IRQ number. 652 * @param devno Device number of the device generating inr. 653 * @param method Use this method for notifying me. 654 * @param ucode Top-half pseudocode handler. 655 * 656 * @return Value returned by the kernel. 657 */ 658 int ipc_register_irq(int inr, int devno, int method, irq_code_t *ucode) 659 { 660 return __SYSCALL4(SYS_IPC_REGISTER_IRQ, inr, devno, method, 661 (sysarg_t) ucode); 662 } 663 664 /** Unregister IRQ notification. 665 * 666 * @param inr IRQ number. 667 * @param devno Device number of the device generating inr. 668 * 669 * @return Value returned by the kernel. 670 */ 671 int ipc_unregister_irq(int inr, int devno) 672 { 673 return __SYSCALL2(SYS_IPC_UNREGISTER_IRQ, inr, devno); 674 } 675 693 676 /** Forward a received call to another destination. 694 677 * 695 * For non-system methods, the old method, arg1 and arg2 are rewritten 696 * by the new values. For system methods, the new method, arg1 and arg2 697 * are written to the old arg1, arg2 and arg3, respectivelly. Calls with 698 * immutable methods are forwarded verbatim. 699 * 700 * @param callid Hash of the call to forward. 701 * @param phoneid Phone handle to use for forwarding. 702 * @param imethod New interface and method for the forwarded call. 703 * @param arg1 New value of the first argument for the forwarded call. 704 * @param arg2 New value of the second argument for the forwarded call. 705 * @param mode Flags specifying mode of the forward operation. 706 * 707 * @return Zero on success or an error code. 708 * 709 */ 710 int ipc_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod, 711 sysarg_t arg1, sysarg_t arg2, unsigned int mode) 712 { 713 return __SYSCALL6(SYS_IPC_FORWARD_FAST, callid, phoneid, imethod, arg1, 678 * @param callid Hash of the call to forward. 679 * @param phoneid Phone handle to use for forwarding. 680 * @param method New method for the forwarded call. 681 * @param arg1 New value of the first argument for the forwarded call. 682 * @param arg2 New value of the second argument for the forwarded call. 683 * @param mode Flags specifying mode of the forward operation. 684 * 685 * @return Zero on success or an error code. 686 * 687 * For non-system methods, the old method, arg1 and arg2 are rewritten by the 688 * new values. For system methods, the new method, arg1 and arg2 are written 689 * to the old arg1, arg2 and arg3, respectivelly. Calls with immutable 690 * methods are forwarded verbatim. 691 */ 692 int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, 693 ipcarg_t arg1, ipcarg_t arg2, int mode) 694 { 695 return __SYSCALL6(SYS_IPC_FORWARD_FAST, callid, phoneid, method, arg1, 714 696 arg2, mode); 715 697 } 716 698 717 int ipc_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod, 718 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 719 unsigned int mode) 699 700 int ipc_forward_slow(ipc_callid_t callid, int phoneid, int method, 701 ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, 702 int mode) 720 703 { 721 704 ipc_call_t data; 722 723 IPC_SET_ IMETHOD(data, imethod);705 706 IPC_SET_METHOD(data, method); 724 707 IPC_SET_ARG1(data, arg1); 725 708 IPC_SET_ARG2(data, arg2); … … 727 710 IPC_SET_ARG4(data, arg4); 728 711 IPC_SET_ARG5(data, arg5); 729 730 return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, 731 mode); 732 } 733 734 /** Wrapper for IPC_M_SHARE_IN calls. 735 * 736 * @param phoneid Phone that will be used to contact the receiving side. 737 * @param dst Destination address space area base. 738 * @param size Size of the destination address space area. 739 * @param arg User defined argument. 740 * @param flags Storage for received flags. Can be NULL. 741 * 742 * @return Zero on success or a negative error code from errno.h. 743 * 744 */ 745 int ipc_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 746 unsigned int *flags) 712 713 return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode); 714 } 715 716 /** Wrapper for making IPC_M_SHARE_IN calls. 717 * 718 * @param phoneid Phone that will be used to contact the receiving side. 719 * @param dst Destination address space area base. 720 * @param size Size of the destination address space area. 721 * @param arg User defined argument. 722 * @param flags Storage where the received flags will be stored. Can be 723 * NULL. 724 * 725 * @return Zero on success or a negative error code from errno.h. 726 */ 727 int ipc_share_in_start(int phoneid, void *dst, size_t size, ipcarg_t arg, 728 int *flags) 747 729 { 748 730 sysarg_t tmp_flags = 0; 749 int res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, ( sysarg_t) dst,750 ( sysarg_t) size, arg, NULL, &tmp_flags);731 int res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst, 732 (ipcarg_t) size, arg, NULL, &tmp_flags); 751 733 752 734 if (flags) 753 *flags = (unsigned int)tmp_flags;735 *flags = tmp_flags; 754 736 755 737 return res; … … 758 740 /** Wrapper for answering the IPC_M_SHARE_IN calls. 759 741 * 760 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 761 * calls so that the user doesn't have to remember the meaning of each 762 * IPC argument. 763 * 764 * @param callid Hash of the IPC_M_DATA_READ call to answer. 765 * @param src Source address space base. 766 * @param flags Flags to be used for sharing. Bits can be only cleared. 767 * 768 * @return Zero on success or a value from @ref errno.h on failure. 769 * 770 */ 771 int ipc_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags) 772 { 773 return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) flags); 774 } 775 776 /** Wrapper for IPC_M_SHARE_OUT calls. 777 * 778 * @param phoneid Phone that will be used to contact the receiving side. 779 * @param src Source address space area base address. 780 * @param flags Flags to be used for sharing. Bits can be only cleared. 781 * 782 * @return Zero on success or a negative error code from errno.h. 783 * 784 */ 785 int ipc_share_out_start(int phoneid, void *src, unsigned int flags) 786 { 787 return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0, 788 (sysarg_t) flags); 742 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 743 * so that the user doesn't have to remember the meaning of each IPC argument. 744 * 745 * @param callid Hash of the IPC_M_DATA_READ call to answer. 746 * @param src Source address space base. 747 * @param flags Flags to be used for sharing. Bits can be only cleared. 748 * 749 * @return Zero on success or a value from @ref errno.h on failure. 750 */ 751 int ipc_share_in_finalize(ipc_callid_t callid, void *src, int flags) 752 { 753 return ipc_answer_2(callid, EOK, (ipcarg_t) src, (ipcarg_t) flags); 754 } 755 756 /** Wrapper for making IPC_M_SHARE_OUT calls. 757 * 758 * @param phoneid Phone that will be used to contact the receiving side. 759 * @param src Source address space area base address. 760 * @param flags Flags to be used for sharing. Bits can be only cleared. 761 * 762 * @return Zero on success or a negative error code from errno.h. 763 */ 764 int ipc_share_out_start(int phoneid, void *src, int flags) 765 { 766 return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0, 767 (ipcarg_t) flags); 789 768 } 790 769 791 770 /** Wrapper for answering the IPC_M_SHARE_OUT calls. 792 771 * 793 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT 794 * calls so that the user doesn't have to remember the meaning of each 795 * IPC argument. 796 * 797 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 798 * @param dst Destination address space area base address. 799 * 800 * @return Zero on success or a value from @ref errno.h on failure. 801 * 772 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls 773 * so that the user doesn't have to remember the meaning of each IPC argument. 774 * 775 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 776 * @param dst Destination address space area base address. 777 * 778 * @return Zero on success or a value from @ref errno.h on failure. 802 779 */ 803 780 int ipc_share_out_finalize(ipc_callid_t callid, void *dst) 804 781 { 805 return ipc_answer_1(callid, EOK, ( sysarg_t) dst);806 } 807 808 /** Wrapper for IPC_M_DATA_READ calls. 809 * 810 * @param phoneid Phone that will be used to contact the receiving side.811 * @param dst Address of the beginning of the destination buffer.812 * @param size Sizeof the destination buffer.813 * 814 * @return Zero on success or a negative error code from errno.h.815 * 782 return ipc_answer_1(callid, EOK, (ipcarg_t) dst); 783 } 784 785 786 /** Wrapper for making IPC_M_DATA_READ calls. 787 * 788 * @param phoneid Phone that will be used to contact the receiving side. 789 * @param dst Address of the beginning of the destination buffer. 790 * @param size Size of the destination buffer. 791 * 792 * @return Zero on success or a negative error code from errno.h. 816 793 */ 817 794 int ipc_data_read_start(int phoneid, void *dst, size_t size) 818 795 { 819 return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, ( sysarg_t) dst,820 ( sysarg_t) size);796 return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst, 797 (ipcarg_t) size); 821 798 } 822 799 823 800 /** Wrapper for answering the IPC_M_DATA_READ calls. 824 801 * 825 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 826 * calls so that the user doesn't have to remember the meaning of each 827 * IPC argument. 828 * 829 * @param callid Hash of the IPC_M_DATA_READ call to answer. 830 * @param src Source address for the IPC_M_DATA_READ call. 831 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 832 * the maximum size announced by the sender. 833 * 834 * @return Zero on success or a value from @ref errno.h on failure. 835 * 802 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 803 * so that the user doesn't have to remember the meaning of each IPC argument. 804 * 805 * @param callid Hash of the IPC_M_DATA_READ call to answer. 806 * @param src Source address for the IPC_M_DATA_READ call. 807 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 808 * the maximum size announced by the sender. 809 * 810 * @return Zero on success or a value from @ref errno.h on failure. 836 811 */ 837 812 int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size) 838 813 { 839 return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) size); 840 } 841 842 /** Wrapper for IPC_M_DATA_WRITE calls. 843 * 844 * @param phoneid Phone that will be used to contact the receiving side. 845 * @param src Address of the beginning of the source buffer. 846 * @param size Size of the source buffer. 847 * 848 * @return Zero on success or a negative error code from errno.h. 849 * 814 return ipc_answer_2(callid, EOK, (ipcarg_t) src, (ipcarg_t) size); 815 } 816 817 /** Wrapper for making IPC_M_DATA_WRITE calls. 818 * 819 * @param phoneid Phone that will be used to contact the receiving side. 820 * @param src Address of the beginning of the source buffer. 821 * @param size Size of the source buffer. 822 * 823 * @return Zero on success or a negative error code from errno.h. 850 824 */ 851 825 int ipc_data_write_start(int phoneid, const void *src, size_t size) 852 826 { 853 return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, ( sysarg_t) src,854 ( sysarg_t) size);827 return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src, 828 (ipcarg_t) size); 855 829 } 856 830 857 831 /** Wrapper for answering the IPC_M_DATA_WRITE calls. 858 832 * 859 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE 860 * calls so that the user doesn't have to remember the meaning of each 861 * IPC argument. 862 * 863 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 864 * @param dst Final destination address for the IPC_M_DATA_WRITE call. 865 * @param size Final size for the IPC_M_DATA_WRITE call. 866 * 867 * @return Zero on success or a value from @ref errno.h on failure. 868 * 833 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls 834 * so that the user doesn't have to remember the meaning of each IPC argument. 835 * 836 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 837 * @param dst Final destination address for the IPC_M_DATA_WRITE call. 838 * @param size Final size for the IPC_M_DATA_WRITE call. 839 * 840 * @return Zero on success or a value from @ref errno.h on failure. 869 841 */ 870 842 int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size) 871 843 { 872 return ipc_answer_2(callid, EOK, (sysarg_t) dst, (sysarg_t) size); 873 } 874 844 return ipc_answer_2(callid, EOK, (ipcarg_t) dst, (ipcarg_t) size); 845 } 846 847 #include <kernel/syscall/sysarg64.h> 875 848 /** Connect to a task specified by id. 876 *877 849 */ 878 850 int ipc_connect_kbox(task_id_t id) 879 851 { 880 #ifdef __32_BITS__ 881 sysarg64_t arg = (sysarg64_t) id; 852 sysarg64_t arg; 853 854 arg.value = (unsigned long long) id; 855 882 856 return __SYSCALL1(SYS_IPC_CONNECT_KBOX, (sysarg_t) &arg); 883 #endif 884 885 #ifdef __64_BITS__ 886 return __SYSCALL1(SYS_IPC_CONNECT_KBOX, (sysarg_t) id); 887 #endif 888 } 889 857 } 858 890 859 /** @} 891 860 */
Note:
See TracChangeset
for help on using the changeset viewer.