source: mainline/ns/ns.c@ afa6e74

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since afa6e74 was afa6e74, checked in by Jakub Vana <jakub.vana@…>, 20 years ago

Earliest version of Userspace Framebuffer driver, with stream support in libc.
Also Virtual framebuffers made as split on main fb and its usage by streams

(please test it and report)

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/*
2 * Copyright (C) 2006 Ondrej Palkovsky
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/**
30 * @file ns.c
31 * @brief Naming service for HelenOS IPC.
32 */
33
34#include <ipc/ipc.h>
35#include <ipc/ns.h>
36#include <stdio.h>
37#include <unistd.h>
38#include <stdlib.h>
39#include <errno.h>
40#include <assert.h>
41#include <libadt/list.h>
42#include <libadt/hash_table.h>
43
44#define NAME "NS"
45
46#define NS_HASH_TABLE_CHAINS 20
47
48extern int __DONT_OPEN_STDIO__=1;
49
50static int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call);
51static int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid);
52
53/* Static functions implementing NS hash table operations. */
54static hash_index_t ns_hash(unsigned long *key);
55static int ns_compare(unsigned long *key, hash_count_t keys, link_t *item);
56static void ns_remove(link_t *item);
57
58/** Operations for NS hash table. */
59static hash_table_operations_t ns_hash_table_ops = {
60 .hash = ns_hash,
61 .compare = ns_compare,
62 .remove_callback = ns_remove
63};
64
65/** NS hash table structure. */
66static hash_table_t ns_hash_table;
67
68/** NS hash table item. */
69typedef struct {
70 link_t link;
71 ipcarg_t service; /**< Number of the service. */
72 ipcarg_t phone; /**< Phone registered with the service. */
73 ipcarg_t in_phone_hash; /**< Incoming phone hash. */
74} hashed_service_t;
75
76int static ping_phone;
77
78int main(int argc, char **argv)
79{
80 ipc_call_t call;
81 ipc_callid_t callid;
82 char *as_area;
83
84 ipcarg_t retval, arg1, arg2;
85
86// printf("%s: Naming service started.\n", NAME);
87
88 if (!hash_table_create(&ns_hash_table, NS_HASH_TABLE_CHAINS, 3, &ns_hash_table_ops)) {
89// printf("%s: cannot create hash table\n", NAME);
90 return ENOMEM;
91 }
92
93 while (1) {
94 callid = ipc_wait_for_call(&call, 0);
95// printf("NS: Call in_phone_hash=%lX...", call.in_phone_hash);
96 switch (IPC_GET_METHOD(call)) {
97 case IPC_M_AS_AREA_SEND:
98 as_area = (char *)IPC_GET_ARG2(call);
99// printf("Received as_area: %P, size:%d\n", as_area, IPC_GET_ARG3(call));
100 retval = ipc_answer_fast(callid, 0,(sysarg_t)(1024*1024), 0);
101 if (!retval) {
102// printf("Reading shared memory...");
103// printf("Text: %s", as_area);
104 } else
105// printf("Failed answer: %d\n", retval);
106 continue;
107 break;
108 case IPC_M_INTERRUPT:
109// printf("GOT INTERRUPT: %c\n", IPC_GET_ARG2(call));
110 break;
111 case IPC_M_PHONE_HUNGUP:
112// printf("Phone hung up.\n");
113 retval = 0;
114 break;
115 case IPC_M_CONNECT_TO_ME:
116 /*
117 * Server requests service registration.
118 */
119 retval = register_service(IPC_GET_ARG1(call), IPC_GET_ARG3(call), &call);
120 ping_phone = IPC_GET_ARG3(call);
121 break;
122 case IPC_M_CONNECT_ME_TO:
123 /*
124 * Client requests to be connected to a service.
125 */
126 retval = connect_to_service(IPC_GET_ARG1(call), &call, callid);
127 break;
128 case NS_HANGUP:
129// printf("Closing connection.\n");
130 retval = EHANGUP;
131 break;
132 case NS_PING:
133// printf("Ping...%P %P\n", IPC_GET_ARG1(call),
134// IPC_GET_ARG2(call));
135 retval = 0;
136 arg1 = 0xdead;
137 arg2 = 0xbeef;
138 break;
139 case NS_PING_SVC:
140// printf("NS:Pinging service %d\n", ping_phone);
141 ipc_call_sync(ping_phone, NS_PING, 0xbeef, 0);
142// printf("NS:Got pong\n");
143 break;
144 default:
145// printf("Unknown method: %zd\n", IPC_GET_METHOD(call));
146 retval = ENOENT;
147 break;
148 }
149 if (! (callid & IPC_CALLID_NOTIFICATION)) {
150// printf("Answering.\n");
151 ipc_answer_fast(callid, retval, arg1, arg2);
152 }
153 }
154}
155
156/** Register service.
157 *
158 * @param service Service to be registered.
159 * @param phone phone Phone to be used for connections to the service.
160 * @param call Pointer to call structure.
161 *
162 * @return Zero on success or a value from @ref errno.h.
163 */
164int register_service(ipcarg_t service, ipcarg_t phone, ipc_call_t *call)
165{
166 unsigned long keys[3] = { service, call->in_phone_hash, 0 };
167 hashed_service_t *hs;
168
169// printf("Registering service %d on phone %d...", service, phone);
170
171 if (hash_table_find(&ns_hash_table, keys)) {
172// printf("Service %d already registered.\n", service);
173 return EEXISTS;
174 }
175
176 hs = (hashed_service_t *) malloc(sizeof(hashed_service_t));
177 if (!hs) {
178// printf("Failed to register service %d.\n", service);
179 return ENOMEM;
180 }
181
182 link_initialize(&hs->link);
183 hs->service = service;
184 hs->phone = phone;
185 hs->in_phone_hash = call->in_phone_hash;
186 hash_table_insert(&ns_hash_table, keys, &hs->link);
187
188 return 0;
189}
190
191/** Connect client to service.
192 *
193 * @param service Service to be connected to.
194 * @param call Pointer to call structure.
195 * @param callid Call ID of the request.
196 *
197 * @return Zero on success or a value from @ref errno.h.
198 */
199int connect_to_service(ipcarg_t service, ipc_call_t *call, ipc_callid_t callid)
200{
201 unsigned long keys[3] = { service, 0, 0 };
202 link_t *hlp;
203 hashed_service_t *hs;
204
205 hlp = hash_table_find(&ns_hash_table, keys);
206 if (!hlp) {
207// printf("Service %d not registered.\n", service);
208 return ENOENT;
209 }
210 hs = hash_table_get_instance(hlp, hashed_service_t, link);
211// printf("Connecting in_phone_hash=%lX to service at phone %d...", call->in_phone_hash, hs->phone);
212 return ipc_forward_fast(callid, hs->phone, 0, 0);
213}
214
215/** Compute hash index into NS hash table.
216 *
217 * @param key Pointer keys. However, only the first key (i.e. service number)
218 * is used to compute the hash index.
219 * @return Hash index corresponding to key[0].
220 */
221hash_index_t ns_hash(unsigned long *key)
222{
223 assert(key);
224 return *key % NS_HASH_TABLE_CHAINS;
225}
226
227/** Compare a key with hashed item.
228 *
229 * This compare function always ignores the third key.
230 * It exists only to make it possible to remove records
231 * originating from connection with key[1] in_phone_hash
232 * value. Note that this is close to being classified
233 * as a nasty hack.
234 *
235 * @param key Array of keys.
236 * @param keys Must be lesser or equal to 3.
237 * @param item Pointer to a hash table item.
238 * @return Non-zero if the key matches the item, zero otherwise.
239 */
240int ns_compare(unsigned long key[], hash_count_t keys, link_t *item)
241{
242 hashed_service_t *hs;
243
244 assert(key);
245 assert(keys <= 3);
246 assert(item);
247
248 hs = hash_table_get_instance(item, hashed_service_t, link);
249
250 if (keys == 2)
251 return key[1] == hs->in_phone_hash;
252 else
253 return key[0] == hs->service;
254}
255
256/** Perform actions after removal of item from the hash table.
257 *
258 * @param item Item that was removed from the hash table.
259 */
260void ns_remove(link_t *item)
261{
262 assert(item);
263 free(hash_table_get_instance(item, hashed_service_t, link));
264}
Note: See TracBrowser for help on using the repository browser.