]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/dope/server/common/appman.c
Inital import
[l4.git] / l4 / pkg / dope / server / common / appman.c
1 /*
2  * \brief   DOpE application manager module
3  * \date    2002-11-13
4  * \author  Norman Feske <nf2@inf.tu-dresden.de>
5  *
6  * This module is used to manage DOpE-clients.
7  * It handles all needed application specific
8  * information such as its name, variables etc.
9  */
10
11 /*
12  * Copyright (C) 2002-2004  Norman Feske  <nf2@os.inf.tu-dresden.de>
13  * Technische Universitaet Dresden, Operating Systems Research Group
14  *
15  * This file is part of the DOpE package, which is distributed under
16  * the  terms  of the  GNU General Public Licence 2.  Please see the
17  * COPYING file for details.
18  */
19
20 #include "dopestd.h"
21 #include "hashtab.h"
22 #include "thread.h"
23 #include "appman.h"
24 #include "screen.h"
25 #include "scope.h"
26
27 #define APP_NAMELEN       64    /* application identifier string length    */
28
29 static struct hashtab_services *hashtab;
30 static struct thread_services  *thread;
31 //static struct scope_services   *scope;
32
33 struct app {
34         char name[APP_NAMELEN];     /* identifier string of the application    */
35         THREAD  *app_thread;        /* application thread                      */
36         SCOPE   *rootscope;         /* root scope of the application           */
37         void    *listener;          /* associated result/event listener        */
38         THREAD  *list_thread;       /* listener thread (optional)              */
39 };
40
41
42 extern SCREEN *curr_scr;
43
44 static struct app *apps[MAX_APPS];
45
46 int init_appman(struct dope_services *d);
47
48
49 /**********************************
50  *** FUNCTIONS FOR INTERNAL USE ***
51  **********************************/
52
53 /*** RETURN THE FIRST FREE APPLICATION ID ***/
54 static s32 get_free_app_id(void) {
55         u32 i;
56
57         for (i=1; i<MAX_APPS; i++) {
58                 if (!apps[i]) return i;
59         }
60         INFO(printf("AppMan(get_free_app_id): no free dope application id!\n");)
61         return -1;
62 }
63
64
65 /*** CREATE NEW APPLICATION ***/
66 static struct app *new_app(void) {
67         struct app *new;
68
69         /* get memory for application structure */
70         new = zalloc(sizeof(struct app));
71         if (!new) {
72                 INFO(printf("AppMan(new_app): out of memory!\n");)
73                 return NULL;
74         }
75
76         /* create hash table to store the variables of the application */
77 //      new->rootscope = (SCOPE *)scope->create();
78
79         new->app_thread = thread->alloc_thread();
80         return new;
81 }
82
83
84 /*** SET THE IDENTIFIER STRING OF AN APPLICATION ***/
85 static void set_app_name(struct app *app, const char *appname) {
86         u32 i;
87
88         if (!app || !appname) return;
89
90         /* copy application name into application data structure */
91         for (i=0;i<APP_NAMELEN;i++) {
92                 app->name[i]=appname[i];
93                 if (!appname[i]) break;
94         }
95         app->name[APP_NAMELEN-1]=0;
96 }
97
98
99 /*** TEST IF AN APP_ID IS A VALID ONE ***/
100 static u16 app_id_valid(u32 app_id) {
101
102         if (app_id>=MAX_APPS) {
103                 INFO(printf("AppMan(app_id_value): invalid app_id (out of range)\n");)
104                 return 0;
105         }
106         if (!apps[app_id]) {
107                 INFO(printf("AppMan(unregister): invalid app_id (no application with this id)\n");)
108                 return 0;
109         }
110         return 1;
111 }
112
113
114 /*** RETURN NAME OF APPLICATION WITH THE SPECIFIED ID ***/
115 static char *get_app_name(s32 app_id) {
116         struct app *app;
117         if (!app_id_valid(app_id)) return "";
118         app = apps[app_id];
119         return app->name;
120 }
121
122
123 /*************************
124  *** SERVICE FUNCTIONS ***
125  *************************/
126
127 /*** REGISTER NEW APPLICATION ***
128  *
129  * app_name: identifier string for the application
130  * returns dope_client id
131  */
132 static s32 register_app(const char *app_name) {
133         s32 newapp_id;
134
135         newapp_id = get_free_app_id();
136         if (newapp_id < 0) {
137                 INFO(printf("AppMan(register): application registering failed (no free app id)\n");)
138                 return -1;
139         }
140
141         /* create data structures for the DOpE internal representation of the app */
142         apps[newapp_id] = new_app();
143         if (!apps[newapp_id]) {
144                 INFO(printf("AppMan(register): application registering failed.\n");)
145                 return -1;
146         }
147
148         set_app_name(apps[newapp_id], app_name);
149         return newapp_id;
150 }
151
152
153 /*** UNREGISTER AN APPLICATION AND FREE ALL ASSOCIATED INTERNAL RESSOURCES ***/
154 static s32 unregister_app(u32 app_id) {
155         struct app *app;
156         if (!app_id_valid(app_id)) return -1;
157
158         app = apps[app_id];
159         if (!app) return -1;
160
161         curr_scr->gen->lock((WIDGET *)curr_scr);
162
163         /* prevent any events to be delivered anymore */
164         app->listener = NULL;
165
166         /* delete root namespace */
167         if (app->rootscope) app->rootscope->gen->dec_ref((WIDGET *)app->rootscope);
168
169         /* deallocate thread ids */
170         if (app->list_thread) thread->free_thread(app->list_thread);
171         if (app->app_thread)  thread->free_thread(app->app_thread);
172
173         /* free the memory for the internal application representation */
174         free(app);
175
176         /* mark the corresponding app_id to be free */
177         apps[app_id] = NULL;
178
179         curr_scr->gen->unlock((WIDGET *)curr_scr);
180         return 0;
181 }
182
183
184 /*** DEFINE ROOT SCOPE OF AN APPLICATION ***/
185 static void set_rootscope(u32 app_id, SCOPE *rootscope) {
186         if (!app_id_valid(app_id) || !rootscope) return;
187         apps[app_id]->rootscope = rootscope;
188         if (curr_scr) curr_scr->gen->inc_ref((WIDGET *)curr_scr);
189         rootscope->scope->set_var(rootscope, "Screen", "screen", 255, (WIDGET *)curr_scr);
190 }
191
192
193 /*** REQUEST ROOT SCOPE OF AN APPLICATION ***/
194 static SCOPE *get_rootscope(u32 app_id) {
195         if (!app_id_valid(app_id)) return NULL;
196         return apps[app_id]->rootscope;
197 }
198
199
200 /*** REGISTER EVENT LISTENER DESTINATION POINT OF AN APPLICATION ***
201  *
202  * The listener is not necessarily a thread. It could be a socket descriptor
203  * or something else. We never know what hides behind the listener pointer.
204  */
205 static void reg_listener(s32 app_id, void *listener) {
206         if (!app_id_valid(app_id)) return;
207         apps[app_id]->listener = listener;
208 }
209
210
211 /*** REGISTER EVENT LISTENER THREAD OF AN APPLICATION ***
212  *
213  * We only store this optional listener thread id for proper resource deallocation.
214  */
215 static void reg_list_thread(s32 app_id, THREAD *listener_thread) {
216         if (!app_id_valid(app_id)) return;
217         apps[app_id]->list_thread = listener_thread;
218 }
219
220
221 /*** REQUEST EVENT LISTENER THREAD OF AN APPLICATION ***/
222 static void *get_listener(s32 app_id) {
223         if (!app_id_valid(app_id)) return NULL;
224         return apps[app_id]->listener;
225 }
226
227
228 /*** REGISTER APPLICATION THREAD ***/
229 static void reg_app_thread(s32 app_id, THREAD *app_thread) {
230         if (!app_id_valid(app_id)) return;
231         thread->copy_thread(app_thread, apps[app_id]->app_thread);
232 }
233
234
235 /*** REQUEST APPLICATION THREAD ***/
236 static THREAD *get_app_thread(s32 app_id) {
237         if (!app_id_valid(app_id)) return NULL;
238         return apps[app_id]->app_thread;
239 }
240
241
242 /*** FIND APPLICATION IF OF SPECIFIED APPLICATION THREAD ***/
243 static s32 app_id_of_thread(THREAD *app_thread) {
244         u32 i;
245         for (i=1; i<MAX_APPS; i++) {
246                 if (apps[i] && thread->thread_equal(apps[i]->listener, app_thread)) {
247                         INFO(printf("Appman(app_id_of_thread): found app_id, return %d\n", (int)i));
248                         return i;
249                 }
250         }
251         return -1;
252 }
253
254
255 /*** RESOLVE APPLICATION ID BY ITS NAME ***/
256 static s32 app_id_of_name(char *app_name) {
257         u32 i;
258         for (i=1; i<MAX_APPS; i++) {
259                 if (apps[i] && dope_streq(app_name, apps[i]->name, 255)) {
260                         return i;
261                 }
262         }
263
264         return -1;
265 }
266
267
268 /*** LOCK APPLICATION FOR MUTUAL EXCLUSIVE MODIFICATIONS ***/
269 static void lock(s32 app_id) {
270     (void)app_id;
271 //      SCOPE *s;
272 //      if (!app_id_valid(app_id) || !apps[app_id]->rootscope) return;
273 //      s = apps[app_id]->rootscope;
274 //      s->gen->lock((WIDGET *)s);
275 ////    thread->mutex_down(global_lock);
276         if (curr_scr) {
277                 curr_scr->gen->lock((WIDGET *)curr_scr);
278         } else {
279                 printf("AppMan(lock): lock not possible because curr_scr is not defined.\n");
280         }
281 }
282
283
284 /*** UNLOCK APPLICATION ***/
285 static void unlock(s32 app_id) {
286     (void)app_id;
287 //      SCOPE *s;
288 //      if (!app_id_valid(app_id) || !apps[app_id]->rootscope) return;
289 //      s = apps[app_id]->rootscope;
290 //      s->gen->unlock((WIDGET *)s);
291 ////    thread->mutex_up(global_lock);
292         if (curr_scr) curr_scr->gen->unlock((WIDGET *)curr_scr);
293 }
294
295
296 /****************************************
297  *** SERVICE STRUCTURE OF THIS MODULE ***
298  ****************************************/
299
300 static struct appman_services services = {
301         register_app,
302         unregister_app,
303         set_rootscope,
304         get_rootscope,
305         reg_listener,
306         reg_list_thread,
307         get_listener,
308         get_app_name,
309         reg_app_thread,
310         get_app_thread,
311         app_id_of_thread,
312         app_id_of_name,
313         lock,
314         unlock,
315 };
316
317
318 /**************************
319  *** MODULE ENTRY POINT ***
320  **************************/
321
322 int init_appman(struct dope_services *d) {
323
324         hashtab = d->get_module("HashTable 1.0");
325         thread  = d->get_module("Thread 1.0");
326 //      scope   = d->get_module("Scope 1.0");
327
328 //      global_lock = thread->create_mutex(0);
329
330         d->register_module("ApplicationManager 1.0", &services);
331         return 1;
332 }