Subversion Repositories shark

Rev

Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
/**
22
 ------------
14 pj 23
 CVS :        $Id: hartport.c,v 1.2 2002-10-28 07:55:54 pj Exp $
2 pj 24
 
25
 File:        $File$
14 pj 26
 Revision:    $Revision: 1.2 $
27
 Last update: $Date: 2002-10-28 07:55:54 $
2 pj 28
 ------------
29
 
30
 This file contains the Hartik 3.3.1 Port functions
31
 
32
 Author:      Giuseppe Lipari
33
 Date:        2/7/96
34
 
35
 File:  Port.C (renamed to hartport.c)
36
 Revision:    1.4
37
 
38
**/
39
 
40
/*
41
 * Copyright (C) 2000 Paolo Gai
42
 *
43
 * This program is free software; you can redistribute it and/or modify
44
 * it under the terms of the GNU General Public License as published by
45
 * the Free Software Foundation; either version 2 of the License, or
46
 * (at your option) any later version.
47
 *
48
 * This program is distributed in the hope that it will be useful,
49
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
50
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
51
 * GNU General Public License for more details.
52
 *
53
 * You should have received a copy of the GNU General Public License
54
 * along with this program; if not, write to the Free Software
55
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
56
 *
57
 */
58
 
59
 
60
#include <modules/hartport.h>
61
#include <kernel/config.h>
62
#include <ll/ll.h>
63
#include <ll/string.h>
64
#include <ll/stdio.h>
65
#include <kernel/model.h>
66
#include <kernel/const.h>
67
#include <sys/types.h>
68
#include <kernel/descr.h>
69
#include <errno.h>
70
#include <kernel/var.h>
71
#include <kernel/func.h>
72
 
73
 
74
static sem_t hash_mutex;
75
 
76
#define __PORT_DBG__
77
 
78
struct hash_port {
79
        char    name[MAX_PORT_NAME];
80
        PID     port_index;
81
        BYTE    blocked;
82
        sem_t   sem;
83
        BYTE    valid;
84
        int     port_int;
85
};
86
 
87
struct port_ker {
88
        BYTE    valid;
89
        int     next;
90
        WORD    dim_block;
91
        BYTE    *mem_block;
92
        BYTE    *head;
93
        BYTE    *tail;
94
        BYTE    type;
95
        sem_t   mutex;
96
        sem_t   pieno;
97
        sem_t   vuoto;
98
};
99
 
100
struct port_com {
101
        BYTE    valid;
102
        int     next;
103
        PID     proc_id;
104
        BYTE    access;
105
        int     port_index;
106
        WORD    dim_mes;
107
        int     h_index;
108
};
109
 
110
struct hash_port        htable[MAX_HASH_ENTRY];
111
struct port_ker         port_des[MAX_PORT];
112
struct port_com         port_int[MAX_PORT_INT];
113
QUEUE   freeportdes;
114
QUEUE   freeportint;
115
 
116
static int port_installed = 0;
117
 
118
 
119
/*----------------------------------------------------------------------*/
120
/* port_init() : inizializza le strutture delle porte; da chiamare      */
121
/* dentro __hartik_register_levels__().                                 */
122
/*----------------------------------------------------------------------*/
123
void HARTPORT_init(void)
124
{
125
    int i;
126
 
127
    if (port_installed)
128
      return;
129
    port_installed = 1;
130
 
131
    /* Init hash table                  */
132
    for (i = 0; i < MAX_HASH_ENTRY; i++) {
133
        htable[i].valid = FALSE;
134
        htable[i].port_int = NIL;
135
        htable[i].blocked = 0;
136
    }
137
 
138
    /* mutex sem on the hash table              */
139
    sem_init(&hash_mutex, 0, 1);
140
 
141
    /* init the port descriptor table   */
142
    for (i = 0; i < MAX_PORT - 1; i++) {
143
        port_des[i].next = i+1;
144
        port_des[i].valid = FALSE;
145
    }
146
    port_des[MAX_PORT - 1].next = NIL;
147
    port_des[MAX_PORT - 1].valid = FALSE;
148
    freeportdes = 0;
149
 
150
    /* Init the port interface table    */
151
    for (i = 0; i < MAX_PORT_INT - 1; i++) {
152
        port_int[i].next = i+1;
153
        port_int[i].valid = FALSE;
154
    }
155
    port_int[MAX_PORT_INT - 1].next = NIL;
156
    port_int[MAX_PORT_INT - 1].valid = FALSE;
157
//    for (i = PORT_NO_MORE_DESCR; i <= PORT_UNVALID_DESCR; i++)
158
//        exc_set(i,port_exception);
159
    freeportint = 0;
160
}
161
 
162
 
163
/*----------------------------------------------------------------------*/
164
/* hash_fun() : address hash table                                      */
165
/*----------------------------------------------------------------------*/
166
static int hash_fun(char *name)
167
{
168
    return (*name % MAX_HASH_ENTRY);
169
}
170
 
171
 
172
/*----------------------------------------------------------------------*/
173
/* getfreedes : restituisce l'indice di un descrittore di porta libero  */
174
/*----------------------------------------------------------------------*/
175
static int getfreedes(void)
176
{
177
    int p;
178
 
179
    kern_cli();
180
    if (freeportdes == NIL) {
181
        errno = EPORT_NO_MORE_DESCR;
182
        kern_sti();
183
        return -1;
184
    }
185
    p = freeportdes;
186
    freeportdes = port_des[p].next;
187
    kern_sti();
188
    return(p);
189
}        
190
 
191
/*----------------------------------------------------------------------*/
192
/* ungetdes() : mette il descrittore tra quelli disponibile             */
193
/*----------------------------------------------------------------------*/
194
static void ungetdes(int pd)
195
{
196
    kern_cli();
197
    port_des[pd].next = freeportdes;
198
    freeportdes = pd;
199
    kern_sti();
200
}
201
 
202
/*----------------------------------------------------------------------*/
203
/* get freeint : restituisce una interfaccia di porta libera            */
204
/*----------------------------------------------------------------------*/
205
static int getfreeint(void)
206
{
207
    int p;
208
 
209
    kern_cli();
210
    if (freeportint == NIL) {
211
        errno = EPORT_NO_MORE_INTERF;
212
        kern_sti();
213
        return -1;
214
    }
215
    p = freeportint;
216
    freeportint = port_int[p].next;
217
    kern_sti();
218
    return(p);
219
}      
220
 
221
/*----------------------------------------------------------------------*/
222
/* ungetint : rende disponibile l'interfaccia di porta specificata      */
223
/*----------------------------------------------------------------------*/
224
static void ungetint(int pi)
225
{
226
    kern_cli();
227
    port_int[pi].next = freeportint;
228
    freeportint = pi;
229
    kern_sti();
230
}
231
 
232
/*----------------------------------------------------------------------*/
233
/* port_create(): Apre la porta specificata dalla stringa, effettuando  */
234
/* automaticamente il collegamento                                      */
235
/* WARNING : La funzione e' bloccante per la mutua esclusione sulla     */
236
/* hash table                                                   */
237
/*----------------------------------------------------------------------*/
238
PORT port_create(char *name, int dim_mes, int num_mes, BYTE type, BYTE access)
239
{
240
    int i, pd, pi;
241
    WORD letti = 0;
242
    BYTE flag = FALSE;
243
 
244
/*
245
   Prendo un descrittore di porta.
246
*/
247
    #ifdef __PORT_DBG__
248
        if ((type == MAILBOX) && (access == WRITE)) {
249
           errno = EPORT_INCOMPAT_MESSAGE;
250
           return -1;
251
        }
252
        if ((type == STICK  ) && (access == READ )) {
253
           errno = EPORT_INCOMPAT_MESSAGE;
254
           return -1;
255
        }
256
    #endif
257
    pd = getfreedes();
258
    if (pd == -1) return -1;
259
/*
260
   Devo andare in mutua esclusione sulla tabella di hash ! Poiche' questa
261
   viene acceduta dalle openport e dalle connect sono sicuro che una
262
   connect non puo' interrompere una openport.
263
*/
264
    sem_wait(&hash_mutex);
265
/*
266
   Scorro la tabella di hash fino a trovare un'entrata libera, oppure
267
   una entrata occupata in precedenza da una connect che ci si e' bloccata
268
   sopra (blocked > 0). Se ne trovo una gia' aperta da un'altra openport
269
   esco con errore. Lo stesso se sono state occupate tutte le entrate della
270
   tabella (tramite la var. letti);
271
*/
272
    i = hash_fun(name);
273
    while (!flag) {
274
        if (htable[i].valid == FALSE) flag = TRUE;
275
        else {
276
            if (strcmp(htable[i].name,name) == 0) {
277
                if (htable[i].blocked == 0) {
278
                    errno = EPORT_ALREADY_OPEN;
279
                    sem_post(&hash_mutex);
280
                    return -1;
281
                }
282
                else flag = TRUE;
283
            }
284
            else {
285
                i = (i+1) % MAX_HASH_ENTRY;
286
                letti++;
287
            }
288
        }
289
        if (letti > MAX_HASH_ENTRY-1) {
290
            errno = EPORT_NO_MORE_HASHENTRY;
291
            sem_post(&hash_mutex);
292
            return -1;
293
        }
294
 
295
    }
296
    htable[i].valid = TRUE;
297
    strcpy(htable[i].name, name);
298
 
299
    htable[i].port_index = pd;
300
/*
301
   A questo punto inizializzo tutta la struttura del descrittore di porta
302
*/
303
    if (type == STICK)  port_des[pd].dim_block = dim_mes;
304
    else port_des[pd].dim_block = dim_mes * num_mes;
305
 
306
    kern_cli();
307
    port_des[pd].mem_block = kern_alloc(port_des[pd].dim_block);
308
    kern_sti();
309
    if (port_des[pd].mem_block == NULL) {
310
        errno = EPORT_2_CONNECT;
311
        sem_post(&hash_mutex);
312
        return -1;
313
    }
314
 
315
    port_des[pd].head = port_des[pd].tail = port_des[pd].mem_block;
316
 
317
    sem_init(&port_des[pd].mutex,0,1);
318
    sem_init(&port_des[pd].pieno,0,port_des[pd].dim_block);
319
    sem_init(&port_des[pd].vuoto,0,0);
320
    port_des[pd].type = type;
321
/*
322
   Prendo e inizializzo la struttura dell'interfaccia di porta verso il
323
   processo (e' la varibile pi quella che restituisco)
324
*/
325
    pi = getfreeint();
326
    if (pi == -1) {
327
        sem_post(&hash_mutex);
328
        return -1;
329
    }
330
 
331
/*  port_int[pi].proc_id = exec_shadow; */
332
    port_int[pi].access = access;
333
    port_int[pi].port_index = pd;
334
    port_int[pi].dim_mes = dim_mes;
335
    port_int[pi].next = NIL;
336
    port_int[pi].h_index = i;
337
    port_des[pd].valid = TRUE;
338
    port_int[pi].valid = TRUE;
339
/*
340
   Sblocco eventuali processi che avevano fatto la connect nella coda
341
   semaforica che sta nell'entrata relativa della hash table !
342
*/
343
    if (htable[i].blocked > 0) {
344
        sem_xpost(&htable[i].sem, htable[i].blocked);
345
        htable[i].blocked = 0;
346
        sem_destroy(&htable[i].sem);
347
    }
348
/*
349
   Infine libero la mutua esclusione.
350
*/
351
    sem_post(&hash_mutex);
352
    return (pi);
353
}
354
 
355
/*----------------------------------------------------------------------*/
356
/* port_connect(): collega la porta specificata dalla stringa.          */
357
/* WARNING : La funzione e' bloccante per la mutua esclusione sulle     */
358
/* strutture delle porte                                                */
359
/*----------------------------------------------------------------------*/
360
PORT port_connect(char *name, int dim_mes, BYTE type, BYTE access)
361
{
362
    int i, pi, pd, pn,letti = 0;
363
    BYTE flag = FALSE, create = FALSE;
364
 
365
    #ifdef __PORT_DBG__
366
        if ((type == MAILBOX) && (access == READ )) {
367
            errno = EPORT_INCOMPAT_MESSAGE;
368
            return -1;
369
        }
370
        if ((type == STICK  ) && (access == WRITE)) {
371
           errno = EPORT_INCOMPAT_MESSAGE;
372
           return -1;
373
        }
374
    #endif
375
/*
376
   Per prima cosa mi prendo una interfaccia di porta e la riempio
377
   parzialmente.       
378
*/
379
    pi = getfreeint();
380
    if (pi == -1) return -1;
381
/*  port_int[pi].proc_id = exec_shadow; */
382
    port_int[pi].access = access;
383
    port_int[pi].dim_mes = dim_mes;
384
    port_int[pi].next = NIL;
385
/*
386
   Mutua esclusione sulla tabella di hash
387
*/
388
    sem_wait(&hash_mutex);
389
/*
390
   Cerco il descrittore appropriato : Se la porta e' gia' stata aperta
391
   allora esco dal ciclo con flag = TRUE, create = FALSE, l'indice i che
392
   punta all'entrata della tabella di hash, e con htable[i].blocked = 0;
393
   In tutti gli altri casi significa che la porta non e' stata aperta e
394
   quindi devo bloccarmi.
395
*/
396
    i = hash_fun(name);
397
    while (!flag) {
398
        /* Devo crearla */
399
        if (htable[i].valid == FALSE) {
400
            flag = TRUE;
401
            create = TRUE;
402
        }
403
        /* l'ho trovata (ma non so ancora se e' stata aperta) */
404
        else if (strcmp(htable[i].name, name) == 0) flag = TRUE;
405
        /* scandisco l'entrata successiva */
406
        else {
407
            i = (i+1) % MAX_HASH_ENTRY;
408
            letti ++;
409
        }
410
        #ifdef __PORT_DBG__
411
            /* se ho scorso tutto l'array senza trovare nulla */
412
            if (letti > MAX_HASH_ENTRY) {
413
                errno = EPORT_NO_MORE_HASHENTRY;
414
                sem_post(&hash_mutex);
415
                return -1;
416
            }
417
        #endif
418
    }
419
 
420
/*
421
   Se devo aspettare che venga aperta (create = TRUE) allora mi blocco in
422
   attesa sul semaforo della htable. Per non avere troppi semafori inutili
423
   in giro, me lo creo sul momento.
424
*/
425
    if (create == TRUE) {
426
        htable[i].valid = TRUE;
427
        htable[i].blocked = 1;
428
        strcpy(htable[i].name, name);
429
        sem_init(&htable[i].sem, 0, 0);
430
        sem_post(&hash_mutex);
431
        sem_xwait(&htable[i].sem,1,BLOCK);
432
    }
433
/*
434
   Se invece si e' gia' bloccata un'altra connect sopra, mi blocco anch'io.
435
   in ogni caso devo liberare la mutua esclusione sulla hash dato che ho
436
   gia' fatto tutto quello che dovevo fare con la hash.
437
*/
438
    else {
439
        if (htable[i].blocked > 0) {
440
            htable[i].blocked++;
441
            sem_post(&hash_mutex);
442
            sem_xwait(&htable[i].sem,1,BLOCK);
443
        }
444
        else sem_post(&hash_mutex);
445
    }
446
/*
447
   Controlli di errore.
448
*/
449
    pd = htable[i].port_index;
450
    #ifdef __PORT_DBG__
451
        if (type != port_des[pd].type) {
452
            errno = EPORT_UNSUPPORTED_ACC;
453
            return -1;
454
        }
455
        if ((type == STICK) && (dim_mes != port_des[pd].dim_block)) {
456
            errno = EPORT_WRONG_OP;
457
            return -1;
458
        }
459
        if ((type != STICK) && (port_des[pd].dim_block % dim_mes) != 0) {
460
            errno = EPORT_WRONG_OP;
461
            return -1;
462
        }
463
    #endif
464
 
465
    sem_wait(&hash_mutex);
466
    pn = htable[i].port_int;
467
    if (pn != NIL) {
468
        #ifdef __PORT_DBG__
469
            if (type == STREAM) {
470
                errno = EPORT_WRONG_TYPE;
471
                sem_post(&hash_mutex);
472
                return -1;
473
            }
474
            if (dim_mes != port_int[pn].dim_mes) {
475
                errno = EPORT_WRONG_OP;
476
                sem_post(&hash_mutex);
477
                return -1;
478
            }
479
        #endif
480
        port_int[pi].next = htable[i].port_int;
481
        htable[i].port_int = pi;
482
    }
483
    else htable[i].port_int = pi;
484
    sem_post(&hash_mutex);
485
    port_int[pi].h_index = i;
486
    port_int[pi].port_index = pd;
487
    port_int[pi].valid = TRUE;
488
    return(pi);
489
}
490
 
491
/*----------------------------------------------------------------------*/
492
/* port_delete() : inversa di port_open, libera tutto                   */
493
/*----------------------------------------------------------------------*/
494
void port_delete(PORT pi)
495
{
496
    int i;
497
    struct port_ker *pd;
498
    struct port_com *pp;
499
 
500
    pp = &port_int[pi];
501
    sem_wait(&hash_mutex);
502
    i = pp->h_index;
503
    pd = &port_des[htable[i].port_index];
504
    pd->valid = FALSE;
505
    sem_destroy(&pd->mutex);
506
    sem_destroy(&pd->pieno);
507
    sem_destroy(&pd->vuoto);
508
 
509
    kern_cli();
510
    kern_free(pd->mem_block, pd->dim_block);
511
    kern_sti();
512
 
513
    ungetdes(htable[i].port_index);
514
    pp->valid = FALSE;
515
    htable[i].port_int = pp->next;
516
    ungetint(pi);
517
    htable[i].valid = FALSE;
518
    sem_post(&hash_mutex);
519
}
520
 
521
/*----------------------------------------------------------------------*/
522
/* port_disconnect() : libera l'interfaccia di porta                    */
523
/*----------------------------------------------------------------------*/
524
void port_disconnect(PORT pi)
525
{
526
    sem_wait(&hash_mutex);
527
    if (htable[port_int[pi].h_index].valid == TRUE)
528
        htable[port_int[pi].h_index].port_int = port_int[pi].next;
529
    port_int[pi].valid = FALSE;
530
    ungetint(pi);
531
    sem_post(&hash_mutex);
532
}
533
 
534
/*----------------------------------------------------------------------*/
535
/* port_send() : Invia un messaggio alla porta                          */
536
/*----------------------------------------------------------------------*/
537
WORD port_send(PORT pi, void *msg, BYTE wait)
538
{
539
    struct port_ker *pd;
540
    struct port_com *pp;
541
 
542
    pp = &(port_int[pi]);
543
    pd = &(port_des[pp->port_index]);
544
 
545
    #ifdef __PORT_DBG__
546
        if (pp->access == READ) {
547
          errno = EPORT_WRONG_OP;
548
          return -1;
549
        }
550
        if (!pd->valid) {
14 pj 551
          errno = EPORT_INVALID_DESCR;
2 pj 552
          return -1;
553
        }
554
 
555
    #endif
556
 
557
    if (pd->type == STICK) sem_wait(&pd->mutex);
558
    else if (pd->type == STREAM) {
559
            if (sem_xwait(&pd->pieno,pp->dim_mes,wait)) return(FALSE);
560
    }
561
    else {
562
        if (sem_xwait(&pd->pieno, pp->dim_mes,wait)) return(FALSE);
563
        sem_wait(&pd->mutex);
564
    }
565
 
566
    memcpy(pd->head, msg, pp->dim_mes);
567
 
568
    pd->head += pp->dim_mes;
569
 
570
    if (pd->head >= (pd->mem_block + pd->dim_block))
571
        pd->head -= pd->dim_block;
572
 
573
    if (pd->type == STICK) sem_post(&pd->mutex);
574
    else if (pd->type == STREAM) sem_xpost(&pd->vuoto, pp->dim_mes);
575
    else {
576
        sem_xpost(&pd->vuoto, pp->dim_mes);
577
        sem_post(&pd->mutex);
578
    }
579
    return(TRUE);
580
}
581
 
582
/*----------------------------------------------------------------------*/
583
/* port_receive() : Riceve un messaggio dalla porta                     */
584
/*----------------------------------------------------------------------*/
585
WORD port_receive(PORT pi,void *msg,BYTE wait)
586
{
587
    struct port_ker *pd;
588
    struct port_com *pp;
589
 
590
    pp = &(port_int[pi]);
591
    pd = &(port_des[pp->port_index]);
592
 
593
    #ifdef __PORT_DBG__
594
        if (pp->access == WRITE) {
595
          errno = EPORT_WRONG_OP;
596
          return -1;
597
        }
598
        if (!pd->valid) {
14 pj 599
          errno = EPORT_INVALID_DESCR;
2 pj 600
          return -1;
601
        }
602
    #endif      
603
 
604
    if (pd->type == STICK) sem_wait(&pd->mutex);
605
    else if (pd->type == STREAM) {
606
         if (sem_xwait(&pd->vuoto,pp->dim_mes,wait)) return(FALSE);
607
    }
608
    else {
609
        if (sem_xwait(&pd->vuoto,pp->dim_mes,wait)) return(FALSE);
610
        sem_wait(&pd->mutex);
611
    }
612
 
613
    memcpy(msg, pd->tail, pp->dim_mes);
614
 
615
    pd->tail += pp->dim_mes;
616
    if (pd->tail >= (pd->mem_block + pd->dim_block))
617
        pd->tail -= pd->dim_block;
618
 
619
    if (pd->type == STICK) sem_post(&pd->mutex);
620
    else if (pd->type == STREAM) sem_xpost(&pd->pieno, pp->dim_mes);
621
    else {
622
        sem_xpost(&pd->pieno, pp->dim_mes);
623
        sem_post(&pd->mutex);
624
    }
625
    return(TRUE);
626
}
627
 
628
#ifdef __PORT_DBG__
629
 
630
void print_port(void)
631
{
632
    int i;
633
    struct port_ker *pd;
634
    struct port_com *pp;
635
 
636
/*
637
        kern_printf("Hash Table :\n");
638
        for (i=0; i<MAX_HASH_ENTRY; i++)
639
                kern_printf("%d\tvl: %d\tbl: %d\tpd: %d\t%s\n", i,
640
                        htable[i].valid, htable[i].blocked, htable[i].port_index,
641
                        htable[i].name);
642
*/
643
        kern_printf("Port des :\n");
644
        kern_printf("Free port des : %d\n", freeportdes);
645
        for (i=0; i<MAX_PORT_INT; i++)
646
            if (port_int[i].valid) {
647
                pp = &port_int[i];
648
                pd = &port_des[pp->port_index];
649
                kern_printf("%d %s  vt: %d      pn: %d\n",i,htable[pp->h_index].name,
650
                pd->vuoto,pd->pieno);
651
            }
652
/*
653
        kern_printf("Port int :\n");
654
        kern_printf("Free port int : %d\n", freeportint);
655
        for (i=0; i<MAX_PORT_INT; i++)
656
                kern_printf("%d  vl : %d  dm : %d  port_index : %d  proc_id : %d\n", i,
657
                        port_int[i].valid, port_int[i].dim_mes,
658
                        port_int[i].port_index, port_int[i].proc_id);
659
*/
660
}
661
 
662
void port_write(PORT p)
663
{
664
    struct port_ker *pd;
665
    struct port_com *pp;
666
    char msg[80];
667
 
668
    pp = &port_int[p];
669
    pd = &port_des[pp->port_index];
670
 
671
    kern_printf(msg,"%d  pd: %d   vt: %d      pn: %d ",p,pp->port_index,
672
        pd->vuoto,pd->pieno);
673
}
674
 
675
#endif