Subversion Repositories HelenOS

Rev

Rev 977 | Rev 1005 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2005 Martin Decky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. #include <syscall/syscall.h>
  30. #include <proc/thread.h>
  31. #include <mm/as.h>
  32. #include <print.h>
  33. #include <putchar.h>
  34. #include <ipc/ipc.h>
  35. #include <errno.h>
  36. #include <proc/task.h>
  37. #include <arch.h>
  38. #include <debug.h>
  39.  
  40. static __native sys_ctl(void) {
  41.     printf("Thread finished\n");
  42.     thread_exit();
  43.     /* Unreachable */
  44.     return 0;
  45. }
  46.  
  47. static __native sys_io(int fd, const void * buf, size_t count) {
  48.    
  49.     // TODO: buf sanity checks and a lot of other stuff ...
  50.  
  51.     size_t i;
  52.    
  53.     for (i = 0; i < count; i++)
  54.         putchar(((char *) buf)[i]);
  55.    
  56.     return count;
  57. }
  58.  
  59. static phone_t * get_phone(__native phoneid)
  60. {
  61.     phone_t *phone;
  62.  
  63.     if (phoneid >= IPC_MAX_PHONES)
  64.         return NULL;
  65.  
  66.     phone = &TASK->phones[phoneid];
  67.     if (!phone->callee)
  68.         return NULL;
  69.     return phone;
  70. }
  71.  
  72. /** Send a call over IPC, wait for reply, return to user
  73.  *
  74.  * @return Call identification, returns -1 on fatal error,
  75.            -2 on 'Too many async request, handle answers first
  76.  */
  77. static __native sys_ipc_call_sync_fast(__native phoneid, __native method,
  78.                        __native arg1, __native *data)
  79. {
  80.     call_t call;
  81.     phone_t *phone;
  82.     /* Special answerbox for synchronous messages */
  83.  
  84.     phone = get_phone(phoneid);
  85.     if (!phone)
  86.         return IPC_CALLRET_FATAL;
  87.  
  88.     ipc_call_init(&call);
  89.     IPC_SET_METHOD(call.data, method);
  90.     IPC_SET_ARG1(call.data, arg1);
  91.    
  92.     ipc_call_sync(phone, &call);
  93.  
  94.     copy_to_uspace(data, &call.data, sizeof(call.data));
  95.  
  96.     return 0;
  97. }
  98.  
  99. /** Synchronous IPC call allowing to send whole message */
  100. static __native sys_ipc_call_sync(__native phoneid, __native *data)
  101. {
  102.     call_t call;
  103.     phone_t *phone;
  104.     /* Special answerbox for synchronous messages */
  105.  
  106.     phone = get_phone(phoneid);
  107.     if (!phone)
  108.         return IPC_CALLRET_FATAL;
  109.  
  110.     ipc_call_init(&call);
  111.     copy_from_uspace(&call.data, data, sizeof(call.data));
  112.    
  113.     ipc_call_sync(phone, &call);
  114.  
  115.     copy_to_uspace(data, &call.data, sizeof(call.data));
  116.  
  117.     return 0;
  118. }
  119.  
  120. /** Check that the task did not exceed allowed limit
  121.  *
  122.  * @return 0 - Limit OK,   -1 - limit exceeded
  123.  */
  124. static int check_call_limit(void)
  125. {
  126.     if (atomic_inc_post(&TASK->active_calls) > IPC_MAX_ASYNC_CALLS) {
  127.         atomic_dec(&TASK->active_calls);
  128.         return -1;
  129.     }
  130.     return 0;
  131. }
  132.  
  133. /** Send an asynchronous call over ipc
  134.  *
  135.  * @return Call identification, returns -1 on fatal error,
  136.            -2 on 'Too many async request, handle answers first
  137.  */
  138. static __native sys_ipc_call_async_fast(__native phoneid, __native method,
  139.                     __native arg1, __native arg2)
  140. {
  141.     call_t *call;
  142.     phone_t *phone;
  143.  
  144.     phone = get_phone(phoneid);
  145.     if (!phone)
  146.         return IPC_CALLRET_FATAL;
  147.  
  148.     if (check_call_limit())
  149.         return IPC_CALLRET_TEMPORARY;
  150.  
  151.     call = ipc_call_alloc();
  152.     IPC_SET_METHOD(call->data, method);
  153.     IPC_SET_ARG1(call->data, arg1);
  154.     IPC_SET_ARG2(call->data, arg2);
  155.  
  156.     ipc_call(phone, call);
  157.  
  158.     return (__native) call;
  159. }
  160.  
  161. /** Synchronous IPC call allowing to send whole message
  162.  *
  163.  * @return The same as sys_ipc_call_async
  164.  */
  165. static __native sys_ipc_call_async(__native phoneid, __native *data)
  166. {
  167.     call_t *call;
  168.     phone_t *phone;
  169.  
  170.     phone = get_phone(phoneid);
  171.     if (!phone)
  172.         return IPC_CALLRET_FATAL;
  173.  
  174.     if (check_call_limit())
  175.         return IPC_CALLRET_TEMPORARY;
  176.  
  177.     call = ipc_call_alloc();
  178.     copy_from_uspace(&call->data, data, sizeof(call->data));
  179.    
  180.     ipc_call(phone, call);
  181.  
  182.     return (__native) call;
  183. }
  184.  
  185.  
  186. /** Send IPC answer */
  187. static __native sys_ipc_answer(__native callid, __native retval, __native arg1,
  188.                    __native arg2)
  189. {
  190.     call_t *call;
  191.  
  192.     /* Check that the user is not sending us answer callid */
  193.     ASSERT(! (callid & 1));
  194.     /* TODO: Check that the callid is in the dispatch table */
  195.     call = (call_t *) callid;
  196.  
  197.     IPC_SET_RETVAL(call->data, retval);
  198.     IPC_SET_ARG1(call->data, arg1);
  199.     IPC_SET_ARG2(call->data, arg2);
  200.  
  201.     ipc_answer(&TASK->answerbox, call);
  202.     return 0;
  203. }
  204.  
  205. /** Wait for incoming ipc call or answer
  206.  *
  207.  * @param result
  208.  * @param flags
  209.  * @return Callid, if callid & 1, then the call is answer
  210.  */
  211. static __native sys_ipc_wait_for_call(__native *calldata, __native flags)
  212. {
  213.     call_t *call;
  214.    
  215.     call = ipc_wait_for_call(&TASK->answerbox, flags);
  216.  
  217.     copy_to_uspace(calldata, &call->data, sizeof(call->data));
  218.  
  219.     if (call->flags & IPC_CALL_ANSWERED) {
  220.         ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
  221.         ipc_call_free(call);
  222.         atomic_dec(&TASK->active_calls);
  223.         return ((__native)call) | IPC_CALLID_ANSWERED;
  224.     }
  225.     return (__native)call;
  226. }
  227.  
  228. static __native sys_mremap(void *address, size_t size, unsigned long flags)
  229. {
  230.     return as_remap(AS, (__address) address, size, 0);
  231. }
  232.  
  233. syshandler_t syscall_table[SYSCALL_END] = {
  234.     sys_ctl,
  235.     sys_io,
  236.     sys_mremap,
  237.     sys_ipc_call_sync_fast,
  238.     sys_ipc_call_sync,
  239.     sys_ipc_call_async_fast,
  240.     sys_ipc_call_async,
  241.     sys_ipc_answer,
  242.     sys_ipc_wait_for_call
  243. };
  244.