Browse code

we use now three semaphore sets for transaction timers, retransmission timers and hash table entries

Jiri Kuthan authored on 22/11/2001 07:59:14
Showing 6 changed files
... ...
@@ -14,6 +14,8 @@ MKDEP=gcc -M
14 14
 
15 15
 ALLDEP=Makefile
16 16
 
17
+DEFS=-DFAKED_PARSER
18
+
17 19
 auto_gen=
18 20
 sources= $(filter-out $(auto_gen), $(wildcard *.c)) $(auto_gen)
19 21
 objs= $(sources:.c=.o)
... ...
@@ -1,7 +1,12 @@
1 1
 #include "h_table.h"
2 2
 
3
+
3 4
 int table_entries;
4 5
 
6
+struct cell      *T;
7
+unsigned int  global_msg_id;
8
+
9
+
5 10
 
6 11
 void free_cell( struct cell* dead_cell )
7 12
 {
... ...
@@ -87,30 +92,31 @@ struct s_table* init_hash_table()
87 87
    /*allocs the table*/
88 88
    hash_table = sh_malloc(  sizeof( struct s_table ) );
89 89
    if ( !hash_table )
90
-   {
91
-       free_hash_table( hash_table );
92
-      return 0;
93
-   }
90
+	goto error;
94 91
 
95 92
    /*inits the time*/
96 93
    hash_table->time = 0;
97 94
 
98
-   /* allocs the entry's table */
99 95
     table_entries = TABLE_ENTRIES;
96
+
97
+   /* try first allocating all the structures needed for syncing */
98
+   if (lock_initialize()==-1)
99
+	goto error;
100
+
101
+   /* allocs the entry's table */
100 102
     hash_table->entrys  = sh_malloc( table_entries * sizeof( struct entry )  );
101 103
     if ( !hash_table->entrys )
102
-    {
103
-        free_hash_table( hash_table );
104
-       return 0;
105
-    }
104
+	goto error;
106 105
 
107
-   /* allocs the timer's table */
106
+   /* allocs the transaction timer's table */
108 107
     hash_table->timers  = sh_malloc( NR_OF_TIMER_LISTS * sizeof( struct timer )  );
109 108
     if ( !hash_table->timers )
110
-    {
111
-        free_hash_table( hash_table );
112
-       return 0;
113
-    }
109
+	goto error;
110
+
111
+    /* allocs the retransmission timer's table */
112
+    hash_table->retr_timers = sh_malloc( NR_OF_RT_LISTS * sizeof (struct timer ) );
113
+    if ( !hash_table->retr_timers )
114
+	goto error;
114 115
 
115 116
     /* inits the entrys */
116 117
     for(  i=0 ; i<table_entries; i++ )
... ...
@@ -129,12 +135,25 @@ struct s_table* init_hash_table()
129 129
        //init_timerlist_lock( hash_table, (hash_table->timers)+i );
130 130
     }
131 131
 
132
+   /* init the retransmission timers */
133
+   for ( i=0; i<NR_OF_RT_LISTS; i++)
134
+   {
135
+       hash_table->timers[i].first_cell = 0;
136
+       hash_table->timers[i].last_cell = 0;
137
+       //init_retr_timer_lock( hash_table, (hash_table->timers)+i );
138
+   }
139
+
132 140
 #ifdef THREAD
133 141
    /* starts the timer thread/ process */
134 142
    pthread_create( &(hash_table->timer_thread_id), NULL, timer_routine, hash_table );
135 143
 #endif
136 144
 
137 145
    return  hash_table;
146
+
147
+error:
148
+   free_hash_table( hash_table );
149
+   lock_cleanup();
150
+   return 0;
138 151
 }
139 152
 
140 153
 
... ...
@@ -8,8 +8,6 @@
8 8
 #endif
9 9
 #include <sys/types.h>
10 10
 #include <sys/ipc.h>
11
-#include <sys/sem.h>
12
-
13 11
 #include "../../msg_parser.h"
14 12
 
15 13
 struct s_table;
... ...
@@ -28,9 +26,6 @@ struct cell;
28 28
 #define MAX_FORK           20
29 29
 
30 30
 
31
-extern  struct cell      *T;
32
-extern  unsigned int  global_msg_id;
33
-
34 31
 /* all you need to put a cell in a timer list:
35 32
    links to neighbours and timer value         */
36 33
 typedef struct timer_link
... ...
@@ -41,11 +36,16 @@ typedef struct timer_link
41 41
 
42 42
 
43 43
 /* timer list: includes head, tail and protection semaphore */
44
+
45
+/* RETRANSMISSION: CONSIDER rewriting for more generality; particularly,
46
+   rertransmission timers will not point to cells but to
47
+   outbound messages
48
+*/
44 49
 typedef struct  timer
45 50
 {
46 51
    struct cell*    first_cell;
47 52
    struct cell*    last_cell;
48
-   int                  sem;
53
+   /* int                  sem; */
49 54
    lock_t   mutex;
50 55
 } timer_type;
51 56
 
... ...
@@ -109,6 +109,8 @@ struct s_table
109 109
    struct entry*   entrys;
110 110
    /* table of timer lists */
111 111
    struct timer*   timers;
112
+   /* retransmission lists */
113
+   struct timer*   retr_timers;
112 114
 #ifdef THREADS
113 115
    pthread_t         timer_thread_id;
114 116
 #endif
... ...
@@ -6,78 +6,99 @@
6 6
 
7 7
 /* we implement mutex here using System V semaphores; as number of
8 8
    sempahores is limited and number of synchronized elements
9
-   high, we partition the SER elements and share semaphores in
10
-   each of them; we try to use as much semaphores as OS
9
+   high, we partition the sync'ed SER elements and share semaphores 
10
+   in each of the partitions; we try to use as many semaphores as OS
11 11
    gives us for finest granularity; perhaps later we will
12 12
    add some arch-dependent mutex code that will not have
13 13
    ipc's dimensioning limitations and will provide us with
14
-   fast unlimited mutexing
14
+   fast unlimited (=no sharing) mutexing
15 15
 
16 16
    we allocate the locks according to the following plans:
17 17
 
18
-   1) we try to allocate as many semaphores as possible
19
-   2) we grab first NR_OF_TIMER_LISTS semaphores for the
20
-      timer list
21
-   3) we take the remainder of semaphores R, and split
22
-      the hash-table table_entries into R partitiones;
23
-      within each partition, each entry shares the same
24
-      semaphore
25
-   4) every cell shares the same semaphore as its entry
18
+   1) transaction timer lists have each a semaphore in
19
+      a semaphore set
20
+   2) retransmission timer lists have each a semaphore
21
+      in a semaphore set
22
+   3) we allocate a semaphore set for hash_entries and
23
+      try to use as many semaphores in it as OS allows;
24
+      we partition the the hash_entries by available
25
+      semaphores which are shared  in each partition
26
+   4) cells get always the same semaphore as its hash
27
+      entry in which they live
26 28
 
27 29
 */
28 30
 
29 31
 /* keep the semaphore here */
30
-int semaphore;
31
-/* and the number of semaphores */
32
+int entry_semaphore=0, transaction_timer_semaphore=0, retrasmission_timer_semaphore=0;
33
+/* and the number of semaphores in the entry_semaphore set */
32 34
 int sem_nr;
33 35
 
34 36
 
35
-/* intitialize the locks; return 0 for unlimited number of locks
36
-   available, +int if number of locks limited, -1 on failure
37
-
38
-  with semaphores, use a single set with maximum number
39
-  of semaphores in it; return this number on success
37
+/* intitialize the locks; return 0 on success, -1 otherwise 
40 38
 */
41 39
 
42 40
 
43 41
 int lock_initialize()
44 42
 {
45
-	int i;
43
+	/* first try allocating semaphore sets with fixed number of semaphores */
44
+
45
+	/* transaction timers */
46
+	if ((transaction_timer_semaphore=init_semaphore_set( NR_OF_TIMER_LISTS) )==-1) {
47
+		DBG("transaction timer semaphore allocation failure\n");
48
+		goto error;
49
+	}
50
+
51
+	/* message retransmission timers */
52
+        if ((retrasmission_timer_semaphore=init_semaphore_set( NR_OF_RT_LISTS) )==-1) {
53
+                DBG("retransmission timer semaphore initialization failure\n");
54
+                goto error;
55
+        }
46 56
 	
47 57
 	sem_nr=12;
48 58
 	/* probing should return if too big:
49 59
 		Solaris: EINVAL
50 60
 		Linux: ENOSPC
51 61
 	*/
52
-	semaphore=semget ( IPC_PRIVATE, sem_nr, IPC_CREAT | IPC_PERMISSIONS );
53
-	/* if we failed to initialize, return */
54
-	if (semaphore==-1) return -1;
55
-
56
-
57
-	/* initialize semaphores */
58
-	
59
-	for (i=0; i<sem_nr; i++) {
60
-		union semun {
61
-			int val;
62
-			struct semid_ds *buf;
63
-			ushort *array;
64
-		} argument;
65
-		/* binary lock */
66
-		argument.val = +1;
67
-		if (semctl( semaphore , i , SETVAL , argument )==-1) {
68
-			/* return semaphore */
69
-			DBG("failed to initialize semaphore\n");
70
-			lock_cleanup();
71
-			return -1;
72
-		}
73
-	}
62
+        if ((entry_semaphore=init_semaphore_set( sem_nr ) )==-1) {
63
+                DBG("retransmission timer semaphore initialization failure\n");
64
+                goto error;
65
+        }
74 66
 	
75 67
 	/* return number of  sempahores in the set */
76
-	return sem_nr;
68
+	return 0;
69
+error:
70
+	lock_cleanup();
71
+	return -1;
77 72
 }
78 73
 
74
+int init_semaphore_set( int size )
75
+{
76
+	int new_semaphore, i;
77
+
78
+	new_semaphore=semget ( IPC_PRIVATE, size, IPC_CREAT | IPC_PERMISSIONS );
79
+	if (new_semaphore==-1) return new_semaphore;
80
+	for (i=0; i<size; i++) {
81
+                union semun {
82
+                        int val;
83
+                        struct semid_ds *buf;
84
+                        ushort *array;
85
+                } argument;
86
+                /* binary lock */
87
+                argument.val = +1;
88
+                if (semctl( new_semaphore, i , SETVAL , argument )==-1) {
89
+			DBG("ERROR: failure to initialize a semaphore\n");
90
+			if (semctl( entry_semaphore, 0 , IPC_RMID , 0 )==-1)
91
+				DBG("ERROR: failure to release a semaphore\n");
92
+			return -1;
93
+                }
94
+        }
95
+	return new_semaphore;
96
+}
97
+
98
+
99
+
79 100
 /* remove the semaphore set from system */
80
-int lock_cleanup()
101
+void lock_cleanup()
81 102
 {
82 103
 	/* that's system-wide; all othe processes trying to use
83 104
 	   the semaphore will fail! call only if it is for sure
... ...
@@ -87,7 +108,16 @@ int lock_cleanup()
87 87
 	DBG("clean-up still not implemented properly\n");
88 88
 	/* sibling double-check missing here; install a signal handler */
89 89
 
90
-	return  semctl( semaphore, 0 , IPC_RMID , 0 ) ;
90
+	if (entry_semaphore > 0 && 
91
+	    semctl( entry_semaphore, 0 , IPC_RMID , 0 )==-1)
92
+		DBG("ERROR: entry_semaphore cleanup failed\n"); 
93
+	if (transaction_timer_semaphore > 0 && 
94
+	    semctl( transaction_timer_semaphore, 0 , IPC_RMID , 0 )==-1)
95
+		DBG("ERROR: transaction_timer_semaphore cleanup failed\n"); 
96
+	if (retrasmission_timer_semaphore > 0 &&
97
+	    semctl( retrasmission_timer_semaphore, 0 , IPC_RMID , 0 )==-1)
98
+		DBG("ERROR: retrasmission_timer_semaphore cleanup failed\n"); 
99
+	
91 100
 }
92 101
 
93 102
 /* lock sempahore s */
... ...
@@ -102,21 +132,21 @@ int unlock( lock_t s )
102 102
 }
103 103
 
104 104
 
105
-int change_semaphore( int semaphore_id , int val )
105
+int change_semaphore( lock_t s  , int val )
106 106
 {
107 107
    struct sembuf pbuf;
108 108
    int r;
109 109
 
110
-   pbuf.sem_num = semaphore_id ;
110
+   pbuf.sem_num = s.semaphore_index ;
111 111
    pbuf.sem_op =val;
112 112
    pbuf.sem_flg = 0;
113 113
 
114 114
 tryagain:
115
-   r=semop( semaphore , &pbuf ,  1 /* just 1 op */ );
115
+   r=semop( s.semaphore_set, &pbuf ,  1 /* just 1 op */ );
116 116
 
117 117
    if (r==-1) {
118
-	printf("ERROR occured in change_semaphore: %d, %d, %s\n", 
119
-		semaphore_id, val, strerror(errno));
118
+	printf("ERROR occured in change_semaphore: %s\n", 
119
+		strerror(errno));
120 120
 	if (errno=EINTR) {
121 121
 		DBG("signal received in a semaphore\n");
122 122
 		goto tryagain;
... ...
@@ -129,8 +159,10 @@ int init_cell_lock( struct cell *cell )
129 129
 {
130 130
 	/* just advice which of the available semaphores to use;
131 131
 	   specifically, all cells in an entry use the same one
132
+	   shared with its entry lock
132 133
         */
133
-	cell->mutex=cell->hash_index / sem_nr + NR_OF_TIMER_LISTS;
134
+	cell->mutex.semaphore_set=entry_semaphore, 
135
+	cell->mutex.semaphore_index=cell->hash_index / sem_nr;
134 136
 }
135 137
 
136 138
 int init_entry_lock( struct s_table* hash_table, struct entry *entry )
... ...
@@ -139,16 +171,26 @@ int init_entry_lock( struct s_table* hash_table, struct entry *entry )
139 139
 	   specifically, all entries are partitioned into as
140 140
 	   many partitions as number of available semaphors allows
141 141
         */
142
-	entry->mutex=  ((void *)entry - (void *)(hash_table->entrys ) )
143
-			/ sizeof(struct entry) + NR_OF_TIMER_LISTS;
142
+	entry->mutex.semaphore_set=entry_semaphore;
143
+	entry->mutex.semaphore_index = 
144
+		((void *)entry - (void *)(hash_table->entrys ) )
145
+			/ ( sizeof(struct entry) * sem_nr );
144 146
 }
145 147
 
146 148
 int init_timerlist_lock( struct s_table* hash_table, enum lists timerlist_id)
147 149
 {
148 150
 	/* each timer list has its own semaphore */
149
-	hash_table->timers[timerlist_id].mutex = timerlist_id;
151
+	hash_table->timers[timerlist_id].mutex.semaphore_set=transaction_timer_semaphore;
152
+	hash_table->timers[timerlist_id].mutex.semaphore_index=timerlist_id;
150 153
 }
151 154
 
155
+int init_retr_timer_lock( struct s_table* hash_table, enum retransmission_lists list_id )
156
+{
157
+	hash_table->retr_timers[list_id].mutex.semaphore_set=retrasmission_timer_semaphore;
158
+ 	hash_table->retr_timers[list_id].mutex.semaphore_index=list_id;
159
+}
160
+
161
+
152 162
 int release_cell_lock( struct cell *cell )
153 163
 {
154 164
 	/* don't do anything here -- the init_*_lock procedures
... ...
@@ -165,3 +207,7 @@ release_timerlist_lock( struct timer *timerlist )
165 165
 {
166 166
 	/* the same as above */
167 167
 }
168
+int release_retr_timer_lock( struct timer *timerlist )
169
+{
170
+	
171
+}
... ...
@@ -7,7 +7,10 @@
7 7
 
8 8
 /* typedef to structure we use for mutexing;
9 9
    currently, index to a semaphore set identifier now */
10
-typedef int lock_t;
10
+typedef struct {
11
+	int semaphore_set;
12
+	int semaphore_index;
13
+} lock_t;
11 14
 
12 15
 #include "h_table.h"
13 16
 
... ...
@@ -15,22 +18,18 @@ typedef int lock_t;
15 15
 #define IPC_PERMISSIONS 0666
16 16
 
17 17
 
18
-/* try to allocate as long set as possible;
19
-   return set size or -1 on error
20
-*/
21
-
22 18
 int lock_initialize();
23
-
24
-int lock_cleanup();
19
+int init_semaphore_set( int size );
20
+void lock_cleanup();
25 21
 
26 22
 int lock( lock_t s );
27 23
 int unlock( lock_t s );
28
-
29
-int change_semaphore( int semaphore_id , int val );
24
+int change_semaphore( lock_t s  , int val );
30 25
 
31 26
 int init_cell_lock( struct cell *cell );
32 27
 int init_entry_lock( struct s_table* hash_table, struct entry *entry );
33 28
 int init_timerlist_lock( struct s_table* hash_table, enum lists timerlist_id);
29
+int init_retr_timer_lock( struct s_table* hash_table, enum retransmission_lists list_id );
34 30
 
35 31
 int release_cell_lock( struct cell *cell );
36 32
 int release_entry_lock( struct entry *entry );
... ...
@@ -3,6 +3,12 @@
3 3
 
4 4
 enum lists { FR_TIMER_LIST, WT_TIMER_LIST, DELETE_LIST, NR_OF_TIMER_LISTS };
5 5
 
6
+/* we maintain separate retransmission lists for each of retransmission
7
+   periods; that allows us to keep the lists ordered while just adding
8
+   new items to list's tail (FIFO)
9
+*/
10
+enum retransmission_lists { RT_T1_TO1, RT_T1_TO_2, RT_T1_TO_3, RT_T2, NR_OF_RT_LISTS };
11
+
6 12
 #include "h_table.h"
7 13
 
8 14
 /* FINAL_RESPONSE_TIMER ... tells how long should the transaction engine