+ exec* functions
[meinos.git] / kernel2 / rpc.c
blobd21987c79fd726f76a5c3df5baf75439fd427452
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <rpc.h>
20 #include <procm.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <llist.h>
24 #include <debug.h>
25 #include <syscall.h>
26 #include <interrupt.h>
28 #include <cpu.h>
30 int rpc_init() {
31 rpc_functions = llist_create();
32 rpc_lastid = 0;
33 if (syscall_create(SYSCALL_RPC_CREATE,rpc_function_create,4)==-1) return -1;
34 if (syscall_create(SYSCALL_RPC_DESTROY,rpc_function_destroy,1)==-1) return -1;
35 if (syscall_create(SYSCALL_RPC_GETINFO,rpc_function_getinfo,8)==-1) return -1;
36 if (syscall_create(SYSCALL_RPC_CALL,rpc_function_call,5)==-1) return -1;
37 if (syscall_create(SYSCALL_RPC_POLL,rpc_call_poll,4)==-1) return -1;
38 if (syscall_create(SYSCALL_RPC_RETURN,rpc_call_return,3)==-1) return -1;
39 if (syscall_create(SYSCALL_RPC_LIST,rpc_list,3)==-1) return -1;
40 return 0;
43 /**
44 * Creates a RPC function (Syscall)
45 * @param name Function name
46 * @param rpc_handler RPC handler
47 * @param func Function pointer
48 * @param synopsis Funtion synopsis
49 * @return Function ID
51 int rpc_function_create(char *name,void *func,char *synopsis,size_t params_size) {
52 rpc_function_t *new = malloc(sizeof(rpc_function_t));
53 new->id = rpc_lastid++;
54 new->name = strdup(name);
55 new->func = func;
56 new->synopsis = strdup(synopsis);
57 new->owner = proc_current;
58 new->calls = llist_create();
59 new->params_size = params_size;
60 llist_push(rpc_functions,new);
61 return new->id;
64 /**
65 * Destroys a RPC function (Syscall)
66 * @param id Function ID
67 * @return Success?
69 int rpc_function_destroy(int id) {
70 rpc_function_t *func = rpc_find(id,NULL,NULL,0,0);
71 if (func!=NULL) {
72 if (func->owner==proc_current) {
73 free(func->name);
74 free(func->synopsis);
75 rpc_call_t *call;
76 while ((call = llist_pop(func->calls))) rpc_call_destroy(call);
77 return 0;
79 else return -EACCES;
81 else return -EINVAL;
84 /**
85 * Gets information about RPC function (Syscall)
86 * @param id Function ID (or -1)
87 * @param name Function name (or NULL)
88 * @param pid Function owner's PID (or 0)
89 * @param has_calls Whether function must have calls
90 * @param params_size Reference for size of params
91 * @param synopsis Buffer for synopsis
92 * @param maxlen Maxlen for synopsis
93 * @param sleep Whether to sleep til next found (works only for owner)
94 * @return Function ID
96 int rpc_function_getinfo(int id,char *name,pid_t pid,int has_calls,size_t *params_size,char *synopsis,size_t maxlen,int sleep) {
97 rpc_function_t *func = rpc_find(id,name,NULL,pid,has_calls);
98 if (func!=NULL) {
99 strncpy(synopsis,func->synopsis,maxlen);
100 *params_size = func->params_size;
101 return func->id;
103 else if (sleep && has_calls && pid==proc_current->pid) {
104 *(interrupt_curregs.eax) = -1;
105 proc_sleep(proc_current);
106 return -1;
108 else return -EINVAL;
112 * Calls a RPC function (Syscall)
113 * @param id Function ID
114 * @param params Parameters
115 * @param ret Reference for return value
116 * @param ret_params Reference for return parameters (can be NULL)
117 * @param error Reference for RPC error
118 * @param sleep Sleep Reference
119 * @return Success?
121 int rpc_function_call(int id,void *params,int *ret,void *ret_params,int *error) {
122 rpc_function_t *func = rpc_find(id,NULL,NULL,0,0);
123 if (func!=NULL) {
124 rpc_call_t *new = malloc(sizeof(rpc_call_t));
125 new->caller = proc_current;
126 new->ret = ret;
127 new->ret_params = ret_params;
128 new->params = memcpy(malloc(func->params_size),params,func->params_size);
129 new->error = error;
130 llist_push(func->calls,new);
131 if (error!=NULL) *error = 1;
132 proc_wake(func->owner);
133 *(interrupt_curregs.eax) = 0;
134 proc_sleep(proc_current);
135 return 0;
137 else return -EINVAL;
141 * Destroys a RPC Call
142 * @param call RPC Call
143 * @return Success?
145 int rpc_call_destroy(rpc_call_t *call) {
146 free(call->params);
147 free(call);
148 return 0;
152 * Checks for new calls (Syscall)
153 * @param id Function ID (or -1)
154 * @param func Reference for function pointer
155 * @param params Buffer for params
156 * @param caller Reference for caller PID
157 * @return Success?
159 int rpc_call_poll(int id,void **func_ptr,void *params,pid_t *caller) {
160 rpc_function_t *func = rpc_find(-1,NULL,proc_current,0,1);
161 if (func!=NULL) {
162 rpc_call_t *call = llist_pop(func->calls);
163 func->current = call;
164 *func_ptr = func->func;
165 *caller = call->caller->pid;
166 memcpy(params,call->params,func->params_size);
167 return 0;
169 else return -EINVAL;
173 * Returns from a RPC functions (Syscall)
174 * @param id Function ID (or -1)
175 * @param ret Return value
176 * @param ret_params Return params
177 * @return Success?
179 int rpc_call_return(int id,int ret,void *ret_params) {
180 rpc_function_t *func = rpc_find(id,NULL,proc_current,0,0);
181 if (func!=NULL) {
182 rpc_call_t *call = func->current;
183 if (call!=NULL) {
184 if (call->ret_params!=NULL) {
185 void *buf = memcpy(malloc(func->params_size),ret_params,func->params_size);
186 memuser_load_addrspace(call->caller->addrspace);
187 memcpy(call->ret_params,buf,func->params_size);
189 else memuser_load_addrspace(call->caller->addrspace);
190 if (call->ret!=NULL) *(call->ret) = ret;
191 if (call->error!=NULL) *(call->error) = 0;
192 memuser_load_addrspace(proc_current->addrspace);
193 proc_wake(call->caller);
194 rpc_call_destroy(call);
195 func->current = NULL;
196 return 0;
199 return -EINVAL;
203 * Finds a RPC function
204 * @param id Function ID (or -1)
205 * @param name Function name (or NULL)
206 * @param owner Function owner (or NULL)
207 * @param pid Function owner's PID (or 0)
208 * @param has_calls Whether to check if functions is called
209 * @return RPC function
211 rpc_function_t *rpc_find(int id,char *name,proc_t *owner,pid_t pid,int has_calls) {
212 rpc_function_t *func;
213 size_t i;
214 for (i=0;(func = llist_get(rpc_functions,i));i++) {
215 if ((id==-1 || id==func->id) && (name==NULL || strcmp(name,func->name)==0) && (owner==NULL || owner==func->owner) && (pid==0 || pid==func->owner->pid) && (has_calls==0 || !llist_empty(func->calls))) return func;
217 return NULL;
221 * "Lists" RPC function.
222 * @param i Index of current function
223 * @param buf Buffer for name
224 * @param bufsize Size of buffer
225 * @return Count of copied bytes
227 size_t rpc_list(size_t i,char *buf,size_t bufsize) {
228 rpc_function_t *func;
229 func = llist_get(rpc_functions,i);
230 if (func!=NULL) {
231 if (buf==NULL || bufsize==0) { // only return size
232 return strlen(func->name)+1;
234 else {
235 strncpy(buf,func->name,bufsize);
236 return strlen(buf)+1;
239 else return 0;